summaryrefslogtreecommitdiff
path: root/libjava/classpath/java
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-16 00:30:23 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-16 00:30:23 +0000
commitc8875fb97fc03779a5bba09872227b1d08e5d52a (patch)
treea0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/java
parentc40c1730800ed292b6db39a83d592476fa59623c (diff)
downloadgcc-c8875fb97fc03779a5bba09872227b1d08e5d52a.tar.gz
Initial revision
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102074 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/classpath/java')
-rw-r--r--libjava/classpath/java/applet/Applet.java524
-rw-r--r--libjava/classpath/java/applet/AppletContext.java154
-rw-r--r--libjava/classpath/java/applet/AppletStub.java103
-rw-r--r--libjava/classpath/java/applet/AudioClip.java68
-rw-r--r--libjava/classpath/java/applet/package.html47
-rw-r--r--libjava/classpath/java/awt/AWTError.java64
-rw-r--r--libjava/classpath/java/awt/AWTEvent.java278
-rw-r--r--libjava/classpath/java/awt/AWTEventMulticaster.java1209
-rw-r--r--libjava/classpath/java/awt/AWTException.java64
-rw-r--r--libjava/classpath/java/awt/AWTKeyStroke.java660
-rw-r--r--libjava/classpath/java/awt/AWTPermission.java121
-rw-r--r--libjava/classpath/java/awt/ActiveEvent.java61
-rw-r--r--libjava/classpath/java/awt/Adjustable.java171
-rw-r--r--libjava/classpath/java/awt/AlphaComposite.java167
-rw-r--r--libjava/classpath/java/awt/AttributeValue.java98
-rw-r--r--libjava/classpath/java/awt/BasicStroke.java248
-rw-r--r--libjava/classpath/java/awt/BorderLayout.java731
-rw-r--r--libjava/classpath/java/awt/BufferCapabilities.java253
-rw-r--r--libjava/classpath/java/awt/Button.java466
-rw-r--r--libjava/classpath/java/awt/Canvas.java354
-rw-r--r--libjava/classpath/java/awt/CardLayout.java483
-rw-r--r--libjava/classpath/java/awt/Checkbox.java649
-rw-r--r--libjava/classpath/java/awt/CheckboxGroup.java173
-rw-r--r--libjava/classpath/java/awt/CheckboxMenuItem.java355
-rw-r--r--libjava/classpath/java/awt/Choice.java638
-rw-r--r--libjava/classpath/java/awt/Color.java1008
-rw-r--r--libjava/classpath/java/awt/ColorPaintContext.java195
-rw-r--r--libjava/classpath/java/awt/Component.java6017
-rw-r--r--libjava/classpath/java/awt/ComponentOrientation.java215
-rw-r--r--libjava/classpath/java/awt/Composite.java73
-rw-r--r--libjava/classpath/java/awt/CompositeContext.java71
-rw-r--r--libjava/classpath/java/awt/Container.java2026
-rw-r--r--libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java413
-rw-r--r--libjava/classpath/java/awt/Cursor.java224
-rw-r--r--libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java109
-rw-r--r--libjava/classpath/java/awt/DefaultKeyboardFocusManager.java536
-rw-r--r--libjava/classpath/java/awt/Dialog.java553
-rw-r--r--libjava/classpath/java/awt/Dimension.java234
-rw-r--r--libjava/classpath/java/awt/DisplayMode.java164
-rw-r--r--libjava/classpath/java/awt/Event.java185
-rw-r--r--libjava/classpath/java/awt/EventDispatchThread.java94
-rw-r--r--libjava/classpath/java/awt/EventQueue.java552
-rw-r--r--libjava/classpath/java/awt/FileDialog.java318
-rw-r--r--libjava/classpath/java/awt/FlowLayout.java364
-rw-r--r--libjava/classpath/java/awt/FocusTraversalPolicy.java103
-rw-r--r--libjava/classpath/java/awt/Font.java1336
-rw-r--r--libjava/classpath/java/awt/FontFormatException.java65
-rw-r--r--libjava/classpath/java/awt/FontMetrics.java425
-rw-r--r--libjava/classpath/java/awt/Frame.java649
-rw-r--r--libjava/classpath/java/awt/GradientPaint.java229
-rw-r--r--libjava/classpath/java/awt/Graphics.java767
-rw-r--r--libjava/classpath/java/awt/Graphics2D.java158
-rw-r--r--libjava/classpath/java/awt/GraphicsConfigTemplate.java106
-rw-r--r--libjava/classpath/java/awt/GraphicsConfiguration.java218
-rw-r--r--libjava/classpath/java/awt/GraphicsDevice.java292
-rw-r--r--libjava/classpath/java/awt/GraphicsEnvironment.java244
-rw-r--r--libjava/classpath/java/awt/GridBagConstraints.java195
-rw-r--r--libjava/classpath/java/awt/GridBagLayout.java1069
-rw-r--r--libjava/classpath/java/awt/GridBagLayoutInfo.java70
-rw-r--r--libjava/classpath/java/awt/GridLayout.java360
-rw-r--r--libjava/classpath/java/awt/HeadlessException.java72
-rw-r--r--libjava/classpath/java/awt/IllegalComponentStateException.java71
-rw-r--r--libjava/classpath/java/awt/Image.java203
-rw-r--r--libjava/classpath/java/awt/ImageCapabilities.java107
-rw-r--r--libjava/classpath/java/awt/Insets.java158
-rw-r--r--libjava/classpath/java/awt/ItemSelectable.java75
-rw-r--r--libjava/classpath/java/awt/JobAttributes.java500
-rw-r--r--libjava/classpath/java/awt/KeyEventDispatcher.java82
-rw-r--r--libjava/classpath/java/awt/KeyEventPostProcessor.java81
-rw-r--r--libjava/classpath/java/awt/KeyboardFocusManager.java1478
-rw-r--r--libjava/classpath/java/awt/Label.java314
-rw-r--r--libjava/classpath/java/awt/LayoutManager.java92
-rw-r--r--libjava/classpath/java/awt/LayoutManager2.java100
-rw-r--r--libjava/classpath/java/awt/List.java1263
-rw-r--r--libjava/classpath/java/awt/MediaTracker.java697
-rw-r--r--libjava/classpath/java/awt/Menu.java468
-rw-r--r--libjava/classpath/java/awt/MenuBar.java423
-rw-r--r--libjava/classpath/java/awt/MenuComponent.java1324
-rw-r--r--libjava/classpath/java/awt/MenuContainer.java71
-rw-r--r--libjava/classpath/java/awt/MenuItem.java603
-rw-r--r--libjava/classpath/java/awt/MenuShortcut.java207
-rw-r--r--libjava/classpath/java/awt/PageAttributes.java482
-rw-r--r--libjava/classpath/java/awt/Paint.java79
-rw-r--r--libjava/classpath/java/awt/PaintContext.java76
-rw-r--r--libjava/classpath/java/awt/Panel.java173
-rw-r--r--libjava/classpath/java/awt/Point.java245
-rw-r--r--libjava/classpath/java/awt/Polygon.java613
-rw-r--r--libjava/classpath/java/awt/PopupMenu.java169
-rw-r--r--libjava/classpath/java/awt/PrintGraphics.java57
-rw-r--r--libjava/classpath/java/awt/PrintJob.java104
-rw-r--r--libjava/classpath/java/awt/Rectangle.java749
-rw-r--r--libjava/classpath/java/awt/RenderingHints.java803
-rw-r--r--libjava/classpath/java/awt/Robot.java423
-rw-r--r--libjava/classpath/java/awt/ScrollPane.java615
-rw-r--r--libjava/classpath/java/awt/ScrollPaneAdjustable.java200
-rw-r--r--libjava/classpath/java/awt/Scrollbar.java825
-rw-r--r--libjava/classpath/java/awt/Shape.java203
-rw-r--r--libjava/classpath/java/awt/Stroke.java65
-rw-r--r--libjava/classpath/java/awt/SystemColor.java462
-rw-r--r--libjava/classpath/java/awt/TextArea.java629
-rw-r--r--libjava/classpath/java/awt/TextComponent.java739
-rw-r--r--libjava/classpath/java/awt/TextField.java541
-rw-r--r--libjava/classpath/java/awt/TexturePaint.java75
-rw-r--r--libjava/classpath/java/awt/Toolkit.java995
-rw-r--r--libjava/classpath/java/awt/Transparency.java67
-rw-r--r--libjava/classpath/java/awt/Window.java1125
-rw-r--r--libjava/classpath/java/awt/color/CMMException.java63
-rw-r--r--libjava/classpath/java/awt/color/ColorSpace.java183
-rw-r--r--libjava/classpath/java/awt/color/ICC_ColorSpace.java314
-rw-r--r--libjava/classpath/java/awt/color/ICC_Profile.java1244
-rw-r--r--libjava/classpath/java/awt/color/ICC_ProfileGray.java133
-rw-r--r--libjava/classpath/java/awt/color/ICC_ProfileRGB.java227
-rw-r--r--libjava/classpath/java/awt/color/ProfileDataException.java64
-rw-r--r--libjava/classpath/java/awt/color/package.html46
-rw-r--r--libjava/classpath/java/awt/datatransfer/Clipboard.java114
-rw-r--r--libjava/classpath/java/awt/datatransfer/ClipboardOwner.java57
-rw-r--r--libjava/classpath/java/awt/datatransfer/DataFlavor.java1034
-rw-r--r--libjava/classpath/java/awt/datatransfer/FlavorMap.java75
-rw-r--r--libjava/classpath/java/awt/datatransfer/FlavorTable.java73
-rw-r--r--libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java70
-rw-r--r--libjava/classpath/java/awt/datatransfer/StringSelection.java158
-rw-r--r--libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java169
-rw-r--r--libjava/classpath/java/awt/datatransfer/Transferable.java83
-rw-r--r--libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java65
-rw-r--r--libjava/classpath/java/awt/datatransfer/package.html47
-rw-r--r--libjava/classpath/java/awt/dnd/Autoscroll.java70
-rw-r--r--libjava/classpath/java/awt/dnd/DnDConstants.java77
-rw-r--r--libjava/classpath/java/awt/dnd/DnDEventMulticaster.java74
-rw-r--r--libjava/classpath/java/awt/dnd/DragGestureEvent.java156
-rw-r--r--libjava/classpath/java/awt/dnd/DragGestureListener.java63
-rw-r--r--libjava/classpath/java/awt/dnd/DragGestureRecognizer.java179
-rw-r--r--libjava/classpath/java/awt/dnd/DragSource.java257
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceAdapter.java126
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceContext.java200
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceDragEvent.java102
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceDropEvent.java89
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceEvent.java93
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceListener.java97
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceMotionListener.java64
-rw-r--r--libjava/classpath/java/awt/dnd/DropTarget.java293
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetAdapter.java100
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetContext.java188
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetDragEvent.java140
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetDropEvent.java170
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetEvent.java56
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetListener.java89
-rw-r--r--libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java73
-rw-r--r--libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java131
-rw-r--r--libjava/classpath/java/awt/dnd/package.html46
-rw-r--r--libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java57
-rw-r--r--libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java68
-rw-r--r--libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java48
-rw-r--r--libjava/classpath/java/awt/dnd/peer/package.html46
-rw-r--r--libjava/classpath/java/awt/event/AWTEventListener.java65
-rw-r--r--libjava/classpath/java/awt/event/AWTEventListenerProxy.java155
-rw-r--r--libjava/classpath/java/awt/event/ActionEvent.java226
-rw-r--r--libjava/classpath/java/awt/event/ActionListener.java59
-rw-r--r--libjava/classpath/java/awt/event/AdjustmentEvent.java222
-rw-r--r--libjava/classpath/java/awt/event/AdjustmentListener.java58
-rw-r--r--libjava/classpath/java/awt/event/ComponentAdapter.java97
-rw-r--r--libjava/classpath/java/awt/event/ComponentEvent.java137
-rw-r--r--libjava/classpath/java/awt/event/ComponentListener.java84
-rw-r--r--libjava/classpath/java/awt/event/ContainerAdapter.java79
-rw-r--r--libjava/classpath/java/awt/event/ContainerEvent.java135
-rw-r--r--libjava/classpath/java/awt/event/ContainerListener.java70
-rw-r--r--libjava/classpath/java/awt/event/FocusAdapter.java79
-rw-r--r--libjava/classpath/java/awt/event/FocusEvent.java181
-rw-r--r--libjava/classpath/java/awt/event/FocusListener.java69
-rw-r--r--libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java78
-rw-r--r--libjava/classpath/java/awt/event/HierarchyBoundsListener.java70
-rw-r--r--libjava/classpath/java/awt/event/HierarchyEvent.java253
-rw-r--r--libjava/classpath/java/awt/event/HierarchyListener.java62
-rw-r--r--libjava/classpath/java/awt/event/InputEvent.java381
-rw-r--r--libjava/classpath/java/awt/event/InputMethodEvent.java303
-rw-r--r--libjava/classpath/java/awt/event/InputMethodListener.java70
-rw-r--r--libjava/classpath/java/awt/event/InvocationEvent.java237
-rw-r--r--libjava/classpath/java/awt/event/ItemEvent.java155
-rw-r--r--libjava/classpath/java/awt/event/ItemListener.java62
-rw-r--r--libjava/classpath/java/awt/event/KeyAdapter.java88
-rw-r--r--libjava/classpath/java/awt/event/KeyEvent.java1740
-rw-r--r--libjava/classpath/java/awt/event/KeyListener.java77
-rw-r--r--libjava/classpath/java/awt/event/MouseAdapter.java106
-rw-r--r--libjava/classpath/java/awt/event/MouseEvent.java432
-rw-r--r--libjava/classpath/java/awt/event/MouseListener.java94
-rw-r--r--libjava/classpath/java/awt/event/MouseMotionAdapter.java79
-rw-r--r--libjava/classpath/java/awt/event/MouseMotionListener.java72
-rw-r--r--libjava/classpath/java/awt/event/MouseWheelEvent.java232
-rw-r--r--libjava/classpath/java/awt/event/MouseWheelListener.java60
-rw-r--r--libjava/classpath/java/awt/event/PaintEvent.java127
-rw-r--r--libjava/classpath/java/awt/event/TextEvent.java93
-rw-r--r--libjava/classpath/java/awt/event/TextListener.java60
-rw-r--r--libjava/classpath/java/awt/event/WindowAdapter.java156
-rw-r--r--libjava/classpath/java/awt/event/WindowEvent.java312
-rw-r--r--libjava/classpath/java/awt/event/WindowFocusListener.java68
-rw-r--r--libjava/classpath/java/awt/event/WindowListener.java109
-rw-r--r--libjava/classpath/java/awt/event/WindowStateListener.java62
-rw-r--r--libjava/classpath/java/awt/event/package.html46
-rw-r--r--libjava/classpath/java/awt/font/FontRenderContext.java126
-rw-r--r--libjava/classpath/java/awt/font/GlyphJustificationInfo.java77
-rw-r--r--libjava/classpath/java/awt/font/GlyphMetrics.java134
-rw-r--r--libjava/classpath/java/awt/font/GlyphVector.java145
-rw-r--r--libjava/classpath/java/awt/font/GraphicAttribute.java84
-rw-r--r--libjava/classpath/java/awt/font/ImageGraphicAttribute.java109
-rw-r--r--libjava/classpath/java/awt/font/LineBreakMeasurer.java113
-rw-r--r--libjava/classpath/java/awt/font/LineMetrics.java67
-rw-r--r--libjava/classpath/java/awt/font/MultipleMaster.java61
-rw-r--r--libjava/classpath/java/awt/font/NumericShaper.java137
-rw-r--r--libjava/classpath/java/awt/font/OpenType.java111
-rw-r--r--libjava/classpath/java/awt/font/ShapeGraphicAttribute.java105
-rw-r--r--libjava/classpath/java/awt/font/TextAttribute.java309
-rw-r--r--libjava/classpath/java/awt/font/TextHitInfo.java125
-rw-r--r--libjava/classpath/java/awt/font/TextLayout.java332
-rw-r--r--libjava/classpath/java/awt/font/TextMeasurer.java97
-rw-r--r--libjava/classpath/java/awt/font/TransformAttribute.java100
-rw-r--r--libjava/classpath/java/awt/font/package.html46
-rw-r--r--libjava/classpath/java/awt/geom/AffineTransform.java1487
-rw-r--r--libjava/classpath/java/awt/geom/Arc2D.java1399
-rw-r--r--libjava/classpath/java/awt/geom/Area.java3312
-rw-r--r--libjava/classpath/java/awt/geom/CubicCurve2D.java1724
-rw-r--r--libjava/classpath/java/awt/geom/Dimension2D.java118
-rw-r--r--libjava/classpath/java/awt/geom/Ellipse2D.java413
-rw-r--r--libjava/classpath/java/awt/geom/FlatteningPathIterator.java579
-rw-r--r--libjava/classpath/java/awt/geom/GeneralPath.java958
-rw-r--r--libjava/classpath/java/awt/geom/IllegalPathStateException.java71
-rw-r--r--libjava/classpath/java/awt/geom/Line2D.java1182
-rw-r--r--libjava/classpath/java/awt/geom/NoninvertibleTransformException.java65
-rw-r--r--libjava/classpath/java/awt/geom/PathIterator.java189
-rw-r--r--libjava/classpath/java/awt/geom/Point2D.java396
-rw-r--r--libjava/classpath/java/awt/geom/QuadCurve2D.java1467
-rw-r--r--libjava/classpath/java/awt/geom/Rectangle2D.java992
-rw-r--r--libjava/classpath/java/awt/geom/RectangularShape.java385
-rw-r--r--libjava/classpath/java/awt/geom/RoundRectangle2D.java533
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/Area-1.pngbin0 -> 21447 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.pngbin0 -> 6280 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.pngbin0 -> 5791 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.pngbin0 -> 13168 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.pngbin0 -> 7839 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.pngbin0 -> 5112 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/Ellipse-1.pngbin0 -> 19426 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html481
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.pngbin0 -> 13111 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.pngbin0 -> 6363 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.pngbin0 -> 5872 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.pngbin0 -> 12334 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.pngbin0 -> 7797 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.pngbin0 -> 4757 bytes
-rw-r--r--libjava/classpath/java/awt/geom/package.html46
-rw-r--r--libjava/classpath/java/awt/im/InputContext.java434
-rw-r--r--libjava/classpath/java/awt/im/InputMethodHighlight.java185
-rw-r--r--libjava/classpath/java/awt/im/InputMethodRequests.java153
-rw-r--r--libjava/classpath/java/awt/im/InputSubset.java129
-rw-r--r--libjava/classpath/java/awt/im/package.html46
-rw-r--r--libjava/classpath/java/awt/im/spi/InputMethod.java240
-rw-r--r--libjava/classpath/java/awt/im/spi/InputMethodContext.java123
-rw-r--r--libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java113
-rw-r--r--libjava/classpath/java/awt/im/spi/package.html46
-rw-r--r--libjava/classpath/java/awt/image/AffineTransformOp.java375
-rw-r--r--libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java127
-rw-r--r--libjava/classpath/java/awt/image/BandCombineOp.java168
-rw-r--r--libjava/classpath/java/awt/image/BandedSampleModel.java548
-rw-r--r--libjava/classpath/java/awt/image/BufferStrategy.java124
-rw-r--r--libjava/classpath/java/awt/image/BufferedImage.java693
-rw-r--r--libjava/classpath/java/awt/image/BufferedImageFilter.java110
-rw-r--r--libjava/classpath/java/awt/image/BufferedImageOp.java55
-rw-r--r--libjava/classpath/java/awt/image/ByteLookupTable.java166
-rw-r--r--libjava/classpath/java/awt/image/ColorConvertOp.java319
-rw-r--r--libjava/classpath/java/awt/image/ColorModel.java758
-rw-r--r--libjava/classpath/java/awt/image/ComponentColorModel.java391
-rw-r--r--libjava/classpath/java/awt/image/ComponentSampleModel.java544
-rw-r--r--libjava/classpath/java/awt/image/ConvolveOp.java337
-rw-r--r--libjava/classpath/java/awt/image/CropImageFilter.java180
-rw-r--r--libjava/classpath/java/awt/image/DataBuffer.java436
-rw-r--r--libjava/classpath/java/awt/image/DataBufferByte.java245
-rw-r--r--libjava/classpath/java/awt/image/DataBufferDouble.java288
-rw-r--r--libjava/classpath/java/awt/image/DataBufferFloat.java286
-rw-r--r--libjava/classpath/java/awt/image/DataBufferInt.java244
-rw-r--r--libjava/classpath/java/awt/image/DataBufferShort.java245
-rw-r--r--libjava/classpath/java/awt/image/DataBufferUShort.java246
-rw-r--r--libjava/classpath/java/awt/image/DirectColorModel.java420
-rw-r--r--libjava/classpath/java/awt/image/FilteredImageSource.java125
-rw-r--r--libjava/classpath/java/awt/image/ImageConsumer.java216
-rw-r--r--libjava/classpath/java/awt/image/ImageFilter.java221
-rw-r--r--libjava/classpath/java/awt/image/ImageObserver.java129
-rw-r--r--libjava/classpath/java/awt/image/ImageProducer.java85
-rw-r--r--libjava/classpath/java/awt/image/ImagingOpException.java66
-rw-r--r--libjava/classpath/java/awt/image/IndexColorModel.java697
-rw-r--r--libjava/classpath/java/awt/image/Kernel.java143
-rw-r--r--libjava/classpath/java/awt/image/LookupOp.java252
-rw-r--r--libjava/classpath/java/awt/image/LookupTable.java109
-rw-r--r--libjava/classpath/java/awt/image/MemoryImageSource.java373
-rw-r--r--libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java388
-rw-r--r--libjava/classpath/java/awt/image/PackedColorModel.java192
-rw-r--r--libjava/classpath/java/awt/image/PixelGrabber.java618
-rw-r--r--libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java98
-rw-r--r--libjava/classpath/java/awt/image/RGBImageFilter.java267
-rw-r--r--libjava/classpath/java/awt/image/Raster.java546
-rw-r--r--libjava/classpath/java/awt/image/RasterFormatException.java65
-rw-r--r--libjava/classpath/java/awt/image/RasterOp.java57
-rw-r--r--libjava/classpath/java/awt/image/RenderedImage.java70
-rw-r--r--libjava/classpath/java/awt/image/ReplicateScaleFilter.java244
-rw-r--r--libjava/classpath/java/awt/image/RescaleOp.java218
-rw-r--r--libjava/classpath/java/awt/image/SampleModel.java477
-rw-r--r--libjava/classpath/java/awt/image/ShortLookupTable.java162
-rw-r--r--libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java449
-rw-r--r--libjava/classpath/java/awt/image/TileObserver.java47
-rw-r--r--libjava/classpath/java/awt/image/VolatileImage.java253
-rw-r--r--libjava/classpath/java/awt/image/WritableRaster.java265
-rw-r--r--libjava/classpath/java/awt/image/WritableRenderedImage.java56
-rw-r--r--libjava/classpath/java/awt/image/package.html46
-rw-r--r--libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java56
-rw-r--r--libjava/classpath/java/awt/image/renderable/ParameterBlock.java308
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderContext.java141
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderableImage.java62
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderableImageOp.java157
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java79
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java47
-rw-r--r--libjava/classpath/java/awt/image/renderable/package.html46
-rw-r--r--libjava/classpath/java/awt/package.html46
-rw-r--r--libjava/classpath/java/awt/peer/ButtonPeer.java46
-rw-r--r--libjava/classpath/java/awt/peer/CanvasPeer.java45
-rw-r--r--libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java46
-rw-r--r--libjava/classpath/java/awt/peer/CheckboxPeer.java52
-rw-r--r--libjava/classpath/java/awt/peer/ChoicePeer.java54
-rw-r--r--libjava/classpath/java/awt/peer/ComponentPeer.java187
-rw-r--r--libjava/classpath/java/awt/peer/ContainerPeer.java59
-rw-r--r--libjava/classpath/java/awt/peer/DialogPeer.java48
-rw-r--r--libjava/classpath/java/awt/peer/FileDialogPeer.java52
-rw-r--r--libjava/classpath/java/awt/peer/FontPeer.java45
-rw-r--r--libjava/classpath/java/awt/peer/FramePeer.java55
-rw-r--r--libjava/classpath/java/awt/peer/LabelPeer.java46
-rw-r--r--libjava/classpath/java/awt/peer/LightweightPeer.java45
-rw-r--r--libjava/classpath/java/awt/peer/ListPeer.java61
-rw-r--r--libjava/classpath/java/awt/peer/MenuBarPeer.java48
-rw-r--r--libjava/classpath/java/awt/peer/MenuComponentPeer.java45
-rw-r--r--libjava/classpath/java/awt/peer/MenuItemPeer.java48
-rw-r--r--libjava/classpath/java/awt/peer/MenuPeer.java48
-rw-r--r--libjava/classpath/java/awt/peer/PanelPeer.java45
-rw-r--r--libjava/classpath/java/awt/peer/PopupMenuPeer.java53
-rw-r--r--libjava/classpath/java/awt/peer/RobotPeer.java54
-rw-r--r--libjava/classpath/java/awt/peer/ScrollPanePeer.java52
-rw-r--r--libjava/classpath/java/awt/peer/ScrollbarPeer.java47
-rw-r--r--libjava/classpath/java/awt/peer/TextAreaPeer.java53
-rw-r--r--libjava/classpath/java/awt/peer/TextComponentPeer.java57
-rw-r--r--libjava/classpath/java/awt/peer/TextFieldPeer.java52
-rw-r--r--libjava/classpath/java/awt/peer/WindowPeer.java46
-rw-r--r--libjava/classpath/java/awt/peer/package.html46
-rw-r--r--libjava/classpath/java/awt/print/Book.java159
-rw-r--r--libjava/classpath/java/awt/print/PageFormat.java292
-rw-r--r--libjava/classpath/java/awt/print/Pageable.java113
-rw-r--r--libjava/classpath/java/awt/print/Paper.java236
-rw-r--r--libjava/classpath/java/awt/print/Printable.java80
-rw-r--r--libjava/classpath/java/awt/print/PrinterAbortException.java71
-rw-r--r--libjava/classpath/java/awt/print/PrinterException.java71
-rw-r--r--libjava/classpath/java/awt/print/PrinterGraphics.java61
-rw-r--r--libjava/classpath/java/awt/print/PrinterIOException.java98
-rw-r--r--libjava/classpath/java/awt/print/PrinterJob.java299
-rw-r--r--libjava/classpath/java/awt/print/package.html46
-rw-r--r--libjava/classpath/java/beans/AppletInitializer.java61
-rw-r--r--libjava/classpath/java/beans/BeanDescriptor.java89
-rw-r--r--libjava/classpath/java/beans/BeanInfo.java181
-rw-r--r--libjava/classpath/java/beans/Beans.java368
-rw-r--r--libjava/classpath/java/beans/Customizer.java86
-rw-r--r--libjava/classpath/java/beans/DesignMode.java93
-rw-r--r--libjava/classpath/java/beans/EventHandler.java606
-rw-r--r--libjava/classpath/java/beans/EventSetDescriptor.java442
-rw-r--r--libjava/classpath/java/beans/ExceptionListener.java57
-rw-r--r--libjava/classpath/java/beans/Expression.java133
-rw-r--r--libjava/classpath/java/beans/FeatureDescriptor.java232
-rw-r--r--libjava/classpath/java/beans/IndexedPropertyDescriptor.java307
-rw-r--r--libjava/classpath/java/beans/IntrospectionException.java67
-rw-r--r--libjava/classpath/java/beans/Introspector.java608
-rw-r--r--libjava/classpath/java/beans/MethodDescriptor.java88
-rw-r--r--libjava/classpath/java/beans/ParameterDescriptor.java52
-rw-r--r--libjava/classpath/java/beans/PropertyChangeEvent.java189
-rw-r--r--libjava/classpath/java/beans/PropertyChangeListener.java61
-rw-r--r--libjava/classpath/java/beans/PropertyChangeListenerProxy.java102
-rw-r--r--libjava/classpath/java/beans/PropertyChangeSupport.java488
-rw-r--r--libjava/classpath/java/beans/PropertyDescriptor.java583
-rw-r--r--libjava/classpath/java/beans/PropertyEditor.java209
-rw-r--r--libjava/classpath/java/beans/PropertyEditorManager.java215
-rw-r--r--libjava/classpath/java/beans/PropertyEditorSupport.java265
-rw-r--r--libjava/classpath/java/beans/PropertyVetoException.java85
-rw-r--r--libjava/classpath/java/beans/SimpleBeanInfo.java139
-rw-r--r--libjava/classpath/java/beans/Statement.java326
-rw-r--r--libjava/classpath/java/beans/TODO4
-rw-r--r--libjava/classpath/java/beans/VetoableChangeListener.java73
-rw-r--r--libjava/classpath/java/beans/VetoableChangeListenerProxy.java102
-rw-r--r--libjava/classpath/java/beans/VetoableChangeSupport.java530
-rw-r--r--libjava/classpath/java/beans/Visibility.java85
-rw-r--r--libjava/classpath/java/beans/XMLDecoder.java307
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContext.java272
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextChild.java174
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextChildComponentProxy.java60
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextChildSupport.java381
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextContainerProxy.java63
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextEvent.java110
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextMembershipEvent.java112
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextMembershipListener.java70
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextProxy.java65
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceAvailableEvent.java95
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceProvider.java138
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java60
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedEvent.java110
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedListener.java62
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServices.java216
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServicesListener.java56
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java300
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextSupport.java460
-rw-r--r--libjava/classpath/java/beans/beancontext/package.html46
-rw-r--r--libjava/classpath/java/beans/package.html46
-rw-r--r--libjava/classpath/java/io/BufferedInputStream.java379
-rw-r--r--libjava/classpath/java/io/BufferedOutputStream.java192
-rw-r--r--libjava/classpath/java/io/BufferedReader.java581
-rw-r--r--libjava/classpath/java/io/BufferedWriter.java262
-rw-r--r--libjava/classpath/java/io/ByteArrayInputStream.java251
-rw-r--r--libjava/classpath/java/io/ByteArrayOutputStream.java283
-rw-r--r--libjava/classpath/java/io/CharArrayReader.java305
-rw-r--r--libjava/classpath/java/io/CharArrayWriter.java274
-rw-r--r--libjava/classpath/java/io/CharConversionException.java73
-rw-r--r--libjava/classpath/java/io/Closeable.java63
-rw-r--r--libjava/classpath/java/io/DataInput.java456
-rw-r--r--libjava/classpath/java/io/DataInputStream.java739
-rw-r--r--libjava/classpath/java/io/DataOutput.java326
-rw-r--r--libjava/classpath/java/io/DataOutputStream.java455
-rw-r--r--libjava/classpath/java/io/DeleteFileHelper.java109
-rw-r--r--libjava/classpath/java/io/EOFException.java76
-rw-r--r--libjava/classpath/java/io/Externalizable.java107
-rw-r--r--libjava/classpath/java/io/File.java1357
-rw-r--r--libjava/classpath/java/io/FileDescriptor.java139
-rw-r--r--libjava/classpath/java/io/FileFilter.java65
-rw-r--r--libjava/classpath/java/io/FileInputStream.java309
-rw-r--r--libjava/classpath/java/io/FileNotFoundException.java73
-rw-r--r--libjava/classpath/java/io/FileOutputStream.java296
-rw-r--r--libjava/classpath/java/io/FilePermission.java292
-rw-r--r--libjava/classpath/java/io/FileReader.java92
-rw-r--r--libjava/classpath/java/io/FileWriter.java137
-rw-r--r--libjava/classpath/java/io/FilenameFilter.java76
-rw-r--r--libjava/classpath/java/io/FilterInputStream.java203
-rw-r--r--libjava/classpath/java/io/FilterOutputStream.java150
-rw-r--r--libjava/classpath/java/io/FilterReader.java185
-rw-r--r--libjava/classpath/java/io/FilterWriter.java147
-rw-r--r--libjava/classpath/java/io/Flushable.java62
-rw-r--r--libjava/classpath/java/io/IOException.java74
-rw-r--r--libjava/classpath/java/io/InputStream.java272
-rw-r--r--libjava/classpath/java/io/InputStreamReader.java438
-rw-r--r--libjava/classpath/java/io/InterruptedIOException.java94
-rw-r--r--libjava/classpath/java/io/InvalidClassException.java111
-rw-r--r--libjava/classpath/java/io/InvalidObjectException.java66
-rw-r--r--libjava/classpath/java/io/LineNumberInputStream.java315
-rw-r--r--libjava/classpath/java/io/LineNumberReader.java417
-rw-r--r--libjava/classpath/java/io/NotActiveException.java72
-rw-r--r--libjava/classpath/java/io/NotSerializableException.java74
-rw-r--r--libjava/classpath/java/io/ObjectInput.java140
-rw-r--r--libjava/classpath/java/io/ObjectInputStream.java1956
-rw-r--r--libjava/classpath/java/io/ObjectInputValidation.java67
-rw-r--r--libjava/classpath/java/io/ObjectOutput.java111
-rw-r--r--libjava/classpath/java/io/ObjectOutputStream.java1578
-rw-r--r--libjava/classpath/java/io/ObjectStreamClass.java976
-rw-r--r--libjava/classpath/java/io/ObjectStreamConstants.java89
-rw-r--r--libjava/classpath/java/io/ObjectStreamException.java74
-rw-r--r--libjava/classpath/java/io/ObjectStreamField.java412
-rw-r--r--libjava/classpath/java/io/OptionalDataException.java91
-rw-r--r--libjava/classpath/java/io/OutputStream.java140
-rw-r--r--libjava/classpath/java/io/OutputStreamWriter.java356
-rw-r--r--libjava/classpath/java/io/PipedInputStream.java374
-rw-r--r--libjava/classpath/java/io/PipedOutputStream.java181
-rw-r--r--libjava/classpath/java/io/PipedReader.java361
-rw-r--r--libjava/classpath/java/io/PipedWriter.java182
-rw-r--r--libjava/classpath/java/io/PrintStream.java553
-rw-r--r--libjava/classpath/java/io/PrintWriter.java571
-rw-r--r--libjava/classpath/java/io/PushbackInputStream.java328
-rw-r--r--libjava/classpath/java/io/PushbackReader.java384
-rw-r--r--libjava/classpath/java/io/RandomAccessFile.java991
-rw-r--r--libjava/classpath/java/io/Reader.java271
-rw-r--r--libjava/classpath/java/io/SequenceInputStream.java221
-rw-r--r--libjava/classpath/java/io/Serializable.java54
-rw-r--r--libjava/classpath/java/io/SerializablePermission.java113
-rw-r--r--libjava/classpath/java/io/StreamCorruptedException.java73
-rw-r--r--libjava/classpath/java/io/StreamTokenizer.java708
-rw-r--r--libjava/classpath/java/io/StringBufferInputStream.java187
-rw-r--r--libjava/classpath/java/io/StringReader.java209
-rw-r--r--libjava/classpath/java/io/StringWriter.java191
-rw-r--r--libjava/classpath/java/io/SyncFailedException.java66
-rw-r--r--libjava/classpath/java/io/UTFDataFormatException.java74
-rw-r--r--libjava/classpath/java/io/UnsupportedEncodingException.java73
-rw-r--r--libjava/classpath/java/io/WriteAbortedException.java109
-rw-r--r--libjava/classpath/java/io/Writer.java192
-rw-r--r--libjava/classpath/java/io/class-dependencies.conf100
-rw-r--r--libjava/classpath/java/io/package.html46
-rw-r--r--libjava/classpath/java/lang/AbstractMethodError.java75
-rw-r--r--libjava/classpath/java/lang/Appendable.java122
-rw-r--r--libjava/classpath/java/lang/ArithmeticException.java77
-rw-r--r--libjava/classpath/java/lang/ArrayIndexOutOfBoundsException.java87
-rw-r--r--libjava/classpath/java/lang/ArrayStoreException.java77
-rw-r--r--libjava/classpath/java/lang/AssertionError.java148
-rw-r--r--libjava/classpath/java/lang/Boolean.java224
-rw-r--r--libjava/classpath/java/lang/Byte.java357
-rw-r--r--libjava/classpath/java/lang/CharSequence.java99
-rw-r--r--libjava/classpath/java/lang/Character.java2253
-rw-r--r--libjava/classpath/java/lang/Class.java1324
-rw-r--r--libjava/classpath/java/lang/ClassCastException.java76
-rw-r--r--libjava/classpath/java/lang/ClassCircularityError.java73
-rw-r--r--libjava/classpath/java/lang/ClassFormatError.java72
-rw-r--r--libjava/classpath/java/lang/ClassLoader.java1116
-rw-r--r--libjava/classpath/java/lang/ClassNotFoundException.java125
-rw-r--r--libjava/classpath/java/lang/CloneNotSupportedException.java92
-rw-r--r--libjava/classpath/java/lang/Cloneable.java78
-rw-r--r--libjava/classpath/java/lang/Comparable.java98
-rw-r--r--libjava/classpath/java/lang/Compiler.java127
-rw-r--r--libjava/classpath/java/lang/Double.java521
-rw-r--r--libjava/classpath/java/lang/Error.java107
-rw-r--r--libjava/classpath/java/lang/Exception.java104
-rw-r--r--libjava/classpath/java/lang/ExceptionInInitializerError.java123
-rw-r--r--libjava/classpath/java/lang/Float.java527
-rw-r--r--libjava/classpath/java/lang/IllegalAccessError.java76
-rw-r--r--libjava/classpath/java/lang/IllegalAccessException.java99
-rw-r--r--libjava/classpath/java/lang/IllegalArgumentException.java75
-rw-r--r--libjava/classpath/java/lang/IllegalMonitorStateException.java78
-rw-r--r--libjava/classpath/java/lang/IllegalStateException.java80
-rw-r--r--libjava/classpath/java/lang/IllegalThreadStateException.java75
-rw-r--r--libjava/classpath/java/lang/IncompatibleClassChangeError.java73
-rw-r--r--libjava/classpath/java/lang/IndexOutOfBoundsException.java75
-rw-r--r--libjava/classpath/java/lang/InheritableThreadLocal.java116
-rw-r--r--libjava/classpath/java/lang/InstantiationError.java75
-rw-r--r--libjava/classpath/java/lang/InstantiationException.java74
-rw-r--r--libjava/classpath/java/lang/Integer.java772
-rw-r--r--libjava/classpath/java/lang/InternalError.java72
-rw-r--r--libjava/classpath/java/lang/InterruptedException.java80
-rw-r--r--libjava/classpath/java/lang/LinkageError.java74
-rw-r--r--libjava/classpath/java/lang/Long.java614
-rw-r--r--libjava/classpath/java/lang/Math.java650
-rw-r--r--libjava/classpath/java/lang/NegativeArraySizeException.java77
-rw-r--r--libjava/classpath/java/lang/NoClassDefFoundError.java76
-rw-r--r--libjava/classpath/java/lang/NoSuchFieldError.java74
-rw-r--r--libjava/classpath/java/lang/NoSuchFieldException.java73
-rw-r--r--libjava/classpath/java/lang/NoSuchMethodError.java74
-rw-r--r--libjava/classpath/java/lang/NoSuchMethodException.java72
-rw-r--r--libjava/classpath/java/lang/NullPointerException.java82
-rw-r--r--libjava/classpath/java/lang/Number.java131
-rw-r--r--libjava/classpath/java/lang/NumberFormatException.java73
-rw-r--r--libjava/classpath/java/lang/Object.java530
-rw-r--r--libjava/classpath/java/lang/OutOfMemoryError.java73
-rw-r--r--libjava/classpath/java/lang/Package.java318
-rw-r--r--libjava/classpath/java/lang/Process.java129
-rw-r--r--libjava/classpath/java/lang/Readable.java71
-rw-r--r--libjava/classpath/java/lang/Runnable.java62
-rw-r--r--libjava/classpath/java/lang/Runtime.java796
-rw-r--r--libjava/classpath/java/lang/RuntimeException.java102
-rw-r--r--libjava/classpath/java/lang/RuntimePermission.java208
-rw-r--r--libjava/classpath/java/lang/SecurityException.java74
-rw-r--r--libjava/classpath/java/lang/SecurityManager.java1062
-rw-r--r--libjava/classpath/java/lang/Short.java353
-rw-r--r--libjava/classpath/java/lang/StackOverflowError.java72
-rw-r--r--libjava/classpath/java/lang/StackTraceElement.java259
-rw-r--r--libjava/classpath/java/lang/StrictMath.java1844
-rw-r--r--libjava/classpath/java/lang/String.java1750
-rw-r--r--libjava/classpath/java/lang/StringBuffer.java931
-rw-r--r--libjava/classpath/java/lang/StringBuilder.java944
-rw-r--r--libjava/classpath/java/lang/StringIndexOutOfBoundsException.java85
-rw-r--r--libjava/classpath/java/lang/System.java528
-rw-r--r--libjava/classpath/java/lang/Thread.java999
-rw-r--r--libjava/classpath/java/lang/ThreadDeath.java68
-rw-r--r--libjava/classpath/java/lang/ThreadGroup.java749
-rw-r--r--libjava/classpath/java/lang/ThreadLocal.java171
-rw-r--r--libjava/classpath/java/lang/Throwable.java563
-rw-r--r--libjava/classpath/java/lang/TypeNotPresentException.java97
-rw-r--r--libjava/classpath/java/lang/UnknownError.java72
-rw-r--r--libjava/classpath/java/lang/UnsatisfiedLinkError.java74
-rw-r--r--libjava/classpath/java/lang/UnsupportedClassVersionError.java74
-rw-r--r--libjava/classpath/java/lang/UnsupportedOperationException.java73
-rw-r--r--libjava/classpath/java/lang/VerifyError.java72
-rw-r--r--libjava/classpath/java/lang/VirtualMachineError.java73
-rw-r--r--libjava/classpath/java/lang/Void.java68
-rw-r--r--libjava/classpath/java/lang/annotation/AnnotationFormatError.java104
-rw-r--r--libjava/classpath/java/lang/annotation/AnnotationTypeMismatchException.java116
-rw-r--r--libjava/classpath/java/lang/annotation/package.html46
-rw-r--r--libjava/classpath/java/lang/class-dependencies.conf58
-rw-r--r--libjava/classpath/java/lang/package.html48
-rw-r--r--libjava/classpath/java/lang/ref/PhantomReference.java73
-rw-r--r--libjava/classpath/java/lang/ref/Reference.java177
-rw-r--r--libjava/classpath/java/lang/ref/ReferenceQueue.java145
-rw-r--r--libjava/classpath/java/lang/ref/SoftReference.java84
-rw-r--r--libjava/classpath/java/lang/ref/WeakReference.java79
-rw-r--r--libjava/classpath/java/lang/ref/package.html46
-rw-r--r--libjava/classpath/java/lang/reflect/AccessibleObject.java159
-rw-r--r--libjava/classpath/java/lang/reflect/Array.java675
-rw-r--r--libjava/classpath/java/lang/reflect/GenericArrayType.java61
-rw-r--r--libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java62
-rw-r--r--libjava/classpath/java/lang/reflect/InvocationHandler.java137
-rw-r--r--libjava/classpath/java/lang/reflect/InvocationTargetException.java123
-rw-r--r--libjava/classpath/java/lang/reflect/Member.java100
-rw-r--r--libjava/classpath/java/lang/reflect/Modifier.java332
-rw-r--r--libjava/classpath/java/lang/reflect/ParameterizedType.java122
-rw-r--r--libjava/classpath/java/lang/reflect/Proxy.java1615
-rw-r--r--libjava/classpath/java/lang/reflect/README4
-rw-r--r--libjava/classpath/java/lang/reflect/ReflectPermission.java102
-rwxr-xr-xlibjava/classpath/java/lang/reflect/TODO4
-rw-r--r--libjava/classpath/java/lang/reflect/Type.java55
-rw-r--r--libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java128
-rw-r--r--libjava/classpath/java/lang/reflect/WildcardType.java115
-rw-r--r--libjava/classpath/java/lang/reflect/package.html47
-rw-r--r--libjava/classpath/java/math/BigDecimal.java517
-rw-r--r--libjava/classpath/java/math/BigInteger.java2230
-rw-r--r--libjava/classpath/java/math/class-dependencies.conf58
-rw-r--r--libjava/classpath/java/math/package.html46
-rw-r--r--libjava/classpath/java/net/Authenticator.java313
-rw-r--r--libjava/classpath/java/net/BindException.java74
-rw-r--r--libjava/classpath/java/net/ConnectException.java75
-rw-r--r--libjava/classpath/java/net/ContentHandler.java126
-rw-r--r--libjava/classpath/java/net/ContentHandlerFactory.java65
-rw-r--r--libjava/classpath/java/net/DatagramPacket.java391
-rw-r--r--libjava/classpath/java/net/DatagramSocket.java933
-rw-r--r--libjava/classpath/java/net/DatagramSocketImpl.java296
-rw-r--r--libjava/classpath/java/net/DatagramSocketImplFactory.java60
-rw-r--r--libjava/classpath/java/net/FileNameMap.java65
-rw-r--r--libjava/classpath/java/net/HttpURLConnection.java589
-rw-r--r--libjava/classpath/java/net/Inet4Address.java233
-rw-r--r--libjava/classpath/java/net/Inet6Address.java261
-rw-r--r--libjava/classpath/java/net/InetAddress.java813
-rw-r--r--libjava/classpath/java/net/InetSocketAddress.java221
-rw-r--r--libjava/classpath/java/net/JarURLConnection.java228
-rw-r--r--libjava/classpath/java/net/MalformedURLException.java74
-rw-r--r--libjava/classpath/java/net/MimeTypeMapper.java213
-rw-r--r--libjava/classpath/java/net/MulticastSocket.java486
-rw-r--r--libjava/classpath/java/net/NetPermission.java90
-rw-r--r--libjava/classpath/java/net/NetworkInterface.java259
-rw-r--r--libjava/classpath/java/net/NoRouteToHostException.java74
-rw-r--r--libjava/classpath/java/net/PasswordAuthentication.java92
-rw-r--r--libjava/classpath/java/net/PortUnreachableException.java72
-rw-r--r--libjava/classpath/java/net/ProtocolException.java75
-rw-r--r--libjava/classpath/java/net/STATUS48
-rw-r--r--libjava/classpath/java/net/ServerSocket.java599
-rw-r--r--libjava/classpath/java/net/Socket.java1284
-rw-r--r--libjava/classpath/java/net/SocketAddress.java63
-rw-r--r--libjava/classpath/java/net/SocketException.java75
-rw-r--r--libjava/classpath/java/net/SocketImpl.java321
-rw-r--r--libjava/classpath/java/net/SocketImplFactory.java59
-rw-r--r--libjava/classpath/java/net/SocketOptions.java166
-rw-r--r--libjava/classpath/java/net/SocketPermission.java408
-rw-r--r--libjava/classpath/java/net/SocketTimeoutException.java73
-rw-r--r--libjava/classpath/java/net/TODO24
-rw-r--r--libjava/classpath/java/net/URI.java1438
-rw-r--r--libjava/classpath/java/net/URISyntaxException.java144
-rw-r--r--libjava/classpath/java/net/URL.java956
-rw-r--r--libjava/classpath/java/net/URLClassLoader.java1171
-rw-r--r--libjava/classpath/java/net/URLConnection.java1021
-rw-r--r--libjava/classpath/java/net/URLDecoder.java180
-rw-r--r--libjava/classpath/java/net/URLEncoder.java184
-rw-r--r--libjava/classpath/java/net/URLStreamHandler.java532
-rw-r--r--libjava/classpath/java/net/URLStreamHandlerFactory.java65
-rw-r--r--libjava/classpath/java/net/UnknownHostException.java77
-rw-r--r--libjava/classpath/java/net/UnknownServiceException.java76
-rw-r--r--libjava/classpath/java/net/class-dependencies.conf122
-rw-r--r--libjava/classpath/java/net/package.html46
-rw-r--r--libjava/classpath/java/nio/Buffer.java361
-rw-r--r--libjava/classpath/java/nio/BufferOverflowException.java51
-rw-r--r--libjava/classpath/java/nio/BufferUnderflowException.java51
-rw-r--r--libjava/classpath/java/nio/ByteBuffer.java651
-rw-r--r--libjava/classpath/java/nio/ByteBufferHelper.java344
-rw-r--r--libjava/classpath/java/nio/ByteBufferImpl.java379
-rw-r--r--libjava/classpath/java/nio/ByteOrder.java82
-rw-r--r--libjava/classpath/java/nio/CharBuffer.java508
-rw-r--r--libjava/classpath/java/nio/CharBufferImpl.java219
-rw-r--r--libjava/classpath/java/nio/CharViewBufferImpl.java187
-rw-r--r--libjava/classpath/java/nio/DirectByteBufferImpl.java419
-rw-r--r--libjava/classpath/java/nio/DoubleBuffer.java383
-rw-r--r--libjava/classpath/java/nio/DoubleBufferImpl.java172
-rw-r--r--libjava/classpath/java/nio/DoubleViewBufferImpl.java172
-rw-r--r--libjava/classpath/java/nio/FloatBuffer.java383
-rw-r--r--libjava/classpath/java/nio/FloatBufferImpl.java172
-rw-r--r--libjava/classpath/java/nio/FloatViewBufferImpl.java173
-rw-r--r--libjava/classpath/java/nio/IntBuffer.java383
-rw-r--r--libjava/classpath/java/nio/IntBufferImpl.java172
-rw-r--r--libjava/classpath/java/nio/IntViewBufferImpl.java173
-rw-r--r--libjava/classpath/java/nio/InvalidMarkException.java52
-rw-r--r--libjava/classpath/java/nio/LongBuffer.java383
-rw-r--r--libjava/classpath/java/nio/LongBufferImpl.java172
-rw-r--r--libjava/classpath/java/nio/LongViewBufferImpl.java173
-rw-r--r--libjava/classpath/java/nio/MappedByteBuffer.java93
-rw-r--r--libjava/classpath/java/nio/MappedByteBufferImpl.java360
-rw-r--r--libjava/classpath/java/nio/ReadOnlyBufferException.java52
-rw-r--r--libjava/classpath/java/nio/ShortBuffer.java383
-rw-r--r--libjava/classpath/java/nio/ShortBufferImpl.java172
-rw-r--r--libjava/classpath/java/nio/ShortViewBufferImpl.java173
-rw-r--r--libjava/classpath/java/nio/channels/AlreadyConnectedException.java48
-rw-r--r--libjava/classpath/java/nio/channels/AsynchronousCloseException.java53
-rw-r--r--libjava/classpath/java/nio/channels/ByteChannel.java43
-rw-r--r--libjava/classpath/java/nio/channels/CancelledKeyException.java53
-rw-r--r--libjava/classpath/java/nio/channels/Channel.java59
-rw-r--r--libjava/classpath/java/nio/channels/Channels.java143
-rw-r--r--libjava/classpath/java/nio/channels/ClosedByInterruptException.java53
-rw-r--r--libjava/classpath/java/nio/channels/ClosedChannelException.java55
-rw-r--r--libjava/classpath/java/nio/channels/ClosedSelectorException.java53
-rw-r--r--libjava/classpath/java/nio/channels/ConnectionPendingException.java53
-rw-r--r--libjava/classpath/java/nio/channels/DatagramChannel.java210
-rw-r--r--libjava/classpath/java/nio/channels/FileChannel.java367
-rw-r--r--libjava/classpath/java/nio/channels/FileLock.java150
-rw-r--r--libjava/classpath/java/nio/channels/FileLockInterruptionException.java55
-rw-r--r--libjava/classpath/java/nio/channels/GatheringByteChannel.java79
-rw-r--r--libjava/classpath/java/nio/channels/IllegalBlockingModeException.java57
-rw-r--r--libjava/classpath/java/nio/channels/IllegalSelectorException.java53
-rw-r--r--libjava/classpath/java/nio/channels/InterruptibleChannel.java51
-rw-r--r--libjava/classpath/java/nio/channels/NoConnectionPendingException.java53
-rw-r--r--libjava/classpath/java/nio/channels/NonReadableChannelException.java53
-rw-r--r--libjava/classpath/java/nio/channels/NonWritableChannelException.java53
-rw-r--r--libjava/classpath/java/nio/channels/NotYetBoundException.java53
-rw-r--r--libjava/classpath/java/nio/channels/NotYetConnectedException.java53
-rw-r--r--libjava/classpath/java/nio/channels/OverlappingFileLockException.java53
-rw-r--r--libjava/classpath/java/nio/channels/Pipe.java121
-rw-r--r--libjava/classpath/java/nio/channels/ReadableByteChannel.java64
-rw-r--r--libjava/classpath/java/nio/channels/ScatteringByteChannel.java79
-rw-r--r--libjava/classpath/java/nio/channels/SelectableChannel.java140
-rw-r--r--libjava/classpath/java/nio/channels/SelectionKey.java164
-rw-r--r--libjava/classpath/java/nio/channels/Selector.java134
-rw-r--r--libjava/classpath/java/nio/channels/ServerSocketChannel.java98
-rw-r--r--libjava/classpath/java/nio/channels/SocketChannel.java248
-rw-r--r--libjava/classpath/java/nio/channels/UnresolvedAddressException.java53
-rw-r--r--libjava/classpath/java/nio/channels/UnsupportedAddressTypeException.java53
-rw-r--r--libjava/classpath/java/nio/channels/WritableByteChannel.java60
-rw-r--r--libjava/classpath/java/nio/channels/package.html47
-rw-r--r--libjava/classpath/java/nio/channels/spi/AbstractInterruptibleChannel.java119
-rw-r--r--libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java256
-rw-r--r--libjava/classpath/java/nio/channels/spi/AbstractSelectionKey.java78
-rw-r--r--libjava/classpath/java/nio/channels/spi/AbstractSelector.java167
-rw-r--r--libjava/classpath/java/nio/channels/spi/SelectorProvider.java151
-rw-r--r--libjava/classpath/java/nio/channels/spi/package.html46
-rw-r--r--libjava/classpath/java/nio/charset/CharacterCodingException.java53
-rw-r--r--libjava/classpath/java/nio/charset/Charset.java406
-rw-r--r--libjava/classpath/java/nio/charset/CharsetDecoder.java317
-rw-r--r--libjava/classpath/java/nio/charset/CharsetEncoder.java369
-rw-r--r--libjava/classpath/java/nio/charset/CoderMalfunctionError.java52
-rw-r--r--libjava/classpath/java/nio/charset/CoderResult.java189
-rw-r--r--libjava/classpath/java/nio/charset/CodingErrorAction.java66
-rw-r--r--libjava/classpath/java/nio/charset/IllegalCharsetNameException.java73
-rw-r--r--libjava/classpath/java/nio/charset/MalformedInputException.java77
-rw-r--r--libjava/classpath/java/nio/charset/UnmappableCharacterException.java71
-rw-r--r--libjava/classpath/java/nio/charset/UnsupportedCharsetException.java69
-rw-r--r--libjava/classpath/java/nio/charset/package.html47
-rw-r--r--libjava/classpath/java/nio/charset/spi/CharsetProvider.java91
-rw-r--r--libjava/classpath/java/nio/charset/spi/package.html46
-rw-r--r--libjava/classpath/java/nio/class-dependencies.conf58
-rw-r--r--libjava/classpath/java/nio/package.html46
-rw-r--r--libjava/classpath/java/rmi/AccessException.java76
-rw-r--r--libjava/classpath/java/rmi/AlreadyBoundException.java73
-rw-r--r--libjava/classpath/java/rmi/ConnectException.java74
-rw-r--r--libjava/classpath/java/rmi/ConnectIOException.java74
-rw-r--r--libjava/classpath/java/rmi/MarshalException.java76
-rw-r--r--libjava/classpath/java/rmi/MarshalledObject.java113
-rw-r--r--libjava/classpath/java/rmi/Naming.java220
-rw-r--r--libjava/classpath/java/rmi/NoSuchObjectException.java68
-rw-r--r--libjava/classpath/java/rmi/NotBoundException.java75
-rw-r--r--libjava/classpath/java/rmi/RMISecurityException.java77
-rw-r--r--libjava/classpath/java/rmi/RMISecurityManager.java48
-rw-r--r--libjava/classpath/java/rmi/Remote.java41
-rw-r--r--libjava/classpath/java/rmi/RemoteException.java127
-rw-r--r--libjava/classpath/java/rmi/ServerError.java64
-rw-r--r--libjava/classpath/java/rmi/ServerException.java74
-rw-r--r--libjava/classpath/java/rmi/ServerRuntimeException.java67
-rw-r--r--libjava/classpath/java/rmi/StubNotFoundException.java77
-rw-r--r--libjava/classpath/java/rmi/UnexpectedException.java75
-rw-r--r--libjava/classpath/java/rmi/UnknownHostException.java75
-rw-r--r--libjava/classpath/java/rmi/UnmarshalException.java88
-rw-r--r--libjava/classpath/java/rmi/activation/Activatable.java105
-rw-r--r--libjava/classpath/java/rmi/activation/ActivateFailedException.java76
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationDesc.java113
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationException.java122
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationGroup.java85
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationGroupDesc.java134
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationGroupID.java70
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationID.java72
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationInstantiator.java50
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationMonitor.java55
-rw-r--r--libjava/classpath/java/rmi/activation/ActivationSystem.java78
-rw-r--r--libjava/classpath/java/rmi/activation/Activator.java50
-rw-r--r--libjava/classpath/java/rmi/activation/UnknownGroupException.java69
-rw-r--r--libjava/classpath/java/rmi/activation/UnknownObjectException.java69
-rw-r--r--libjava/classpath/java/rmi/activation/package.html46
-rw-r--r--libjava/classpath/java/rmi/dgc/DGC.java51
-rw-r--r--libjava/classpath/java/rmi/dgc/Lease.java67
-rw-r--r--libjava/classpath/java/rmi/dgc/VMID.java138
-rw-r--r--libjava/classpath/java/rmi/dgc/package.html46
-rw-r--r--libjava/classpath/java/rmi/package.html46
-rw-r--r--libjava/classpath/java/rmi/registry/LocateRegistry.java87
-rw-r--r--libjava/classpath/java/rmi/registry/Registry.java65
-rw-r--r--libjava/classpath/java/rmi/registry/RegistryHandler.java58
-rw-r--r--libjava/classpath/java/rmi/registry/package.html46
-rw-r--r--libjava/classpath/java/rmi/server/ExportException.java78
-rw-r--r--libjava/classpath/java/rmi/server/LoaderHandler.java66
-rw-r--r--libjava/classpath/java/rmi/server/LogStream.java146
-rw-r--r--libjava/classpath/java/rmi/server/ObjID.java103
-rw-r--r--libjava/classpath/java/rmi/server/Operation.java70
-rw-r--r--libjava/classpath/java/rmi/server/RMIClassLoader.java339
-rw-r--r--libjava/classpath/java/rmi/server/RMIClassLoaderSpi.java64
-rw-r--r--libjava/classpath/java/rmi/server/RMIClientSocketFactory.java47
-rw-r--r--libjava/classpath/java/rmi/server/RMIFailureHandler.java46
-rw-r--r--libjava/classpath/java/rmi/server/RMIServerSocketFactory.java47
-rw-r--r--libjava/classpath/java/rmi/server/RMISocketFactory.java108
-rw-r--r--libjava/classpath/java/rmi/server/RemoteCall.java86
-rw-r--r--libjava/classpath/java/rmi/server/RemoteObject.java160
-rw-r--r--libjava/classpath/java/rmi/server/RemoteRef.java79
-rw-r--r--libjava/classpath/java/rmi/server/RemoteServer.java76
-rw-r--r--libjava/classpath/java/rmi/server/RemoteStub.java61
-rw-r--r--libjava/classpath/java/rmi/server/ServerCloneException.java117
-rw-r--r--libjava/classpath/java/rmi/server/ServerNotActiveException.java72
-rw-r--r--libjava/classpath/java/rmi/server/ServerRef.java51
-rw-r--r--libjava/classpath/java/rmi/server/Skeleton.java57
-rw-r--r--libjava/classpath/java/rmi/server/SkeletonMismatchException.java68
-rw-r--r--libjava/classpath/java/rmi/server/SkeletonNotFoundException.java79
-rw-r--r--libjava/classpath/java/rmi/server/SocketSecurityException.java75
-rw-r--r--libjava/classpath/java/rmi/server/UID.java127
-rw-r--r--libjava/classpath/java/rmi/server/UnicastRemoteObject.java133
-rw-r--r--libjava/classpath/java/rmi/server/Unreferenced.java43
-rw-r--r--libjava/classpath/java/rmi/server/package.html46
-rw-r--r--libjava/classpath/java/security/AccessControlContext.java176
-rw-r--r--libjava/classpath/java/security/AccessControlException.java97
-rw-r--r--libjava/classpath/java/security/AccessController.java221
-rw-r--r--libjava/classpath/java/security/AlgorithmParameterGenerator.java302
-rw-r--r--libjava/classpath/java/security/AlgorithmParameterGeneratorSpi.java94
-rw-r--r--libjava/classpath/java/security/AlgorithmParameters.java340
-rw-r--r--libjava/classpath/java/security/AlgorithmParametersSpi.java149
-rw-r--r--libjava/classpath/java/security/AllPermission.java198
-rw-r--r--libjava/classpath/java/security/BasicPermission.java308
-rw-r--r--libjava/classpath/java/security/Certificate.java125
-rw-r--r--libjava/classpath/java/security/CodeSource.java354
-rw-r--r--libjava/classpath/java/security/DigestException.java70
-rw-r--r--libjava/classpath/java/security/DigestInputStream.java167
-rw-r--r--libjava/classpath/java/security/DigestOutputStream.java158
-rw-r--r--libjava/classpath/java/security/DomainCombiner.java67
-rw-r--r--libjava/classpath/java/security/DummyKeyPairGenerator.java75
-rw-r--r--libjava/classpath/java/security/DummyMessageDigest.java90
-rw-r--r--libjava/classpath/java/security/DummySignature.java102
-rw-r--r--libjava/classpath/java/security/GeneralSecurityException.java75
-rw-r--r--libjava/classpath/java/security/Guard.java60
-rw-r--r--libjava/classpath/java/security/GuardedObject.java121
-rw-r--r--libjava/classpath/java/security/Identity.java407
-rw-r--r--libjava/classpath/java/security/IdentityScope.java226
-rw-r--r--libjava/classpath/java/security/IntersectingDomainCombiner.java82
-rw-r--r--libjava/classpath/java/security/InvalidAlgorithmParameterException.java73
-rw-r--r--libjava/classpath/java/security/InvalidKeyException.java69
-rw-r--r--libjava/classpath/java/security/InvalidParameterException.java70
-rw-r--r--libjava/classpath/java/security/Key.java94
-rw-r--r--libjava/classpath/java/security/KeyException.java72
-rw-r--r--libjava/classpath/java/security/KeyFactory.java297
-rw-r--r--libjava/classpath/java/security/KeyFactorySpi.java133
-rw-r--r--libjava/classpath/java/security/KeyManagementException.java71
-rw-r--r--libjava/classpath/java/security/KeyPair.java87
-rw-r--r--libjava/classpath/java/security/KeyPairGenerator.java401
-rw-r--r--libjava/classpath/java/security/KeyPairGeneratorSpi.java102
-rw-r--r--libjava/classpath/java/security/KeyStore.java507
-rw-r--r--libjava/classpath/java/security/KeyStoreException.java70
-rw-r--r--libjava/classpath/java/security/KeyStoreSpi.java275
-rw-r--r--libjava/classpath/java/security/MessageDigest.java413
-rw-r--r--libjava/classpath/java/security/MessageDigestSpi.java155
-rw-r--r--libjava/classpath/java/security/NoSuchAlgorithmException.java70
-rw-r--r--libjava/classpath/java/security/NoSuchProviderException.java70
-rw-r--r--libjava/classpath/java/security/Permission.java187
-rw-r--r--libjava/classpath/java/security/PermissionCollection.java167
-rw-r--r--libjava/classpath/java/security/Permissions.java254
-rw-r--r--libjava/classpath/java/security/Policy.java310
-rw-r--r--libjava/classpath/java/security/Principal.java85
-rw-r--r--libjava/classpath/java/security/PrivateKey.java62
-rw-r--r--libjava/classpath/java/security/PrivilegedAction.java64
-rw-r--r--libjava/classpath/java/security/PrivilegedActionException.java109
-rw-r--r--libjava/classpath/java/security/PrivilegedExceptionAction.java65
-rw-r--r--libjava/classpath/java/security/ProtectionDomain.java269
-rw-r--r--libjava/classpath/java/security/Provider.java202
-rw-r--r--libjava/classpath/java/security/ProviderException.java70
-rw-r--r--libjava/classpath/java/security/PublicKey.java60
-rw-r--r--libjava/classpath/java/security/SecureClassLoader.java128
-rw-r--r--libjava/classpath/java/security/SecureRandom.java380
-rw-r--r--libjava/classpath/java/security/SecureRandomSpi.java85
-rw-r--r--libjava/classpath/java/security/Security.java740
-rw-r--r--libjava/classpath/java/security/SecurityPermission.java178
-rw-r--r--libjava/classpath/java/security/Signature.java636
-rw-r--r--libjava/classpath/java/security/SignatureException.java70
-rw-r--r--libjava/classpath/java/security/SignatureSpi.java302
-rw-r--r--libjava/classpath/java/security/SignedObject.java240
-rw-r--r--libjava/classpath/java/security/Signer.java164
-rw-r--r--libjava/classpath/java/security/UnrecoverableKeyException.java71
-rw-r--r--libjava/classpath/java/security/UnresolvedPermission.java304
-rw-r--r--libjava/classpath/java/security/acl/Acl.java153
-rw-r--r--libjava/classpath/java/security/acl/AclEntry.java143
-rw-r--r--libjava/classpath/java/security/acl/AclNotFoundException.java60
-rw-r--r--libjava/classpath/java/security/acl/Group.java90
-rw-r--r--libjava/classpath/java/security/acl/LastOwnerException.java62
-rw-r--r--libjava/classpath/java/security/acl/NotOwnerException.java62
-rw-r--r--libjava/classpath/java/security/acl/Owner.java95
-rw-r--r--libjava/classpath/java/security/acl/Permission.java67
-rw-r--r--libjava/classpath/java/security/acl/package.html46
-rw-r--r--libjava/classpath/java/security/cert/CRL.java98
-rw-r--r--libjava/classpath/java/security/cert/CRLException.java73
-rw-r--r--libjava/classpath/java/security/cert/CRLSelector.java69
-rw-r--r--libjava/classpath/java/security/cert/CertPath.java252
-rw-r--r--libjava/classpath/java/security/cert/CertPathBuilder.java238
-rw-r--r--libjava/classpath/java/security/cert/CertPathBuilderException.java159
-rw-r--r--libjava/classpath/java/security/cert/CertPathBuilderResult.java63
-rw-r--r--libjava/classpath/java/security/cert/CertPathBuilderSpi.java74
-rw-r--r--libjava/classpath/java/security/cert/CertPathParameters.java58
-rw-r--r--libjava/classpath/java/security/cert/CertPathValidator.java249
-rw-r--r--libjava/classpath/java/security/cert/CertPathValidatorException.java226
-rw-r--r--libjava/classpath/java/security/cert/CertPathValidatorResult.java63
-rw-r--r--libjava/classpath/java/security/cert/CertPathValidatorSpi.java79
-rw-r--r--libjava/classpath/java/security/cert/CertSelector.java58
-rw-r--r--libjava/classpath/java/security/cert/CertStore.java294
-rw-r--r--libjava/classpath/java/security/cert/CertStoreException.java159
-rw-r--r--libjava/classpath/java/security/cert/CertStoreParameters.java60
-rw-r--r--libjava/classpath/java/security/cert/CertStoreSpi.java102
-rw-r--r--libjava/classpath/java/security/cert/Certificate.java306
-rw-r--r--libjava/classpath/java/security/cert/CertificateEncodingException.java71
-rw-r--r--libjava/classpath/java/security/cert/CertificateException.java74
-rw-r--r--libjava/classpath/java/security/cert/CertificateExpiredException.java71
-rw-r--r--libjava/classpath/java/security/cert/CertificateFactory.java358
-rw-r--r--libjava/classpath/java/security/cert/CertificateFactorySpi.java225
-rw-r--r--libjava/classpath/java/security/cert/CertificateNotYetValidException.java71
-rw-r--r--libjava/classpath/java/security/cert/CertificateParsingException.java71
-rw-r--r--libjava/classpath/java/security/cert/CollectionCertStoreParameters.java121
-rw-r--r--libjava/classpath/java/security/cert/LDAPCertStoreParameters.java140
-rw-r--r--libjava/classpath/java/security/cert/PKIXBuilderParameters.java145
-rw-r--r--libjava/classpath/java/security/cert/PKIXCertPathBuilderResult.java102
-rw-r--r--libjava/classpath/java/security/cert/PKIXCertPathChecker.java133
-rw-r--r--libjava/classpath/java/security/cert/PKIXCertPathValidatorResult.java142
-rw-r--r--libjava/classpath/java/security/cert/PKIXParameters.java546
-rw-r--r--libjava/classpath/java/security/cert/PolicyNode.java102
-rw-r--r--libjava/classpath/java/security/cert/PolicyQualifierInfo.java168
-rw-r--r--libjava/classpath/java/security/cert/TrustAnchor.java185
-rw-r--r--libjava/classpath/java/security/cert/X509CRL.java397
-rw-r--r--libjava/classpath/java/security/cert/X509CRLEntry.java169
-rw-r--r--libjava/classpath/java/security/cert/X509CRLSelector.java440
-rw-r--r--libjava/classpath/java/security/cert/X509CertSelector.java1106
-rw-r--r--libjava/classpath/java/security/cert/X509Certificate.java588
-rw-r--r--libjava/classpath/java/security/cert/X509Extension.java113
-rw-r--r--libjava/classpath/java/security/cert/package.html46
-rw-r--r--libjava/classpath/java/security/interfaces/DSAKey.java56
-rw-r--r--libjava/classpath/java/security/interfaces/DSAKeyPairGenerator.java85
-rw-r--r--libjava/classpath/java/security/interfaces/DSAParams.java72
-rw-r--r--libjava/classpath/java/security/interfaces/DSAPrivateKey.java61
-rw-r--r--libjava/classpath/java/security/interfaces/DSAPublicKey.java61
-rw-r--r--libjava/classpath/java/security/interfaces/RSAKey.java57
-rw-r--r--libjava/classpath/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java111
-rw-r--r--libjava/classpath/java/security/interfaces/RSAPrivateCrtKey.java95
-rw-r--r--libjava/classpath/java/security/interfaces/RSAPrivateKey.java60
-rw-r--r--libjava/classpath/java/security/interfaces/RSAPublicKey.java60
-rw-r--r--libjava/classpath/java/security/interfaces/package.html46
-rw-r--r--libjava/classpath/java/security/package.html46
-rw-r--r--libjava/classpath/java/security/spec/AlgorithmParameterSpec.java52
-rw-r--r--libjava/classpath/java/security/spec/DSAParameterSpec.java101
-rw-r--r--libjava/classpath/java/security/spec/DSAPrivateKeySpec.java113
-rw-r--r--libjava/classpath/java/security/spec/DSAPublicKeySpec.java113
-rw-r--r--libjava/classpath/java/security/spec/EncodedKeySpec.java85
-rw-r--r--libjava/classpath/java/security/spec/InvalidKeySpecException.java74
-rw-r--r--libjava/classpath/java/security/spec/InvalidParameterSpecException.java76
-rw-r--r--libjava/classpath/java/security/spec/KeySpec.java52
-rw-r--r--libjava/classpath/java/security/spec/PKCS8EncodedKeySpec.java81
-rw-r--r--libjava/classpath/java/security/spec/PSSParameterSpec.java90
-rw-r--r--libjava/classpath/java/security/spec/RSAKeyGenParameterSpec.java97
-rw-r--r--libjava/classpath/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java217
-rw-r--r--libjava/classpath/java/security/spec/RSAOtherPrimeInfo.java133
-rw-r--r--libjava/classpath/java/security/spec/RSAPrivateCrtKeySpec.java151
-rw-r--r--libjava/classpath/java/security/spec/RSAPrivateKeySpec.java88
-rw-r--r--libjava/classpath/java/security/spec/RSAPublicKeySpec.java88
-rw-r--r--libjava/classpath/java/security/spec/X509EncodedKeySpec.java82
-rw-r--r--libjava/classpath/java/security/spec/package.html46
-rw-r--r--libjava/classpath/java/sql/Array.java185
-rw-r--r--libjava/classpath/java/sql/BatchUpdateException.java141
-rw-r--r--libjava/classpath/java/sql/Blob.java131
-rw-r--r--libjava/classpath/java/sql/CallableStatement.java651
-rw-r--r--libjava/classpath/java/sql/Clob.java152
-rw-r--r--libjava/classpath/java/sql/Connection.java420
-rw-r--r--libjava/classpath/java/sql/DataTruncation.java157
-rw-r--r--libjava/classpath/java/sql/DatabaseMetaData.java2214
-rw-r--r--libjava/classpath/java/sql/Date.java188
-rw-r--r--libjava/classpath/java/sql/Driver.java123
-rw-r--r--libjava/classpath/java/sql/DriverManager.java346
-rw-r--r--libjava/classpath/java/sql/DriverPropertyInfo.java88
-rw-r--r--libjava/classpath/java/sql/ParameterMetaData.java103
-rw-r--r--libjava/classpath/java/sql/PreparedStatement.java438
-rw-r--r--libjava/classpath/java/sql/Ref.java75
-rw-r--r--libjava/classpath/java/sql/ResultSet.java1530
-rw-r--r--libjava/classpath/java/sql/ResultSetMetaData.java281
-rw-r--r--libjava/classpath/java/sql/SQLData.java72
-rw-r--r--libjava/classpath/java/sql/SQLException.java167
-rw-r--r--libjava/classpath/java/sql/SQLInput.java259
-rw-r--r--libjava/classpath/java/sql/SQLOutput.java257
-rw-r--r--libjava/classpath/java/sql/SQLPermission.java57
-rw-r--r--libjava/classpath/java/sql/SQLWarning.java120
-rw-r--r--libjava/classpath/java/sql/Savepoint.java55
-rw-r--r--libjava/classpath/java/sql/Statement.java366
-rw-r--r--libjava/classpath/java/sql/Struct.java77
-rw-r--r--libjava/classpath/java/sql/Time.java205
-rw-r--r--libjava/classpath/java/sql/Timestamp.java315
-rw-r--r--libjava/classpath/java/sql/Types.java85
-rw-r--r--libjava/classpath/java/sql/package.html47
-rw-r--r--libjava/classpath/java/text/Annotation.java113
-rw-r--r--libjava/classpath/java/text/AttributedCharacterIterator.java268
-rw-r--r--libjava/classpath/java/text/AttributedString.java425
-rw-r--r--libjava/classpath/java/text/AttributedStringIterator.java348
-rw-r--r--libjava/classpath/java/text/BreakIterator.java374
-rw-r--r--libjava/classpath/java/text/CharacterIterator.java144
-rw-r--r--libjava/classpath/java/text/ChoiceFormat.java503
-rw-r--r--libjava/classpath/java/text/CollationElementIterator.java467
-rw-r--r--libjava/classpath/java/text/CollationKey.java199
-rw-r--r--libjava/classpath/java/text/Collator.java400
-rw-r--r--libjava/classpath/java/text/DateFormat.java892
-rw-r--r--libjava/classpath/java/text/DateFormatSymbols.java525
-rw-r--r--libjava/classpath/java/text/DecimalFormat.java1435
-rw-r--r--libjava/classpath/java/text/DecimalFormatSymbols.java688
-rw-r--r--libjava/classpath/java/text/FieldPosition.java232
-rw-r--r--libjava/classpath/java/text/Format.java181
-rw-r--r--libjava/classpath/java/text/MessageFormat.java832
-rw-r--r--libjava/classpath/java/text/NumberFormat.java808
-rw-r--r--libjava/classpath/java/text/ParseException.java86
-rw-r--r--libjava/classpath/java/text/ParsePosition.java151
-rw-r--r--libjava/classpath/java/text/RuleBasedCollator.java1017
-rw-r--r--libjava/classpath/java/text/SimpleDateFormat.java1257
-rw-r--r--libjava/classpath/java/text/StringCharacterIterator.java356
-rw-r--r--libjava/classpath/java/text/class-dependencies.conf220
-rw-r--r--libjava/classpath/java/text/package.html47
-rw-r--r--libjava/classpath/java/util/.cvsignore1
-rw-r--r--libjava/classpath/java/util/AbstractCollection.java470
-rw-r--r--libjava/classpath/java/util/AbstractList.java1225
-rw-r--r--libjava/classpath/java/util/AbstractMap.java749
-rw-r--r--libjava/classpath/java/util/AbstractSequentialList.java235
-rw-r--r--libjava/classpath/java/util/AbstractSet.java139
-rw-r--r--libjava/classpath/java/util/ArrayList.java591
-rw-r--r--libjava/classpath/java/util/Arrays.java2510
-rw-r--r--libjava/classpath/java/util/BitSet.java744
-rw-r--r--libjava/classpath/java/util/Calendar.java1277
-rw-r--r--libjava/classpath/java/util/Collection.java288
-rw-r--r--libjava/classpath/java/util/Collections.java5493
-rw-r--r--libjava/classpath/java/util/Comparator.java119
-rw-r--r--libjava/classpath/java/util/ConcurrentModificationException.java92
-rw-r--r--libjava/classpath/java/util/Currency.java437
-rw-r--r--libjava/classpath/java/util/Date.java1263
-rw-r--r--libjava/classpath/java/util/Dictionary.java136
-rw-r--r--libjava/classpath/java/util/EmptyStackException.java69
-rw-r--r--libjava/classpath/java/util/Enumeration.java81
-rw-r--r--libjava/classpath/java/util/EventListener.java54
-rw-r--r--libjava/classpath/java/util/EventListenerProxy.java75
-rw-r--r--libjava/classpath/java/util/EventObject.java101
-rw-r--r--libjava/classpath/java/util/GregorianCalendar.java1343
-rw-r--r--libjava/classpath/java/util/HashMap.java906
-rw-r--r--libjava/classpath/java/util/HashSet.java293
-rw-r--r--libjava/classpath/java/util/Hashtable.java1151
-rw-r--r--libjava/classpath/java/util/IdentityHashMap.java935
-rw-r--r--libjava/classpath/java/util/Iterator.java87
-rw-r--r--libjava/classpath/java/util/LinkedHashMap.java501
-rw-r--r--libjava/classpath/java/util/LinkedHashSet.java160
-rw-r--r--libjava/classpath/java/util/LinkedList.java958
-rw-r--r--libjava/classpath/java/util/List.java451
-rw-r--r--libjava/classpath/java/util/ListIterator.java170
-rw-r--r--libjava/classpath/java/util/ListResourceBundle.java140
-rw-r--r--libjava/classpath/java/util/Locale.java952
-rw-r--r--libjava/classpath/java/util/Map.java338
-rw-r--r--libjava/classpath/java/util/MissingResourceException.java105
-rw-r--r--libjava/classpath/java/util/NoSuchElementException.java88
-rw-r--r--libjava/classpath/java/util/Observable.java180
-rw-r--r--libjava/classpath/java/util/Observer.java60
-rw-r--r--libjava/classpath/java/util/Properties.java574
-rw-r--r--libjava/classpath/java/util/PropertyPermission.java271
-rw-r--r--libjava/classpath/java/util/PropertyPermissionCollection.java166
-rw-r--r--libjava/classpath/java/util/PropertyResourceBundle.java152
-rw-r--r--libjava/classpath/java/util/Random.java429
-rw-r--r--libjava/classpath/java/util/RandomAccess.java64
-rw-r--r--libjava/classpath/java/util/ResourceBundle.java580
-rw-r--r--libjava/classpath/java/util/Set.java264
-rw-r--r--libjava/classpath/java/util/SimpleTimeZone.java1077
-rw-r--r--libjava/classpath/java/util/SortedMap.java173
-rw-r--r--libjava/classpath/java/util/SortedSet.java176
-rw-r--r--libjava/classpath/java/util/Stack.java158
-rw-r--r--libjava/classpath/java/util/StringTokenizer.java268
-rw-r--r--libjava/classpath/java/util/TimeZone.java1523
-rw-r--r--libjava/classpath/java/util/Timer.java615
-rw-r--r--libjava/classpath/java/util/TimerTask.java145
-rw-r--r--libjava/classpath/java/util/TooManyListenersException.java78
-rw-r--r--libjava/classpath/java/util/TreeMap.java1781
-rw-r--r--libjava/classpath/java/util/TreeSet.java416
-rw-r--r--libjava/classpath/java/util/Vector.java931
-rw-r--r--libjava/classpath/java/util/WeakHashMap.java881
-rw-r--r--libjava/classpath/java/util/class-dependencies.conf78
-rw-r--r--libjava/classpath/java/util/jar/Attributes.java630
-rw-r--r--libjava/classpath/java/util/jar/JarEntry.java165
-rw-r--r--libjava/classpath/java/util/jar/JarException.java77
-rw-r--r--libjava/classpath/java/util/jar/JarFile.java1059
-rw-r--r--libjava/classpath/java/util/jar/JarInputStream.java200
-rw-r--r--libjava/classpath/java/util/jar/JarOutputStream.java113
-rw-r--r--libjava/classpath/java/util/jar/Manifest.java472
-rw-r--r--libjava/classpath/java/util/jar/package.html47
-rw-r--r--libjava/classpath/java/util/logging/ConsoleHandler.java125
-rw-r--r--libjava/classpath/java/util/logging/ErrorManager.java194
-rw-r--r--libjava/classpath/java/util/logging/FileHandler.java646
-rw-r--r--libjava/classpath/java/util/logging/Filter.java64
-rw-r--r--libjava/classpath/java/util/logging/Formatter.java171
-rw-r--r--libjava/classpath/java/util/logging/Handler.java386
-rw-r--r--libjava/classpath/java/util/logging/Level.java414
-rw-r--r--libjava/classpath/java/util/logging/LogManager.java829
-rw-r--r--libjava/classpath/java/util/logging/LogRecord.java672
-rw-r--r--libjava/classpath/java/util/logging/Logger.java1199
-rw-r--r--libjava/classpath/java/util/logging/LoggingPermission.java73
-rw-r--r--libjava/classpath/java/util/logging/MemoryHandler.java345
-rw-r--r--libjava/classpath/java/util/logging/SimpleFormatter.java119
-rw-r--r--libjava/classpath/java/util/logging/SocketHandler.java221
-rw-r--r--libjava/classpath/java/util/logging/StreamHandler.java521
-rw-r--r--libjava/classpath/java/util/logging/XMLFormatter.java387
-rw-r--r--libjava/classpath/java/util/logging/package.html46
-rw-r--r--libjava/classpath/java/util/package.html48
-rw-r--r--libjava/classpath/java/util/prefs/AbstractPreferences.java1272
-rw-r--r--libjava/classpath/java/util/prefs/BackingStoreException.java104
-rw-r--r--libjava/classpath/java/util/prefs/InvalidPreferencesFormatException.java116
-rw-r--r--libjava/classpath/java/util/prefs/NodeChangeEvent.java91
-rw-r--r--libjava/classpath/java/util/prefs/NodeChangeListener.java64
-rw-r--r--libjava/classpath/java/util/prefs/PreferenceChangeEvent.java105
-rw-r--r--libjava/classpath/java/util/prefs/PreferenceChangeListener.java60
-rw-r--r--libjava/classpath/java/util/prefs/Preferences.java668
-rw-r--r--libjava/classpath/java/util/prefs/PreferencesFactory.java65
-rw-r--r--libjava/classpath/java/util/prefs/package.html46
-rw-r--r--libjava/classpath/java/util/regex/Matcher.java301
-rw-r--r--libjava/classpath/java/util/regex/Pattern.java254
-rw-r--r--libjava/classpath/java/util/regex/PatternSyntaxException.java132
-rw-r--r--libjava/classpath/java/util/regex/package.html46
-rw-r--r--libjava/classpath/java/util/zip/Adler32.java205
-rw-r--r--libjava/classpath/java/util/zip/CRC32.java132
-rw-r--r--libjava/classpath/java/util/zip/CheckedInputStream.java135
-rw-r--r--libjava/classpath/java/util/zip/CheckedOutputStream.java100
-rw-r--r--libjava/classpath/java/util/zip/Checksum.java86
-rw-r--r--libjava/classpath/java/util/zip/DataFormatException.java71
-rw-r--r--libjava/classpath/java/util/zip/Deflater.java520
-rw-r--r--libjava/classpath/java/util/zip/DeflaterConstants.java78
-rw-r--r--libjava/classpath/java/util/zip/DeflaterEngine.java696
-rw-r--r--libjava/classpath/java/util/zip/DeflaterHuffman.java776
-rw-r--r--libjava/classpath/java/util/zip/DeflaterOutputStream.java198
-rw-r--r--libjava/classpath/java/util/zip/DeflaterPending.java54
-rw-r--r--libjava/classpath/java/util/zip/GZIPInputStream.java355
-rw-r--r--libjava/classpath/java/util/zip/GZIPOutputStream.java151
-rw-r--r--libjava/classpath/java/util/zip/Inflater.java715
-rw-r--r--libjava/classpath/java/util/zip/InflaterDynHeader.java203
-rw-r--r--libjava/classpath/java/util/zip/InflaterHuffmanTree.java217
-rw-r--r--libjava/classpath/java/util/zip/InflaterInputStream.java261
-rw-r--r--libjava/classpath/java/util/zip/OutputWindow.java178
-rw-r--r--libjava/classpath/java/util/zip/PendingBuffer.java200
-rw-r--r--libjava/classpath/java/util/zip/StreamManipulator.java216
-rw-r--r--libjava/classpath/java/util/zip/ZipConstants.java97
-rw-r--r--libjava/classpath/java/util/zip/ZipEntry.java432
-rw-r--r--libjava/classpath/java/util/zip/ZipException.java72
-rw-r--r--libjava/classpath/java/util/zip/ZipFile.java595
-rw-r--r--libjava/classpath/java/util/zip/ZipInputStream.java371
-rw-r--r--libjava/classpath/java/util/zip/ZipOutputStream.java399
-rw-r--r--libjava/classpath/java/util/zip/package.html47
1147 files changed, 301154 insertions, 0 deletions
diff --git a/libjava/classpath/java/applet/Applet.java b/libjava/classpath/java/applet/Applet.java
new file mode 100644
index 00000000000..d0610ba0ea1
--- /dev/null
+++ b/libjava/classpath/java/applet/Applet.java
@@ -0,0 +1,524 @@
+/* Applet.java -- Java base applet class
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.applet;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Panel;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Locale;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This is the base applet class. An applet is a Java program that
+ * runs inside a web browser or other applet viewer in a restricted
+ * environment.
+ *
+ * <p>To be useful, a subclass should override at least start(). Also useful
+ * are init, stop, and destroy for control purposes, and getAppletInfo and
+ * getParameterInfo for descriptive purposes.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Applet extends Panel
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -5836846270535785031L;
+
+ /** The applet stub for this applet. */
+ private transient AppletStub stub;
+
+ /** Some applets call setSize in their constructors. In that case,
+ these fields are used to store width and height values until a
+ stub is set. */
+ private transient int width;
+ private transient int height;
+
+ /**
+ * The accessibility context for this applet.
+ *
+ * @serial the accessibleContext for this
+ * @since 1.2
+ */
+ private AccessibleContext accessibleContext;
+
+ /**
+ * Default constructor for subclasses.
+ *
+ * @throws HeadlessException if in a headless environment
+ */
+ public Applet()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
+
+ /**
+ * The browser calls this method to set the applet's stub, which is the
+ * low level interface to the browser. Manually setting this to null is
+ * asking for problems down the road.
+ *
+ * @param stub the applet stub for this applet
+ */
+ public final void setStub(AppletStub stub)
+ {
+ this.stub = stub;
+
+ if (width != 0 && height != 0)
+ stub.appletResize (width, height);
+ }
+
+ /**
+ * Tests whether or not this applet is currently active. An applet is active
+ * just before the browser invokes start(), and becomes inactive just
+ * before the browser invokes stop().
+ *
+ * @return <code>true</code> if this applet is active
+ */
+ public boolean isActive()
+ {
+ return stub.isActive();
+ }
+
+ /**
+ * Returns the basename URL of the document this applet is embedded in. This
+ * is everything up to the final '/'.
+ *
+ * @return the URL of the document this applet is embedded in
+ * @see #getCodeBase()
+ */
+ public URL getDocumentBase()
+ {
+ return stub.getDocumentBase();
+ }
+
+ /**
+ * Returns the URL of the code base for this applet.
+ *
+ * @return the URL of the code base for this applet
+ */
+ public URL getCodeBase()
+ {
+ return stub.getCodeBase();
+ }
+
+ /**
+ * Returns the value of the specified parameter that was specified in
+ * the <code>&lt;APPLET&gt;</code> tag for this applet.
+ *
+ * @param name the parameter name
+ * @return the parameter value, or null if the parameter does not exist
+ * @throws NullPointerException if name is null
+ */
+ public String getParameter(String name)
+ {
+ return stub.getParameter(name);
+ }
+
+ /**
+ * Returns the applet context for this applet.
+ *
+ * @return the applet context for this applet
+ */
+ public AppletContext getAppletContext()
+ {
+ return stub.getAppletContext();
+ }
+
+ /**
+ * Requests that the applet window for this applet be resized.
+ *
+ * @param width the new width in pixels
+ * @param height the new height in pixels
+ */
+ public void resize(int width, int height)
+ {
+ if (stub == null)
+ {
+ this.width = width;
+ this.height = height;
+ }
+ else
+ stub.appletResize(width, height);
+ }
+
+ /**
+ * Requests that the applet window for this applet be resized.
+ *
+ * @param dim the requested dimensions
+ * @throws NullPointerException if dim is null
+ */
+ public void resize(Dimension dim)
+ {
+ resize(dim.width, dim.height);
+ }
+
+ /**
+ * Displays the specified message in the status window if that window
+ * exists.
+ *
+ * @param message the status message, may be null
+ */
+ public void showStatus(String message)
+ {
+ getAppletContext().showStatus(message);
+ }
+
+ /**
+ * Returns an image from the specified URL. Note that the image is not
+ * actually retrieved until the applet attempts to display it, so this
+ * method returns immediately.
+ *
+ * @param url the URL of the image
+ * @return the retrieved image
+ * @throws NullPointerException if url is null
+ */
+ public Image getImage(URL url)
+ {
+ return getAppletContext().getImage(url);
+ }
+
+ /**
+ * Returns an image from the specified absolute URL, and relative path
+ * from that URL. Note that the image is not actually retrieved until the
+ * applet attempts to display it, so this method returns immediately.
+ * This calls <code>getImage(new URL(url, name))</code>, but if building
+ * the new URL fails, this returns null.
+ *
+ * @param url the base URL of the image
+ * @param name the name of the image relative to the URL
+ * @return the retrieved image, or null on failure
+ * @see #getImage(URL)
+ */
+ public Image getImage(URL url, String name)
+ {
+ try
+ {
+ return getImage(new URL(url, name));
+ }
+ catch (MalformedURLException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns an audio clip from the specified URL. This clip is not tied to
+ * any particular applet.
+ *
+ * XXX Classpath does not yet implement this.
+ *
+ * @param url the URL of the audio clip
+ * @return the retrieved audio clip
+ * @throws NullPointerException if url is null
+ * @see #getAudioClip(URL)
+ * @since 1.2
+ */
+ public static final AudioClip newAudioClip(URL url)
+ {
+ // This requires an implementation of AudioClip in gnu.java.applet.
+ throw new Error("Not implemented");
+ }
+
+ /**
+ * Returns an audio clip from the specified URL. Note that the clip is not
+ * actually retrieved until the applet attempts to play it, so this method
+ * returns immediately.
+ *
+ * @param url the URL of the audio clip
+ * @return the retrieved audio clip
+ * @throws NullPointerException if url is null
+ */
+ public AudioClip getAudioClip(URL url)
+ {
+ return getAppletContext().getAudioClip(url);
+ }
+
+ /**
+ * Returns an audio clip from the specified absolute URL, and relative path
+ * from that URL. Note that the clip is not actually retrieved until the
+ * applet attempts to play it, so this method returns immediately. This
+ * calls <code>getAudioClip(new URL(url, name))</code>, but if building
+ * the new URL fails, this returns null.
+ *
+ * @param url the base URL of the audio clip
+ * @param name the name of the clip relative to the URL
+ * @return the retrieved audio clip, or null on failure
+ * @see #getAudioClip(URL)
+ */
+ public AudioClip getAudioClip(URL url, String name)
+ {
+ try
+ {
+ return getAudioClip(new URL(url, name));
+ }
+ catch (MalformedURLException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns a descriptive string with applet defined information. The
+ * implementation in this class returns <code>null</code>, so subclasses
+ * must override to return information.
+ *
+ * @return a string describing the author, version, and applet copyright
+ */
+ public String getAppletInfo()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the locale for this applet, if it has been set. If no applet
+ * specific locale has been set, the default locale is returned.
+ *
+ * @return the locale for this applet
+ * @see Component#setLocale(Locale)
+ * @since 1.1
+ */
+ public Locale getLocale()
+ {
+ return super.getLocale();
+ }
+
+ /**
+ * Returns a list of parameters this applet supports. Each element of
+ * the outer array is an array of three strings with the name of the
+ * parameter, the data type or valid values, and a description. This
+ * method is optional and the default implementation returns null.
+ *
+ * @return the list of parameters supported by this applet
+ */
+ public String[][] getParameterInfo()
+ {
+ return null;
+ }
+
+ /**
+ * Loads and plays the audio clip pointed to by the specified URL. This does
+ * nothing if the URL does not point to a valid audio clip.
+ *
+ * @param url the URL of the audio clip
+ * @throws NullPointerException if url is null
+ * @see #getAudioClip(URL)
+ */
+ public void play(URL url)
+ {
+ AudioClip ac = getAudioClip(url);
+ try
+ {
+ ac.play();
+ }
+ catch (Exception ignored)
+ {
+ }
+ }
+
+ /**
+ * Loads and plays the audio clip pointed to by the specified absolute URL,
+ * and relative path from that URL. This does nothing if the URL cannot be
+ * constructed, or if it does not point to a valid audio clip.
+ *
+ * @param url the base URL of the audio clip
+ * @param name the name of the audio clip relative to the URL
+ * @see #getAudioClip(URL, String)
+ * @see #play(URL)
+ */
+ public void play(URL url, String name)
+ {
+ try
+ {
+ getAudioClip(url, name).play();
+ }
+ catch (Exception ignored)
+ {
+ }
+ }
+
+ /**
+ * This method is called when the applet is first loaded, before start().
+ * The default implementation does nothing; override to do any one-time
+ * initialization.
+ *
+ * @see #start()
+ * @see #stop()
+ * @see #destroy()
+ */
+ public void init()
+ {
+ }
+
+ /**
+ * This method is called when the applet should start running. This is
+ * normally each time a web page containing it is loaded. The default
+ * implemention does nothing; override for your applet to be useful.
+ *
+ * @see #init()
+ * @see #stop()
+ * @see #destroy()
+ */
+ public void start()
+ {
+ }
+
+ /**
+ * This method is called when the applet should stop running. This is
+ * normally when the next web page is loaded. The default implementation
+ * does nothing; override for your applet to stop using resources when
+ * it is no longer visible, but may be restarted soon.
+ *
+ * @see #init()
+ * @see #start()
+ * @see #destroy()
+ */
+ public void stop()
+ {
+ }
+
+ /**
+ * This method is called when the applet is being unloaded. The default
+ * implementation does nothing; override for your applet to clean up
+ * resources on exit.
+ *
+ * @see #init()
+ * @see #start()
+ * @see #stop()
+ */
+ public void destroy()
+ {
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this applet, creating one if
+ * necessary. This always returns an instance of {@link AccessibleApplet}.
+ *
+ * @return the accessibility context of this applet
+ * @since 1.3
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleApplet();
+ return accessibleContext;
+ }
+
+ /**
+ * Read an applet from an object stream. This checks for a headless
+ * environment, then does the normal read.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if a class is not found
+ * @throws IOException if deserialization fails
+ * @throws HeadlessException if this is a headless environment
+ * @see GraphicsEnvironment#isHeadless()
+ * @since 1.4
+ */
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ s.defaultReadObject();
+ }
+
+ /**
+ * This class provides accessibility support for Applets, and is the
+ * runtime type returned by {@link #getAccessibleContext()}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ */
+ protected class AccessibleApplet extends AccessibleAWTPanel
+ {
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 8127374778187708896L;
+
+ /**
+ * The default constructor.
+ */
+ protected AccessibleApplet()
+ {
+ }
+
+ /**
+ * Get the role of this accessible object, a frame.
+ *
+ * @return the role of the object
+ * @see AccessibleRole#FRAME
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.FRAME;
+ }
+
+ /**
+ * Get the state set of this accessible object. In addition to the default
+ * states of a Component, the applet can also be active.
+ *
+ * @return the role of the object
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet s = super.getAccessibleStateSet();
+ if (isActive())
+ s.add(AccessibleState.ACTIVE);
+ return s;
+ }
+ } // class AccessibleApplet
+} // class Applet
diff --git a/libjava/classpath/java/applet/AppletContext.java b/libjava/classpath/java/applet/AppletContext.java
new file mode 100644
index 00000000000..a17508fd4a4
--- /dev/null
+++ b/libjava/classpath/java/applet/AppletContext.java
@@ -0,0 +1,154 @@
+/* AppletContext.java -- access the applet's runtime environment
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.applet;
+
+import java.awt.Image;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+/**
+ * This interface allows an applet access to the browser to retrieve
+ * additional data files and display documents. It also allows the
+ * applet to find out other applets in the same document.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface AppletContext
+{
+ /**
+ * Returns an audio clip from the specified URL.
+ *
+ * @param url the URL of the audio clip
+ * @return the retrieved audio clip
+ * @throws NullPointerException if url is null
+ */
+ AudioClip getAudioClip(URL url);
+
+ /**
+ * Returns an image from the specified URL. Note that the image is not
+ * actually retrieved until the applet attempts to display it, so this
+ * method returns immediately.
+ *
+ * @param url the absolute URL of the image
+ * @return the retrieved image
+ * @throws NullPointerException if url is null
+ */
+ Image getImage(URL url);
+
+ /**
+ * Returns the applet in the document for this object that has the
+ * specified name.
+ *
+ * @param name the applet name
+ * @return the requested applet, or <code>null</code> if not found
+ */
+ Applet getApplet(String name);
+
+ /**
+ * Returns a list of all the applets in the document for this object.
+ *
+ * @return a list of all the applets
+ */
+ Enumeration getApplets();
+
+ /**
+ * Displays the web page pointed to by the specified URL in the window
+ * for this object. This page replaces the document that is currently
+ * there.
+ *
+ * @param url the URL of the web page to load; unspecified on an error
+ */
+ void showDocument(URL url);
+
+ /**
+ * Displays the web page pointed to be the sepcified URL in the window
+ * with the specified name. The standard names "_top", "_blank",
+ * "_parent", and "_self" are allowed. An applet viewer may disregard
+ * this request.
+ *
+ * @param url the URL of the web page to load
+ * @param target the target window
+ */
+ void showDocument(URL url, String target);
+
+ /**
+ * Displays the specified message in the status window if that window
+ * exists.
+ *
+ * @param message the status message, may be null
+ */
+ void showStatus(String message);
+
+ /**
+ * Associate a stream to a key for this applet context, possibly replacing
+ * the old value. Stream associations are local to the applet context, for
+ * security purposes.
+ *
+ * @param key the key to associate with
+ * @param stream the stream value to tie to the key, or null to remove
+ * @throws IOException if the stream is too large
+ * @since 1.4
+ */
+ void setStream(String key, InputStream stream) throws IOException;
+
+ /**
+ * Return the stream associated with a given key in this applet context, or
+ * null if nothing is associated. Stream associations are local to the
+ * applet context, for security purposes.
+ *
+ * @param key the key to look up
+ * @return the associated stream, or null
+ * @since 1.4
+ */
+ InputStream getStream(String key);
+
+ /**
+ * Iterate over all keys that have associated streams. Stream associated
+ * are local to the applet context, for security purposes.
+ *
+ * @return an iterator over the association keys
+ * @since 1.4
+ */
+ Iterator getStreamKeys();
+} // interface AppletContext
diff --git a/libjava/classpath/java/applet/AppletStub.java b/libjava/classpath/java/applet/AppletStub.java
new file mode 100644
index 00000000000..879a01638a5
--- /dev/null
+++ b/libjava/classpath/java/applet/AppletStub.java
@@ -0,0 +1,103 @@
+/* AppletStub.java -- low level interface to the browser
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.applet;
+
+import java.net.URL;
+
+/**
+ * This interface is the low level interface between the applet and the
+ * browser.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Applet#setStub(AppletStub)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface AppletStub
+{
+ /**
+ * Tests whether or not this applet is currently active. An applet is active
+ * just before the browser invokes start(), and becomes inactive just
+ * before the browser invokes stop().
+ *
+ * @return <code>true</code> if this applet is active
+ */
+ boolean isActive();
+
+ /**
+ * Returns the basename URL of the document this applet is embedded in. This
+ * is everything up to the final '/'.
+ *
+ * @return the URL of the document this applet is embedded in
+ * @see #getCodeBase()
+ */
+ URL getDocumentBase();
+
+ /**
+ * Returns the URL of the code base for this applet.
+ *
+ * @return the URL of the code base for this applet
+ */
+ URL getCodeBase();
+
+ /**
+ * Returns the value of the specified parameter that was specified in
+ * the <code>&lt;APPLET&gt;</code> tag for this applet.
+ *
+ * @param name the parameter name
+ * @return the parameter value, or null if the parameter does not exist
+ * @throws NullPointerException if name is null
+ */
+ String getParameter(String name);
+
+ /**
+ * Returns the applet context for this applet.
+ *
+ * @return the applet context for this applet
+ */
+ AppletContext getAppletContext();
+
+ /**
+ * Requests that the applet window for this applet be resized.
+ *
+ * @param width the new width in pixels
+ * @param height the new height in pixels
+ */
+ void appletResize(int width, int height);
+} // interface AppletStub
diff --git a/libjava/classpath/java/applet/AudioClip.java b/libjava/classpath/java/applet/AudioClip.java
new file mode 100644
index 00000000000..eeafa8aa7a8
--- /dev/null
+++ b/libjava/classpath/java/applet/AudioClip.java
@@ -0,0 +1,68 @@
+/* AudioClip.java -- play an audio clip in an applet
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.applet;
+
+
+/**
+ * This interface provides a simple mechanism for playing audio clips.
+ * If multiple clips are played at once, the browser combines them into a
+ * composite clip.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface AudioClip
+{
+ /**
+ * Plays the audio clip starting from the beginning.
+ */
+ void play();
+
+ /**
+ * Stops playing this audio clip. There is no mechanism for restarting
+ * at the point where the clip is stopped.
+ */
+ void stop();
+
+ /**
+ * Plays this audio clip in a continuous loop.
+ */
+ void loop();
+} // interface AudioClip
diff --git a/libjava/classpath/java/applet/package.html b/libjava/classpath/java/applet/package.html
new file mode 100644
index 00000000000..f2cbc57260f
--- /dev/null
+++ b/libjava/classpath/java/applet/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.applet package.
+ Copyright (C) 2002 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 - java.applet</title></head>
+
+<body>
+<p>Classes and interfaces for small embeddable applications
+often used in web pages.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/AWTError.java b/libjava/classpath/java/awt/AWTError.java
new file mode 100644
index 00000000000..80356eee440
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTError.java
@@ -0,0 +1,64 @@
+/* AWTError.java -- A serious AWT error occurred.
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This error is thrown when a critical Abstract Window Toolkit (AWT) error
+ * occurs.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class AWTError extends Error
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -1819846354050686206L;
+
+ /**
+ * Create a new instance with the specified descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public AWTError(String message)
+ {
+ super(message);
+ }
+} // class AWTError
diff --git a/libjava/classpath/java/awt/AWTEvent.java b/libjava/classpath/java/awt/AWTEvent.java
new file mode 100644
index 00000000000..ad9533f9c26
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTEvent.java
@@ -0,0 +1,278 @@
+
+/* AWTEvent.java -- the root event in AWT
+ Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.util.EventObject;
+
+/**
+ * AWTEvent is the root event class for all AWT events in the JDK 1.1 event
+ * model. It supersedes the Event class from JDK 1.0. Subclasses outside of
+ * the java.awt package should have IDs greater than RESERVED_ID_MAX.
+ *
+ * <p>Event masks defined here are used by components in
+ * <code>enableEvents</code> to select event types not selected by registered
+ * listeners. Event masks are appropriately set when registering on
+ * components.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class AWTEvent extends EventObject
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -1825314779160409405L;
+
+ /**
+ * The ID of the event.
+ *
+ * @see #getID()
+ * @see #AWTEvent(Object, int)
+ * @serial the identifier number of this event
+ */
+ protected int id;
+
+ /**
+ * Indicates if the event has been consumed. False mean it is passed to
+ * the peer, true means it has already been processed. Semantic events
+ * generated by low-level events always have the value true.
+ *
+ * @see #consume()
+ * @see #isConsumed()
+ * @serial whether the event has been consumed
+ */
+ protected boolean consumed;
+
+ /**
+ * Who knows? It's in the serial version.
+ *
+ * @serial No idea what this is for.
+ */
+ byte[] bdata;
+
+ /** Mask for selecting component events. */
+ public static final long COMPONENT_EVENT_MASK = 0x00001;
+
+ /** Mask for selecting container events. */
+ public static final long CONTAINER_EVENT_MASK = 0x00002;
+
+ /** Mask for selecting component focus events. */
+ public static final long FOCUS_EVENT_MASK = 0x00004;
+
+ /** Mask for selecting keyboard events. */
+ public static final long KEY_EVENT_MASK = 0x00008;
+
+ /** Mask for mouse button events. */
+ public static final long MOUSE_EVENT_MASK = 0x00010;
+
+ /** Mask for mouse motion events. */
+ public static final long MOUSE_MOTION_EVENT_MASK = 0x00020;
+
+ /** Mask for window events. */
+ public static final long WINDOW_EVENT_MASK = 0x00040;
+
+ /** Mask for action events. */
+ public static final long ACTION_EVENT_MASK = 0x00080;
+
+ /** Mask for adjustment events. */
+ public static final long ADJUSTMENT_EVENT_MASK = 0x00100;
+
+ /** Mask for item events. */
+ public static final long ITEM_EVENT_MASK = 0x00200;
+
+ /** Mask for text events. */
+ public static final long TEXT_EVENT_MASK = 0x00400;
+
+ /**
+ * Mask for input method events.
+ * @since 1.3
+ */
+ public static final long INPUT_METHOD_EVENT_MASK = 0x00800;
+
+ /**
+ * Mask if input methods are enabled. Package visible only.
+ */
+ static final long INPUT_ENABLED_EVENT_MASK = 0x01000;
+
+ /**
+ * Mask for paint events.
+ * @since 1.3
+ */
+ public static final long PAINT_EVENT_MASK = 0x02000;
+
+ /**
+ * Mask for invocation events.
+ * @since 1.3
+ */
+ public static final long INVOCATION_EVENT_MASK = 0x04000;
+
+ /**
+ * Mask for hierarchy events.
+ * @since 1.3
+ */
+ public static final long HIERARCHY_EVENT_MASK = 0x08000;
+
+ /**
+ * Mask for hierarchy bounds events.
+ * @since 1.3
+ */
+ public static final long HIERARCHY_BOUNDS_EVENT_MASK = 0x10000;
+
+ /**
+ * Mask for mouse wheel events.
+ * @since 1.4
+ */
+ public static final long MOUSE_WHEEL_EVENT_MASK = 0x20000;
+
+ /**
+ * Mask for window state events.
+ * @since 1.4
+ */
+ public static final long WINDOW_STATE_EVENT_MASK = 0x40000;
+
+ /**
+ * Mask for window focus events.
+ * @since 1.4
+ */
+ public static final long WINDOW_FOCUS_EVENT_MASK = 0x80000;
+
+ /**
+ * This is the highest number for event ids that are reserved for use by
+ * the AWT system itself. Subclasses outside of java.awt should use higher
+ * ids.
+ */
+ public static final int RESERVED_ID_MAX = 1999;
+
+
+ /**
+ * Initializes a new AWTEvent from the old Java 1.0 event object.
+ *
+ * @param event the old-style event
+ * @throws NullPointerException if event is null
+ */
+ public AWTEvent(Event event)
+ {
+ this(event.target, event.id);
+ consumed = event.consumed;
+ }
+
+ /**
+ * Create an event on the specified source object and id.
+ *
+ * @param source the object that caused the event
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public AWTEvent(Object source, int id)
+ {
+ super(source);
+ this.id = id;
+ }
+
+ /**
+ * Retarget the event, such as converting a heavyweight component to a
+ * lightweight child of the original. This is not for general use, but
+ * is for event targeting systems like KeyboardFocusManager.
+ *
+ * @param source the new source
+ */
+ public void setSource(Object source)
+ {
+ this.source = source;
+ }
+
+ /**
+ * Returns the event type id.
+ *
+ * @return the id number of this event
+ */
+ public int getID()
+ {
+ return id;
+ }
+
+ /**
+ * Create a string that represents this event in the format
+ * <code>classname[eventstring] on sourcecomponentname</code>.
+ *
+ * @return a string representing this event
+ */
+ public String toString ()
+ {
+ String string = getClass ().getName () + "[" + paramString () + "] on "
+ + source;
+
+ return string;
+ }
+
+ /**
+ * Returns a string representation of the state of this event. It may be
+ * empty, but must not be null; it is implementation defined.
+ *
+ * @return a string representation of this event
+ */
+ public String paramString()
+ {
+ return "";
+ }
+
+ /**
+ * Consumes this event so that it will not be processed in the default
+ * manner.
+ */
+ protected void consume()
+ {
+ consumed = true;
+ }
+
+ /**
+ * Tests whether not not this event has been consumed. A consumed event
+ * is not processed in the default manner.
+ *
+ * @return true if this event has been consumed
+ */
+ protected boolean isConsumed()
+ {
+ return consumed;
+ }
+} // class AWTEvent
diff --git a/libjava/classpath/java/awt/AWTEventMulticaster.java b/libjava/classpath/java/awt/AWTEventMulticaster.java
new file mode 100644
index 00000000000..f7b9163cf67
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTEventMulticaster.java
@@ -0,0 +1,1209 @@
+/* AWTEventMulticaster.java -- allows multicast chaining of listeners
+ Copyright (C) 1999, 2000, 2002 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 java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.ContainerEvent;
+import java.awt.event.ContainerListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.HierarchyBoundsListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowFocusListener;
+import java.awt.event.WindowListener;
+import java.awt.event.WindowStateListener;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.EventListener;
+
+/**
+ * This class is used to implement a chain of event handlers. Dispatching
+ * using this class is thread safe. Here is a quick example of how to
+ * add and delete listeners using this class. For this example, we will
+ * assume are firing <code>AdjustmentEvent</code>'s. However, this
+ * same approach is useful for all events in the <code>java.awt.event</code>
+ * package, and more if this class is subclassed.
+ *
+ * <p><code>
+ * AdjustmentListener al;
+ * public void addAdjustmentListener(AdjustmentListener listener)
+ * {
+ * al = AWTEventMulticaster.add(al, listener);
+ * }
+ * public void removeAdjustmentListener(AdjustmentListener listener)
+ * {
+ * al = AWTEventMulticaster.remove(al, listener);
+ * }
+ * </code>
+ *
+ * <p>When it come time to process an event, simply call <code>al</code>,
+ * assuming it is not <code>null</code>, and all listeners in the chain will
+ * be fired.
+ *
+ * <p>The first time <code>add</code> is called it is passed
+ * <code>null</code> and <code>listener</code> as its arguments. This
+ * starts building the chain. This class returns <code>listener</code>
+ * which becomes the new <code>al</code>. The next time, <code>add</code>
+ * is called with <code>al</code> and <code>listener</code> and the
+ * new listener is then chained to the old.
+ *
+ * @author Bryce McKinlay
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class AWTEventMulticaster
+ implements ComponentListener, ContainerListener, FocusListener, KeyListener,
+ MouseListener, MouseMotionListener, WindowListener,
+ WindowFocusListener, WindowStateListener, ActionListener,
+ ItemListener, AdjustmentListener, TextListener,
+ InputMethodListener, HierarchyListener, HierarchyBoundsListener,
+ MouseWheelListener
+{
+ /**
+ * A variable in the event chain.
+ */
+ protected final EventListener a;
+
+ /**
+ * A variable in the event chain.
+ */
+ protected final EventListener b;
+
+ /**
+ * Initializes a new instance of <code>AWTEventMulticaster</code> with
+ * the specified event listener parameters. The parameters should not be
+ * null, although it is not required to enforce this with a
+ * NullPointerException.
+ *
+ * @param a the "a" listener object
+ * @param b the "b" listener object
+ */
+ protected AWTEventMulticaster(EventListener a, EventListener b)
+ {
+ this.a = a;
+ this.b = b;
+ }
+
+ /**
+ * Removes one instance of the specified listener from this multicaster
+ * chain. This descends recursively if either child is a multicaster, and
+ * returns a multicaster chain with the old listener removed.
+ *
+ * @param oldl the object to remove from this multicaster
+ * @return the resulting multicaster with the specified listener removed
+ */
+ protected EventListener remove(EventListener oldl)
+ {
+ // If oldl is an immediate child, return the other child.
+ if (a == oldl)
+ return b;
+ if (b == oldl)
+ return a;
+ // If a and/or b are Multicaster's, search them recursively.
+ if (a instanceof AWTEventMulticaster)
+ {
+ EventListener newa = ((AWTEventMulticaster) a).remove(oldl);
+ if (newa != a)
+ return new AWTEventMulticaster(newa, b);
+ }
+ if (b instanceof AWTEventMulticaster)
+ {
+ EventListener newb = ((AWTEventMulticaster) b).remove(oldl);
+ if (newb != b)
+ return new AWTEventMulticaster(a, newb);
+ }
+ // oldl was not found.
+ return this;
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ ((ComponentListener) a).componentResized(e);
+ ((ComponentListener) b).componentResized(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentMoved(ComponentEvent e)
+ {
+ ((ComponentListener) a).componentMoved(e);
+ ((ComponentListener) b).componentMoved(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentShown(ComponentEvent e)
+ {
+ ((ComponentListener) a).componentShown(e);
+ ((ComponentListener) b).componentShown(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentHidden(ComponentEvent e)
+ {
+ ((ComponentListener) a).componentHidden(e);
+ ((ComponentListener) b).componentHidden(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentAdded(ContainerEvent e)
+ {
+ ((ContainerListener) a).componentAdded(e);
+ ((ContainerListener) b).componentAdded(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentRemoved(ContainerEvent e)
+ {
+ ((ContainerListener) a).componentRemoved(e);
+ ((ContainerListener) b).componentRemoved(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void focusGained(FocusEvent e)
+ {
+ ((FocusListener) a).focusGained(e);
+ ((FocusListener) b).focusGained(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void focusLost(FocusEvent e)
+ {
+ ((FocusListener) a).focusLost(e);
+ ((FocusListener) b).focusLost(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void keyTyped(KeyEvent e)
+ {
+ ((KeyListener) a).keyTyped(e);
+ ((KeyListener) b).keyTyped(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void keyPressed(KeyEvent e)
+ {
+ ((KeyListener) a).keyPressed(e);
+ ((KeyListener) b).keyPressed(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void keyReleased(KeyEvent e)
+ {
+ ((KeyListener) a).keyReleased(e);
+ ((KeyListener) b).keyReleased(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseClicked(MouseEvent e)
+ {
+ ((MouseListener) a).mouseClicked(e);
+ ((MouseListener) b).mouseClicked(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ ((MouseListener) a).mousePressed(e);
+ ((MouseListener) b).mousePressed(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseReleased(MouseEvent e)
+ {
+ ((MouseListener) a).mouseReleased(e);
+ ((MouseListener) b).mouseReleased(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseEntered(MouseEvent e)
+ {
+ ((MouseListener) a).mouseEntered(e);
+ ((MouseListener) b).mouseEntered(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseExited(MouseEvent e)
+ {
+ ((MouseListener) a).mouseExited(e);
+ ((MouseListener) b).mouseExited(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseDragged(MouseEvent e)
+ {
+ ((MouseMotionListener) a).mouseDragged(e);
+ ((MouseMotionListener) b).mouseDragged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseMoved(MouseEvent e)
+ {
+ ((MouseMotionListener) a).mouseMoved(e);
+ ((MouseMotionListener) b).mouseMoved(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowOpened(WindowEvent e)
+ {
+ ((WindowListener) a).windowOpened(e);
+ ((WindowListener) b).windowOpened(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowClosing(WindowEvent e)
+ {
+ ((WindowListener) a).windowClosing(e);
+ ((WindowListener) b).windowClosing(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowClosed(WindowEvent e)
+ {
+ ((WindowListener) a).windowClosed(e);
+ ((WindowListener) b).windowClosed(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowIconified(WindowEvent e)
+ {
+ ((WindowListener) a).windowIconified(e);
+ ((WindowListener) b).windowIconified(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowDeiconified(WindowEvent e)
+ {
+ ((WindowListener) a).windowDeiconified(e);
+ ((WindowListener) b).windowDeiconified(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowActivated(WindowEvent e)
+ {
+ ((WindowListener) a).windowActivated(e);
+ ((WindowListener) b).windowActivated(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowDeactivated(WindowEvent e)
+ {
+ ((WindowListener) a).windowDeactivated(e);
+ ((WindowListener) b).windowDeactivated(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.4
+ */
+ public void windowStateChanged(WindowEvent e)
+ {
+ ((WindowStateListener) a).windowStateChanged(e);
+ ((WindowStateListener) b).windowStateChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.4
+ */
+ public void windowGainedFocus(WindowEvent e)
+ {
+ ((WindowFocusListener) a).windowGainedFocus(e);
+ ((WindowFocusListener) b).windowGainedFocus(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.4
+ */
+ public void windowLostFocus(WindowEvent e)
+ {
+ ((WindowFocusListener) a).windowLostFocus(e);
+ ((WindowFocusListener) b).windowLostFocus(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ ((ActionListener) a).actionPerformed(e);
+ ((ActionListener) b).actionPerformed(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void itemStateChanged(ItemEvent e)
+ {
+ ((ItemListener) a).itemStateChanged(e);
+ ((ItemListener) b).itemStateChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void adjustmentValueChanged(AdjustmentEvent e)
+ {
+ ((AdjustmentListener) a).adjustmentValueChanged(e);
+ ((AdjustmentListener) b).adjustmentValueChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void textValueChanged(TextEvent e)
+ {
+ ((TextListener) a).textValueChanged(e);
+ ((TextListener) b).textValueChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.2
+ */
+ public void inputMethodTextChanged(InputMethodEvent e)
+ {
+ ((InputMethodListener) a).inputMethodTextChanged(e);
+ ((InputMethodListener) b).inputMethodTextChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.2
+ */
+ public void caretPositionChanged(InputMethodEvent e)
+ {
+ ((InputMethodListener) a).caretPositionChanged(e);
+ ((InputMethodListener) b).caretPositionChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.3
+ */
+ public void hierarchyChanged(HierarchyEvent e)
+ {
+ ((HierarchyListener) a).hierarchyChanged(e);
+ ((HierarchyListener) b).hierarchyChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.3
+ */
+ public void ancestorMoved(HierarchyEvent e)
+ {
+ ((HierarchyBoundsListener) a).ancestorMoved(e);
+ ((HierarchyBoundsListener) b).ancestorMoved(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.3
+ */
+ public void ancestorResized(HierarchyEvent e)
+ {
+ ((HierarchyBoundsListener) a).ancestorResized(e);
+ ((HierarchyBoundsListener) b).ancestorResized(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.4
+ */
+ public void mouseWheelMoved(MouseWheelEvent e)
+ {
+ ((MouseWheelListener) a).mouseWheelMoved(e);
+ ((MouseWheelListener) b).mouseWheelMoved(e);
+ }
+
+ /**
+ * Chain <code>ComponentListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static ComponentListener add(ComponentListener a, ComponentListener b)
+ {
+ return (ComponentListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>ContainerListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static ContainerListener add(ContainerListener a, ContainerListener b)
+ {
+ return (ContainerListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>FocusListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static FocusListener add(FocusListener a, FocusListener b)
+ {
+ return (FocusListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>KeyListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static KeyListener add(KeyListener a, KeyListener b)
+ {
+ return (KeyListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>MouseListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static MouseListener add(MouseListener a, MouseListener b)
+ {
+ return (MouseListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>MouseMotionListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static MouseMotionListener add(MouseMotionListener a,
+ MouseMotionListener b)
+ {
+ return (MouseMotionListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>WindowListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static WindowListener add(WindowListener a, WindowListener b)
+ {
+ return (WindowListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>WindowStateListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.4
+ */
+ public static WindowStateListener add(WindowStateListener a,
+ WindowStateListener b)
+ {
+ return (WindowStateListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>WindowFocusListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.4
+ */
+ public static WindowFocusListener add(WindowFocusListener a,
+ WindowFocusListener b)
+ {
+ return (WindowFocusListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>ActionListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static ActionListener add(ActionListener a, ActionListener b)
+ {
+ return (ActionListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>ItemListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static ItemListener add(ItemListener a, ItemListener b)
+ {
+ return (ItemListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>AdjustmentListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static AdjustmentListener add(AdjustmentListener a,
+ AdjustmentListener b)
+ {
+ return (AdjustmentListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>AdjustmentListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static TextListener add(TextListener a, TextListener b)
+ {
+ return (TextListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>InputMethodListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.2
+ */
+ public static InputMethodListener add(InputMethodListener a,
+ InputMethodListener b)
+ {
+ return (InputMethodListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>HierarchyListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.3
+ */
+ public static HierarchyListener add(HierarchyListener a, HierarchyListener b)
+ {
+ return (HierarchyListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>HierarchyBoundsListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.3
+ */
+ public static HierarchyBoundsListener add(HierarchyBoundsListener a,
+ HierarchyBoundsListener b)
+ {
+ return (HierarchyBoundsListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>MouseWheelListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.4
+ */
+ public static MouseWheelListener add(MouseWheelListener a,
+ MouseWheelListener b)
+ {
+ return (MouseWheelListener) addInternal(a, b);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static ComponentListener remove(ComponentListener l,
+ ComponentListener oldl)
+ {
+ return (ComponentListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static ContainerListener remove(ContainerListener l,
+ ContainerListener oldl)
+ {
+ return (ContainerListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static FocusListener remove(FocusListener l, FocusListener oldl)
+ {
+ return (FocusListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static KeyListener remove(KeyListener l, KeyListener oldl)
+ {
+ return (KeyListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static MouseListener remove(MouseListener l, MouseListener oldl)
+ {
+ return (MouseListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static MouseMotionListener remove(MouseMotionListener l,
+ MouseMotionListener oldl)
+ {
+ return (MouseMotionListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static WindowListener remove(WindowListener l, WindowListener oldl)
+ {
+ return (WindowListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.4
+ */
+ public static WindowStateListener remove(WindowStateListener l,
+ WindowStateListener oldl)
+ {
+ return (WindowStateListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.4
+ */
+ public static WindowFocusListener remove(WindowFocusListener l,
+ WindowFocusListener oldl)
+ {
+ return (WindowFocusListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static ActionListener remove(ActionListener l, ActionListener oldl)
+ {
+ return (ActionListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static ItemListener remove(ItemListener l, ItemListener oldl)
+ {
+ return (ItemListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static AdjustmentListener remove(AdjustmentListener l,
+ AdjustmentListener oldl)
+ {
+ return (AdjustmentListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static TextListener remove(TextListener l, TextListener oldl)
+ {
+ return (TextListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.2
+ */
+ public static InputMethodListener remove(InputMethodListener l,
+ InputMethodListener oldl)
+ {
+ return (InputMethodListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.3
+ */
+ public static HierarchyListener remove(HierarchyListener l,
+ HierarchyListener oldl)
+ {
+ return (HierarchyListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.3
+ */
+ public static HierarchyBoundsListener remove(HierarchyBoundsListener l,
+ HierarchyBoundsListener oldl)
+ {
+ return (HierarchyBoundsListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.4
+ */
+ public static MouseWheelListener remove(MouseWheelListener l,
+ MouseWheelListener oldl)
+ {
+ return (MouseWheelListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Chain <code>EventListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ protected static EventListener addInternal(EventListener a, EventListener b)
+ {
+ if (a == null)
+ return b;
+ if (b == null)
+ return a;
+ return new AWTEventMulticaster(a, b);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ protected static EventListener removeInternal(EventListener l,
+ EventListener oldl)
+ {
+ if (l == oldl)
+ return null;
+ if (l instanceof AWTEventMulticaster)
+ return ((AWTEventMulticaster) l).remove(oldl);
+ return l;
+ }
+
+ /**
+ * Saves all Serializable listeners to a serialization stream.
+ *
+ * @param s the stream to save to
+ * @param k a prefix stream put before each serializable listener
+ * @throws IOException if serialization fails
+ */
+ protected void saveInternal(ObjectOutputStream s, String k)
+ throws IOException
+ {
+ // This is not documented by Sun, but I think it is correct.
+ if (a instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) a).saveInternal(s, k);
+ else if (a instanceof Serializable)
+ {
+ s.writeObject(k);
+ s.writeObject(a);
+ }
+ if (b instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) b).saveInternal(s, k);
+ else if (b instanceof Serializable)
+ {
+ s.writeObject(k);
+ s.writeObject(b);
+ }
+ }
+
+ /**
+ * Saves a Serializable listener chain to a serialization stream.
+ *
+ * @param s the stream to save to
+ * @param k a prefix stream put before each serializable listener
+ * @param l the listener chain to save
+ * @throws IOException if serialization fails
+ */
+ protected static void save(ObjectOutputStream s, String k, EventListener l)
+ throws IOException
+ {
+ // This is not documented by Sun, but I think it is correct.
+ if (l instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) l).saveInternal(s, k);
+ else if (l instanceof Serializable)
+ {
+ s.writeObject(k);
+ s.writeObject(l);
+ }
+ }
+
+ /**
+ * Returns an array of all chained listeners of the specified type in the
+ * given chain. A null listener returns an empty array, and a listener
+ * which is not an AWTEventMulticaster returns an array of one element. If
+ * no listeners in the chain are of the specified type, an empty array is
+ * returned.
+ *
+ * @param l the listener chain to convert to an array
+ * @param type the type of listeners to collect
+ * @return an array of the listeners of that type in the chain
+ * @throws ClassCastException if type is not assignable from EventListener
+ * @throws NullPointerException if type is null
+ * @throws IllegalArgumentException if type is Void.TYPE
+ * @since 1.4
+ */
+ public static EventListener[] getListeners(EventListener l, Class type)
+ {
+ ArrayList list = new ArrayList();
+ if (l instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) l).getListeners(list, type);
+ else if (type.isInstance(l))
+ list.add(l);
+ EventListener[] r = (EventListener[]) Array.newInstance(type, list.size());
+ list.toArray(r);
+ return r;
+ }
+
+ /**
+ * Collects all instances of the given type in the chain into the list.
+ *
+ * @param l the list to collect into
+ * @param type the type of listeners to collect
+ * @throws NullPointerException if type is null
+ * @see #getListeners(EventListener, Class)
+ */
+ private void getListeners(ArrayList l, Class type)
+ {
+ if (a instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) a).getListeners(l, type);
+ else if (type.isInstance(a))
+ l.add(a);
+ if (b instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) b).getListeners(l, type);
+ else if (type.isInstance(b))
+ l.add(b);
+ }
+} // class AWTEventMulticaster
diff --git a/libjava/classpath/java/awt/AWTException.java b/libjava/classpath/java/awt/AWTException.java
new file mode 100644
index 00000000000..2df3dd80102
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTException.java
@@ -0,0 +1,64 @@
+/* AWTException.java -- Generic AWT exception
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This is a generic exception that indicates an exception occurred in the
+ * Abstract Window Toolkit (AWT) system.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class AWTException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -1900414231151323879L;
+
+ /**
+ * Create a new instance with the specified detailed error message.
+ *
+ * @param message the detailed error message
+ */
+ public AWTException(String message)
+ {
+ super(message);
+ }
+} // class AWTException
diff --git a/libjava/classpath/java/awt/AWTKeyStroke.java b/libjava/classpath/java/awt/AWTKeyStroke.java
new file mode 100644
index 00000000000..c10d53e4d10
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTKeyStroke.java
@@ -0,0 +1,660 @@
+/* AWTKeyStroke.java -- an immutable key stroke
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * This class mirrors KeyEvents, representing both low-level key presses and
+ * key releases, and high level key typed inputs. However, this class forms
+ * immutable strokes, and can be efficiently reused via the factory methods
+ * for creating them.
+ *
+ * <p>For backwards compatibility with Swing, this supports a way to build
+ * instances of a subclass, using reflection, provided the subclass has a
+ * no-arg constructor (of any accessibility).
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see #getAWTKeyStroke(char)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class AWTKeyStroke implements Serializable
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -6430539691155161871L;
+
+ /** The mask for modifiers. */
+ private static final int MODIFIERS_MASK = 0x3fef;
+
+ /**
+ * The cache of recently created keystrokes. This maps KeyStrokes to
+ * KeyStrokes in a cache which removes the least recently accessed entry,
+ * under the assumption that garbage collection of a new keystroke is
+ * easy when we find the old one that it matches in the cache.
+ */
+ private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true)
+ {
+ /** The largest the keystroke cache can grow. */
+ private static final int MAX_CACHE_SIZE = 2048;
+
+ /** Prune stale entries. */
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ { // XXX - FIXME Use Map.Entry, not just Entry as gcj 3.1 workaround.
+ return size() > MAX_CACHE_SIZE;
+ }
+ };
+
+ /** The most recently generated keystroke, or null. */
+ private static AWTKeyStroke recent;
+
+ /**
+ * The no-arg constructor of a subclass, or null to use AWTKeyStroke. Note
+ * that this will be left accessible, to get around private access; but
+ * it should not be a security risk as it is highly unlikely that creating
+ * protected instances of the subclass via reflection will do much damage.
+ */
+ private static Constructor ctor;
+
+ /**
+ * A table of keyCode names to values. This is package-private to
+ * avoid an accessor method.
+ *
+ * @see #getAWTKeyStroke(String)
+ */
+ static final HashMap vktable = new HashMap();
+ static
+ {
+ // Using reflection saves the hassle of keeping this in sync with KeyEvent,
+ // at the price of an expensive initialization.
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ Field[] fields = KeyEvent.class.getFields();
+ int i = fields.length;
+ try
+ {
+ while (--i >= 0)
+ {
+ Field f = fields[i];
+ String name = f.getName();
+ if (name.startsWith("VK_"))
+ vktable.put(name.substring(3), f.get(null));
+ }
+ }
+ catch (Exception e)
+ {
+ throw (Error) new InternalError().initCause(e);
+ }
+ return null;
+ }
+ });
+ }
+
+ /**
+ * The typed character, or CHAR_UNDEFINED for key presses and releases.
+ *
+ * @serial the keyChar
+ */
+ private char keyChar;
+
+ /**
+ * The virtual key code, or VK_UNDEFINED for key typed. Package visible for
+ * use by Component.
+ *
+ * @serial the keyCode
+ */
+ int keyCode;
+
+ /**
+ * The modifiers in effect. To match Sun, this stores the old style masks
+ * for shift, control, alt, meta, and alt-graph (but not button1); as well
+ * as the new style of extended modifiers for all modifiers.
+ *
+ * @serial bitwise or of the *_DOWN_MASK modifiers
+ */
+ private int modifiers;
+
+ /**
+ * True if this is a key release; should only be true if keyChar is
+ * CHAR_UNDEFINED.
+ *
+ * @serial true to distinguish key pressed from key released
+ */
+ private boolean onKeyRelease;
+
+ /**
+ * Construct a keystroke with default values: it will be interpreted as a
+ * key typed event with an invalid character and no modifiers. Client code
+ * should use the factory methods instead.
+ *
+ * @see #getAWTKeyStroke(char)
+ * @see #getAWTKeyStroke(Character, int)
+ * @see #getAWTKeyStroke(int, int, boolean)
+ * @see #getAWTKeyStroke(int, int)
+ * @see #getAWTKeyStrokeForEvent(KeyEvent)
+ * @see #getAWTKeyStroke(String)
+ */
+ protected AWTKeyStroke()
+ {
+ keyChar = KeyEvent.CHAR_UNDEFINED;
+ }
+
+ /**
+ * Construct a keystroke with the given values. Client code should use the
+ * factory methods instead.
+ *
+ * @param keyChar the character entered, if this is a key typed
+ * @param keyCode the key pressed or released, or VK_UNDEFINED for key typed
+ * @param modifiers the modifier keys for the keystroke, in old or new style
+ * @param onKeyRelease true if this is a key release instead of a press
+ * @see #getAWTKeyStroke(char)
+ * @see #getAWTKeyStroke(Character, int)
+ * @see #getAWTKeyStroke(int, int, boolean)
+ * @see #getAWTKeyStroke(int, int)
+ * @see #getAWTKeyStrokeForEvent(KeyEvent)
+ * @see #getAWTKeyStroke(String)
+ */
+ protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
+ boolean onKeyRelease)
+ {
+ this.keyChar = keyChar;
+ this.keyCode = keyCode;
+ // No need to call extend(), as only trusted code calls this constructor.
+ this.modifiers = modifiers;
+ this.onKeyRelease = onKeyRelease;
+ }
+
+ /**
+ * Registers a new subclass as being the type of keystrokes to generate in
+ * the factory methods. This operation flushes the cache of stored keystrokes
+ * if the class differs from the current one. The new class must be
+ * AWTKeyStroke or a subclass, and must have a no-arg constructor (which may
+ * be private).
+ *
+ * @param subclass the new runtime type of generated keystrokes
+ * @throws IllegalArgumentException subclass doesn't have no-arg constructor
+ * @throws ClassCastException subclass doesn't extend AWTKeyStroke
+ */
+ protected static void registerSubclass(final Class subclass)
+ {
+ if (subclass == null)
+ throw new IllegalArgumentException();
+ if (subclass.equals(ctor == null ? AWTKeyStroke.class
+ : ctor.getDeclaringClass()))
+ return;
+ if (subclass.equals(AWTKeyStroke.class))
+ {
+ cache.clear();
+ recent = null;
+ ctor = null;
+ return;
+ }
+ try
+ {
+ ctor = (Constructor) AccessController.doPrivileged
+ (new PrivilegedExceptionAction()
+ {
+ public Object run()
+ throws NoSuchMethodException, InstantiationException,
+ IllegalAccessException, InvocationTargetException
+ {
+ Constructor c = subclass.getDeclaredConstructor(null);
+ c.setAccessible(true);
+ // Create a new instance, to make sure that we can, and
+ // to cause any ClassCastException.
+ AWTKeyStroke dummy = (AWTKeyStroke) c.newInstance(null);
+ return c;
+ }
+ });
+ }
+ catch (PrivilegedActionException e)
+ {
+ // e.getCause() will not ever be ClassCastException; that should
+ // escape on its own.
+ throw (RuntimeException)
+ new IllegalArgumentException().initCause(e.getCause());
+ }
+ cache.clear();
+ recent = null;
+ }
+
+ /**
+ * Returns a keystroke representing a typed character.
+ *
+ * @param keyChar the typed character
+ * @return the specified keystroke
+ */
+ public static AWTKeyStroke getAWTKeyStroke(char keyChar)
+ {
+ return getAWTKeyStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
+ }
+
+ /**
+ * Returns a keystroke representing a typed character with the given
+ * modifiers. Note that keyChar is a <code>Character</code> instead of a
+ * <code>char</code> to avoid accidental ambiguity with
+ * <code>getAWTKeyStroke(int, int)</code>. The modifiers are the bitwise
+ * or of the masks found in {@link InputEvent}; the new style (*_DOWN_MASK)
+ * is preferred, but the old style will work.
+ *
+ * @param keyChar the typed character
+ * @param modifiers the modifiers, or 0
+ * @return the specified keystroke
+ * @throws IllegalArgumentException if keyChar is null
+ */
+ public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers)
+ {
+ if (keyChar == null)
+ throw new IllegalArgumentException();
+ return getAWTKeyStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
+ extend(modifiers), false);
+ }
+
+ /**
+ * Returns a keystroke representing a pressed or released key event, with
+ * the given modifiers. The "virtual key" should be one of the VK_*
+ * constants in {@link KeyEvent}. The modifiers are the bitwise or of the
+ * masks found in {@link InputEvent}; the new style (*_DOWN_MASK) is
+ * preferred, but the old style will work.
+ *
+ * @param keyCode the virtual key
+ * @param modifiers the modifiers, or 0
+ * @param release true if this is a key release instead of a key press
+ * @return the specified keystroke
+ */
+ public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
+ boolean release)
+ {
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
+ extend(modifiers), release);
+ }
+
+ /**
+ * Returns a keystroke representing a pressed key event, with the given
+ * modifiers. The "virtual key" should be one of the VK_* constants in
+ * {@link KeyEvent}. The modifiers are the bitwise or of the masks found
+ * in {@link InputEvent}; the new style (*_DOWN_MASK) is preferred, but the
+ * old style will work.
+ *
+ * @param keyCode the virtual key
+ * @param modifiers the modifiers, or 0
+ * @return the specified keystroke
+ */
+ public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers)
+ {
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
+ extend(modifiers), false);
+ }
+
+ /**
+ * Returns a keystroke representing what caused the key event.
+ *
+ * @param event the key event to convert
+ * @return the specified keystroke, or null if the event is invalid
+ * @throws NullPointerException if event is null
+ */
+ public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent event)
+ {
+ switch (event.id)
+ {
+ case KeyEvent.KEY_TYPED:
+ return getAWTKeyStroke(event.getKeyChar(), KeyEvent.VK_UNDEFINED,
+ extend(event.getModifiersEx()), false);
+ case KeyEvent.KEY_PRESSED:
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(),
+ extend(event.getModifiersEx()), false);
+ case KeyEvent.KEY_RELEASED:
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(),
+ extend(event.getModifiersEx()), true);
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Parses a string and returns the keystroke that it represents. The syntax
+ * for keystrokes is listed below, with tokens separated by an arbitrary
+ * number of spaces:
+ * <pre>
+ * keyStroke := &lt;modifiers&gt;* ( &lt;typedID&gt; | &lt;codeID&gt; )
+ * modifiers := ( shift | control | ctrl | meta | alt
+ * | button1 | button2 | button3 )
+ * typedID := typed &lt;single Unicode character&gt;
+ * codeID := ( pressed | released )? &lt;name&gt;
+ * name := &lt;the KeyEvent field name less the leading "VK_"&gt;
+ * </pre>
+ *
+ * <p>Note that the grammar is rather weak, and not all valid keystrokes
+ * can be generated in this manner (for example, a typed space, or anything
+ * with the alt-graph modifier!). The output of AWTKeyStroke.toString()
+ * will not meet the grammar. If pressed or released is not specified,
+ * pressed is assumed. Examples:<br>
+ * <code>
+ * "INSERT" =&gt; getAWTKeyStroke(KeyEvent.VK_INSERT, 0);<br>
+ * "control DELETE" =&gt;
+ * getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);<br>
+ * "alt shift X" =&gt; getAWTKeyStroke(KeyEvent.VK_X,
+ * InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);<br>
+ * "alt shift released X" =&gt; getAWTKeyStroke(KeyEvent.VK_X,
+ * InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);<br>
+ * "typed a" =&gt; getAWTKeyStroke('a');
+ * </code>
+ *
+ * @param s the string to parse
+ * @throws IllegalArgumentException if s is null or cannot be parsed
+ * @return the specified keystroke
+ */
+ public static AWTKeyStroke getAWTKeyStroke(String s)
+ {
+ if (s == null)
+ throw new IllegalArgumentException("null argument");
+ StringTokenizer t = new StringTokenizer(s, " ");
+ if (! t.hasMoreTokens())
+ throw new IllegalArgumentException("no tokens '" + s + "'");
+ int modifiers = 0;
+ boolean released = false;
+ String token = null;
+ do
+ {
+ token = t.nextToken();
+ if ("shift".equals(token))
+ modifiers |= KeyEvent.SHIFT_DOWN_MASK;
+ else if ("ctrl".equals(token) || "control".equals(token))
+ modifiers |= KeyEvent.CTRL_DOWN_MASK;
+ else if ("meta".equals(token))
+ modifiers |= KeyEvent.META_DOWN_MASK;
+ else if ("alt".equals(token))
+ modifiers |= KeyEvent.ALT_DOWN_MASK;
+ else if ("button1".equals(token))
+ modifiers |= KeyEvent.BUTTON1_DOWN_MASK;
+ else if ("button2".equals(token))
+ modifiers |= KeyEvent.BUTTON2_DOWN_MASK;
+ else if ("button3".equals(token))
+ modifiers |= KeyEvent.BUTTON3_DOWN_MASK;
+ else if ("typed".equals(token))
+ {
+ if (t.hasMoreTokens())
+ {
+ token = t.nextToken();
+ if (! t.hasMoreTokens() && token.length() == 1)
+ return getAWTKeyStroke(token.charAt(0),
+ KeyEvent.VK_UNDEFINED, modifiers,
+ false);
+ }
+ throw new IllegalArgumentException("Invalid 'typed' argument '"
+ + s + "'");
+ }
+ else if ("pressed".equals(token))
+ {
+ if (t.hasMoreTokens())
+ token = t.nextToken();
+ break;
+ }
+ else if ("released".equals(token))
+ {
+ released = true;
+ if (t.hasMoreTokens())
+ token = t.nextToken();
+ break;
+ }
+ else
+ break;
+ }
+ while (t.hasMoreTokens());
+ // Now token contains the VK name we must parse.
+ Integer code = (Integer) vktable.get(token);
+ if (code == null)
+ throw new IllegalArgumentException("Unknown token '" + token
+ + "' in '" + s + "'");
+ if (t.hasMoreTokens())
+ throw new IllegalArgumentException("Too many tokens: " + s);
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, code.intValue(),
+ modifiers, released);
+ }
+
+ /**
+ * Returns the character of this keystroke, if it was typed.
+ *
+ * @return the character value, or CHAR_UNDEFINED
+ * @see #getAWTKeyStroke(char)
+ */
+ public final char getKeyChar()
+ {
+ return keyChar;
+ }
+
+ /**
+ * Returns the virtual key code of this keystroke, if it was pressed or
+ * released. This will be a VK_* constant from KeyEvent.
+ *
+ * @return the virtual key code value, or VK_UNDEFINED
+ * @see #getAWTKeyStroke(int, int)
+ */
+ public final int getKeyCode()
+ {
+ return keyCode;
+ }
+
+ /**
+ * Returns the modifiers for this keystroke. This will be a bitwise or of
+ * constants from InputEvent; it includes the old style masks for shift,
+ * control, alt, meta, and alt-graph (but not button1); as well as the new
+ * style of extended modifiers for all modifiers.
+ *
+ * @return the modifiers
+ * @see #getAWTKeyStroke(Character, int)
+ * @see #getAWTKeyStroke(int, int)
+ */
+ public final int getModifiers()
+ {
+ return modifiers;
+ }
+
+ /**
+ * Tests if this keystroke is a key release.
+ *
+ * @return true if this is a key release
+ * @see #getAWTKeyStroke(int, int, boolean)
+ */
+ public final boolean isOnKeyRelease()
+ {
+ return onKeyRelease;
+ }
+
+ /**
+ * Returns the AWT event type of this keystroke. This is one of
+ * {@link KeyEvent#KEY_TYPED}, {@link KeyEvent#KEY_PRESSED}, or
+ * {@link KeyEvent#KEY_RELEASED}.
+ *
+ * @return the key event type
+ */
+ public final int getKeyEventType()
+ {
+ return keyCode == KeyEvent.VK_UNDEFINED ? KeyEvent.KEY_TYPED
+ : onKeyRelease ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED;
+ }
+
+ /**
+ * Returns a hashcode for this key event. It is not documented, but appears
+ * to be: <code>(getKeyChar() + 1) * (getKeyCode() + 1)
+ * * (getModifiers() + 1) * 2 + (isOnKeyRelease() ? 1 : 2)</code>.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ return (keyChar + 1) * (keyCode + 1) * (modifiers + 1) * 2
+ + (onKeyRelease ? 1 : 2);
+ }
+
+ /**
+ * Tests two keystrokes for equality.
+ *
+ * @param o the object to test
+ * @return true if it is equal
+ */
+ public final boolean equals(Object o)
+ {
+ if (! (o instanceof AWTKeyStroke))
+ return false;
+ AWTKeyStroke s = (AWTKeyStroke) o;
+ return this == o || (keyChar == s.keyChar && keyCode == s.keyCode
+ && modifiers == s.modifiers
+ && onKeyRelease == s.onKeyRelease);
+ }
+
+ /**
+ * Returns a string representation of this keystroke. For typed keystrokes,
+ * this is <code>"keyChar " + KeyEvent.getKeyModifiersText(getModifiers())
+ + getKeyChar()</code>; for pressed and released keystrokes, this is
+ * <code>"keyCode " + KeyEvent.getKeyModifiersText(getModifiers())
+ * + KeyEvent.getKeyText(getKeyCode())
+ * + (isOnKeyRelease() ? "-R" : "-P")</code>.
+ *
+ * @return a string representation
+ */
+ public String toString()
+ {
+ if (keyCode == KeyEvent.VK_UNDEFINED)
+ return "keyChar " + KeyEvent.getKeyModifiersText(modifiers) + keyChar;
+ return "keyCode " + KeyEvent.getKeyModifiersText(modifiers)
+ + KeyEvent.getKeyText(keyCode) + (onKeyRelease ? "-R" : "-P");
+ }
+
+ /**
+ * Returns a cached version of the deserialized keystroke, if available.
+ *
+ * @return a cached replacement
+ * @throws ObjectStreamException if something goes wrong
+ */
+ protected Object readResolve() throws ObjectStreamException
+ {
+ AWTKeyStroke s = (AWTKeyStroke) cache.get(this);
+ if (s != null)
+ return s;
+ cache.put(this, this);
+ return this;
+ }
+
+ /**
+ * Gets the appropriate keystroke, creating one if necessary.
+ *
+ * @param keyChar the keyChar
+ * @param keyCode the keyCode
+ * @param modifiers the modifiers
+ * @param release true for key release
+ * @return the specified keystroke
+ */
+ private static AWTKeyStroke getAWTKeyStroke(char keyChar, int keyCode,
+ int modifiers, boolean release)
+ {
+ // Check level 0 cache.
+ AWTKeyStroke stroke = recent; // Avoid thread races.
+ if (stroke != null && stroke.keyChar == keyChar
+ && stroke.keyCode == keyCode && stroke.modifiers == modifiers
+ && stroke.onKeyRelease == release)
+ return stroke;
+ // Create a new object, on the assumption that if it has a match in the
+ // cache, the VM can easily garbage collect it as it is temporary.
+ Constructor c = ctor; // Avoid thread races.
+ if (c == null)
+ stroke = new AWTKeyStroke(keyChar, keyCode, modifiers, release);
+ else
+ try
+ {
+ stroke = (AWTKeyStroke) c.newInstance(null);
+ stroke.keyChar = keyChar;
+ stroke.keyCode = keyCode;
+ stroke.modifiers = modifiers;
+ stroke.onKeyRelease = release;
+ }
+ catch (Exception e)
+ {
+ throw (Error) new InternalError().initCause(e);
+ }
+ // Check level 1 cache.
+ AWTKeyStroke cached = (AWTKeyStroke) cache.get(stroke);
+ if (cached == null)
+ cache.put(stroke, stroke);
+ else
+ stroke = cached;
+ return recent = stroke;
+ }
+
+ /**
+ * Converts the modifiers to the appropriate format.
+ *
+ * @param mod the modifiers to convert
+ * @return the adjusted modifiers
+ */
+ private static int extend(int mod)
+ {
+ if ((mod & (KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK)) != 0)
+ mod |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK;
+ if ((mod & (KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK)) != 0)
+ mod |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK;
+ if ((mod & (KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK)) != 0)
+ mod |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK;
+ if ((mod & (KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK)) != 0)
+ mod |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK;
+ if ((mod & (KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK)) != 0)
+ mod |= KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK;
+ if ((mod & KeyEvent.BUTTON1_MASK) != 0)
+ mod |= KeyEvent.BUTTON1_DOWN_MASK;
+ return mod & MODIFIERS_MASK;
+ }
+} // class AWTKeyStroke
diff --git a/libjava/classpath/java/awt/AWTPermission.java b/libjava/classpath/java/awt/AWTPermission.java
new file mode 100644
index 00000000000..3e50c059f88
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTPermission.java
@@ -0,0 +1,121 @@
+/* AWTPermission.java -- AWT related permissions
+ Copyright (C) 2000, 2002 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 java.security.BasicPermission;
+
+/**
+ * This class implements permissions for AWT. This is a named
+ * permission. No actions are defined.
+ *
+ * <p>The following table provides a list of all the possible AWTPermission
+ * permission names with a description of what that permission allows.<br>
+ * <table border=1>
+ * <tr><th>Permission Name</th><th>Permission Allows</th><th>Risks</th</tr>
+ * <tr>
+ * <td><code>accessClipboard</code></td>
+ * <td>posting and reading the AWT clipboard</td>
+ * <td>the clipboard may contain sensitive data</td></tr>
+ * <tr>
+ * <td><code>accessEventQueue</code></td>
+ * <td>access to the AWT event queue</td>
+ * <td>malicious code could remove real events and replace them with bogus
+ * ones, including simulating the user granting permission</td></tr>
+ * <tr>
+ * <td><code>listenToAllAWTEvents</code></td>
+ * <td>listen to system-wide AWT events</td>
+ * <td>malicious code can read passwords entered in an AWT event, and in
+ * combination with accessEventQueue, could fake system events</td></tr>
+ * <tr>
+ * <td><code>showWindowWithoutWarningBanner</code></td>
+ * <td>display a window without a banner notification of insecurity</td>
+ * <td>malicious code could install a Trojan horse applet that looks like
+ * a normal window, and thus steal data like passwords</td></tr>
+ * <tr>
+ * <td><code>readDisplayPixels</code></td>
+ * <td>read back pixels from the display screen</td>
+ * <td>malicious code could snoop on the user's actions</td></tr>
+ * <tr>
+ * <td><code>createRobot</code></td>
+ * <td>create an instance of java.awt.Robot</td>
+ * <td>these objects can generate events as though they were the user; so
+ * malicious code could control the system</td></tr>
+ * <tr>
+ * <td><code>fullScreenExclusive</code></td>
+ * <td>enter full-screen exclusive mode</td>
+ * <td>malicious code could masquerade as a trusted program</td></tr>
+ * </table>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class AWTPermission extends BasicPermission
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 8890392402588814465L;
+
+ /**
+ * Construct a AWTPermission with the given name.
+ *
+ * @param name the permission name
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException if name is invalid
+ */
+ public AWTPermission(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Create a new permission with the specified name. The actions argument
+ * is ignored, as AWT permissions have no actions.
+ *
+ * @param name the permission name
+ * @param actions ignored
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException if name is invalid
+ */
+ public AWTPermission(String name, String actions)
+ {
+ super(name);
+ }
+} // class AWTPermission
diff --git a/libjava/classpath/java/awt/ActiveEvent.java b/libjava/classpath/java/awt/ActiveEvent.java
new file mode 100644
index 00000000000..e42959fe3d6
--- /dev/null
+++ b/libjava/classpath/java/awt/ActiveEvent.java
@@ -0,0 +1,61 @@
+/* ActiveEvent.java -- a self-dispatching event
+ Copyright (C) 2000, 2002 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;
+
+/**
+ * An interface for events which can dispatch themselves in another thread.
+ * This has two uses: first, if your code is in a critical section, calling a
+ * synchronized method might deadlock. But by using an ActiveEvent to call
+ * the second section, it will not obtain the lock until you have left the
+ * critical section, avoiding deadlock. The second use is for calling
+ * untrusted code. For example, system code should use an ActiveEvent to
+ * invoke user code securely.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface ActiveEvent
+{
+ /**
+ * Dispatch the event, according to what the event needs done. Invoked
+ * automatically if this is placed on the <code>EventDispatchQueue</code>.
+ */
+ void dispatch();
+} // interface ActiveEvent
diff --git a/libjava/classpath/java/awt/Adjustable.java b/libjava/classpath/java/awt/Adjustable.java
new file mode 100644
index 00000000000..8f633e91a62
--- /dev/null
+++ b/libjava/classpath/java/awt/Adjustable.java
@@ -0,0 +1,171 @@
+/* Adjustable.java -- Objects with a numeric adjustment scale
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.AdjustmentListener;
+
+/**
+ * This interface is for objects that take a numeric value that can be
+ * adjusted within a bounded range. For example, a scroll bar.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface Adjustable
+{
+ /** Constant for an adjustable object with horizontal orientation. */
+ int HORIZONTAL = 0;
+
+ /** Constant for an adjustable object with vertical orientation. */
+ int VERTICAL = 1;
+
+ /** Constant for an adjustable object with no orientation. */
+ int NO_ORIENTATION = 2;
+
+ /**
+ * Returns a constant representing the orientation of the object.
+ *
+ * @return the orientation of this object
+ * @see #HORIZONTAL
+ * @see #VERTICAL
+ * @see #NO_ORIENTATION
+ */
+ int getOrientation();
+
+ /**
+ * Sets the minimum value this object can have.
+ *
+ * @param minimum the new minimum value
+ */
+ void setMinimum(int minimum);
+
+ /**
+ * Returns the minimum value this object can have.
+ *
+ * @return the minimum value
+ */
+ int getMinimum();
+
+ /**
+ * Sets the maximum value this object can have.
+ *
+ * @param maximum the new maximum value
+ */
+ void setMaximum(int maximum);
+
+ /**
+ * Returns the maximum value this object can have.
+ *
+ * @return the maximum value
+ */
+ int getMaximum();
+
+ /**
+ * Sets the increment value for incrementing the value by units.
+ *
+ * @param increment the unit increment value
+ */
+ void setUnitIncrement(int increment);
+
+ /**
+ * Returns the increment value for incrementing the value by units.
+ *
+ * @return the unit increment value
+ */
+ int getUnitIncrement();
+
+ /**
+ * Sets the increment value for incrementing the value by blocks.
+ *
+ * @param increment the block increment value
+ */
+ void setBlockIncrement(int increment);
+
+ /**
+ * Returns the increment value for incrementing the value by blocks.
+ *
+ * @return the block increment value
+ */
+ int getBlockIncrement();
+
+ /**
+ * Sets the length of the indicator for this object to the specified value.
+ *
+ * @param length the indicator length
+ */
+ void setVisibleAmount(int length);
+
+ /**
+ * Returns the length of the indicator for this object.
+ *
+ * @return the indicator length
+ */
+ int getVisibleAmount();
+
+ /**
+ * Sets the current value of the object.
+ *
+ * @param value the new value
+ */
+ void setValue(int value);
+
+ /**
+ * Returns the current value of the object.
+ *
+ * @return the current value
+ */
+ int getValue();
+
+ /**
+ * Adds a listener that will receive adjustment events for this object.
+ *
+ * @param listener the adjustment listener to add
+ * @see java.awt.event.AdjustmentEvent
+ */
+ void addAdjustmentListener(AdjustmentListener listener);
+
+ /**
+ * Removes an adjustment listener from this object.
+ *
+ * @param listener the adjustment listener to remove
+ * @see java.awt.event.AdjustmentEvent
+ */
+ void removeAdjustmentListener(AdjustmentListener listener);
+} // interface Adjustable
diff --git a/libjava/classpath/java/awt/AlphaComposite.java b/libjava/classpath/java/awt/AlphaComposite.java
new file mode 100644
index 00000000000..435cfd054c3
--- /dev/null
+++ b/libjava/classpath/java/awt/AlphaComposite.java
@@ -0,0 +1,167 @@
+/* AlphaComposite.java -- provides a context for performing alpha compositing
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ColorModel;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Composite
+ * @see CompositeContext
+ * @since 1.3
+ * @status updated to 1.4 except for createContext, needs documentation
+ */
+public final class AlphaComposite implements Composite
+{
+ /** Map Long to AlphaComposites. See getInstance for details. */
+ private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true)
+ {
+ /** The largest the alpha composite cache can grow. */
+ private static final int MAX_CACHE_SIZE = 2048;
+
+ /** Prune stale entries. */
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ { // XXX - FIXME Use Map.Entry, not just Entry as gcj 3.1 workaround.
+ return size() > MAX_CACHE_SIZE;
+ }
+ };
+
+ public static final int CLEAR = 1;
+ public static final int SRC = 2;
+ public static final int DST = 9;
+ public static final int SRC_OVER = 3;
+ public static final int DST_OVER = 4;
+ public static final int SRC_IN = 5;
+ public static final int DST_IN = 6;
+ public static final int SRC_OUT = 7;
+ public static final int DST_OUT = 8;
+ public static final int SRC_ATOP = 10;
+ public static final int DST_ATOP = 11;
+ public static final int XOR = 12;
+ public static final AlphaComposite Clear = getInstance(CLEAR);
+ public static final AlphaComposite Src = getInstance(SRC);
+ public static final AlphaComposite Dst = getInstance(DST);
+ public static final AlphaComposite SrcOver = getInstance(SRC_OVER);
+ public static final AlphaComposite DstOver = getInstance(DST_OVER);
+ public static final AlphaComposite SrcIn = getInstance(SRC_IN);
+ public static final AlphaComposite DstIn = getInstance(DST_IN);
+ public static final AlphaComposite SrcOut = getInstance(SRC_OUT);
+ public static final AlphaComposite DstOut = getInstance(DST_OUT);
+ public static final AlphaComposite SrcAtop = getInstance(SRC_ATOP);
+ public static final AlphaComposite DstAtop = getInstance(DST_ATOP);
+ public static final AlphaComposite Xor = getInstance(XOR);
+
+ private final int rule;
+ private final float alpha;
+ private AlphaComposite(int rule, float alpha)
+ {
+ this.rule = rule;
+ this.alpha = alpha;
+ }
+
+ /**
+ * Creates an AlphaComposite object with the specified rule.
+ *
+ * @param rule The compositing rule.
+ *
+ * @exception IllegalArgumentException If rule is not one of the following:
+ * CLEAR, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT,
+ * SRC_ATOP, DST_ATOP, or XOR.
+ */
+ public static AlphaComposite getInstance(int rule)
+ {
+ return getInstance(rule, 1);
+ }
+
+ /**
+ * Creates an AlphaComposite object with the specified rule and the constant
+ * alpha to multiply with the alpha of the source. The source is multiplied
+ * with the specified alpha before being composited with the destination.
+ *
+ * @param rule The compositing rule.
+ *
+ * @exception IllegalArgumentException If rule is not one of the following:
+ * CLEAR, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT,
+ * SRC_ATOP, DST_ATOP, or XOR.
+ */
+ public static AlphaComposite getInstance(int rule, float alpha)
+ {
+ if (rule < CLEAR || rule > XOR || ! (alpha >= 0 && alpha <= 1))
+ throw new IllegalArgumentException();
+ // This long is guaranteed unique for all valid alpha composites.
+ Long l = new Long(rule + Double.doubleToLongBits(alpha));
+ AlphaComposite a = (AlphaComposite) cache.get(l);
+ if (a == null)
+ {
+ a = new AlphaComposite(rule, alpha);
+ cache.put(l, a);
+ }
+ return a;
+ }
+ public CompositeContext createContext(ColorModel srcColorModel,
+ ColorModel dstColorModel,
+ RenderingHints hints)
+ {
+ // XXX Implement. Sun uses undocumented implementation class
+ // sun.java2d.SunCompositeContext.
+ throw new Error("not implemented");
+ }
+ public float getAlpha()
+ {
+ return alpha;
+ }
+ public int getRule()
+ {
+ return rule;
+ }
+ public int hashCode()
+ {
+ return 31 * Float.floatToIntBits(alpha) + rule;
+ }
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof AlphaComposite))
+ return false;
+ AlphaComposite a = (AlphaComposite) o;
+ return rule == a.rule && alpha == a.alpha;
+ }
+} // class AlphaComposite
diff --git a/libjava/classpath/java/awt/AttributeValue.java b/libjava/classpath/java/awt/AttributeValue.java
new file mode 100644
index 00000000000..080e92e221f
--- /dev/null
+++ b/libjava/classpath/java/awt/AttributeValue.java
@@ -0,0 +1,98 @@
+/* AttributeValue.java -- parent of type-safe enums of attributes
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class is undocumented by Sun, but it is the parent of several other
+ * classes, all of which are type-safe enumerations. This takes care of
+ * <code>equals</code>, <code>toString</code>, and <code>hashCode</code>, so
+ * that you don't have to (although hashCode is commonly overridden).
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+class AttributeValue
+{
+ /** The value of the enumeration. Package visible for speed. */
+ final int value;
+
+ /** The list of enumeration names for the given subclass. */
+ private final String[] names;
+
+ /**
+ * Construct a type-safe enumeration element. For example,<br>
+ * <pre>
+ * class Foo extends AttributeValue
+ * {
+ * private static final String[] names = { "one", "two" }
+ * public static final Foo ONE = new Foo(0);
+ * public static final Foo TWO = new Foo(1);
+ * private Foo(int value) { super(value, names); }
+ * }
+ * </pre>
+ *
+ * @param value the position of this enumeration element, consecutive from 0
+ * @param names the constant list of enumeration names for the subclass
+ */
+ AttributeValue(int value, String[] names)
+ {
+ this.value = value;
+ this.names = names;
+ }
+
+ /**
+ * Returns the hashcode of this element. This is the index of the element
+ * in the enumeration. Note that equals defaults to the == relation.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the name of this enumeration element.
+ *
+ * @return the element name
+ */
+ public String toString()
+ {
+ return names[value];
+ }
+} // class AttributeValue
diff --git a/libjava/classpath/java/awt/BasicStroke.java b/libjava/classpath/java/awt/BasicStroke.java
new file mode 100644
index 00000000000..bb008e4c791
--- /dev/null
+++ b/libjava/classpath/java/awt/BasicStroke.java
@@ -0,0 +1,248 @@
+/* BasicStroke.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.util.Arrays;
+
+/**
+ * STUB CLASS ONLY
+ */
+public class BasicStroke implements Stroke
+{
+ public static final int JOIN_MITER = 0;
+ public static final int JOIN_ROUND = 1;
+ public static final int JOIN_BEVEL = 2;
+
+ public static final int CAP_BUTT = 0;
+ public static final int CAP_ROUND = 1;
+ public static final int CAP_SQUARE = 2;
+
+ private final float width;
+ private final int cap;
+ private final int join;
+ private final float limit;
+ private final float[] dash;
+ private final float phase;
+
+ /**
+ * Creates a basic stroke.
+ *
+ * @param width May not be negative .
+ * @param cap May be either CAP_BUTT, CAP_ROUND or CAP_SQUARE.
+ * @param join May be either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER.
+ * @param miterlimit the limit to trim the miter join. The miterlimit must be
+ * greater than or equal to 1.0f.
+ * @param dash The array representing the dashing pattern. There must be at
+ * least one non-zero entry.
+ * @param dashPhase is negative and dash is not null.
+ *
+ * @exception IllegalArgumentException If one input parameter doesn't meet
+ * its needs.
+ */
+ public BasicStroke(float width, int cap, int join, float miterlimit,
+ float[] dash, float dashPhase)
+ {
+ if (width < 0.0f )
+ throw new IllegalArgumentException("width " + width + " < 0");
+ else if (cap < CAP_BUTT || cap > CAP_SQUARE)
+ throw new IllegalArgumentException("cap " + cap + " out of range ["
+ + CAP_BUTT + ".." + CAP_SQUARE + "]");
+ else if (miterlimit < 1.0f && join == JOIN_MITER)
+ throw new IllegalArgumentException("miterlimit " + miterlimit
+ + " < 1.0f while join == JOIN_MITER");
+ else if (join < JOIN_MITER || join > JOIN_BEVEL)
+ throw new IllegalArgumentException("join " + join + " out of range ["
+ + JOIN_MITER + ".." + JOIN_BEVEL
+ + "]");
+ else if (dashPhase < 0.0f && dash != null)
+ throw new IllegalArgumentException("dashPhase " + dashPhase
+ + " < 0.0f while dash != null");
+ else if (dash != null)
+ if (dash.length == 0)
+ throw new IllegalArgumentException("dash.length is 0");
+ else
+ {
+ boolean allZero = true;
+
+ for ( int i = 0; i < dash.length; ++i)
+ {
+ if (dash[i] != 0.0f)
+ {
+ allZero = false;
+ break;
+ }
+ }
+
+ if (allZero)
+ throw new IllegalArgumentException("all dashes are 0.0f");
+ }
+
+ this.width = width;
+ this.cap = cap;
+ this.join = join;
+ limit = miterlimit;
+ this.dash = dash == null ? null : (float[]) dash.clone();
+ phase = dashPhase;
+ }
+
+ /**
+ * Creates a basic stroke.
+ *
+ * @param width The width of the BasicStroke. May not be negative .
+ * @param cap May be either CAP_BUTT, CAP_ROUND or CAP_SQUARE.
+ * @param join May be either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER.
+ * @param miterlimit the limit to trim the miter join. The miterlimit must be
+ * greater than or equal to 1.0f.
+ *
+ * @exception IllegalArgumentException If one input parameter doesn't meet
+ * its needs.
+ */
+ public BasicStroke(float width, int cap, int join, float miterlimit)
+ {
+ this(width, cap, join, miterlimit, null, 0);
+ }
+
+ /**
+ * Creates a basic stroke.
+ *
+ * @param width The width of the BasicStroke. May not be nehative.
+ * @param cap May be either CAP_BUTT, CAP_ROUND or CAP_SQUARE.
+ * @param join May be either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER.
+ *
+ * @exception IllegalArgumentException If one input parameter doesn't meet
+ * its needs.
+ * @exception IllegalArgumentException FIXME
+ */
+ public BasicStroke(float width, int cap, int join)
+ {
+ this(width, cap, join, 10, null, 0);
+ }
+
+ /**
+ * Creates a basic stroke.
+ *
+ * @param width The width of the BasicStroke.
+ *
+ * @exception IllegalArgumentException If width is negative.
+ */
+ public BasicStroke(float width)
+ {
+ this(width, CAP_SQUARE, JOIN_MITER, 10, null, 0);
+ }
+
+ /**
+ * Creates a basic stroke.
+ */
+ public BasicStroke()
+ {
+ this(1, CAP_SQUARE, JOIN_MITER, 10, null, 0);
+ }
+
+ public Shape createStrokedShape(Shape s)
+ {
+ throw new Error("not implemented");
+ }
+
+ public float getLineWidth()
+ {
+ return width;
+ }
+
+ public int getEndCap()
+ {
+ return cap;
+ }
+
+ public int getLineJoin()
+ {
+ return join;
+ }
+
+ public float getMiterLimit()
+ {
+ return limit;
+ }
+
+ public float[] getDashArray()
+ {
+ return dash;
+ }
+
+ public float getDashPhase()
+ {
+ return phase;
+ }
+
+ /**
+ * Returns the hash code for this object. The hash is calculated by
+ * xoring the hash, cap, join, limit, dash array and phase values
+ * (converted to <code>int</code> first with
+ * <code>Float.floatToIntBits()</code> if the value is a
+ * <code>float</code>).
+ */
+ public int hashCode()
+ {
+ int hash = Float.floatToIntBits(width);
+ hash ^= cap;
+ hash ^= join;
+ hash ^= Float.floatToIntBits(limit);
+
+ if (dash != null)
+ for (int i = 0; i < dash.length; i++)
+ hash ^= Float.floatToIntBits(dash[i]);
+
+ hash ^= Float.floatToIntBits(phase);
+
+ return hash;
+ }
+
+ /**
+ * Returns true if the given Object is an instance of BasicStroke
+ * and the width, cap, join, limit, dash array and phase are all
+ * equal.
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof BasicStroke))
+ return false;
+ BasicStroke s = (BasicStroke) o;
+ return width == s.width && cap == s.cap && join == s.join
+ && limit == s.limit && Arrays.equals(dash, s.dash) && phase == s.phase;
+ }
+} // class BasicStroke
diff --git a/libjava/classpath/java/awt/BorderLayout.java b/libjava/classpath/java/awt/BorderLayout.java
new file mode 100644
index 00000000000..c9eb5dd8c37
--- /dev/null
+++ b/libjava/classpath/java/awt/BorderLayout.java
@@ -0,0 +1,731 @@
+/* BorderLayout.java -- A layout manager class
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class implements a layout manager that positions components
+ * in certain sectors of the parent container.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class BorderLayout implements LayoutManager2, java.io.Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * Constant indicating the top of the container
+ */
+public static final String NORTH = "North";
+
+/**
+ * Constant indicating the bottom of the container
+ */
+public static final String SOUTH = "South";
+
+/**
+ * Constant indicating the right side of the container
+ */
+public static final String EAST = "East";
+
+/**
+ * Constant indicating the left side of the container
+ */
+public static final String WEST = "West";
+
+/**
+ * Constant indicating the center of the container
+ */
+public static final String CENTER = "Center";
+
+
+ /**
+ * The constant indicating the position before the first line of the
+ * layout. The exact position depends on the writing system: For a
+ * top-to-bottom orientation, it is the same as {@link #NORTH}, for
+ * a bottom-to-top orientation, it is the same as {@link #SOUTH}.
+ *
+ * <p>This constant is an older name for {@link #PAGE_START} which
+ * has exactly the same value.
+ *
+ * @since 1.2
+ */
+ public static final String BEFORE_FIRST_LINE = "First";
+
+
+ /**
+ * The constant indicating the position after the last line of the
+ * layout. The exact position depends on the writing system: For a
+ * top-to-bottom orientation, it is the same as {@link #SOUTH}, for
+ * a bottom-to-top orientation, it is the same as {@link #NORTH}.
+ *
+ * <p>This constant is an older name for {@link #PAGE_END} which
+ * has exactly the same value.
+ *
+ * @since 1.2
+ */
+ public static final String AFTER_LAST_LINE = "Last";
+
+
+ /**
+ * The constant indicating the position before the first item of the
+ * layout. The exact position depends on the writing system: For a
+ * left-to-right orientation, it is the same as {@link #WEST}, for
+ * a right-to-left orientation, it is the same as {@link #EAST}.
+ *
+ * <p>This constant is an older name for {@link #LINE_START} which
+ * has exactly the same value.
+ *
+ * @since 1.2
+ */
+ public static final String BEFORE_LINE_BEGINS = "Before";
+
+
+ /**
+ * The constant indicating the position after the last item of the
+ * layout. The exact position depends on the writing system: For a
+ * left-to-right orientation, it is the same as {@link #EAST}, for
+ * a right-to-left orientation, it is the same as {@link #WEST}.
+ *
+ * <p>This constant is an older name for {@link #LINE_END} which
+ * has exactly the same value.
+ *
+ * @since 1.2
+ */
+ public static final String AFTER_LINE_ENDS = "After";
+
+
+ /**
+ * The constant indicating the position before the first line of the
+ * layout. The exact position depends on the writing system: For a
+ * top-to-bottom orientation, it is the same as {@link #NORTH}, for
+ * a bottom-to-top orientation, it is the same as {@link #SOUTH}.
+ *
+ * @since 1.4
+ */
+ public static final String PAGE_START = BEFORE_FIRST_LINE;
+
+
+ /**
+ * The constant indicating the position after the last line of the
+ * layout. The exact position depends on the writing system: For a
+ * top-to-bottom orientation, it is the same as {@link #SOUTH}, for
+ * a bottom-to-top orientation, it is the same as {@link #NORTH}.
+ *
+ * @since 1.4
+ */
+ public static final String PAGE_END = AFTER_LAST_LINE;
+
+
+ /**
+ * The constant indicating the position before the first item of the
+ * layout. The exact position depends on the writing system: For a
+ * left-to-right orientation, it is the same as {@link #WEST}, for
+ * a right-to-left orientation, it is the same as {@link #EAST}.
+ *
+ * @since 1.4
+ */
+ public static final String LINE_START = BEFORE_LINE_BEGINS;
+
+
+ /**
+ * The constant indicating the position after the last item of the
+ * layout. The exact position depends on the writing system: For a
+ * left-to-right orientation, it is the same as {@link #EAST}, for
+ * a right-to-left orientation, it is the same as {@link #WEST}.
+ *
+ * @since 1.4
+ */
+ public static final String LINE_END = AFTER_LINE_ENDS;
+
+
+
+// Serialization constant
+private static final long serialVersionUID = -8658291919501921765L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial
+ */
+private Component north;
+
+/**
+ * @serial
+ */
+private Component south;
+
+/**
+ * @serial
+ */
+private Component east;
+
+/**
+ * @serial
+ */
+private Component west;
+
+/**
+ * @serial
+ */
+private Component center;
+
+/**
+ * @serial
+ */
+private Component firstLine;
+
+/**
+ * @serial
+ */
+private Component lastLine;
+
+/**
+ * @serial
+ */
+private Component firstItem;
+
+/**
+ * @serial
+ */
+private Component lastItem;
+
+/**
+ * @serial The horizontal gap between components
+ */
+private int hgap;
+
+/**
+ * @serial The vertical gap between components
+ */
+private int vgap;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>BorderLayout</code> with no
+ * horiztonal or vertical gaps between components.
+ */
+public
+BorderLayout()
+{
+ this(0,0);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>BorderLayout</code> with the
+ * specified horiztonal and vertical gaps between components.
+ *
+ * @param hgap The horizontal gap between components.
+ * @param vgap The vertical gap between components.
+ */
+public
+BorderLayout(int hgap, int vgap)
+{
+ this.hgap = hgap;
+ this.vgap = vgap;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the horitzontal gap value.
+ *
+ * @return The horitzontal gap value.
+ */
+public int
+getHgap()
+{
+ return(hgap);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the horizontal gap to the specified value.
+ *
+ * @param hgap The new horizontal gap.
+ */
+public void
+setHgap(int hgap)
+{
+ this.hgap = hgap;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the vertical gap value.
+ *
+ * @return The vertical gap value.
+ */
+public int
+getVgap()
+{
+ return(vgap);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the vertical gap to the specified value.
+ *
+ * @param vgap The new vertical gap value.
+ */
+public void
+setVgap(int vgap)
+{
+ this.vgap = vgap;
+}
+
+/*************************************************************************/
+
+/**
+ * Adds a component to the layout in the specified constraint position,
+ * which must be one of the string constants defined in this class.
+ *
+ * @param component The component to add.
+ * @param constraints The constraint string.
+ *
+ * @exception IllegalArgumentException If the constraint object is not
+ * a string, or is not one of the specified constants in this class.
+ */
+public void
+addLayoutComponent(Component component, Object constraints)
+{
+ if (constraints != null && ! (constraints instanceof String))
+ throw new IllegalArgumentException("Constraint must be a string");
+
+ addLayoutComponent((String) constraints, component);
+}
+
+/*************************************************************************/
+
+/**
+ * Adds a component to the layout in the specified constraint position,
+ * which must be one of the string constants defined in this class.
+ *
+ * @param constraints The constraint string.
+ * @param component The component to add.
+ *
+ * @exception IllegalArgumentException If the constraint object is not
+ * one of the specified constants in this class.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>addLayoutComponent(Component, Object)</code>.
+ */
+public void
+addLayoutComponent(String constraints, Component component)
+{
+ String str = constraints;
+
+ if (str == null || str.equals(CENTER))
+ center = component;
+ else if (str.equals(NORTH))
+ north = component;
+ else if (str.equals(SOUTH))
+ south = component;
+ else if (str.equals(EAST))
+ east = component;
+ else if (str.equals(WEST))
+ west = component;
+ else if (str.equals(BEFORE_FIRST_LINE))
+ firstLine = component;
+ else if (str.equals(AFTER_LAST_LINE))
+ lastLine = component;
+ else if (str.equals(BEFORE_LINE_BEGINS))
+ firstItem = component;
+ else if (str.equals(AFTER_LINE_ENDS))
+ lastItem = component;
+ else
+ throw new IllegalArgumentException("Constraint value not valid: " + str);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified component from the layout.
+ *
+ * @param component The component to remove from the layout.
+ */
+public void
+removeLayoutComponent(Component component)
+{
+ if (north == component)
+ north = null;
+ if (south == component)
+ south = null;
+ if (east == component)
+ east = null;
+ if (west == component)
+ west = null;
+ if (center == component)
+ center = null;
+ if (firstItem == component)
+ firstItem = null;
+ if (lastItem == component)
+ lastItem = null;
+ if (firstLine == component)
+ firstLine = null;
+ if (lastLine == component)
+ lastLine = null;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size of the specified container using this layout.
+ *
+ * @param target The container to calculate the minimum size for.
+ *
+ * @return The minimum size of the container
+ */
+public Dimension
+minimumLayoutSize(Container target)
+{
+ return calcSize(target, MIN);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size of the specified container using this layout.
+ *
+ * @param target The container to calculate the preferred size for.
+ *
+ * @return The preferred size of the container
+ */
+public Dimension
+preferredLayoutSize(Container target)
+{
+ return calcSize(target, PREF);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the maximum size of the specified container using this layout.
+ *
+ * @param target The container to calculate the maximum size for.
+ *
+ * @return The maximum size of the container
+ */
+public Dimension
+maximumLayoutSize(Container target)
+{
+ return calcSize(target, MAX);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the X axis alignment, which is a <code>float</code> indicating
+ * where along the X axis this container wishs to position its layout.
+ * 0 indicates align to the left, 1 indicates align to the right, and 0.5
+ * indicates align to the center.
+ *
+ * @param parent The parent container.
+ *
+ * @return The X alignment value.
+ */
+public float
+getLayoutAlignmentX(Container parent)
+{
+ return(parent.getAlignmentX());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the Y axis alignment, which is a <code>float</code> indicating
+ * where along the Y axis this container wishs to position its layout.
+ * 0 indicates align to the top, 1 indicates align to the bottom, and 0.5
+ * indicates align to the center.
+ *
+ * @param parent The parent container.
+ *
+ * @return The Y alignment value.
+ */
+public float
+getLayoutAlignmentY(Container parent)
+{
+ return(parent.getAlignmentY());
+}
+
+/*************************************************************************/
+
+/**
+ * Instructs this object to discard any layout information it might
+ * have cached.
+ *
+ * @param parent The parent container.
+ */
+public void
+invalidateLayout(Container parent)
+{
+}
+
+/*************************************************************************/
+
+/**
+ * Lays out the specified container according to the constraints
+ * in this object.
+ *
+ * @param target The container to lay out.
+ */
+public void
+layoutContainer(Container target)
+{
+ synchronized (target.getTreeLock ())
+ {
+ Insets i = target.getInsets();
+
+ ComponentOrientation orient = target.getComponentOrientation ();
+ boolean left_to_right = orient.isLeftToRight ();
+
+ Component my_north = north;
+ Component my_east = east;
+ Component my_south = south;
+ Component my_west = west;
+
+ // Note that we currently don't handle vertical layouts. Neither
+ // does JDK 1.3.
+ if (firstLine != null)
+ my_north = firstLine;
+ if (lastLine != null)
+ my_south = lastLine;
+ if (firstItem != null)
+ {
+ if (left_to_right)
+ my_west = firstItem;
+ else
+ my_east = firstItem;
+ }
+ if (lastItem != null)
+ {
+ if (left_to_right)
+ my_east = lastItem;
+ else
+ my_west = lastItem;
+ }
+
+ Dimension c = calcCompSize(center, PREF);
+ Dimension n = calcCompSize(my_north, PREF);
+ Dimension s = calcCompSize(my_south, PREF);
+ Dimension e = calcCompSize(my_east, PREF);
+ Dimension w = calcCompSize(my_west, PREF);
+ Dimension t = target.getSize();
+
+ /*
+ <-> hgap <-> hgap
+ +----------------------------+ }
+ |t | } i.top
+ | +----------------------+ | --- y1 }
+ | |n | |
+ | +----------------------+ | } vgap
+ | +---+ +----------+ +---+ | --- y2 } }
+ | |w | |c | |e | | } hh
+ | +---+ +----------+ +---+ | } vgap }
+ | +----------------------+ | --- y3 }
+ | |s | |
+ | +----------------------+ | }
+ | | } i.bottom
+ +----------------------------+ }
+ |x1 |x2 |x3
+ <---------------------->
+ <--> ww <-->
+ i.left i.right
+ */
+
+ int x1 = i.left;
+ int x2 = x1 + w.width + hgap;
+ int x3;
+ if (t.width <= i.right + e.width)
+ x3 = x2 + w.width + hgap;
+ else
+ x3 = t.width - i.right - e.width;
+ int ww = t.width - i.right - i.left;
+
+ int y1 = i.top;
+ int y2 = y1 + n.height + vgap;
+ int midh = Math.max(e.height, Math.max(w.height, c.height));
+ int y3;
+ if (t.height <= i.bottom + s.height)
+ y3 = y2 + midh + vgap;
+ else
+ y3 = t.height - i.bottom - s.height;
+ int hh = y3-y2-vgap;
+
+ setBounds(center, x2, y2, x3-x2-hgap, hh);
+ setBounds(my_north, x1, y1, ww, n.height);
+ setBounds(my_south, x1, y3, ww, s.height);
+ setBounds(my_west, x1, y2, w.width, hh);
+ setBounds(my_east, x3, y2, e.width, hh);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this layout manager.
+ *
+ * @return A string representation of this object.
+ */
+public String
+toString()
+{
+ return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
+}
+
+private void
+setBounds(Component comp, int x, int y, int w, int h)
+{
+ if (comp == null)
+ return;
+ comp.setBounds(x, y, w, h);
+}
+
+// Some constants for use with calcSize().
+private static final int MIN = 0;
+private static final int MAX = 1;
+private static final int PREF = 2;
+
+private Dimension
+calcCompSize(Component comp, int what)
+{
+ if (comp == null || !comp.isVisible())
+ return new Dimension(0, 0);
+ if (what == MIN)
+ return comp.getMinimumSize();
+ else if (what == MAX)
+ return comp.getMaximumSize();
+ return comp.getPreferredSize();
+}
+
+// This is a helper function used to compute the various sizes for
+// this layout.
+private Dimension
+calcSize(Container target, int what)
+{
+ synchronized (target.getTreeLock ())
+ {
+ Insets ins = target.getInsets();
+
+ ComponentOrientation orient = target.getComponentOrientation ();
+ boolean left_to_right = orient.isLeftToRight ();
+
+ Component my_north = north;
+ Component my_east = east;
+ Component my_south = south;
+ Component my_west = west;
+
+ // Note that we currently don't handle vertical layouts. Neither
+ // does JDK 1.3.
+ if (firstLine != null)
+ my_north = firstLine;
+ if (lastLine != null)
+ my_south = lastLine;
+ if (firstItem != null)
+ {
+ if (left_to_right)
+ my_west = firstItem;
+ else
+ my_east = firstItem;
+ }
+ if (lastItem != null)
+ {
+ if (left_to_right)
+ my_east = lastItem;
+ else
+ my_west = lastItem;
+ }
+
+ Dimension ndim = calcCompSize(my_north, what);
+ Dimension sdim = calcCompSize(my_south, what);
+ Dimension edim = calcCompSize(my_east, what);
+ Dimension wdim = calcCompSize(my_west, what);
+ Dimension cdim = calcCompSize(center, what);
+
+ int width = edim.width + cdim.width + wdim.width + (hgap * 2);
+ // check for overflow
+ if (width < edim.width || width < cdim.width || width < cdim.width)
+ width = Integer.MAX_VALUE;
+
+ if (ndim.width > width)
+ width = ndim.width;
+ if (sdim.width > width)
+ width = sdim.width;
+
+ width += (ins.left + ins.right);
+
+ int height = edim.height;
+ if (cdim.height > height)
+ height = cdim.height;
+ if (wdim.height > height)
+ height = wdim.height;
+
+ int addedHeight = height + (ndim.height + sdim.height + (vgap * 2)
+ + ins.top + ins.bottom);
+ // check for overflow
+ if (addedHeight < height)
+ height = Integer.MAX_VALUE;
+ else
+ height = addedHeight;
+
+ return(new Dimension(width, height));
+ }
+}
+} // class BorderLayout
diff --git a/libjava/classpath/java/awt/BufferCapabilities.java b/libjava/classpath/java/awt/BufferCapabilities.java
new file mode 100644
index 00000000000..bba83dcb0d9
--- /dev/null
+++ b/libjava/classpath/java/awt/BufferCapabilities.java
@@ -0,0 +1,253 @@
+/* BufferCapabilities.java -- double-buffering capabilities descriptor
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.BufferStrategy;
+
+/**
+ * A double-buffering capability descriptor. This class exposes
+ * details about the double-buffering algorithms used by image
+ * buffers.
+ *
+ * BufferCapabilities represents algorithms that involve at least two
+ * buffers but it can also specify so-called "multi-buffer" schemes
+ * involving more than two buffers. This class describes the
+ * capabilities of the front and back buffers as well as the results
+ * of "flipping" -- that is, what happens when an image is transferred
+ * from the back buffer to the front buffer.
+ *
+ * Flipping may or may not be supported or may be supported only in
+ * fullscreen mode. If it is not supported then "blitting" is implied
+ * -- that is, the contents of the back buffer are copied using a fast
+ * block transfer operation from the back buffer to the front buffer.
+ *
+ * The front buffer is the one that is displayed.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @see BufferStrategy#getCapabilities()
+ * @see GraphicsConfiguration#getBufferCapabilities()
+ *
+ * @since 1.4
+ */
+public class BufferCapabilities implements Cloneable
+{
+ /**
+ * A type-safe enumeration of buffer flipping results.
+ *
+ * @see AttributeValue
+ */
+ public static final class FlipContents extends AttributeValue
+ {
+ /**
+ * The names of the different flipping results.
+ */
+ private static final String[] NAMES
+ = { "undefined", "background", "prior", "copied" };
+
+ /**
+ * The contents of the back buffer are undefined after flipping.
+ */
+ public static final FlipContents UNDEFINED = new FlipContents(0);
+
+ /**
+ * The back buffer is cleared with the background color after
+ * flipping.
+ */
+ public static final FlipContents BACKGROUND = new FlipContents(1);
+
+ /**
+ * The back buffer contains the pre-flipping contents of the front
+ * buffer after flipping. In other words a true "flip" has been
+ * performed.
+ */
+ public static final FlipContents PRIOR = new FlipContents(2);
+
+ /**
+ * The back buffer has the same contents as the front buffer after
+ * flipping.
+ */
+ public static final FlipContents COPIED = new FlipContents(3);
+
+ /**
+ * Create a new flipping result descriptor.
+ *
+ * @param value the enumeration value
+ */
+ private FlipContents(int value)
+ {
+ super(value, NAMES);
+ }
+ }
+
+ /**
+ * Front buffer capabilities descriptor.
+ */
+ private final ImageCapabilities front;
+
+ /**
+ * Back buffer capabilities descriptor.
+ */
+ private final ImageCapabilities back;
+
+ /**
+ * Describes the results of a "flip" operation.
+ */
+ private final FlipContents flip;
+
+ /**
+ * Creates a buffer capabilities object.
+ *
+ * @param frontCaps front buffer capabilities descriptor
+ * @param backCaps back buffer capabilities descriptor
+ * @param flip the results of a flip operation or null if
+ * flipping is not supported
+ *
+ * @exception IllegalArgumentException if frontCaps or backCaps is
+ * null
+ */
+ public BufferCapabilities(ImageCapabilities frontCaps,
+ ImageCapabilities backCaps,
+ FlipContents flip)
+ {
+ if (frontCaps == null || backCaps == null)
+ throw new IllegalArgumentException();
+ this.front = frontCaps;
+ this.back = backCaps;
+ this.flip = flip;
+ }
+
+ /**
+ * Retrieve the front buffer's image capabilities.
+ *
+ * @return the front buffer's image capabilities
+ */
+ public ImageCapabilities getFrontBufferCapabilities()
+ {
+ return front;
+ }
+
+ /**
+ * Retrieve the back buffer's image capabilities.
+ *
+ * @return the back buffer's image capabilities
+ */
+ public ImageCapabilities getBackBufferCapabilities()
+ {
+ return back;
+ }
+
+ /**
+ * Return whether or not flipping is supported.
+ *
+ * @return true if flipping is supported, false otherwise
+ */
+ public boolean isPageFlipping()
+ {
+ return flip != null;
+ }
+
+ /**
+ * Retrieve the result of a flipping operation. If this method
+ * returns null then flipping is not supported. This implies that
+ * "blitting", a fast block transfer, is used to copy the contents
+ * of the back buffer to the front buffer. Other possible return
+ * values are:
+ * <ul>
+ * <li><code>FlipContents.UNDEFINED</code> the contents of the
+ * back buffer are undefined after flipping.</li>
+ * <li><code>FlipContents.BACKGROUND</code> the contents of the
+ * back buffer are cleared to the background color after
+ * flipping.</li>
+ * <li><code>FlipContents.PRIOR</code> the back buffer contains
+ * the pre-flipping contents of the front * buffer after
+ * flipping.</li>
+ * <li><code>FlipContents.COPIED</code> the back buffer has the
+ * same contents as the front buffer after flipping.</li>
+ * </ul>
+ *
+ * @return the result of a flipping operation or null if flipping is
+ * not supported
+ */
+ public FlipContents getFlipContents()
+ {
+ return flip;
+ }
+
+ /**
+ * Returns true if flipping is only supported in fullscreen mode.
+ *
+ * @return true if flipping is only supported in fullscreen mode,
+ * false otherwise
+ */
+ public boolean isFullScreenRequired()
+ {
+ return true;
+ }
+
+ /**
+ * Returns true if flipping can involve more than two buffers. One
+ * or more intermediate buffers may be available in addition to the
+ * front and back buffers.
+ *
+ * @return true if there are more than two buffers available for
+ * flipping, false otherwise
+ */
+ public boolean isMultiBufferAvailable()
+ {
+ return false;
+ }
+
+ /**
+ * Clone this buffering capability descriptor.
+ *
+ * @return a clone of this buffer capability descriptor
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/Button.java b/libjava/classpath/java/awt/Button.java
new file mode 100644
index 00000000000..90be1e5b111
--- /dev/null
+++ b/libjava/classpath/java/awt/Button.java
@@ -0,0 +1,466 @@
+/* Button.java -- AWT button widget
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.ButtonPeer;
+import java.lang.reflect.Array;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class provides a button widget for the AWT.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class Button extends Component
+ implements java.io.Serializable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+// FIXME: Need readObject/writeObject for serialization
+
+// Serialization version constant
+private static final long serialVersionUID = -8774683716313001058L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The action command name for this button.
+ * This is package-private to avoid an accessor method.
+ */
+String actionCommand;
+
+/**
+ * @serial The label for this button.
+ * This is package-private to avoid an accessor method.
+ */
+String label;
+
+// List of ActionListeners for this class.
+private transient ActionListener action_listeners;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_button_number;
+
+ protected class AccessibleAWTButton extends AccessibleAWTComponent
+ implements AccessibleAction, AccessibleValue
+ {
+ protected AccessibleAWTButton()
+ {
+ // Do nothing here.
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
+ */
+ public int getAccessibleActionCount()
+ {
+ // Only 1 action possible
+ return 1;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ // JDK 1.4.2 returns the string "click" for action 0. However, the API
+ // docs don't say what the string to be returned is, beyond being a
+ // description of the action. So we return the same thing for
+ // compatibility with 1.4.2.
+ if (i == 0)
+ return "click";
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ if (i != 0)
+ return false;
+ processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand));
+ return true;
+ }
+
+ public String getAccessibleName()
+ {
+ return label;
+ }
+
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ public AccessibleValue getAccessibleValue()
+ {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
+ */
+ public Number getCurrentAccessibleValue()
+ {
+ // Docs say return 1 if selected, but buttons can't be selected, right?
+ return new Integer(0);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
+ */
+ public boolean setCurrentAccessibleValue(Number number)
+ {
+ // Since there's no selection with buttons, we're ignoring this.
+ // TODO someone who knows shoulw check this.
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
+ */
+ public Number getMinimumAccessibleValue()
+ {
+ return new Integer(0);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
+ */
+ public Number getMaximumAccessibleValue()
+ {
+ return new Integer(0);
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.PUSH_BUTTON;
+ }
+ }
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>Button</code> with no label.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true
+ */
+public
+Button()
+{
+ this("");
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Button</code> with the specified
+ * label. The action command name is also initialized to this value.
+ *
+ * @param label The label to display on the button.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true
+ */
+public
+Button(String label)
+{
+ this.label = label;
+ actionCommand = label;
+
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the label for this button.
+ *
+ * @return The label for this button.
+ */
+public String
+getLabel()
+{
+ return(label);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the label for this button to the specified value.
+ *
+ * @param label The new label for this button.
+ */
+public synchronized void
+setLabel(String label)
+{
+ this.label = label;
+ actionCommand = label;
+ if (peer != null)
+ {
+ ButtonPeer bp = (ButtonPeer) peer;
+ bp.setLabel (label);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the action command name for this button.
+ *
+ * @return The action command name for this button.
+ */
+public String
+getActionCommand()
+{
+ return(actionCommand);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the action command name for this button to the specified value.
+ *
+ * @param actionCommand The new action command name.
+ */
+public void
+setActionCommand(String actionCommand)
+{
+ this.actionCommand = actionCommand == null ? label : actionCommand;
+}
+
+/*************************************************************************/
+
+/**
+ * Adds a new entry to the list of listeners that will receive
+ * action events from this button.
+ *
+ * @param listener The listener to add.
+ */
+public synchronized void
+addActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified listener from the list of listeners that will
+ * receive action events from this button.
+ *
+ * @param listener The listener to remove.
+ */
+public synchronized void
+removeActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
+}
+
+ /**
+ * Returns all added <code>ActionListener</code> objects.
+ *
+ * @return an array of listeners
+ *
+ * @since 1.4
+ */
+ public synchronized ActionListener[] getActionListeners()
+ {
+ return (ActionListener[])
+ AWTEventMulticaster.getListeners(action_listeners,
+ ActionListener.class);
+ }
+
+/**
+ * Returns all registered EventListers of the given listenerType.
+ * listenerType must be a subclass of EventListener, or a
+ * ClassClassException is thrown.
+ *
+ * @param listenerType the listener type to return
+ *
+ * @return an array of listeners
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements @see java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ if (listenerType == ActionListener.class)
+ return getActionListeners();
+ return (EventListener[]) Array.newInstance(listenerType, 0);
+ }
+
+/*************************************************************************/
+
+/**
+ * Notifies this button that it should create its native peer object.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createButton (this);
+ super.addNotify();
+}
+
+/*************************************************************************/
+
+/**
+ * Processes an event for this button. If the specified event is an
+ * instance of <code>ActionEvent</code>, then the
+ * <code>processActionEvent()</code> method is called to dispatch it
+ * to any registered listeners. Otherwise, the superclass method
+ * will be invoked. Note that this method will not be called at all
+ * unless <code>ActionEvent</code>'s are enabled. This will be done
+ * implicitly if any listeners are added.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+ else
+ super.processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * This method dispatches an action event for this button to any
+ * registered listeners.
+ *
+ * @param event The event to process.
+ */
+protected void
+processActionEvent(ActionEvent event)
+{
+ if (action_listeners != null)
+ action_listeners.actionPerformed(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ActionEvent.ACTION_LAST
+ && e.id >= ActionEvent.ACTION_FIRST
+ && (action_listeners != null
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this button.
+ *
+ * @return A debugging string for this button.
+ */
+protected String
+paramString()
+{
+ return getName () + "," + getX () + "," + getY () + ","
+ + getWidth () + "x" + getHeight () + ",label=" + getLabel ();
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>Button</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTButton();
+ return accessibleContext;
+}
+
+ /**
+ * Generate a unique name for this button.
+ *
+ * @return A unique name for this button.
+ */
+ String generateName ()
+ {
+ return "button" + getUniqueLong ();
+ }
+
+ private static synchronized long getUniqueLong ()
+ {
+ return next_button_number++;
+ }
+
+} // class Button
+
diff --git a/libjava/classpath/java/awt/Canvas.java b/libjava/classpath/java/awt/Canvas.java
new file mode 100644
index 00000000000..fe2f854847a
--- /dev/null
+++ b/libjava/classpath/java/awt/Canvas.java
@@ -0,0 +1,354 @@
+/* Canvas.java --
+ Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.BufferStrategy;
+import java.awt.peer.ComponentPeer;
+import java.io.Serializable;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * The <code>Canvas</code> component provides a blank rectangular
+ * area, which the client application can use for drawing and for
+ * capturing events. By overriding the <code>paint()</code> method,
+ * the canvas can be used for anything from simple line drawings to
+ * full-scale custom components.
+ *
+ * @author Original author unknown
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.0
+ */
+
+public class Canvas
+ extends Component
+ implements Serializable, Accessible
+{
+
+ /**
+ * Compatible with Sun's JDK.
+ */
+ private static final long serialVersionUID = -2284879212465893870L;
+
+ /**
+ * The graphics configuration associated with the canvas.
+ */
+ transient GraphicsConfiguration graphicsConfiguration;
+
+ /**
+ * The buffer strategy associated with this canvas.
+ */
+ transient BufferStrategy bufferStrategy;
+
+ /**
+ * Initializes a new instance of <code>Canvas</code>.
+ */
+ public Canvas()
+ {
+ }
+
+ /**
+ * Initializes a new instance of <code>Canvas</code>
+ * with the supplied graphics configuration.
+ *
+ * @param graphicsConfiguration the graphics configuration to use
+ * for this particular canvas.
+ */
+ public Canvas(GraphicsConfiguration graphicsConfiguration)
+ {
+ this.graphicsConfiguration = graphicsConfiguration;
+ }
+
+ GraphicsConfiguration getGraphicsConfigurationImpl()
+ {
+ if (graphicsConfiguration != null)
+ return graphicsConfiguration;
+ return super.getGraphicsConfigurationImpl();
+ }
+
+ /**
+ * Creates the native peer for this object.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = (ComponentPeer) getToolkit().createCanvas(this);
+ super.addNotify();
+ }
+
+ /**
+ * Repaints the canvas window. This method should be overridden by
+ * a subclass to do something useful, as this method simply paints
+ * the window with the background color.
+ *
+ * @param gfx the <code>Graphics</code> to use for painting
+ */
+ public void paint(Graphics gfx)
+ {
+ /* This implementation doesn't make much sense since the filling
+ of background color is guaranteed for heavyweight components
+ such as this. But there's no need to worry, since paint() is
+ usually overridden anyway. */
+ gfx.setColor(getBackground());
+ Dimension size = getSize();
+ gfx.fillRect(0, 0, size.width, size.height);
+ }
+
+ /**
+ * This class provides accessibility support for the canvas.
+ */
+ protected class AccessibleAWTCanvas
+ extends AccessibleAWTComponent
+ {
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = -6325592262103146699L;
+
+ /**
+ * Constructor for the accessible canvas.
+ */
+ protected AccessibleAWTCanvas()
+ {
+ }
+
+ /**
+ * Returns the accessible role for the canvas.
+ *
+ * @return an instance of <code>AccessibleRole</code>, describing
+ * the role of the canvas.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.CANVAS;
+ }
+
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Canvas</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTCanvas();
+ return accessibleContext;
+ }
+
+ /**
+ * A BltBufferStrategy for canvases.
+ */
+ private class CanvasBltBufferStrategy extends BltBufferStrategy
+ {
+ /**
+ * Creates a block transfer strategy for this canvas.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ * @param accelerated true if the buffer should be accelerated,
+ * false otherwise
+ */
+ CanvasBltBufferStrategy(int numBuffers, boolean accelerated)
+ {
+ super(numBuffers,
+ new BufferCapabilities(new ImageCapabilities(accelerated),
+ new ImageCapabilities(accelerated),
+ BufferCapabilities.FlipContents.COPIED));
+ }
+ }
+
+ /**
+ * A FlipBufferStrategy for canvases.
+ */
+ private class CanvasFlipBufferStrategy extends FlipBufferStrategy
+ {
+ /**
+ * Creates a flip buffer strategy for this canvas.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ *
+ * @throws AWTException if the requested number of buffers is not
+ * supported
+ */
+ CanvasFlipBufferStrategy(int numBuffers)
+ throws AWTException
+ {
+ super(numBuffers,
+ new BufferCapabilities(new ImageCapabilities(true),
+ new ImageCapabilities(true),
+ BufferCapabilities.FlipContents.COPIED));
+ }
+ }
+
+ /**
+ * Creates a buffering strategy that manages how this canvas is
+ * repainted. This method attempts to create the optimum strategy
+ * based on the desired number of buffers. Hardware or software
+ * acceleration may be used.
+ *
+ * createBufferStrategy attempts different levels of optimization,
+ * but guarantees that some strategy with the requested number of
+ * buffers will be created even if it is not optimal. First it
+ * attempts to create a page flipping strategy, then an accelerated
+ * blitting strategy, then an unaccelerated blitting strategy.
+ *
+ * Calling this method causes any existing buffer strategy to be
+ * destroyed.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ *
+ * @throws IllegalArgumentException if requested number of buffers
+ * is less than one
+ * @throws IllegalStateException if this canvas is not displayable
+ *
+ * @since 1.4
+ */
+ public void createBufferStrategy(int numBuffers)
+ {
+ if (numBuffers < 1)
+ throw new IllegalArgumentException("Canvas.createBufferStrategy: number"
+ + " of buffers is less than one");
+
+ if (!isDisplayable())
+ throw new IllegalStateException("Canvas.createBufferStrategy: canvas is"
+ + " not displayable");
+
+ BufferStrategy newStrategy = null;
+
+ // try a flipping strategy
+ try
+ {
+ newStrategy = new CanvasFlipBufferStrategy(numBuffers);
+ }
+ catch (AWTException e)
+ {
+ }
+
+ // fall back to an accelerated blitting strategy
+ if (newStrategy == null)
+ newStrategy = new CanvasBltBufferStrategy(numBuffers, true);
+
+ bufferStrategy = newStrategy;
+ }
+
+ /**
+ * Creates a buffering strategy that manages how this canvas is
+ * repainted. This method attempts to create a strategy based on
+ * the specified capabilities and throws an exception if the
+ * requested strategy is not supported.
+ *
+ * Calling this method causes any existing buffer strategy to be
+ * destroyed.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ * @param caps the requested buffering capabilities
+ *
+ * @throws AWTException if the requested capabilities are not
+ * supported
+ * @throws IllegalArgumentException if requested number of buffers
+ * is less than one or if caps is null
+ *
+ * @since 1.4
+ */
+ public void createBufferStrategy(int numBuffers,
+ BufferCapabilities caps)
+ {
+ if (numBuffers < 1)
+ throw new IllegalArgumentException("Canvas.createBufferStrategy: number"
+ + " of buffers is less than one");
+
+ if (caps == null)
+ throw new IllegalArgumentException("Canvas.createBufferStrategy:"
+ + " capabilities object is null");
+
+ // a flipping strategy was requested
+ if (caps.isPageFlipping())
+ {
+ try
+ {
+ bufferStrategy = new CanvasFlipBufferStrategy(numBuffers);
+ }
+ catch (AWTException e)
+ {
+ }
+ }
+ else
+ bufferStrategy = new CanvasBltBufferStrategy(numBuffers, true);
+ }
+
+ /**
+ * Returns the buffer strategy used by the canvas.
+ *
+ * @return the buffer strategy.
+ * @since 1.4
+ */
+ public BufferStrategy getBufferStrategy()
+ {
+ return bufferStrategy;
+ }
+
+ /**
+ * Updates the canvas in response to a request to
+ * <code>repaint()</code> it. The canvas is cleared
+ * with the current background colour, before <code>paint()</code>
+ * is called to add the new contents. Subclasses
+ * which override this method should either call this
+ * method via <code>super.update(graphics)</code> or re-implement
+ * this behaviour, so as to ensure that the canvas is
+ * clear before painting takes place.
+ *
+ * @param graphics the graphics context.
+ */
+ public void update(Graphics graphics)
+ {
+ Dimension size;
+
+ /* Clear the canvas */
+ size = getSize();
+ graphics.clearRect(0, 0, size.width, size.height);
+ /* Call the paint method */
+ paint(graphics);
+ }
+}
diff --git a/libjava/classpath/java/awt/CardLayout.java b/libjava/classpath/java/awt/CardLayout.java
new file mode 100644
index 00000000000..8582c5f099b
--- /dev/null
+++ b/libjava/classpath/java/awt/CardLayout.java
@@ -0,0 +1,483 @@
+/* CardLayout.java -- Card-based layout engine
+ Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * This class implements a card-based layout scheme. Each included
+ * component is treated as a card. Only one card can be shown at a
+ * time. This class includes methods for changing which card is
+ * shown.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class CardLayout implements LayoutManager2, Serializable
+{
+ private static final long serialVersionUID = -4328196481005934313L;
+
+ /**
+ * Initializes a new instance of <code>CardLayout</code> with horizontal
+ * and vertical gaps of 0.
+ */
+ public CardLayout ()
+ {
+ this (0, 0);
+ }
+
+ /**
+ * Create a new <code>CardLayout</code> object with the specified
+ * horizontal and vertical gaps.
+ *
+ * @param hgap The horizontal gap
+ * @param vgap The vertical gap
+ */
+ public CardLayout (int hgap, int vgap)
+ {
+ this.hgap = hgap;
+ this.vgap = vgap;
+ this.tab = new Hashtable ();
+ }
+
+ /**
+ * Add a new component to the layout. The constraint must be a
+ * string which is used to name the component. This string can
+ * later be used to refer to the particular component.
+ *
+ * @param comp The component to add
+ * @param constraints The name by which the component can later be called
+ *
+ * @exception IllegalArgumentException If `constraints' is not a
+ * <code>String</code>
+ */
+ public void addLayoutComponent (Component comp, Object constraints)
+ {
+ if (! (constraints instanceof String))
+ throw new IllegalArgumentException ("Object " + constraints
+ + " is not a string");
+ addLayoutComponent ((String) constraints, comp);
+ }
+
+ /**
+ * Add a new component to the layout. The name can be used later
+ * to refer to the component.
+ *
+ * @param name The name by which the component can later be called
+ * @param comp The component to add
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>addLayoutComponent(Component, Object)</code>.
+ */
+ public void addLayoutComponent (String name, Component comp)
+ {
+ tab.put (name, comp);
+ // First component added is the default component.
+ comp.setVisible(tab.size() == 1);
+ }
+
+ /**
+ * Cause the first component in the container to be displayed.
+ *
+ * @param parent The parent container
+ */
+ public void first (Container parent)
+ {
+ gotoComponent (parent, FIRST);
+ }
+
+ /**
+ * Return this layout manager's horizontal gap.
+ *
+ * @return the horizontal gap
+ */
+ public int getHgap ()
+ {
+ return hgap;
+ }
+
+ /**
+ * Return this layout manager's x alignment. This method always
+ * returns Component.CENTER_ALIGNMENT.
+ *
+ * @param parent Container using this layout manager instance
+ *
+ * @return the x-axis alignment
+ */
+ public float getLayoutAlignmentX (Container parent)
+ {
+ return Component.CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Returns this layout manager's y alignment. This method always
+ * returns Component.CENTER_ALIGNMENT.
+ *
+ * @param parent Container using this layout manager instance
+ *
+ * @return the y-axis alignment
+ */
+ public float getLayoutAlignmentY (Container parent)
+ {
+ return Component.CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Return this layout manager's vertical gap.
+ *
+ * @return the vertical gap
+ */
+ public int getVgap ()
+ {
+ return vgap;
+ }
+
+ /**
+ * Invalidate this layout manager's state.
+ */
+ public void invalidateLayout (Container target)
+ {
+ // Do nothing.
+ }
+
+ /**
+ * Cause the last component in the container to be displayed.
+ *
+ * @param parent The parent container
+ */
+ public void last (Container parent)
+ {
+ gotoComponent (parent, LAST);
+ }
+
+ /**
+ * Lays out the container. This is done by resizing the child components
+ * to be the same size as the parent, less insets and gaps.
+ *
+ * @param parent The parent container.
+ */
+ public void layoutContainer (Container parent)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int width = parent.width;
+ int height = parent.height;
+
+ Insets ins = parent.getInsets ();
+
+ int num = parent.ncomponents;
+ Component[] comps = parent.component;
+
+ int x = ins.left + hgap;
+ int y = ins.top + vgap;
+ width = width - 2 * hgap - ins.left - ins.right;
+ height = height - 2 * vgap - ins.top - ins.bottom;
+
+ for (int i = 0; i < num; ++i)
+ comps[i].setBounds (x, y, width, height);
+ }
+ }
+
+ /**
+ * Get the maximum layout size of the container.
+ *
+ * @param target The parent container
+ *
+ * @return the maximum layout size
+ */
+ public Dimension maximumLayoutSize (Container target)
+ {
+ // The JCL says that this returns Integer.MAX_VALUE for both
+ // dimensions. But that just seems wrong to me.
+ return getSize (target, MAX);
+ }
+
+ /**
+ * Get the minimum layout size of the container.
+ *
+ * @param target The parent container
+ *
+ * @return the minimum layout size
+ */
+ public Dimension minimumLayoutSize (Container target)
+ {
+ return getSize (target, MIN);
+ }
+
+ /**
+ * Cause the next component in the container to be displayed. If
+ * this current card is the last one in the deck, the first
+ * component is displayed.
+ *
+ * @param parent The parent container
+ */
+ public void next (Container parent)
+ {
+ gotoComponent (parent, NEXT);
+ }
+
+ /**
+ * Get the preferred layout size of the container.
+ *
+ * @param parent The parent container
+ *
+ * @return the preferred layout size
+ */
+ public Dimension preferredLayoutSize (Container parent)
+ {
+ return getSize (parent, PREF);
+ }
+
+ /**
+ * Cause the previous component in the container to be displayed.
+ * If this current card is the first one in the deck, the last
+ * component is displayed.
+ *
+ * @param parent The parent container
+ */
+ public void previous (Container parent)
+ {
+ gotoComponent (parent, PREV);
+ }
+
+ /**
+ * Remove the indicated component from this layout manager.
+ *
+ * @param comp The component to remove
+ */
+ public void removeLayoutComponent (Component comp)
+ {
+ Enumeration e = tab.keys ();
+ while (e.hasMoreElements ())
+ {
+ Object key = e.nextElement ();
+ if (tab.get (key) == comp)
+ {
+ tab.remove (key);
+ Container parent = comp.getParent();
+ next(parent);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Set this layout manager's horizontal gap.
+ *
+ * @param hgap The new gap
+ */
+ public void setHgap (int hgap)
+ {
+ this.hgap = hgap;
+ }
+
+ /**
+ * Set this layout manager's vertical gap.
+ *
+ * @param vgap The new gap
+ */
+ public void setVgap (int vgap)
+ {
+ this.vgap = vgap;
+ }
+
+ /**
+ * Cause the named component to be shown. If the component name is
+ * unknown, this method does nothing.
+ *
+ * @param parent The parent container
+ * @param name The name of the component to show
+ */
+ public void show (Container parent, String name)
+ {
+ Object target = tab.get (name);
+ if (target != null)
+ {
+ int num = parent.ncomponents;
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+ for (int i = 0; i < num; ++i)
+ {
+ if (comps[i].isVisible())
+ {
+ if (target == comps[i])
+ return;
+ comps[i].setVisible (false);
+ }
+ }
+ ((Component) target).setVisible (true);
+ }
+ }
+
+ /**
+ * Returns a string representation of this layout manager.
+ *
+ * @return A string representation of this object.
+ */
+ public String toString ()
+ {
+ return getClass ().getName () + "[" + hgap + "," + vgap + "]";
+ }
+
+ /**
+ * This implements first(), last(), next(), and previous().
+ *
+ * @param parent The parent container
+ * @param what The type of goto: FIRST, LAST, NEXT or PREV
+ */
+ private void gotoComponent (Container parent, int what)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int num = parent.ncomponents;
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ if (num == 1)
+ {
+ comps[0].setVisible(true);
+ return;
+ }
+
+ int choice = -1;
+
+ if (what == FIRST)
+ choice = 0;
+ else if (what == LAST)
+ choice = num - 1;
+
+ for (int i = 0; i < num; ++i)
+ {
+ if (comps[i].isVisible ())
+ {
+ if (what == NEXT)
+ {
+ choice = i + 1;
+ if (choice == num)
+ choice = 0;
+ }
+ else if (what == PREV)
+ {
+ choice = i - 1;
+ if (choice < 0)
+ choice = num - 1;
+ }
+ else if (choice == i)
+ {
+ // Do nothing if we're already looking at the right
+ // component.
+ return;
+ }
+ comps[i].setVisible (false);
+
+ if (choice >= 0)
+ break;
+ }
+ }
+
+ if (choice >= 0 && choice < num)
+ comps[choice].setVisible (true);
+ }
+ }
+
+ // Compute the size according to WHAT.
+ private Dimension getSize (Container parent, int what)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int w = 0, h = 0, num = parent.ncomponents;
+ Component[] comps = parent.component;
+
+ for (int i = 0; i < num; ++i)
+ {
+ Dimension d;
+
+ if (what == MIN)
+ d = comps[i].getMinimumSize ();
+ else if (what == MAX)
+ d = comps[i].getMaximumSize ();
+ else
+ d = comps[i].getPreferredSize ();
+
+ w = Math.max (d.width, w);
+ h = Math.max (d.height, h);
+ }
+
+ Insets i = parent.getInsets ();
+ w += 2 * hgap + i.right + i.left;
+ h += 2 * vgap + i.bottom + i.top;
+
+ // Handle overflow.
+ if (w < 0)
+ w = Integer.MAX_VALUE;
+ if (h < 0)
+ h = Integer.MAX_VALUE;
+
+ return new Dimension (w, h);
+ }
+ }
+
+ /**
+ * @serial Horizontal gap value.
+ */
+ private int hgap;
+
+ /**
+ * @serial Vertical gap value.
+ */
+ private int vgap;
+
+ /**
+ * @serial Table of named components.
+ */
+ private Hashtable tab;
+
+ // These constants are used by the private gotoComponent method.
+ private static final int FIRST = 0;
+ private static final int LAST = 1;
+ private static final int NEXT = 2;
+ private static final int PREV = 3;
+
+ // These constants are used by the private getSize method.
+ private static final int MIN = 0;
+ private static final int MAX = 1;
+ private static final int PREF = 2;
+}
diff --git a/libjava/classpath/java/awt/Checkbox.java b/libjava/classpath/java/awt/Checkbox.java
new file mode 100644
index 00000000000..cd39ad43617
--- /dev/null
+++ b/libjava/classpath/java/awt/Checkbox.java
@@ -0,0 +1,649 @@
+/* Checkbox.java -- An AWT checkbox widget
+ Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.peer.CheckboxPeer;
+import java.io.Serializable;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class implements a component which has an on/off state. Two
+ * or more Checkboxes can be grouped by a CheckboxGroup.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class Checkbox extends Component
+ implements ItemSelectable, Accessible, Serializable
+{
+
+// FIXME: Need readObject/writeObject for this.
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = 7270714317450821763L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The checkbox group for this checkbox.
+ */
+private CheckboxGroup group;
+
+/**
+ * @serial The label on this checkbox.
+ */
+private String label;
+
+/**
+ * @serial The state of this checkbox.
+ * This is package-private to avoid an accessor method.
+ */
+boolean state;
+
+// The list of listeners for this object.
+private transient ItemListener item_listeners;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_checkbox_number;
+
+/**
+ * This class provides accessibility support for the
+ * checkbox.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+protected class AccessibleAWTCheckbox
+ extends AccessibleAWTComponent
+ implements ItemListener, AccessibleAction, AccessibleValue
+{
+ /**
+ * Serialization constant to match JDK 1.5
+ */
+ private static final long serialVersionUID = 7881579233144754107L;
+
+ /**
+ * Default constructor which simply calls the
+ * super class for generic component accessibility
+ * handling.
+ */
+ public AccessibleAWTCheckbox()
+ {
+ super();
+ }
+
+ /**
+ * Captures changes to the state of the checkbox and
+ * fires appropriate accessible property change events.
+ *
+ * @param event the event fired.
+ * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
+ */
+ public void itemStateChanged(ItemEvent event)
+ {
+ firePropertyChange(ACCESSIBLE_STATE_PROPERTY,
+ state ? null : AccessibleState.CHECKED,
+ state ? AccessibleState.CHECKED : null);
+ }
+
+ /**
+ * Returns an implementation of the <code>AccessibleAction</code>
+ * interface for this accessible object. In this case, the
+ * current instance is simply returned (with a more appropriate
+ * type), as it also implements the accessible action as well as
+ * the context.
+ *
+ * @return the accessible action associated with this context.
+ * @see javax.accessibility.AccessibleAction
+ */
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ /**
+ * Returns an implementation of the <code>AccessibleValue</code>
+ * interface for this accessible object. In this case, the
+ * current instance is simply returned (with a more appropriate
+ * type), as it also implements the accessible value as well as
+ * the context.
+ *
+ * @return the accessible value associated with this context.
+ * @see javax.accessibility.AccessibleValue
+ */
+ public AccessibleValue getAccessibleValue()
+ {
+ return this;
+ }
+
+ /*
+ * The following methods are implemented in the JDK (up to
+ * 1.5) as stubs. We do likewise here.
+ */
+
+ /**
+ * Returns the number of actions associated with this accessible
+ * object. This default implementation returns 0.
+ *
+ * @return the number of accessible actions available.
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
+ */
+ public int getAccessibleActionCount()
+ {
+ // 1.4.1 and 1.5 do this
+ return 0;
+ }
+
+ /**
+ * Returns a description of the action with the supplied id.
+ * This default implementation always returns null.
+ *
+ * @param i the id of the action whose description should be
+ * retrieved.
+ * @return a <code>String</code> describing the action.
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ // 1.5 does this
+ return null;
+ }
+
+ /**
+ * Executes the action with the specified id. This
+ * default implementation simply returns false.
+ *
+ * @param i the id of the action to perform.
+ * @return true if the action was performed.
+ * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ // 1.5 does this
+ return false;
+ }
+
+ /**
+ * Returns the current value of this accessible object.
+ * If no value has been set, null is returned. This
+ * default implementation always returns null, regardless.
+ *
+ * @return the numeric value of this object, or null if
+ * no value has been set.
+ * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
+ */
+ public Number getCurrentAccessibleValue()
+ {
+ // 1.5 does this
+ return null;
+ }
+
+ /**
+ * Sets the current value of this accessible object
+ * to that supplied. In this default implementation,
+ * the value is never set and the method always returns
+ * false.
+ *
+ * @param number the new accessible value.
+ * @return true if the value was set.
+ * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
+ */
+ public boolean setCurrentAccessibleValue(Number number)
+ {
+ // 1.5 does this
+ return false;
+ }
+
+ /**
+ * Returns the minimum acceptable accessible value used
+ * by this object, or null if no minimum value exists.
+ * This default implementation always returns null.
+ *
+ * @return the minimum acceptable accessible value, or null
+ * if there is no minimum.
+ * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
+ */
+ public Number getMinimumAccessibleValue()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the maximum acceptable accessible value used
+ * by this object, or null if no maximum value exists.
+ * This default implementation always returns null.
+ *
+ * @return the maximum acceptable accessible value, or null
+ * if there is no maximum.
+ * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
+ */
+ public Number getMaximumAccessibleValue()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the role of this accessible object.
+ *
+ * @return the instance of <code>AccessibleRole</code>,
+ * which describes this object.
+ * @see javax.accessibility.AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.CHECK_BOX;
+ }
+
+ /**
+ * Returns the state set of this accessible object.
+ *
+ * @return a set of <code>AccessibleState</code>s
+ * which represent the current state of the
+ * accessible object.
+ * @see javax.accessibility.AccessibleState
+ * @see javax.accessibility.AccessibleStateSet
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet set = super.getAccessibleStateSet();
+ if (state)
+ set.add(AccessibleState.CHECKED);
+ return set;
+ }
+
+}
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with no label,
+ * an initial state of off, and that is not part of any checkbox group.
+ */
+public
+Checkbox()
+{
+ this("", false, null);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with the specified
+ * label, an initial state of off, and that is not part of any checkbox
+ * group.
+ *
+ * @param label The label for this checkbox.
+ */
+public
+Checkbox(String label)
+{
+ this(label, false, null);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with the specified
+ * label and initial state, and that is not part of any checkbox
+ * group.
+ *
+ * @param label The label for this checkbox.
+ * @param state The initial state of the checkbox, <code>true</code> for
+ * on, <code>false</code> for off.
+ */
+public
+Checkbox(String label, boolean state)
+{
+ this(label, state, null);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with the specified
+ * label, initial state, and checkbox group.
+ *
+ * @param label The label for this checkbox.
+ * @param group The checkbox group for this box, or <code>null</code>
+ * if there is no checkbox group.
+ * @param state The initial state of the checkbox, <code>true</code> for
+ * on, <code>false</code> for off.
+ */
+public
+Checkbox(String label, CheckboxGroup group, boolean state)
+{
+ this(label, state, group);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with the specified
+ * label, initial state, and checkbox group.
+ *
+ * @param label The label for this checkbox.
+ * @param state The initial state of the checkbox, <code>true</code> for
+ * on, <code>false</code> for off.
+ * @param group The checkbox group for this box, or <code>null</code>
+ * if there is no checkbox group.
+ */
+public
+Checkbox(String label, boolean state, CheckboxGroup group)
+{
+ this.label = label;
+ this.state = state;
+ this.group = group;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the label for this checkbox.
+ *
+ * @return The label for this checkbox.
+ */
+public String
+getLabel()
+{
+ return(label);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the label for this checkbox to the specified value.
+ *
+ * @param label The new checkbox label.
+ */
+public synchronized void
+setLabel(String label)
+{
+ this.label = label;
+ if (peer != null)
+ {
+ CheckboxPeer cp = (CheckboxPeer) peer;
+ cp.setLabel(label);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the state of this checkbox.
+ *
+ * @return The state of this checkbox, which will be <code>true</code> for
+ * on and <code>false</code> for off.
+ */
+public boolean
+getState()
+{
+ return(state);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the state of this checkbox to the specified value.
+ *
+ * @param state The new state of the checkbox, which will be <code>true</code>
+ * for on or <code>false</code> for off.
+ */
+public synchronized void
+setState(boolean state)
+{
+ this.state = state;
+ if (peer != null)
+ {
+ CheckboxPeer cp = (CheckboxPeer) peer;
+ cp.setState (state);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns an array of length one containing the checkbox label if this
+ * checkbox is selected. Otherwise <code>null</code> is returned.
+ *
+ * @return The selection state of this checkbox.
+ */
+public Object[]
+getSelectedObjects()
+{
+ if (state == false)
+ return(null);
+
+ Object[] objs = new Object[1];
+ objs[0] = label;
+
+ return(objs);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the checkbox group this object is a member of, if any.
+ *
+ * @return This object's checkbox group, of <code>null</code> if it is
+ * not a member of any group.
+ */
+public CheckboxGroup
+getCheckboxGroup()
+{
+ return(group);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets this object's checkbox group to the specified group.
+ *
+ * @param group The new checkbox group, or <code>null</code> to make this
+ * object part of no checkbox group.
+ */
+public synchronized void
+setCheckboxGroup(CheckboxGroup group)
+{
+ this.group = group;
+ if (peer != null)
+ {
+ CheckboxPeer cp = (CheckboxPeer) peer;
+ cp.setCheckboxGroup (group);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Creates this object's native peer.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createCheckbox (this);
+ super.addNotify ();
+}
+
+ public ItemListener[] getItemListeners ()
+ {
+ return (ItemListener[])
+ AWTEventMulticaster.getListeners (item_listeners, ItemListener.class);
+ }
+
+/**
+ * Adds a new listeners to the list of registered listeners for this object.
+ *
+ * @param listener The new listener to add.
+ */
+public synchronized void
+addItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.add(item_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes a 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 calling <code>processItemEvent()</code> if it
+ * is any instance of <code>ItemEvent</code>. Otherwise it is passed to
+ * the superclass for processing.
+ *
+ * @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 dispatching it to any registered listeners.
+ *
+ * @param event The <code>ItemEvent</code> to process.
+ */
+protected void
+processItemEvent(ItemEvent event)
+{
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ItemEvent.ITEM_LAST
+ && e.id >= ItemEvent.ITEM_FIRST
+ && (item_listeners != null
+ || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ */
+protected String
+paramString()
+{
+ return ("label=" + label + ",state=" + state + ",group=" + group
+ + "," + super.paramString());
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>Checkbox</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ {
+ AccessibleAWTCheckbox ac = new AccessibleAWTCheckbox();
+ accessibleContext = ac;
+ addItemListener(ac);
+ }
+ return accessibleContext;
+}
+
+ /**
+ * Generate a unique name for this checkbox.
+ *
+ * @return A unique name for this checkbox.
+ */
+ String generateName()
+ {
+ return "checkbox" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_checkbox_number++;
+ }
+}
diff --git a/libjava/classpath/java/awt/CheckboxGroup.java b/libjava/classpath/java/awt/CheckboxGroup.java
new file mode 100644
index 00000000000..31b573e654d
--- /dev/null
+++ b/libjava/classpath/java/awt/CheckboxGroup.java
@@ -0,0 +1,173 @@
+/* CheckboxGroup.java -- A grouping class for checkboxes.
+ Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class if for combining checkboxes into groups so that only
+ * one checkbox in the group can be selected at any one time.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class CheckboxGroup implements java.io.Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization constant
+private static final long serialVersionUID = 3729780091441768983L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The currently selected checkbox.
+ */
+private Checkbox selectedCheckbox;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>CheckboxGroup</code>.
+ */
+public
+CheckboxGroup()
+{
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the currently selected checkbox, or <code>null</code> if none
+ * of the checkboxes in this group are selected.
+ *
+ * @return The selected checkbox.
+ */
+public Checkbox
+getSelectedCheckbox()
+{
+ return getCurrent ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the currently selected checkbox, or <code>null</code> if none
+ * of the checkboxes in this group are selected.
+ *
+ * @return The selected checkbox.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getSelectedCheckbox()</code>.
+ */
+public Checkbox
+getCurrent()
+{
+ return(selectedCheckbox);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the specified checkbox to be the selected on in this
+ * group, and unsets all others.
+ *
+ * @param selectedCheckbox The new selected checkbox.
+ */
+public void
+setSelectedCheckbox(Checkbox selectedCheckbox)
+{
+ setCurrent (selectedCheckbox);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the specified checkbox to be the selected on in this
+ * group, and unsets all others.
+ *
+ * @param selectedCheckbox The new selected checkbox.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>setSelectedCheckbox()</code>.
+ */
+public void
+setCurrent(Checkbox selectedCheckbox)
+{
+ if (this.selectedCheckbox != null)
+ {
+ if (this.selectedCheckbox.getCheckboxGroup() != this)
+ return;
+
+ this.selectedCheckbox.setState(false);
+ }
+
+ this.selectedCheckbox = selectedCheckbox;
+ if (selectedCheckbox != null)
+ selectedCheckbox.setState(true);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this checkbox group.
+ *
+ * @return A string representation of this checkbox group.
+ */
+public String
+toString()
+{
+ return(getClass().getName() + "[selectedCheckbox=" + selectedCheckbox + "]");
+}
+
+} // class CheckboxGroup
+
diff --git a/libjava/classpath/java/awt/CheckboxMenuItem.java b/libjava/classpath/java/awt/CheckboxMenuItem.java
new file mode 100644
index 00000000000..5e446b84c8b
--- /dev/null
+++ b/libjava/classpath/java/awt/CheckboxMenuItem.java
@@ -0,0 +1,355 @@
+/* CheckboxMenuItem.java -- A menu option with a checkbox on it.
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class implements a menu item that has a checkbox on it indicating
+ * the selected state of some option.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class CheckboxMenuItem extends MenuItem
+ implements ItemSelectable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization constant
+private static final long serialVersionUID = 6190621106981774043L;
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The state of the checkbox, with <code>true</code> being on and
+ * <code>false</code> being off.
+ */
+private boolean state;
+
+// List of registered ItemListeners
+private transient ItemListener item_listeners;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>CheckboxMenuItem</code> with no
+ * label and an initial state of off.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+CheckboxMenuItem()
+{
+ this("", false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>CheckboxMenuItem</code> with the
+ * specified label and an initial state of off.
+ *
+ * @param label The label of the menu item.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+CheckboxMenuItem(String label)
+{
+ this(label, false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>CheckboxMenuItem</code> with the
+ * specified label and initial state.
+ *
+ * @param label The label of the menu item.
+ * @param state The initial state of the menu item, where <code>true</code>
+ * is on, and <code>false</code> is off.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+CheckboxMenuItem(String label, boolean state)
+{
+ super(label);
+ this.state = state;
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the state of this menu item.
+ *
+ * @return The state of this menu item.
+ */
+public boolean
+getState()
+{
+ return(state);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the state of this menu item.
+ *
+ * @param state The initial state of the menu item, where <code>true</code>
+ * is on, and <code>false</code> is off.
+ */
+public synchronized void
+setState(boolean state)
+{
+ this.state = state;
+ if (peer != null)
+ {
+ CheckboxMenuItemPeer cp = (CheckboxMenuItemPeer) peer;
+ cp.setState (state);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns an array of length 1 with the menu item label for this object
+ * if the state is on. Otherwise <code>null</code> is returned.
+ *
+ * @return An array with this menu item's label if it has a state of on,
+ * or <code>null</code> otherwise.
+ */
+public Object[]
+getSelectedObjects()
+{
+ if (state == false)
+ return(null);
+
+ Object[] obj = new Object[1];
+ obj[0] = getLabel();
+
+ return(obj);
+}
+
+/*************************************************************************/
+
+/**
+ * Create's this object's native peer
+ */
+public synchronized void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit().createCheckboxMenuItem(this);
+
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified listener to the list of registered item listeners
+ * for this object.
+ *
+ * @param listener The listener to add.
+ */
+public synchronized void
+addItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.add(item_listeners, listener);
+
+ enableEvents(AWTEvent.ITEM_EVENT_MASK);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified listener from the list of registered item
+ * listeners for this object.
+ *
+ * @param listener The listener to remove.
+ */
+public synchronized void
+removeItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event by calling <code>processItemEvent()</code>
+ * if it is an instance of <code>ItemEvent</code> or calling the superclass
+ * method otherwise.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ItemEvent)
+ processItemEvent((ItemEvent)event);
+ else
+ super.processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event by dispatching it to any registered listeners.
+ *
+ * @param event The event to process.
+ */
+protected void
+processItemEvent(ItemEvent event)
+{
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e instanceof ItemEvent)
+ {
+ synchronized (this)
+ {
+ state = (((ItemEvent) e).getStateChange() == ItemEvent.SELECTED);
+ }
+ }
+
+ if (e.id <= ItemEvent.ITEM_LAST
+ && e.id >= ItemEvent.ITEM_FIRST
+ && (item_listeners != null
+ || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+public String
+paramString()
+{
+ return ("label=" + getLabel() + ",state=" + state
+ + "," + super.paramString());
+}
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>CheckboxMenuItem</code>. FooListeners are registered using
+ * the addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ */
+ public EventListener[] getListeners (Class listenerType)
+ {
+ if (listenerType == ItemListener.class)
+ return AWTEventMulticaster.getListeners (item_listeners, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Returns an aray of all item listeners currently registered to this
+ * <code>CheckBoxMenuItem</code>.
+ */
+ public ItemListener[] getItemListeners ()
+ {
+ return (ItemListener[]) getListeners (ItemListener.class);
+ }
+
+
+ protected class AccessibleAWTCheckboxMenuItem extends AccessibleAWTMenuItem
+ implements AccessibleAction, AccessibleValue
+ {
+ // I think the base class provides the necessary implementation
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>CheckboxMenuItem</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTCheckboxMenuItem();
+ return accessibleContext;
+ }
+
+} // class CheckboxMenuItem
+
diff --git a/libjava/classpath/java/awt/Choice.java b/libjava/classpath/java/awt/Choice.java
new file mode 100644
index 00000000000..5075ea92d83
--- /dev/null
+++ b/libjava/classpath/java/awt/Choice.java
@@ -0,0 +1,638 @@
+/* Choice.java -- Java choice button widget.
+ Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.peer.ChoicePeer;
+import java.io.Serializable;
+import java.util.EventListener;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This class implements a drop down choice list.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Choice extends Component
+ implements ItemSelectable, Serializable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization constant
+private static final long serialVersionUID = -4075310674757313071L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @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;
+
+// Listener 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)
+ */
+ protected class AccessibleAWTChoice
+ extends AccessibleAWTComponent
+ implements AccessibleAction
+ {
+
+ /**
+ * Serialization constant to match JDK 1.5
+ */
+ private static final long serialVersionUID = 7175603582428509322L;
+
+ /**
+ * Default constructor which simply calls the
+ * super class for generic component accessibility
+ * handling.
+ */
+ public AccessibleAWTChoice()
+ {
+ super();
+ }
+
+ /**
+ * Returns an implementation of the <code>AccessibleAction</code>
+ * interface for this accessible object. In this case, the
+ * current instance is simply returned (with a more appropriate
+ * type), as it also implements the accessible action as well as
+ * the context.
+ *
+ * @return the accessible action associated with this context.
+ * @see javax.accessibility.AccessibleAction
+ */
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the role of this accessible object.
+ *
+ * @return the instance of <code>AccessibleRole</code>,
+ * which describes this object.
+ * @see javax.accessibility.AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.COMBO_BOX;
+ }
+
+ /**
+ * Returns the number of actions associated with this accessible
+ * object. In this case, it is the number of choices available.
+ *
+ * @return the number of choices available.
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
+ */
+ public int getAccessibleActionCount()
+ {
+ return pItems.size();
+ }
+
+ /**
+ * Returns a description of the action with the supplied id.
+ * In this case, it is the text used in displaying the particular
+ * choice on-screen.
+ *
+ * @param i the id of the choice whose description should be
+ * retrieved.
+ * @return the <code>String</code> used to describe the choice.
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ return (String) pItems.get(i);
+ }
+
+ /**
+ * Executes the action with the specified id. In this case,
+ * calling this method provides the same behaviour as would
+ * choosing a choice from the list in a visual manner.
+ *
+ * @param i the id of the choice to select.
+ * @return true if a valid choice was specified.
+ * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ if (i < 0 || i >= pItems.size())
+ return false;
+
+ Choice.this.processItemEvent(new ItemEvent(Choice.this,
+ ItemEvent.ITEM_STATE_CHANGED,
+ this, ItemEvent.SELECTED));
+ return true;
+ }
+ }
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+ /**
+ * Initializes a new instance of <code>Choice</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true
+ */
+ public Choice()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ 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);
+}
+
+/*************************************************************************/
+
+/**
+ * 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);
+}
+
+/*************************************************************************/
+
+/** 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 ();
+
+ pItems.insertElementAt(item, index);
+
+ if (peer != null)
+ {
+ ChoicePeer cp = (ChoicePeer) peer;
+ cp.add (item, index);
+ }
+ else if (selectedIndex == -1 || selectedIndex >= index)
+ select(0);
+}
+
+/*************************************************************************/
+
+/**
+ * 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)
+{
+ if ((index < 0) || (index > getItemCount()))
+ throw new IllegalArgumentException("Bad index: " + index);
+
+ pItems.removeElementAt(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 > index)
+ --selectedIndex;
+}
+
+/*************************************************************************/
+
+/**
+ * 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;
+}
+
+/*************************************************************************/
+
+/**
+ * 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);
+
+ return(objs);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the index of the selected item.
+ *
+ * @return The index of the selected item.
+ */
+public int
+getSelectedIndex()
+{
+ return(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);
+
+ this.selectedIndex = index;
+ if (peer != null)
+ {
+ ChoicePeer cp = (ChoicePeer) peer;
+ cp.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);
+}
+
+/*************************************************************************/
+
+/**
+ * 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);
+}
+
+/*************************************************************************/
+
+/**
+ * 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 item event by dispatching to any registered listeners.
+ *
+ * @param event The event to process.
+ */
+protected void
+processItemEvent(ItemEvent event)
+{
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ItemEvent.ITEM_LAST
+ && e.id >= ItemEvent.ITEM_FIRST
+ && (item_listeners != null
+ || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * 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
+ * upon this Choice. FooListeners are registered using the addFooListener
+ * method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public EventListener[] getListeners (Class listenerType)
+ {
+ if (listenerType == ItemListener.class)
+ return AWTEventMulticaster.getListeners (item_listeners, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Returns all registered item listeners.
+ *
+ * @since 1.4
+ */
+ public ItemListener[] getItemListeners ()
+ {
+ return (ItemListener[]) getListeners (ItemListener.class);
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Choice</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTChoice();
+ return accessibleContext;
+ }
+} // class Choice
diff --git a/libjava/classpath/java/awt/Color.java b/libjava/classpath/java/awt/Color.java
new file mode 100644
index 00000000000..4ad46d0c07c
--- /dev/null
+++ b/libjava/classpath/java/awt/Color.java
@@ -0,0 +1,1008 @@
+/* Color.java -- represents a color in Java
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+import java.io.Serializable;
+
+/**
+ * This class represents a color value in the AWT system. It uses the sRGB
+ * (standard Red-Green-Blue) system, along with an alpha value ranging from
+ * transparent (0.0f or 0) and opaque (1.0f or 255). The color is not
+ * pre-multiplied by the alpha value an any of the accessor methods. Further
+ * information about sRGB can be found at
+ * <a href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
+ * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html</a>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ColorSpace
+ * @see AlphaComposite
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Color implements Paint, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 118526816881161077L;
+
+ /** Constant for the color white: R=255, G=255, B=255. */
+ public static final Color white = new Color(0xffffff, false);
+
+ /**
+ * Constant for the color white: R=255, G=255, B=255.
+ *
+ * @since 1.4
+ */
+ public static final Color WHITE = white;
+
+ /** Constant for the color light gray: R=192, G=192, B=192. */
+ public static final Color lightGray = new Color(0xc0c0c0, false);
+
+ /**
+ * Constant for the color light gray: R=192, G=192, B=192.
+ *
+ * @since 1.4
+ */
+ public static final Color LIGHT_GRAY = lightGray;
+
+ /** Constant for the color gray: R=128, G=128, B=128. */
+ public static final Color gray = new Color(0x808080, false);
+
+ /**
+ * Constant for the color gray: R=128, G=128, B=128.
+ *
+ * @since 1.4
+ */
+ public static final Color GRAY = gray;
+
+ /** Constant for the color dark gray: R=64, G=64, B=64. */
+ public static final Color darkGray = new Color(0x404040, false);
+
+ /**
+ * Constant for the color dark gray: R=64, G=64, B=64.
+ *
+ * @since 1.4
+ */
+ public static final Color DARK_GRAY = darkGray;
+
+ /** Constant for the color black: R=0, G=0, B=0. */
+ public static final Color black = new Color(0x000000, false);
+
+ /**
+ * Constant for the color black: R=0, G=0, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color BLACK = black;
+
+ /** Constant for the color red: R=255, G=0, B=0. */
+ public static final Color red = new Color(0xff0000, false);
+
+ /**
+ * Constant for the color red: R=255, G=0, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color RED = red;
+
+ /** Constant for the color pink: R=255, G=175, B=175. */
+ public static final Color pink = new Color(0xffafaf, false);
+
+ /**
+ * Constant for the color pink: R=255, G=175, B=175.
+ *
+ * @since 1.4
+ */
+ public static final Color PINK = pink;
+
+ /** Constant for the color orange: R=255, G=200, B=0. */
+ public static final Color orange = new Color(0xffc800, false);
+
+ /**
+ * Constant for the color orange: R=255, G=200, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color ORANGE = orange;
+
+ /** Constant for the color yellow: R=255, G=255, B=0. */
+ public static final Color yellow = new Color(0xffff00, false);
+
+ /**
+ * Constant for the color yellow: R=255, G=255, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color YELLOW = yellow;
+
+ /** Constant for the color green: R=0, G=255, B=0. */
+ public static final Color green = new Color(0x00ff00, false);
+
+ /**
+ * Constant for the color green: R=0, G=255, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color GREEN = green;
+
+ /** Constant for the color magenta: R=255, G=0, B=255. */
+ public static final Color magenta = new Color(0xff00ff, false);
+
+ /**
+ * Constant for the color magenta: R=255, G=0, B=255.
+ *
+ * @since 1.4
+ */
+ public static final Color MAGENTA = magenta;
+
+ /** Constant for the color cyan: R=0, G=255, B=255. */
+ public static final Color cyan = new Color(0x00ffff, false);
+
+ /**
+ * Constant for the color cyan: R=0, G=255, B=255.
+ *
+ * @since 1.4
+ */
+ public static final Color CYAN = cyan;
+
+ /** Constant for the color blue: R=0, G=0, B=255. */
+ public static final Color blue = new Color(0x0000ff, false);
+
+ /**
+ * Constant for the color blue: R=0, G=0, B=255.
+ *
+ * @since 1.4
+ */
+ public static final Color BLUE = blue;
+
+ /** Internal mask for red. */
+ private static final int RED_MASK = 255 << 16;
+
+ /** Internal mask for green. */
+ private static final int GREEN_MASK = 255 << 8;
+
+ /** Internal mask for blue. */
+ private static final int BLUE_MASK = 255;
+
+ /** Internal mask for alpha. Package visible for use in subclass. */
+ static final int ALPHA_MASK = 255 << 24;
+
+ /** Amount to scale a color by when brightening or darkening. */
+ private static final float BRIGHT_SCALE = 0.7f;
+
+ /**
+ * The color value, in sRGB. Note that the actual color may be more
+ * precise if frgbvalue or fvalue is non-null. This class stores alpha, red,
+ * green, and blue, each 0-255, packed in an int. However, the subclass
+ * SystemColor stores an index into an array. Therefore, for serial
+ * compatibility (and because of poor design on Sun's part), this value
+ * cannot be used directly; instead you must use <code>getRGB()</code>.
+ *
+ * @see #getRGB()
+ * @serial the value of the color, whether an RGB literal or array index
+ */
+ final int value;
+
+ /**
+ * The color value, in sRGB. This may be null if the color was constructed
+ * with ints; and it does not include alpha. This stores red, green, and
+ * blue, in the range 0.0f - 1.0f.
+ *
+ * @see #getRGBColorComponents(float[])
+ * @see #getRGBComponents(float[])
+ * @serial the rgb components of the value
+ * @since 1.2
+ */
+ private float[] frgbvalue;
+
+ /**
+ * The color value, in the native ColorSpace components. This may be null
+ * if the color was constructed with ints or in the sRGB color space; and
+ * it does not include alpha.
+ *
+ * @see #getRGBColorComponents(float[])
+ * @see #getRGBComponents(float[])
+ * @serial the original color space components of the color
+ * @since 1.2
+ */
+ private float[] fvalue;
+
+ /**
+ * The alpha value. This is in the range 0.0f - 1.0f, but is invalid if
+ * deserialized as 0.0 when frgbvalue is null.
+ *
+ * @see #getRGBComponents(float[])
+ * @see #getComponents(float[])
+ * @serial the alpha component of this color
+ * @since 1.2
+ */
+ private final float falpha;
+
+ /**
+ * The ColorSpace. Null means the default sRGB space.
+ *
+ * @see #getColor(String)
+ * @see #getColorSpace()
+ * @see #getColorComponents(float[])
+ * @serial the color space for this color
+ * @since 1.2
+ */
+ private final ColorSpace cs;
+
+ /**
+ * The paint context for this solid color. Package visible for use in
+ * subclass.
+ */
+ transient ColorPaintContext context;
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * red, green, and blue values, which must be given as integers in the
+ * range of 0-255. Alpha will default to 255 (opaque). When drawing to
+ * screen, the actual color may be adjusted to the best match of hardware
+ * capabilities.
+ *
+ * @param red the red component of the RGB value
+ * @param green the green component of the RGB value
+ * @param blue the blue component of the RGB value
+ * @throws IllegalArgumentException if the values are out of range 0-255
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getRGB()
+ * @see #Color(int, int, int, int)
+ */
+ public Color(int red, int green, int blue)
+ {
+ this(red, green, blue, 255);
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * red, green, blue, and alpha values, which must be given as integers in
+ * the range of 0-255. When drawing to screen, the actual color may be
+ * adjusted to the best match of hardware capabilities.
+ *
+ * @param red the red component of the RGB value
+ * @param green the green component of the RGB value
+ * @param blue the blue component of the RGB value
+ * @param alpha the alpha value of the color
+ * @throws IllegalArgumentException if the values are out of range 0-255
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getAlpha()
+ * @see #getRGB()
+ */
+ public Color(int red, int green, int blue, int alpha)
+ {
+ if ((red & 255) != red || (green & 255) != green || (blue & 255) != blue
+ || (alpha & 255) != alpha)
+ throw new IllegalArgumentException("Bad RGB values"
+ +" red=0x"+Integer.toHexString(red)
+ +" green=0x"+Integer.toHexString(green)
+ +" blue=0x"+Integer.toHexString(blue)
+ +" alpha=0x"+Integer.toHexString(alpha) );
+
+ value = (alpha << 24) | (red << 16) | (green << 8) | blue;
+ falpha = 1;
+ cs = null;
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * RGB value. The blue value is in bits 0-7, green in bits 8-15, and
+ * red in bits 16-23. The other bits are ignored. The alpha value is set
+ * to 255 (opaque). When drawing to screen, the actual color may be
+ * adjusted to the best match of hardware capabilities.
+ *
+ * @param value the RGB value
+ * @see ColorModel#getRGBdefault()
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getRGB()
+ * @see #Color(int, boolean)
+ */
+ public Color(int value)
+ {
+ this(value, false);
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * RGB value. The blue value is in bits 0-7, green in bits 8-15, and
+ * red in bits 16-23. The alpha value is in bits 24-31, unless hasalpha
+ * is false, in which case alpha is set to 255. When drawing to screen, the
+ * actual color may be adjusted to the best match of hardware capabilities.
+ *
+ * @param value the RGB value
+ * @param hasalpha true if value includes the alpha
+ * @see ColorModel#getRGBdefault()
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getAlpha()
+ * @see #getRGB()
+ */
+ public Color(int value, boolean hasalpha)
+ {
+ // Note: SystemColor calls this constructor, setting falpha to 0; but
+ // code in getRGBComponents correctly reports falpha as 1.0 to the user
+ // for all instances of SystemColor since frgbvalue is left null here.
+ if (hasalpha)
+ falpha = ((value & ALPHA_MASK) >> 24) / 255f;
+ else
+ {
+ value |= ALPHA_MASK;
+ falpha = 1;
+ }
+ this.value = value;
+ cs = null;
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * RGB values. These must be in the range of 0.0-1.0. Alpha is assigned
+ * the value of 1.0 (opaque). When drawing to screen, the actual color may
+ * be adjusted to the best match of hardware capabilities.
+ *
+ * @param red the red component of the RGB value
+ * @param green the green component of the RGB value
+ * @param blue the blue component of the RGB value
+ * @throws IllegalArgumentException tf the values are out of range 0.0f-1.0f
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getRGB()
+ * @see #Color(float, float, float, float)
+ */
+ public Color(float red, float green, float blue)
+ {
+ this(red, green, blue, 1.0f);
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * RGB and alpha values. These must be in the range of 0.0-1.0. When drawing
+ * to screen, the actual color may be adjusted to the best match of
+ * hardware capabilities.
+ *
+ * @param red the red component of the RGB value
+ * @param green the green component of the RGB value
+ * @param blue the blue component of the RGB value
+ * @param alpha the alpha value of the color
+ * @throws IllegalArgumentException tf the values are out of range 0.0f-1.0f
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getAlpha()
+ * @see #getRGB()
+ */
+ public Color(float red, float green, float blue, float alpha)
+ {
+ value = convert(red, green, blue, alpha);
+ frgbvalue = new float[] {red, green, blue};
+ falpha = alpha;
+ cs = null;
+ }
+
+ /**
+ * Creates a color in the given ColorSpace with the specified alpha. The
+ * array must be non-null and have enough elements for the color space
+ * (for example, RGB requires 3 elements, CMYK requires 4). When drawing
+ * to screen, the actual color may be adjusted to the best match of
+ * hardware capabilities.
+ *
+ * @param space the color space of components
+ * @param components the color components, except alpha
+ * @param alpha the alpha value of the color
+ * @throws NullPointerException if cpsace or components is null
+ * @throws ArrayIndexOutOfBoundsException if components is too small
+ * @throws IllegalArgumentException if alpha or any component is out of range
+ * @see #getComponents(float[])
+ * @see #getColorComponents(float[])
+ */
+ public Color(ColorSpace space, float[] components, float alpha)
+ {
+ frgbvalue = space.toRGB(components);
+ fvalue = components;
+ falpha = alpha;
+ cs = space;
+ value = convert(frgbvalue[0], frgbvalue[1], frgbvalue[2], alpha);
+ }
+
+ /**
+ * Returns the red value for this color, as an integer in the range 0-255
+ * in the sRGB color space.
+ *
+ * @return the red value for this color
+ * @see #getRGB()
+ */
+ public int getRed()
+ {
+ // Do not inline getRGB() to value, because of SystemColor.
+ return (getRGB() & RED_MASK) >> 16;
+ }
+
+ /**
+ * Returns the green value for this color, as an integer in the range 0-255
+ * in the sRGB color space.
+ *
+ * @return the green value for this color
+ * @see #getRGB()
+ */
+ public int getGreen()
+ {
+ // Do not inline getRGB() to value, because of SystemColor.
+ return (getRGB() & GREEN_MASK) >> 8;
+ }
+
+ /**
+ * Returns the blue value for this color, as an integer in the range 0-255
+ * in the sRGB color space.
+ *
+ * @return the blue value for this color
+ * @see #getRGB()
+ */
+ public int getBlue()
+ {
+ // Do not inline getRGB() to value, because of SystemColor.
+ return getRGB() & BLUE_MASK;
+ }
+
+ /**
+ * Returns the alpha value for this color, as an integer in the range 0-255.
+ *
+ * @return the alpha value for this color
+ * @see #getRGB()
+ */
+ public int getAlpha()
+ {
+ // Do not inline getRGB() to value, because of SystemColor.
+ return (getRGB() & ALPHA_MASK) >>> 24;
+ }
+
+ /**
+ * Returns the RGB value for this color, in the sRGB color space. The blue
+ * value will be in bits 0-7, green in 8-15, red in 16-23, and alpha value in
+ * 24-31.
+ *
+ * @return the RGB value for this color
+ * @see ColorModel#getRGBdefault()
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getAlpha()
+ */
+ public int getRGB()
+ {
+ return value;
+ }
+
+ /**
+ * Returns a brighter version of this color. This is done by increasing the
+ * RGB values by an arbitrary scale factor. The new color is opaque (an
+ * alpha of 255). Note that this method and the <code>darker()</code>
+ * method are not necessarily inverses.
+ *
+ * @return a brighter version of this color
+ * @see #darker()
+ */
+ public Color brighter()
+ {
+ // Do not inline getRGB() to this.value, because of SystemColor.
+ int value = getRGB();
+ int red = (value & RED_MASK) >> 16;
+ int green = (value & GREEN_MASK) >> 8;
+ int blue = value & BLUE_MASK;
+ // We have to special case 0-2 because they won't scale by division.
+ red = red < 3 ? 3 : (int) Math.min(255, red / BRIGHT_SCALE);
+ green = green < 3 ? 3 : (int) Math.min(255, green / BRIGHT_SCALE);
+ blue = blue < 3 ? 3 : (int) Math.min(255, blue / BRIGHT_SCALE);
+ return new Color(red, green, blue, 255);
+ }
+
+ /**
+ * Returns a darker version of this color. This is done by decreasing the
+ * RGB values by an arbitrary scale factor. The new color is opaque (an
+ * alpha of 255). Note that this method and the <code>brighter()</code>
+ * method are not necessarily inverses.
+ *
+ * @return a darker version of this color
+ * @see #brighter()
+ */
+ public Color darker()
+ {
+ // Do not inline getRGB() to this.value, because of SystemColor.
+ int value = getRGB();
+ return new Color((int) (((value & RED_MASK) >> 16) * BRIGHT_SCALE),
+ (int) (((value & GREEN_MASK) >> 8) * BRIGHT_SCALE),
+ (int) ((value & BLUE_MASK) * BRIGHT_SCALE), 255);
+ }
+
+ /**
+ * Returns a hash value for this color. This is simply the color in 8-bit
+ * precision, in the format 0xAARRGGBB (alpha, red, green, blue).
+ *
+ * @return a hash value for this color
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Tests this object for equality against the specified object. This will
+ * be true if and only if the specified object is an instance of
+ * <code>Color</code> and has the same 8-bit integer red, green, and blue
+ * values as this object. Note that two colors may be slightly different
+ * as float values, but round to the same integer values. Also note that
+ * this does not accurately compare SystemColors, since that class does
+ * not store its internal data in RGB format like regular colors.
+ *
+ * @param obj the object to compare to
+ * @return true if the specified object is semantically equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ return obj instanceof Color && ((Color) obj).value == value;
+ }
+
+ /**
+ * Returns a string representation of this object. Subclasses may return
+ * any desired format, except for null, but this implementation returns
+ * <code>getClass().getName() + "[r=" + getRed() + ",g=" + getGreen()
+ * + ",b=" + getBlue() + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[r=" + ((value & RED_MASK) >> 16)
+ + ",g=" + ((value & GREEN_MASK) >> 8) + ",b=" + (value & BLUE_MASK)
+ + ']';
+ }
+
+ /**
+ * Converts the specified string to a number, using Integer.decode, and
+ * creates a new instance of <code>Color</code> from the value. The alpha
+ * value will be 255 (opaque).
+ *
+ * @param str the numeric color string
+ * @return a new instance of <code>Color</code> for the string
+ * @throws NumberFormatException if the string cannot be parsed
+ * @throws NullPointerException if the string is null
+ * @see Integer#decode(String)
+ * @see #Color(int)
+ * @since 1.1
+ */
+ public static Color decode(String str)
+ {
+ return new Color(Integer.decode(str).intValue(), false);
+ }
+
+ /**
+ * Returns a new instance of <code>Color</code> from the value of the
+ * system property named by the specified string. If the property does not
+ * exist, or cannot be parsed, then <code>null</code> will be returned.
+ *
+ * @param prop the system property to retrieve
+ * @throws SecurityException if getting the property is denied
+ * @see #getColor(String, Color)
+ * @see Integer#getInteger(String)
+ */
+ public static Color getColor(String prop)
+ {
+ return getColor(prop, null);
+ }
+
+ /**
+ * Returns a new instance of <code>Color</code> from the value of the
+ * system property named by the specified string. If the property does
+ * not exist, or cannot be parsed, then the default color value will be
+ * returned.
+ *
+ * @param prop the system property to retrieve
+ * @param defcolor the default color
+ * @throws SecurityException if getting the property is denied
+ * @see Integer#getInteger(String)
+ */
+ public static Color getColor(String prop, Color defcolor)
+ {
+ Integer val = Integer.getInteger(prop, null);
+ return val == null ? defcolor
+ : new Color(val.intValue(), false);
+ }
+
+ /**
+ * Returns a new instance of <code>Color</code> from the value of the
+ * system property named by the specified string. If the property does
+ * not exist, or cannot be parsed, then the default RGB value will be
+ * used to create a return value.
+ *
+ * @param prop the system property to retrieve
+ * @param defrgb the default RGB value
+ * @throws SecurityException if getting the property is denied
+ * @see #getColor(String, Color)
+ * @see Integer#getInteger(String, int)
+ */
+ public static Color getColor(String prop, int defrgb)
+ {
+ Color c = getColor(prop, null);
+ return c == null ? new Color(defrgb, false) : c;
+ }
+
+ /**
+ * Converts from the HSB (hue, saturation, brightness) color model to the
+ * RGB (red, green, blue) color model. The hue may be any floating point;
+ * it's fractional portion is used to select the angle in the HSB model.
+ * The saturation and brightness must be between 0 and 1. The result is
+ * suitable for creating an RGB color with the one-argument constructor.
+ *
+ * @param hue the hue of the HSB value
+ * @param saturation the saturation of the HSB value
+ * @param brightness the brightness of the HSB value
+ * @return the RGB value
+ * @see #getRGB()
+ * @see #Color(int)
+ * @see ColorModel#getRGBdefault()
+ */
+ public static int HSBtoRGB(float hue, float saturation, float brightness)
+ {
+ if (saturation == 0)
+ return convert(brightness, brightness, brightness, 0);
+ if (saturation < 0 || saturation > 1 || brightness < 0 || brightness > 1)
+ throw new IllegalArgumentException();
+ hue = hue - (float) Math.floor(hue);
+ int i = (int) (6 * hue);
+ float f = 6 * hue - i;
+ float p = brightness * (1 - saturation);
+ float q = brightness * (1 - saturation * f);
+ float t = brightness * (1 - saturation * (1 - f));
+ switch (i)
+ {
+ case 0:
+ return convert(brightness, t, p, 0);
+ case 1:
+ return convert(q, brightness, p, 0);
+ case 2:
+ return convert(p, brightness, t, 0);
+ case 3:
+ return convert(p, q, brightness, 0);
+ case 4:
+ return convert(t, p, brightness, 0);
+ case 5:
+ return convert(brightness, p, q, 0);
+ default:
+ throw new InternalError("impossible");
+ }
+ }
+
+ /**
+ * Converts from the RGB (red, green, blue) color model to the HSB (hue,
+ * saturation, brightness) color model. If the array is null, a new one
+ * is created, otherwise it is recycled. The results will be in the range
+ * 0.0-1.0 if the inputs are in the range 0-255.
+ *
+ * @param red the red part of the RGB value
+ * @param green the green part of the RGB value
+ * @param blue the blue part of the RGB value
+ * @param array an array for the result (at least 3 elements), or null
+ * @return the array containing HSB value
+ * @throws ArrayIndexOutOfBoundsException of array is too small
+ * @see #getRGB()
+ * @see #Color(int)
+ * @see ColorModel#getRGBdefault()
+ */
+ public static float[] RGBtoHSB(int red, int green, int blue, float array[])
+ {
+ if (array == null)
+ array = new float[3];
+ // Calculate brightness.
+ int min;
+ int max;
+ if (red < green)
+ {
+ min = red;
+ max = green;
+ }
+ else
+ {
+ min = green;
+ max = red;
+ }
+ if (blue > max)
+ max = blue;
+ else if (blue < min)
+ min = blue;
+ array[2] = max / 255f;
+ // Calculate saturation.
+ if (max == 0)
+ array[1] = 0;
+ else
+ array[1] = (max - min) / max;
+ // Calculate hue.
+ if (array[1] == 0)
+ array[0] = 0;
+ else
+ {
+ float delta = (max - min) * 6;
+ if (red == max)
+ array[0] = (green - blue) / delta;
+ else if (green == max)
+ array[0] = 1f / 3 + (blue - red) / delta;
+ else
+ array[0] = 2f / 3 + (red - green) / delta;
+ if (array[0] < 0)
+ array[0]++;
+ }
+ return array;
+ }
+
+ /**
+ * Returns a new instance of <code>Color</code> based on the specified
+ * HSB values. The hue may be any floating point; it's fractional portion
+ * is used to select the angle in the HSB model. The saturation and
+ * brightness must be between 0 and 1.
+ *
+ * @param hue the hue of the HSB value
+ * @param saturation the saturation of the HSB value
+ * @param brightness the brightness of the HSB value
+ * @return the new <code>Color</code> object
+ */
+ public static Color getHSBColor(float hue, float saturation,
+ float brightness)
+ {
+ return new Color(HSBtoRGB(hue, saturation, brightness), false);
+ }
+
+ /**
+ * Returns a float array with the red, green, and blue components, and the
+ * alpha value, in the default sRGB space, with values in the range 0.0-1.0.
+ * If the array is null, a new one is created, otherwise it is recycled.
+ *
+ * @param array the array to put results into (at least 4 elements), or null
+ * @return the RGB components and alpha value
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ */
+ public float[] getRGBComponents(float[] array)
+ {
+ if (array == null)
+ array = new float[4];
+ getRGBColorComponents(array);
+ // Stupid serialization issues require this check.
+ array[3] = (falpha == 0 && frgbvalue == null
+ ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha);
+ return array;
+ }
+
+ /**
+ * Returns a float array with the red, green, and blue components, in the
+ * default sRGB space, with values in the range 0.0-1.0. If the array is
+ * null, a new one is created, otherwise it is recycled.
+ *
+ * @param array the array to put results into (at least 3 elements), or null
+ * @return the RGB components
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ */
+ public float[] getRGBColorComponents(float[] array)
+ {
+ if (array == null)
+ array = new float[3];
+ else if (array == frgbvalue)
+ return array; // Optimization for getColorComponents(float[]).
+ if (frgbvalue == null)
+ {
+ // Do not inline getRGB() to this.value, because of SystemColor.
+ int value = getRGB();
+ frgbvalue = new float[] { ((value & RED_MASK) >> 16) / 255f,
+ ((value & GREEN_MASK) >> 8) / 255f,
+ (value & BLUE_MASK) / 255f };
+ }
+ array[0] = frgbvalue[0];
+ array[1] = frgbvalue[1];
+ array[2] = frgbvalue[2];
+ return array;
+ }
+
+ /**
+ * Returns a float array containing the color and alpha components of this
+ * color in the ColorSpace it was created with (the constructors which do
+ * not take a ColorSpace parameter use a default sRGB ColorSpace). If the
+ * array is null, a new one is created, otherwise it is recycled, and must
+ * have at least one more position than components used in the color space.
+ *
+ * @param array the array to put results into, or null
+ * @return the original color space components and alpha value
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ */
+ public float[] getComponents(float[] array)
+ {
+ int numComponents = cs == null ? 3 : cs.getNumComponents();
+ if (array == null)
+ array = new float[1 + numComponents];
+ getColorComponents(array);
+ // Stupid serialization issues require this check.
+ array[numComponents] = (falpha == 0 && frgbvalue == null
+ ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha);
+ return array;
+ }
+
+ /**
+ * Returns a float array containing the color components of this color in
+ * the ColorSpace it was created with (the constructors which do not take
+ * a ColorSpace parameter use a default sRGB ColorSpace). If the array is
+ * null, a new one is created, otherwise it is recycled, and must have at
+ * least as many positions as used in the color space.
+ *
+ * @param array the array to put results into, or null
+ * @return the original color space components
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ */
+ public float[] getColorComponents(float[] array)
+ {
+ int numComponents = cs == null ? 3 : cs.getNumComponents();
+ if (array == null)
+ array = new float[numComponents];
+ if (fvalue == null) // If fvalue is null, cs should be null too.
+ fvalue = getRGBColorComponents(frgbvalue);
+ System.arraycopy(fvalue, 0, array, 0, numComponents);
+ return array;
+ }
+
+ /**
+ * Returns a float array containing the color and alpha components of this
+ * color in the given ColorSpace. If the array is null, a new one is
+ * created, otherwise it is recycled, and must have at least one more
+ * position than components used in the color space.
+ *
+ * @param space the color space to translate to
+ * @param array the array to put results into, or null
+ * @return the color space components and alpha value
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ * @throws NullPointerException if space is null
+ */
+ public float[] getComponents(ColorSpace space, float[] array)
+ {
+ int numComponents = space.getNumComponents();
+ if (array == null)
+ array = new float[1 + numComponents];
+ getColorComponents(space, array);
+ // Stupid serialization issues require this check.
+ array[numComponents] = (falpha == 0 && frgbvalue == null
+ ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha);
+ return array;
+ }
+
+ /**
+ * Returns a float array containing the color components of this color in
+ * the given ColorSpace. If the array is null, a new one is created,
+ * otherwise it is recycled, and must have at least as many positions as
+ * used in the color space.
+ *
+ * @param space the color space to translate to
+ * @return the color space components
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ * @throws NullPointerException if space is null
+ */
+ public float[] getColorComponents(ColorSpace space, float[] array)
+ {
+ float[] components = space.fromRGB(getRGBColorComponents(frgbvalue));
+ if (array == null)
+ return components;
+ System.arraycopy(components, 0, array, 0, components.length);
+ return array;
+ }
+
+ /**
+ * Returns the color space of this color. Except for the constructor which
+ * takes a ColorSpace argument, this will be an implementation of
+ * ColorSpace.CS_sRGB.
+ *
+ * @return the color space
+ */
+ public ColorSpace getColorSpace()
+ {
+ return cs == null ? ColorSpace.getInstance(ColorSpace.CS_sRGB) : cs;
+ }
+
+ /**
+ * Returns a paint context, used for filling areas of a raster scan with
+ * this color. Since the color is constant across the entire rectangle, and
+ * since it is always in sRGB space, this implementation returns the same
+ * object, regardless of the parameters. Subclasses, however, may have a
+ * mutable result.
+ *
+ * @param cm the requested color model
+ * @param deviceBounds the bounding box in device coordinates, ignored
+ * @param userBounds the bounding box in user coordinates, ignored
+ * @param xform the bounds transformation, ignored
+ * @param hints any rendering hints, ignored
+ * @return a context for painting this solid color
+ */
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds,
+ AffineTransform xform,
+ RenderingHints hints)
+ {
+ if (context == null || !context.getColorModel().equals(cm))
+ context = new ColorPaintContext(cm,value);
+ return context;
+ }
+
+ /**
+ * Returns the transparency level of this color.
+ *
+ * @return one of {@link #OPAQUE}, {@link #BITMASK}, or {@link #TRANSLUCENT}
+ */
+ public int getTransparency()
+ {
+ // Do not inline getRGB() to this.value, because of SystemColor.
+ int alpha = getRGB() & ALPHA_MASK;
+ return alpha == (255 << 24) ? OPAQUE : alpha == 0 ? BITMASK : TRANSLUCENT;
+ }
+
+ /**
+ * Converts float values to integer value.
+ *
+ * @param red the red value
+ * @param green the green value
+ * @param blue the blue value
+ * @param alpha the alpha value
+ * @return the integer value made of 8-bit sections
+ * @throws IllegalArgumentException if parameters are out of range 0.0-1.0
+ */
+ private static int convert(float red, float green, float blue, float alpha)
+ {
+ if (red < 0 || red > 1 || green < 0 || green > 1 || blue < 0 || blue > 1
+ || alpha < 0 || alpha > 1)
+ throw new IllegalArgumentException("Bad RGB values");
+ int redval = Math.round(255 * red);
+ int greenval = Math.round(255 * green);
+ int blueval = Math.round(255 * blue);
+ int alphaval = Math.round(255 * alpha);
+ return (alphaval << 24) | (redval << 16) | (greenval << 8) | blueval;
+ }
+} // class Color
diff --git a/libjava/classpath/java/awt/ColorPaintContext.java b/libjava/classpath/java/awt/ColorPaintContext.java
new file mode 100644
index 00000000000..759ba9d8734
--- /dev/null
+++ b/libjava/classpath/java/awt/ColorPaintContext.java
@@ -0,0 +1,195 @@
+/* ColorPaintContext.java -- context for painting solid colors
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+
+/**
+ * This class provides a paint context which will fill a rectanglar region of
+ * a raster scan with the given color. However, it is not yet completely
+ * implemented.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+class ColorPaintContext implements PaintContext
+{
+ /**
+ * The color to fill any raster with. Package visible for use in
+ * SystemColor.
+ */
+ final int color;
+ final ColorModel colorModel;
+
+ private ColorRaster cachedRaster;
+
+
+ /**
+ * Create the context for a given color.
+ *
+ * @param c The solid color to use.
+ */
+ ColorPaintContext(int colorRGB)
+ {
+ this(ColorModel.getRGBdefault(), colorRGB);
+ }
+
+ /**
+ * Create the context for a given color.
+ *
+ * @param cm The color model of this context.
+ * @param c The solid color to use.
+ */
+ ColorPaintContext(ColorModel cm,int colorRGB)
+ {
+ color = colorRGB;
+ colorModel = cm;
+ }
+
+ /**
+ * Release the resources allocated for the paint. As the color is constant,
+ * there aren't any resources.
+ */
+ public void dispose()
+ {
+ }
+
+ /**
+ * Return the color model of this context.
+ *
+ * @return the context color model
+ */
+ public ColorModel getColorModel()
+ {
+ return colorModel;
+ }
+
+ /**
+ * Return a raster containing the colors for the graphics operation.
+ *
+ * @param x the x-coordinate, in device space
+ * @param y the y-coordinate, in device space
+ * @param width the width, in device space
+ * @param height the height, in device space
+ * @return a raster for the given area and color
+ */
+ public Raster getRaster(int x, int y, int width, int height)
+ {
+ if( cachedRaster == null
+ || cachedRaster.getWidth() < width
+ || cachedRaster.getHeight() < height)
+ {
+ cachedRaster = new ColorRaster(colorModel, 0, 0, width, height, color);
+ }
+ return cachedRaster.createChild(0 ,0 ,width ,height ,x ,y , null);
+ }
+
+ /**
+ * A ColorRaster is a raster that is completely filled with one color. The
+ * data layout is taken from the color model given to the constructor.
+ */
+ private class ColorRaster extends Raster
+ {
+
+ /**
+ * Create a raster that is compaltible with the given color model and
+ * filled with the given color.
+ * @param cm The color model for this raster.
+ * @param x The smallest horizontal corrdinate in the raster.
+ * @param y The smallest vertical coordinate in the raster.
+ * @param width The width of the raster.
+ * @param height The height of the raster.
+ * @param rgbPixel The RGB value of the color for this raster.
+ */
+ ColorRaster(ColorModel cm,int x, int y, int width, int height, int rgbPixel)
+ {
+ super(cm.createCompatibleSampleModel(width,height),new Point(x,y));
+ Object pixel = cm.getDataElements(rgbPixel,null);
+ getSampleModel().setDataElements(0, 0,
+ width, height,
+ multiplyData(pixel,null,width*height),
+ dataBuffer);
+ }
+
+
+
+ private Object multiplyData(Object src, Object dest, int factor)
+ {
+ Object from;
+ int srcLength = 0;
+ if (src instanceof byte[])
+ {
+ srcLength = ((byte[])src).length;
+
+ if (dest == null) dest = new byte[factor * srcLength];
+ }
+ else if (src instanceof short[])
+ {
+ srcLength = ((short[])src).length;
+ if (dest == null) dest = new short[factor * srcLength];
+ }
+ else if (src instanceof int[])
+ {
+ srcLength = ((int[]) src).length;
+ if (dest == null) dest = new int[factor * srcLength];
+ }
+ else
+ {
+ throw new ClassCastException("Unknown data buffer type");
+ }
+
+ System.arraycopy(src,0,dest,0,srcLength);
+
+ int count = 1;
+ while(count*2 < factor)
+ {
+ System.arraycopy(dest, 0, dest, count * srcLength, count*srcLength);
+ count *= 2;
+ }
+
+ if(factor > count)
+ System.arraycopy(dest,0, dest, count * srcLength,
+ (factor - count) * srcLength );
+
+ return dest;
+ }
+
+ }
+
+} // class ColorPaintContext
diff --git a/libjava/classpath/java/awt/Component.java b/libjava/classpath/java/awt/Component.java
new file mode 100644
index 00000000000..4491904d0a4
--- /dev/null
+++ b/libjava/classpath/java/awt/Component.java
@@ -0,0 +1,6017 @@
+/* Component.java -- a graphics component
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.dnd.DropTarget;
+import java.awt.event.ActionEvent;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.HierarchyBoundsListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.event.InputEvent;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+import java.awt.im.InputContext;
+import java.awt.im.InputMethodRequests;
+import java.awt.image.BufferStrategy;
+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.LightweightPeer;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * The root of all evil. All graphical representations are subclasses of this
+ * giant class, which is designed for screen display and user interaction.
+ * This class can be extended directly to build a lightweight component (one
+ * not associated with a native window); lightweight components must reside
+ * inside a heavyweight window.
+ *
+ * <p>This class is Serializable, which has some big implications. A user can
+ * save the state of all graphical components in one VM, and reload them in
+ * another. Note that this class will only save Serializable listeners, and
+ * ignore the rest, without causing any serialization exceptions. However, by
+ * making a listener serializable, and adding it to another element, you link
+ * in that entire element to the state of this component. To get around this,
+ * use the idiom shown in the example below - make listeners non-serializable
+ * in inner classes, rather than using this object itself as the listener, if
+ * external objects do not need to save the state of this object.
+ *
+ * <pre>
+ * import java.awt.*;
+ * import java.awt.event.*;
+ * import java.io.Serializable;
+ * class MyApp implements Serializable
+ * {
+ * BigObjectThatShouldNotBeSerializedWithAButton bigOne;
+ * // Serializing aButton will not suck in an instance of MyApp, with its
+ * // accompanying field bigOne.
+ * Button aButton = new Button();
+ * class MyActionListener implements ActionListener
+ * {
+ * public void actionPerformed(ActionEvent e)
+ * {
+ * System.out.println("Hello There");
+ * }
+ * }
+ * MyApp()
+ * {
+ * aButton.addActionListener(new MyActionListener());
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Status: Incomplete. The event dispatch mechanism is implemented. All
+ * other methods defined in the J2SE 1.3 API javadoc exist, but are mostly
+ * incomplete or only stubs; except for methods relating to the Drag and
+ * Drop, Input Method, and Accessibility frameworks: These methods are
+ * present but commented out.
+ *
+ * @author original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status still missing 1.4 support
+ */
+public abstract class Component
+ implements ImageObserver, MenuContainer, Serializable
+{
+ // Word to the wise - this file is huge. Search for '\f' (^L) for logical
+ // sectioning by fields, public API, private API, and nested classes.
+
+
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -7644114512714619750L;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> method to indicate
+ * that the component wishes to be aligned to the top relative to
+ * other components.
+ *
+ * @see #getAlignmentY()
+ */
+ public static final float TOP_ALIGNMENT = 0;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> and
+ * <code>getAlignmentX</code> methods to indicate
+ * that the component wishes to be aligned to the center relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ * @see #getAlignmentY()
+ */
+ public static final float CENTER_ALIGNMENT = 0.5f;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> method to indicate
+ * that the component wishes to be aligned to the bottom relative to
+ * other components.
+ *
+ * @see #getAlignmentY()
+ */
+ public static final float BOTTOM_ALIGNMENT = 1;
+
+ /**
+ * Constant returned by the <code>getAlignmentX</code> method to indicate
+ * that the component wishes to be aligned to the right relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ */
+ public static final float RIGHT_ALIGNMENT = 1;
+
+ /**
+ * Constant returned by the <code>getAlignmentX</code> method to indicate
+ * that the component wishes to be aligned to the left relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ */
+ public static final float LEFT_ALIGNMENT = 0;
+
+ /**
+ * Make the treelock a String so that it can easily be identified
+ * in debug dumps. We clone the String in order to avoid a conflict in
+ * the unlikely event that some other package uses exactly the same string
+ * as a lock object.
+ */
+ static final Object treeLock = new String("AWT_TREE_LOCK");
+
+ // Serialized fields from the serialization spec.
+
+ /**
+ * The x position of the component in the parent's coordinate system.
+ *
+ * @see #getLocation()
+ * @serial the x position
+ */
+ int x;
+
+ /**
+ * The y position of the component in the parent's coordinate system.
+ *
+ * @see #getLocation()
+ * @serial the y position
+ */
+ int y;
+
+ /**
+ * The component width.
+ *
+ * @see #getSize()
+ * @serial the width
+ */
+ int width;
+
+ /**
+ * The component height.
+ *
+ * @see #getSize()
+ * @serial the height
+ */
+ int height;
+
+ /**
+ * The foreground color for the component. This may be null.
+ *
+ * @see #getForeground()
+ * @see #setForeground(Color)
+ * @serial the foreground color
+ */
+ Color foreground;
+
+ /**
+ * The background color for the component. This may be null.
+ *
+ * @see #getBackground()
+ * @see #setBackground(Color)
+ * @serial the background color
+ */
+ Color background;
+
+ /**
+ * The default font used in the component. This may be null.
+ *
+ * @see #getFont()
+ * @see #setFont(Font)
+ * @serial the font
+ */
+ Font font;
+
+ /**
+ * The font in use by the peer, or null if there is no peer.
+ *
+ * @serial the peer's font
+ */
+ Font peerFont;
+
+ /**
+ * The cursor displayed when the pointer is over this component. This may
+ * be null.
+ *
+ * @see #getCursor()
+ * @see #setCursor(Cursor)
+ */
+ Cursor cursor;
+
+ /**
+ * The locale for the component.
+ *
+ * @see #getLocale()
+ * @see #setLocale(Locale)
+ */
+ Locale locale = Locale.getDefault ();
+
+ /**
+ * True if the object should ignore repaint events (usually because it is
+ * not showing).
+ *
+ * @see #getIgnoreRepaint()
+ * @see #setIgnoreRepaint(boolean)
+ * @serial true to ignore repaints
+ * @since 1.4
+ */
+ boolean ignoreRepaint;
+
+ /**
+ * True when the object is visible (although it is only showing if all
+ * ancestors are likewise visible). For component, this defaults to true.
+ *
+ * @see #isVisible()
+ * @see #setVisible(boolean)
+ * @serial true if visible
+ */
+ boolean visible = true;
+
+ /**
+ * True if the object is enabled, meaning it can interact with the user.
+ * For component, this defaults to true.
+ *
+ * @see #isEnabled()
+ * @see #setEnabled(boolean)
+ * @serial true if enabled
+ */
+ boolean enabled = true;
+
+ /**
+ * True if the object is valid. This is set to false any time a size
+ * adjustment means the component need to be layed out again.
+ *
+ * @see #isValid()
+ * @see #validate()
+ * @see #invalidate()
+ * @serial true if layout is valid
+ */
+ boolean valid;
+
+ /**
+ * The DropTarget for drag-and-drop operations.
+ *
+ * @see #getDropTarget()
+ * @see #setDropTarget(DropTarget)
+ * @serial the drop target, or null
+ * @since 1.2
+ */
+ DropTarget dropTarget;
+
+ /**
+ * The list of popup menus for this component.
+ *
+ * @see #add(PopupMenu)
+ * @serial the list of popups
+ */
+ Vector popups;
+
+ /**
+ * The component's name. May be null, in which case a default name is
+ * generated on the first use.
+ *
+ * @see #getName()
+ * @see #setName(String)
+ * @serial the name
+ */
+ String name;
+
+ /**
+ * True once the user has set the name. Note that the user may set the name
+ * to null.
+ *
+ * @see #name
+ * @see #getName()
+ * @see #setName(String)
+ * @serial true if the name has been explicitly set
+ */
+ boolean nameExplicitlySet;
+
+ /**
+ * Indicates if the object can be focused. Defaults to true for components.
+ *
+ * @see #isFocusable()
+ * @see #setFocusable(boolean)
+ * @since 1.4
+ */
+ boolean focusable = true;
+
+ /**
+ * Tracks whether this component's {@link #isFocusTraversable}
+ * method has been overridden.
+ *
+ * @since 1.4
+ */
+ int isFocusTraversableOverridden;
+
+ /**
+ * The focus traversal keys, if not inherited from the parent or
+ * default keyboard focus manager. These sets will contain only
+ * AWTKeyStrokes that represent press and release events to use as
+ * focus control.
+ *
+ * @see #getFocusTraversalKeys(int)
+ * @see #setFocusTraversalKeys(int, Set)
+ * @since 1.4
+ */
+ Set[] focusTraversalKeys;
+
+ /**
+ * True if focus traversal keys are enabled. This defaults to true for
+ * Component. If this is true, keystrokes in focusTraversalKeys are trapped
+ * and processed automatically rather than being passed on to the component.
+ *
+ * @see #getFocusTraversalKeysEnabled()
+ * @see #setFocusTraversalKeysEnabled(boolean)
+ * @since 1.4
+ */
+ boolean focusTraversalKeysEnabled = true;
+
+ /**
+ * Cached information on the minimum size. Should have been transient.
+ *
+ * @serial ignore
+ */
+ Dimension minSize;
+
+ /**
+ * Cached information on the preferred size. Should have been transient.
+ *
+ * @serial ignore
+ */
+ Dimension prefSize;
+
+ /**
+ * Set to true if an event is to be handled by this component, false if
+ * it is to be passed up the hierarcy.
+ *
+ * @see #dispatchEvent(AWTEvent)
+ * @serial true to process event locally
+ */
+ boolean newEventsOnly;
+
+ /**
+ * Set by subclasses to enable event handling of particular events, and
+ * left alone when modifying listeners. For component, this defaults to
+ * enabling only input methods.
+ *
+ * @see #enableInputMethods(boolean)
+ * @see AWTEvent
+ * @serial the mask of events to process
+ */
+ long eventMask = AWTEvent.INPUT_ENABLED_EVENT_MASK;
+
+ /**
+ * Describes all registered PropertyChangeListeners.
+ *
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #firePropertyChange(String, Object, Object)
+ * @serial the property change listeners
+ * @since 1.2
+ */
+ PropertyChangeSupport changeSupport;
+
+ /**
+ * True if the component has been packed (layed out).
+ *
+ * @serial true if this is packed
+ */
+ boolean isPacked;
+
+ /**
+ * The serialization version for this class. Currently at version 4.
+ *
+ * XXX How do we handle prior versions?
+ *
+ * @serial the serialization version
+ */
+ int componentSerializedDataVersion = 4;
+
+ /**
+ * The accessible context associated with this component. This is only set
+ * by subclasses.
+ *
+ * @see #getAccessibleContext()
+ * @serial the accessibility context
+ * @since 1.2
+ */
+ AccessibleContext accessibleContext;
+
+
+ // Guess what - listeners are special cased in serialization. See
+ // readObject and writeObject.
+
+ /** Component listener chain. */
+ transient ComponentListener componentListener;
+
+ /** Focus listener chain. */
+ transient FocusListener focusListener;
+
+ /** Key listener chain. */
+ transient KeyListener keyListener;
+
+ /** Mouse listener chain. */
+ transient MouseListener mouseListener;
+
+ /** Mouse motion listener chain. */
+ transient MouseMotionListener mouseMotionListener;
+
+ /**
+ * Mouse wheel listener chain.
+ *
+ * @since 1.4
+ */
+ transient MouseWheelListener mouseWheelListener;
+
+ /**
+ * Input method listener chain.
+ *
+ * @since 1.2
+ */
+ transient InputMethodListener inputMethodListener;
+
+ /**
+ * Hierarcy listener chain.
+ *
+ * @since 1.3
+ */
+ transient HierarchyListener hierarchyListener;
+
+ /**
+ * Hierarcy bounds listener chain.
+ *
+ * @since 1.3
+ */
+ transient HierarchyBoundsListener hierarchyBoundsListener;
+
+ // Anything else is non-serializable, and should be declared "transient".
+
+ /** The parent. */
+ transient Container parent;
+
+ /** The associated native peer. */
+ transient ComponentPeer peer;
+
+ /** The preferred component orientation. */
+ transient ComponentOrientation orientation = ComponentOrientation.UNKNOWN;
+
+ /**
+ * The associated graphics configuration.
+ *
+ * @since 1.4
+ */
+ transient GraphicsConfiguration graphicsConfig;
+
+ /**
+ * The buffer strategy for repainting.
+ *
+ * @since 1.4
+ */
+ transient BufferStrategy bufferStrategy;
+
+ /**
+ * true if requestFocus was called on this component when its
+ * top-level ancestor was not focusable.
+ */
+ private transient FocusEvent pendingFocusRequest = null;
+
+ /**
+ * The system properties that affect image updating.
+ */
+ private static transient boolean incrementalDraw;
+ private static transient Long redrawRate;
+
+ static
+ {
+ incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw");
+ redrawRate = Long.getLong ("awt.image.redrawrate");
+ }
+
+ // Public and protected API.
+
+ /**
+ * Default constructor for subclasses. When Component is extended directly,
+ * it forms a lightweight component that must be hosted in an opaque native
+ * container higher in the tree.
+ */
+ protected Component()
+ {
+ }
+
+ /**
+ * Returns the name of this component.
+ *
+ * @return the name of this component
+ * @see #setName(String)
+ * @since 1.1
+ */
+ public String getName()
+ {
+ if (name == null && ! nameExplicitlySet)
+ name = generateName();
+ return name;
+ }
+
+ /**
+ * Sets the name of this component to the specified name.
+ *
+ * @param name the new name of this component
+ * @see #getName()
+ * @since 1.1
+ */
+ public void setName(String name)
+ {
+ nameExplicitlySet = true;
+ this.name = name;
+ }
+
+ /**
+ * Returns the parent of this component.
+ *
+ * @return the parent of this component
+ */
+ public Container getParent()
+ {
+ return parent;
+ }
+
+ /**
+ * Returns the native windowing system peer for this component. Only the
+ * platform specific implementation code should call this method.
+ *
+ * @return the peer for this component
+ * @deprecated user programs should not directly manipulate peers; use
+ * {@link #isDisplayable()} instead
+ */
+ // Classpath's Gtk peers rely on this.
+ public ComponentPeer getPeer()
+ {
+ return peer;
+ }
+
+ /**
+ * Set the associated drag-and-drop target, which receives events when this
+ * is enabled.
+ *
+ * @param dt the new drop target
+ * @see #isEnabled()
+ */
+ public void setDropTarget(DropTarget dt)
+ {
+ this.dropTarget = dt;
+ }
+
+ /**
+ * Gets the associated drag-and-drop target, if there is one.
+ *
+ * @return the drop target
+ */
+ public DropTarget getDropTarget()
+ {
+ return dropTarget;
+ }
+
+ /**
+ * Returns the graphics configuration of this component, if there is one.
+ * If it has not been set, it is inherited from the parent.
+ *
+ * @return the graphics configuration, or null
+ * @since 1.3
+ */
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ return getGraphicsConfigurationImpl();
+ }
+
+ /**
+ * Returns the object used for synchronization locks on this component
+ * when performing tree and layout functions.
+ *
+ * @return the synchronization lock for this component
+ */
+ public final Object getTreeLock()
+ {
+ return treeLock;
+ }
+
+ /**
+ * Returns the toolkit in use for this component. The toolkit is associated
+ * with the frame this component belongs to.
+ *
+ * @return the toolkit for this component
+ */
+ public Toolkit getToolkit()
+ {
+ if (peer != null)
+ {
+ Toolkit tk = peer.getToolkit();
+ if (tk != null)
+ return tk;
+ }
+ // Get toolkit for lightweight component.
+ if (parent != null)
+ return parent.getToolkit();
+ return Toolkit.getDefaultToolkit();
+ }
+
+ /**
+ * Tests whether or not this component is valid. A invalid component needs
+ * to have its layout redone.
+ *
+ * @return true if this component is valid
+ * @see #validate()
+ * @see #invalidate()
+ */
+ public boolean isValid()
+ {
+ return valid;
+ }
+
+ /**
+ * Tests if the component is displayable. It must be connected to a native
+ * screen resource, and all its ancestors must be displayable. A containment
+ * hierarchy is made displayable when a window is packed or made visible.
+ *
+ * @return true if the component is displayable
+ * @see Container#add(Component)
+ * @see Container#remove(Component)
+ * @see Window#pack()
+ * @see Window#show()
+ * @see Window#dispose()
+ * @since 1.2
+ */
+ public boolean isDisplayable()
+ {
+ if (parent != null)
+ return parent.isDisplayable();
+ return false;
+ }
+
+ /**
+ * Tests whether or not this component is visible. Except for top-level
+ * frames, components are initially visible.
+ *
+ * @return true if the component is visible
+ * @see #setVisible(boolean)
+ */
+ public boolean isVisible()
+ {
+ return visible;
+ }
+
+ /**
+ * Tests whether or not this component is actually being shown on
+ * the screen. This will be true if and only if it this component is
+ * visible and its parent components are all visible.
+ *
+ * @return true if the component is showing on the screen
+ * @see #setVisible(boolean)
+ */
+ public boolean isShowing()
+ {
+ if (! visible || peer == null)
+ return false;
+
+ return parent == null ? true : parent.isShowing();
+ }
+
+ /**
+ * Tests whether or not this component is enabled. Components are enabled
+ * by default, and must be enabled to receive user input or generate events.
+ *
+ * @return true if the component is enabled
+ * @see #setEnabled(boolean)
+ */
+ public boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ /**
+ * Enables or disables this component. The component must be enabled to
+ * receive events (except that lightweight components always receive mouse
+ * events).
+ *
+ * @param enabled true to enable this component
+ *
+ * @see #isEnabled()
+ * @see #isLightweight()
+ *
+ * @since 1.1
+ */
+ public void setEnabled(boolean enabled)
+ {
+ enable(enabled);
+ }
+
+ /**
+ * Enables this component.
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void enable()
+ {
+ this.enabled = true;
+ if (peer != null)
+ peer.setEnabled (true);
+ }
+
+ /**
+ * Enables or disables this component.
+ *
+ * @param enabled true to enable this component
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void enable(boolean enabled)
+ {
+ if (enabled)
+ enable();
+ else
+ disable();
+ }
+
+ /**
+ * Disables this component.
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void disable()
+ {
+ this.enabled = false;
+ if (peer != null)
+ peer.setEnabled (false);
+ }
+
+ /**
+ * Checks if this image is painted to an offscreen image buffer that is
+ * later copied to screen (double buffering reduces flicker). This version
+ * returns false, so subclasses must override it if they provide double
+ * buffering.
+ *
+ * @return true if this is double buffered; defaults to false
+ */
+ public boolean isDoubleBuffered()
+ {
+ return false;
+ }
+
+ /**
+ * Enables or disables input method support for this component. By default,
+ * components have this enabled. Input methods are given the opportunity
+ * to process key events before this component and its listeners.
+ *
+ * @param enable true to enable input method processing
+ * @see #processKeyEvent(KeyEvent)
+ * @since 1.2
+ */
+ public void enableInputMethods(boolean enable)
+ {
+ if (enable)
+ eventMask |= AWTEvent.INPUT_ENABLED_EVENT_MASK;
+ else
+ eventMask &= ~AWTEvent.INPUT_ENABLED_EVENT_MASK;
+ }
+
+ /**
+ * Makes this component visible or invisible. Note that it wtill might
+ * not show the component, if a parent is invisible.
+ *
+ * @param visible true to make this component visible
+ *
+ * @see #isVisible()
+ *
+ * @since 1.1
+ */
+ public void setVisible(boolean visible)
+ {
+ // Inspection by subclassing shows that Sun's implementation calls
+ // show(boolean) which then calls show() or hide(). It is the show()
+ // method that is overriden in subclasses like Window.
+ show(visible);
+ }
+
+ /**
+ * Makes this component visible on the screen.
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void show()
+ {
+ // We must set visible before showing the peer. Otherwise the
+ // peer could post paint events before visible is true, in which
+ // case lightweight components are not initially painted --
+ // Container.paint first calls isShowing () before painting itself
+ // and its children.
+ if(!isVisible())
+ {
+ this.visible = true;
+ if (peer != null)
+ peer.setVisible(true);
+ invalidate();
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ /**
+ * Makes this component visible or invisible.
+ *
+ * @param visible true to make this component visible
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void show(boolean visible)
+ {
+ if (visible)
+ show();
+ else
+ hide();
+ }
+
+ /**
+ * Hides this component so that it is no longer shown on the screen.
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void hide()
+ {
+ if (isVisible())
+ {
+ if (peer != null)
+ peer.setVisible(false);
+ this.visible = false;
+ invalidate();
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ /**
+ * Returns this component's foreground color. If not set, this is inherited
+ * from the parent.
+ *
+ * @return this component's foreground color, or null
+ * @see #setForeground(Color)
+ */
+ public Color getForeground()
+ {
+ if (foreground != null)
+ return foreground;
+ return parent == null ? SystemColor.windowText : parent.getForeground();
+ }
+
+ /**
+ * Sets this component's foreground color to the specified color. This is a
+ * bound property.
+ *
+ * @param c the new foreground color
+ * @see #getForeground()
+ */
+ public void setForeground(Color c)
+ {
+ firePropertyChange("foreground", foreground, c);
+ if (peer != null)
+ peer.setForeground(c);
+ foreground = c;
+ }
+
+ /**
+ * Tests if the foreground was explicitly set, or just inherited from the
+ * parent.
+ *
+ * @return true if the foreground has been set
+ * @since 1.4
+ */
+ public boolean isForegroundSet()
+ {
+ return foreground != null;
+ }
+
+ /**
+ * Returns this component's background color. If not set, this is inherited
+ * from the parent.
+ *
+ * @return the background color of the component, or null
+ * @see #setBackground(Color)
+ */
+ public Color getBackground()
+ {
+ if (background != null)
+ return background;
+ return parent == null ? SystemColor.window : parent.getBackground();
+ }
+
+ /**
+ * Sets this component's background color to the specified color. The parts
+ * of the component affected by the background color may by system dependent.
+ * This is a bound property.
+ *
+ * @param c the new background color
+ * @see #getBackground()
+ */
+ public void setBackground(Color c)
+ {
+ // return if the background is already set to that color.
+ if (background != null && c != null)
+ if (background.equals(c))
+ return;
+ // If c is null, inherit from closest ancestor whose bg is set.
+ if (c == null && parent != null)
+ c = parent.getBackground();
+ firePropertyChange("background", background, c);
+ if (peer != null && c != null)
+ peer.setBackground(c);
+ background = c;
+ }
+
+ /**
+ * Tests if the background was explicitly set, or just inherited from the
+ * parent.
+ *
+ * @return true if the background has been set
+ * @since 1.4
+ */
+ public boolean isBackgroundSet()
+ {
+ return background != null;
+ }
+
+ /**
+ * Returns the font in use for this component. If not set, this is inherited
+ * from the parent.
+ *
+ * @return the font for this component
+ * @see #setFont(Font)
+ */
+ public Font getFont()
+ {
+ if (font != null)
+ return font;
+
+ if (parent != null)
+ return parent.getFont ();
+ else
+ return new Font ("Dialog", Font.PLAIN, 12);
+ }
+
+ /**
+ * Sets the font for this component to the specified font. This is a bound
+ * property.
+ *
+ * @param newFont the new font for this component
+ *
+ * @see #getFont()
+ */
+ public void setFont(Font newFont)
+ {
+ if (font == newFont)
+ return;
+
+ Font oldFont = font;
+ font = newFont;
+ if (peer != null)
+ peer.setFont(font);
+ firePropertyChange("font", oldFont, newFont);
+ invalidate();
+ }
+
+ /**
+ * Tests if the font was explicitly set, or just inherited from the parent.
+ *
+ * @return true if the font has been set
+ * @since 1.4
+ */
+ public boolean isFontSet()
+ {
+ return font != null;
+ }
+
+ /**
+ * Returns the locale for this component. If this component does not
+ * have a locale, the locale of the parent component is returned.
+ *
+ * @return the locale for this component
+ * @throws IllegalComponentStateException if it has no locale or parent
+ * @see #setLocale(Locale)
+ * @since 1.1
+ */
+ public Locale getLocale()
+ {
+ if (locale != null)
+ return locale;
+ if (parent == null)
+ throw new IllegalComponentStateException
+ ("Component has no parent: can't determine Locale");
+ return parent.getLocale();
+ }
+
+ /**
+ * Sets the locale for this component to the specified locale. This is a
+ * bound property.
+ *
+ * @param newLocale the new locale for this component
+ */
+ public void setLocale(Locale newLocale)
+ {
+ if (locale == newLocale)
+ return;
+
+ Locale oldLocale = locale;
+ locale = newLocale;
+ firePropertyChange("locale", oldLocale, newLocale);
+ // New writing/layout direction or more/less room for localized labels.
+ invalidate();
+ }
+
+ /**
+ * Returns the color model of the device this componet is displayed on.
+ *
+ * @return this object's color model
+ * @see Toolkit#getColorModel()
+ */
+ public ColorModel getColorModel()
+ {
+ GraphicsConfiguration config = getGraphicsConfiguration();
+ return config != null ? config.getColorModel()
+ : getToolkit().getColorModel();
+ }
+
+ /**
+ * Returns the location of this component's top left corner relative to
+ * its parent component. This may be outdated, so for synchronous behavior,
+ * you should use a component listner.
+ *
+ * @return the location of this component
+ * @see #setLocation(int, int)
+ * @see #getLocationOnScreen()
+ * @since 1.1
+ */
+ public Point getLocation()
+ {
+ return location ();
+ }
+
+ /**
+ * Returns the location of this component's top left corner in screen
+ * coordinates.
+ *
+ * @return the location of this component in screen coordinates
+ * @throws IllegalComponentStateException if the component is not showing
+ */
+ public Point getLocationOnScreen()
+ {
+ if (! isShowing())
+ throw new IllegalComponentStateException("component "
+ + getClass().getName()
+ + " not showing");
+ // We know peer != null here.
+ return peer.getLocationOnScreen();
+ }
+
+ /**
+ * Returns the location of this component's top left corner relative to
+ * its parent component.
+ *
+ * @return the location of this component
+ * @deprecated use {@link #getLocation()} instead
+ */
+ public Point location()
+ {
+ return new Point (x, y);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param x the new X coordinate of this component
+ * @param y the new Y coordinate of this component
+ * @see #getLocation()
+ * @see #setBounds(int, int, int, int)
+ */
+ public void setLocation(int x, int y)
+ {
+ move (x, y);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param x the new X coordinate of this component
+ * @param y the new Y coordinate of this component
+ * @deprecated use {@link #setLocation(int, int)} instead
+ */
+ public void move(int x, int y)
+ {
+ setBounds(x, y, this.width, this.height);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param p new coordinates for this component
+ * @throws NullPointerException if p is null
+ * @see #getLocation()
+ * @see #setBounds(int, int, int, int)
+ * @since 1.1
+ */
+ public void setLocation(Point p)
+ {
+ setLocation(p.x, p.y);
+ }
+
+ /**
+ * Returns the size of this object.
+ *
+ * @return the size of this object
+ * @see #setSize(int, int)
+ * @since 1.1
+ */
+ public Dimension getSize()
+ {
+ return size ();
+ }
+
+ /**
+ * Returns the size of this object.
+ *
+ * @return the size of this object
+ * @deprecated use {@link #getSize()} instead
+ */
+ public Dimension size()
+ {
+ return new Dimension (width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified width and height.
+ *
+ * @param width the new width of this component
+ * @param height the new height of this component
+ * @see #getSize()
+ * @see #setBounds(int, int, int, int)
+ */
+ public void setSize(int width, int height)
+ {
+ resize (width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param width the new width of the component
+ * @param height the new height of the component
+ * @deprecated use {@link #setSize(int, int)} instead
+ */
+ public void resize(int width, int height)
+ {
+ setBounds(this.x, this.y, width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param d the new size of this component
+ * @throws NullPointerException if d is null
+ * @see #setSize(int, int)
+ * @see #setBounds(int, int, int, int)
+ * @since 1.1
+ */
+ public void setSize(Dimension d)
+ {
+ resize (d);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param d the new size of this component
+ * @throws NullPointerException if d is null
+ * @deprecated use {@link #setSize(Dimension)} instead
+ */
+ public void resize(Dimension d)
+ {
+ resize (d.width, d.height);
+ }
+
+ /**
+ * Returns a bounding rectangle for this component. Note that the
+ * returned rectange is relative to this component's parent, not to
+ * the screen.
+ *
+ * @return the bounding rectangle for this component
+ * @see #setBounds(int, int, int, int)
+ * @see #getLocation()
+ * @see #getSize()
+ */
+ public Rectangle getBounds()
+ {
+ return bounds ();
+ }
+
+ /**
+ * Returns a bounding rectangle for this component. Note that the
+ * returned rectange is relative to this component's parent, not to
+ * the screen.
+ *
+ * @return the bounding rectangle for this component
+ * @deprecated use {@link #getBounds()} instead
+ */
+ public Rectangle bounds()
+ {
+ return new Rectangle (x, y, width, height);
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified values.
+ * Note that these coordinates are relative to the parent, not to the screen.
+ *
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @see #getBounds()
+ * @see #setLocation(int, int)
+ * @see #setLocation(Point)
+ * @see #setSize(int, int)
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public void setBounds(int x, int y, int w, int h)
+ {
+ reshape (x, y, w, h);
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified values.
+ * Note that these coordinates are relative to the parent, not to the screen.
+ *
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ * @deprecated use {@link #setBounds(int, int, int, int)} instead
+ */
+ 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;
+
+ if (this.x == x && this.y == y
+ && this.width == width && this.height == height)
+ return;
+ 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 ())
+ {
+ boolean shouldRepaintParent = false;
+ boolean shouldRepaintSelf = false;
+
+ if (parent != null)
+ {
+ Rectangle parentBounds = parent.getBounds();
+ Rectangle oldBounds = new Rectangle(parent.getX() + oldx,
+ parent.getY() + oldy,
+ oldwidth, oldheight);
+ Rectangle newBounds = new Rectangle(parent.getX() + x,
+ parent.getY() + y,
+ width, height);
+ shouldRepaintParent = parentBounds.intersects(oldBounds);
+ shouldRepaintSelf = parentBounds.intersects(newBounds);
+ }
+
+ if (shouldRepaintParent && parent != null)
+ parent.repaint(oldx, oldy, oldwidth, oldheight);
+ if (shouldRepaintSelf)
+ repaint();
+ }
+
+ // Only post event if this component is visible and has changed size.
+ if (isShowing ()
+ && (oldx != x || oldy != y))
+ {
+ 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);
+ }
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified
+ * rectangle. Note that these coordinates are relative to the parent, not
+ * to the screen.
+ *
+ * @param r the new bounding rectangle
+ * @throws NullPointerException if r is null
+ * @see #getBounds()
+ * @see #setLocation(Point)
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public void setBounds(Rectangle r)
+ {
+ setBounds (r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Gets the x coordinate of the upper left corner. This is more efficient
+ * than getBounds().x or getLocation().x.
+ *
+ * @return the current x coordinate
+ * @since 1.2
+ */
+ public int getX()
+ {
+ return x;
+ }
+
+ /**
+ * Gets the y coordinate of the upper left corner. This is more efficient
+ * than getBounds().y or getLocation().y.
+ *
+ * @return the current y coordinate
+ * @since 1.2
+ */
+ public int getY()
+ {
+ return y;
+ }
+
+ /**
+ * Gets the width of the component. This is more efficient than
+ * getBounds().width or getSize().width.
+ *
+ * @return the current width
+ * @since 1.2
+ */
+ public int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Gets the height of the component. This is more efficient than
+ * getBounds().height or getSize().height.
+ *
+ * @return the current width
+ * @since 1.2
+ */
+ public int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the bounds of this component. This allows reuse of an existing
+ * rectangle, if r is non-null.
+ *
+ * @param r the rectangle to use, or null
+ * @return the bounds
+ */
+ public Rectangle getBounds(Rectangle r)
+ {
+ if (r == null)
+ r = new Rectangle();
+ r.x = x;
+ r.y = y;
+ r.width = width;
+ r.height = height;
+ return r;
+ }
+
+ /**
+ * Returns the size of this component. This allows reuse of an existing
+ * dimension, if d is non-null.
+ *
+ * @param d the dimension to use, or null
+ * @return the size
+ */
+ public Dimension getSize(Dimension d)
+ {
+ if (d == null)
+ d = new Dimension();
+ d.width = width;
+ d.height = height;
+ return d;
+ }
+
+ /**
+ * Returns the location of this component. This allows reuse of an existing
+ * point, if p is non-null.
+ *
+ * @param p the point to use, or null
+ * @return the location
+ */
+ public Point getLocation(Point p)
+ {
+ if (p == null)
+ p = new Point();
+ p.x = x;
+ p.y = y;
+ return p;
+ }
+
+ /**
+ * Tests if this component is opaque. All "heavyweight" (natively-drawn)
+ * components are opaque. A component is opaque if it draws all pixels in
+ * the bounds; a lightweight component is partially transparent if it lets
+ * pixels underneath show through. Subclasses that guarantee that all pixels
+ * will be drawn should override this.
+ *
+ * @return true if this is opaque
+ * @see #isLightweight()
+ * @since 1.2
+ */
+ public boolean isOpaque()
+ {
+ return ! isLightweight();
+ }
+
+ /**
+ * Return whether the component is lightweight. That means the component has
+ * no native peer, but is displayable. This applies to subclasses of
+ * Component not in this package, such as javax.swing.
+ *
+ * @return true if the component has a lightweight peer
+ * @see #isDisplayable()
+ * @since 1.2
+ */
+ public boolean isLightweight()
+ {
+ return peer instanceof LightweightPeer;
+ }
+
+ /**
+ * Returns the component's preferred size.
+ *
+ * @return the component's preferred size
+ * @see #getMinimumSize()
+ * @see LayoutManager
+ */
+ public Dimension getPreferredSize()
+ {
+ return preferredSize();
+ }
+
+ /**
+ * Returns the component's preferred size.
+ *
+ * @return the component's preferred size
+ * @deprecated use {@link #getPreferredSize()} instead
+ */
+ public Dimension preferredSize()
+ {
+ if (prefSize == null)
+ if (peer == null)
+ return new Dimension(width, height);
+ else
+ prefSize = peer.getPreferredSize();
+ return prefSize;
+ }
+
+ /**
+ * Returns the component's minimum size.
+ *
+ * @return the component's minimum size
+ * @see #getPreferredSize()
+ * @see LayoutManager
+ */
+ public Dimension getMinimumSize()
+ {
+ return minimumSize();
+ }
+
+ /**
+ * Returns the component's minimum size.
+ *
+ * @return the component's minimum size
+ * @deprecated use {@link #getMinimumSize()} instead
+ */
+ public Dimension minimumSize()
+ {
+ if (minSize == null)
+ minSize = (peer != null ? peer.getMinimumSize()
+ : new Dimension(width, height));
+ return minSize;
+ }
+
+ /**
+ * Returns the component's maximum size.
+ *
+ * @return the component's maximum size
+ * @see #getMinimumSize()
+ * @see #getPreferredSize()
+ * @see LayoutManager
+ */
+ public Dimension getMaximumSize()
+ {
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Returns the preferred horizontal alignment of this component. The value
+ * returned will be between {@link #LEFT_ALIGNMENT} and
+ * {@link #RIGHT_ALIGNMENT}, inclusive.
+ *
+ * @return the preferred horizontal alignment of this component
+ */
+ public float getAlignmentX()
+ {
+ return CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Returns the preferred vertical alignment of this component. The value
+ * returned will be between {@link #TOP_ALIGNMENT} and
+ * {@link #BOTTOM_ALIGNMENT}, inclusive.
+ *
+ * @return the preferred vertical alignment of this component
+ */
+ public float getAlignmentY()
+ {
+ return CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Calls the layout manager to re-layout the component. This is called
+ * during validation of a container in most cases.
+ *
+ * @see #validate()
+ * @see LayoutManager
+ */
+ public void doLayout()
+ {
+ layout ();
+ }
+
+ /**
+ * Calls the layout manager to re-layout the component. This is called
+ * during validation of a container in most cases.
+ *
+ * @deprecated use {@link #doLayout()} instead
+ */
+ public void layout()
+ {
+ // Nothing to do unless we're a container.
+ }
+
+ /**
+ * Called to ensure that the layout for this component is valid. This is
+ * usually called on containers.
+ *
+ * @see #invalidate()
+ * @see #doLayout()
+ * @see LayoutManager
+ * @see Container#validate()
+ */
+ public void validate()
+ {
+ valid = true;
+ }
+
+ /**
+ * Invalidates this component and all of its parent components. This will
+ * cause them to have their layout redone. This is called frequently, so
+ * make it fast.
+ */
+ public void invalidate()
+ {
+ valid = false;
+ prefSize = null;
+ minSize = null;
+ if (parent != null && parent.valid)
+ parent.invalidate();
+ }
+
+ /**
+ * Returns a graphics object for this component. Returns <code>null</code>
+ * if this component is not currently displayed on the screen.
+ *
+ * @return a graphics object for this component
+ * @see #paint(Graphics)
+ */
+ public Graphics getGraphics()
+ {
+ if (peer != null)
+ {
+ Graphics gfx = peer.getGraphics();
+ if (gfx != null)
+ return gfx;
+ // create graphics for lightweight:
+ Container parent = getParent();
+ if (parent != null)
+ {
+ gfx = parent.getGraphics();
+ Rectangle bounds = getBounds();
+ gfx.setClip(bounds);
+ gfx.translate(bounds.x, bounds.y);
+ return gfx;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the font metrics for the specified font in this component.
+ *
+ * @param font the font to retrieve metrics for
+ * @return the font metrics for the specified font
+ * @throws NullPointerException if font is null
+ * @see #getFont()
+ * @see Toolkit#getFontMetrics(Font)
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return peer == null ? getToolkit().getFontMetrics(font)
+ : peer.getFontMetrics(font);
+ }
+
+ /**
+ * Sets the cursor for this component to the specified cursor. The cursor
+ * is displayed when the point is contained by the component, and the
+ * component is visible, displayable, and enabled. This is inherited by
+ * subcomponents unless they set their own cursor.
+ *
+ * @param cursor the new cursor for this component
+ * @see #isEnabled()
+ * @see #isShowing()
+ * @see #getCursor()
+ * @see #contains(int, int)
+ * @see Toolkit#createCustomCursor(Image, Point, String)
+ */
+ public void setCursor(Cursor cursor)
+ {
+ this.cursor = cursor;
+ if (peer != null)
+ peer.setCursor(cursor);
+ }
+
+ /**
+ * Returns the cursor for this component. If not set, this is inherited
+ * from the parent, or from Cursor.getDefaultCursor().
+ *
+ * @return the cursor for this component
+ */
+ public Cursor getCursor()
+ {
+ if (cursor != null)
+ return cursor;
+ return parent != null ? parent.getCursor() : Cursor.getDefaultCursor();
+ }
+
+ /**
+ * Tests if the cursor was explicitly set, or just inherited from the parent.
+ *
+ * @return true if the cursor has been set
+ * @since 1.4
+ */
+ public boolean isCursorSet()
+ {
+ return cursor != null;
+ }
+
+ /**
+ * Paints this component on the screen. The clipping region in the graphics
+ * context will indicate the region that requires painting. This is called
+ * whenever the component first shows, or needs to be repaired because
+ * something was temporarily drawn on top. It is not necessary for
+ * subclasses to call <code>super.paint(g)</code>. Components with no area
+ * are not painted.
+ *
+ * @param g the graphics context for this paint job
+ * @see #update(Graphics)
+ */
+ public void paint(Graphics g)
+ {
+ // Paint the heavyweight peer
+ if (!isLightweight() && peer != null)
+ peer.paint(g);
+ }
+
+ /**
+ * 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
+ * relative to this component. Subclasses should call either
+ * <code>super.update(g)</code> or <code>paint(g)</code>.
+ *
+ * @param g the graphics context for this update
+ *
+ * @see #paint(Graphics)
+ * @see #repaint()
+ */
+ public void update(Graphics g)
+ {
+ if (!isLightweight())
+ {
+ Rectangle clip = g.getClipBounds();
+ if (clip == null)
+ g.clearRect(0, 0, width, height);
+ else
+ g.clearRect(clip.x, clip.y, clip.width, clip.height);
+ }
+
+ paint(g);
+ }
+
+ /**
+ * Paints this entire component, including any sub-components.
+ *
+ * @param g the graphics context for this paint job
+ *
+ * @see #paint(Graphics)
+ */
+ public void paintAll(Graphics g)
+ {
+ if (! visible)
+ return;
+ paint(g);
+ }
+
+ /**
+ * Repaint this entire component. The <code>update()</code> method
+ * on this component will be called as soon as possible.
+ *
+ * @see #update(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint()
+ {
+ repaint(0, 0, 0, width, height);
+ }
+
+ /**
+ * Repaint this entire component. The <code>update()</code> method on this
+ * component will be called in approximate the specified number of
+ * milliseconds.
+ *
+ * @param tm milliseconds before this component should be repainted
+ * @see #paint(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint(long tm)
+ {
+ repaint(tm, 0, 0, width, height);
+ }
+
+ /**
+ * Repaints the specified rectangular region within this component. The
+ * <code>update</code> method on this component will be called as soon as
+ * possible. The coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the upper left of the region to repaint
+ * @param y the Y coordinate of the upper left of the region to repaint
+ * @param w the width of the region to repaint
+ * @param h the height of the region to repaint
+ * @see #update(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint(int x, int y, int w, int h)
+ {
+ repaint(0, x, y, w, h);
+ }
+
+ /**
+ * Repaints the specified rectangular region within this component. The
+ * <code>update</code> method on this component will be called in
+ * approximately the specified number of milliseconds. The coordinates
+ * are relative to this component.
+ *
+ * @param tm milliseconds before this component should be repainted
+ * @param x the X coordinate of the upper left of the region to repaint
+ * @param y the Y coordinate of the upper left of the region to repaint
+ * @param width the width of the region to repaint
+ * @param height the height of the region to repaint
+ * @see #update(Graphics)
+ */
+ public void repaint(long tm, int x, int y, int width, int height)
+ {
+ // Handle lightweight repainting by forwarding to native parent
+ if (isLightweight() && parent != null)
+ {
+ if (parent != null)
+ parent.repaint(tm, x + getX(), y + getY(), width, height);
+ }
+ else if (peer != null)
+ peer.repaint(tm, x, y, width, height);
+ }
+
+ /**
+ * Prints this component. 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>paint()</code> method.
+ *
+ * @param g the graphics context of the print device
+ *
+ * @see #paint(Graphics)
+ */
+ public void print(Graphics g)
+ {
+ paint(g);
+ }
+
+ /**
+ * 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.
+ *
+ * @param g the graphics context of the print device
+ *
+ * @see #paintAll(Graphics)
+ */
+ public void printAll(Graphics g)
+ {
+ paintAll(g);
+ }
+
+ /**
+ * Called when an image has changed so that this component is repainted.
+ * This incrementally draws an image as more bits are available, when
+ * possible. Incremental drawing is enabled if the system property
+ * <code>awt.image.incrementalDraw</code> is not present or is true, in which
+ * case the redraw rate is set to 100ms or the value of the system property
+ * <code>awt.image.redrawrate</code>.
+ *
+ * <p>The coordinate system used depends on the particular flags.
+ *
+ * @param img the image that has been updated
+ * @param flags tlags as specified in <code>ImageObserver</code>
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ * @param w the width
+ * @param h the height
+ * @return false if the image is completely loaded, loading has been
+ * aborted, or an error has occurred. true if more updates are
+ * required.
+ * @see ImageObserver
+ * @see Graphics#drawImage(Image, int, int, Color, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver)
+ * @see ImageObserver#imageUpdate(Image, int, int, int, int, int)
+ */
+ public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
+ {
+ if ((flags & (FRAMEBITS | ALLBITS)) != 0)
+ repaint ();
+ else if ((flags & SOMEBITS) != 0)
+ {
+ if (incrementalDraw)
+ {
+ if (redrawRate != null)
+ {
+ long tm = redrawRate.longValue();
+ if (tm < 0)
+ tm = 0;
+ repaint (tm);
+ }
+ else
+ repaint (100);
+ }
+ }
+ return (flags & (ALLBITS | ABORT | ERROR)) == 0;
+ }
+
+ /**
+ * Creates an image from the specified producer.
+ *
+ * @param producer the image procedure to create the image from
+ * @return the resulting image
+ */
+ public Image createImage(ImageProducer producer)
+ {
+ // Sun allows producer to be null.
+ if (peer != null)
+ return peer.createImage(producer);
+ else
+ return getToolkit().createImage(producer);
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return the requested image, or null if it is not supported
+ */
+ public Image createImage (int width, int height)
+ {
+ Image returnValue = null;
+ if (!GraphicsEnvironment.isHeadless ())
+ {
+ if (isLightweight () && parent != null)
+ returnValue = parent.createImage (width, height);
+ else if (peer != null)
+ returnValue = peer.createImage (width, height);
+ }
+ return returnValue;
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return the requested image, or null if it is not supported
+ * @since 1.4
+ */
+ public VolatileImage createVolatileImage(int width, int height)
+ {
+ if (GraphicsEnvironment.isHeadless())
+ return null;
+ GraphicsConfiguration config = getGraphicsConfiguration();
+ return config == null ? null
+ : config.createCompatibleVolatileImage(width, height);
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images. The image
+ * will support the specified capabilities.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param caps the requested capabilities
+ * @return the requested image, or null if it is not supported
+ * @throws AWTException if a buffer with the capabilities cannot be created
+ * @since 1.4
+ */
+ public VolatileImage createVolatileImage(int width, int height,
+ ImageCapabilities caps)
+ throws AWTException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ return null;
+ GraphicsConfiguration config = getGraphicsConfiguration();
+ return config == null ? null
+ : config.createCompatibleVolatileImage(width, height, caps);
+ }
+
+ /**
+ * Prepares the specified image for rendering on this component.
+ *
+ * @param image the image to prepare for rendering
+ * @param observer the observer to notify of image preparation status
+ * @return true if the image is already fully prepared
+ * @throws NullPointerException if image is null
+ */
+ public boolean prepareImage(Image image, ImageObserver observer)
+ {
+ return prepareImage(image, image.getWidth(observer),
+ image.getHeight(observer), observer);
+ }
+
+ /**
+ * Prepares the specified image for rendering on this component at the
+ * specified scaled width and height
+ *
+ * @param image the image to prepare for rendering
+ * @param width the scaled width of the image
+ * @param height the scaled height of the image
+ * @param observer the observer to notify of image preparation status
+ * @return true if the image is already fully prepared
+ */
+ public boolean prepareImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ if (peer != null)
+ return peer.prepareImage(image, width, height, observer);
+ else
+ return getToolkit().prepareImage(image, width, height, observer);
+ }
+
+ /**
+ * Returns the status of the loading of the specified image. The value
+ * returned will be those flags defined in <code>ImageObserver</code>.
+ *
+ * @param image the image to check on
+ * @param observer the observer to notify of image loading progress
+ * @return the image observer flags indicating the status of the load
+ * @see #prepareImage(Image, int, int, ImageObserver)
+ * @see Toolkit#checkImage(Image, int, int, ImageObserver)
+ * @throws NullPointerException if image is null
+ */
+ public int checkImage(Image image, ImageObserver observer)
+ {
+ return checkImage(image, -1, -1, observer);
+ }
+
+ /**
+ * Returns the status of the loading of the specified image. The value
+ * returned will be those flags defined in <code>ImageObserver</code>.
+ *
+ * @param image the image to check on
+ * @param width the scaled image width
+ * @param height the scaled image height
+ * @param observer the observer to notify of image loading progress
+ * @return the image observer flags indicating the status of the load
+ * @see #prepareImage(Image, int, int, ImageObserver)
+ * @see Toolkit#checkImage(Image, int, int, ImageObserver)
+ */
+ 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);
+ }
+
+ /**
+ * Sets whether paint messages delivered by the operating system should be
+ * ignored. This does not affect messages from AWT, except for those
+ * triggered by OS messages. Setting this to true can allow faster
+ * performance in full-screen mode or page-flipping.
+ *
+ * @param ignoreRepaint the new setting for ignoring repaint events
+ * @see #getIgnoreRepaint()
+ * @see BufferStrategy
+ * @see GraphicsDevice#setFullScreenWindow(Window)
+ * @since 1.4
+ */
+ public void setIgnoreRepaint(boolean ignoreRepaint)
+ {
+ this.ignoreRepaint = ignoreRepaint;
+ }
+
+ /**
+ * Test whether paint events from the operating system are ignored.
+ *
+ * @return the status of ignoring paint events
+ * @see #setIgnoreRepaint(boolean)
+ * @since 1.4
+ */
+ public boolean getIgnoreRepaint()
+ {
+ return ignoreRepaint;
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is within this component
+ * @see #getComponentAt(int, int)
+ */
+ public boolean contains(int x, int y)
+ {
+ return inside (x, y);
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is within this component
+ * @deprecated use {@link #contains(int, int)} instead
+ */
+ public boolean inside(int x, int y)
+ {
+ return x >= 0 && y >= 0 && x < width && y < height;
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param p the point to test
+ * @return true if the point is within this component
+ * @throws NullPointerException if p is null
+ * @see #getComponentAt(Point)
+ * @since 1.1
+ */
+ public boolean contains(Point p)
+ {
+ return contains (p.x, p.y);
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param x the X coordinate to search for components at
+ * @param y the Y coordinate to search for components at
+ * @return the component at the specified location, or null
+ * @see #contains(int, int)
+ */
+ public Component getComponentAt(int x, int y)
+ {
+ return locate (x, y);
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param x the X coordinate to search for components at
+ * @param y the Y coordinate to search for components at
+ * @return the component at the specified location, or null
+ * @deprecated use {@link #getComponentAt(int, int)} instead
+ */
+ public Component locate(int x, int y)
+ {
+ return contains (x, y) ? this : null;
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param p the point to search for components at
+ * @return the component at the specified location, or null
+ * @throws NullPointerException if p is null
+ * @see #contains(Point)
+ * @since 1.1
+ */
+ public Component getComponentAt(Point p)
+ {
+ return getComponentAt (p.x, p.y);
+ }
+
+ /**
+ * AWT 1.0 event delivery.
+ *
+ * Deliver an AWT 1.0 event to this Component. This method simply
+ * calls {@link #postEvent}.
+ *
+ * @param e the event to deliver
+ * @deprecated use {@link #dispatchEvent (AWTEvent)} instead
+ */
+ public void deliverEvent (Event e)
+ {
+ postEvent (e);
+ }
+
+ /**
+ * Forwards AWT events to processEvent() if:<ul>
+ * <li>Events have been enabled for this type of event via
+ * <code>enableEvents()</code></li>,
+ * <li>There is at least one registered listener for this type of event</li>
+ * </ul>
+ *
+ * @param e the event to dispatch
+ */
+ public final void dispatchEvent(AWTEvent e)
+ {
+ // Some subclasses in the AWT package need to override this behavior,
+ // hence the use of dispatchEventImpl().
+ dispatchEventImpl(e);
+ if (peer != null && ! e.consumed)
+ peer.handleEvent(e);
+ }
+
+ /**
+ * AWT 1.0 event handler.
+ *
+ * This method simply calls handleEvent and returns the result.
+ *
+ * @param e the event to handle
+ * @return true if the event was handled, false otherwise
+ * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
+ */
+ public boolean postEvent (Event e)
+ {
+ boolean handled = handleEvent (e);
+
+ if (!handled && getParent() != null)
+ // FIXME: need to translate event coordinates to parent's
+ // coordinate space.
+ handled = getParent ().postEvent (e);
+
+ return handled;
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see ComponentEvent
+ * @see #removeComponentListener(ComponentListener)
+ * @see #getComponentListeners()
+ * @since 1.1
+ */
+ public synchronized void addComponentListener(ComponentListener listener)
+ {
+ componentListener = AWTEventMulticaster.add(componentListener, listener);
+ if (componentListener != null)
+ enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see ComponentEvent
+ * @see #addComponentListener(ComponentListener)
+ * @see #getComponentListeners()
+ * @since 1.1
+ */
+ public synchronized void removeComponentListener(ComponentListener listener)
+ {
+ componentListener = AWTEventMulticaster.remove(componentListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addComponentListener(ComponentListener)
+ * @see #removeComponentListener(ComponentListener)
+ * @since 1.4
+ */
+ public synchronized ComponentListener[] getComponentListeners()
+ {
+ return (ComponentListener[])
+ AWTEventMulticaster.getListeners(componentListener,
+ ComponentListener.class);
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see FocusEvent
+ * @see #removeFocusListener(FocusListener)
+ * @see #getFocusListeners()
+ * @since 1.1
+ */
+ public synchronized void addFocusListener(FocusListener listener)
+ {
+ focusListener = AWTEventMulticaster.add(focusListener, listener);
+ if (focusListener != null)
+ enableEvents(AWTEvent.FOCUS_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see FocusEvent
+ * @see #addFocusListener(FocusListener)
+ * @see #getFocusListeners()
+ * @since 1.1
+ */
+ public synchronized void removeFocusListener(FocusListener listener)
+ {
+ focusListener = AWTEventMulticaster.remove(focusListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addFocusListener(FocusListener)
+ * @see #removeFocusListener(FocusListener)
+ * @since 1.4
+ */
+ public synchronized FocusListener[] getFocusListeners()
+ {
+ return (FocusListener[])
+ AWTEventMulticaster.getListeners(focusListener, FocusListener.class);
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see HierarchyEvent
+ * @see #removeHierarchyListener(HierarchyListener)
+ * @see #getHierarchyListeners()
+ * @since 1.3
+ */
+ public synchronized void addHierarchyListener(HierarchyListener listener)
+ {
+ hierarchyListener = AWTEventMulticaster.add(hierarchyListener, listener);
+ if (hierarchyListener != null)
+ enableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see HierarchyEvent
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #getHierarchyListeners()
+ * @since 1.3
+ */
+ public synchronized void removeHierarchyListener(HierarchyListener listener)
+ {
+ hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #removeHierarchyListener(HierarchyListener)
+ * @since 1.4
+ */
+ public synchronized HierarchyListener[] getHierarchyListeners()
+ {
+ return (HierarchyListener[])
+ AWTEventMulticaster.getListeners(hierarchyListener,
+ HierarchyListener.class);
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see HierarchyEvent
+ * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #getHierarchyBoundsListeners()
+ * @since 1.3
+ */
+ public synchronized void
+ addHierarchyBoundsListener(HierarchyBoundsListener listener)
+ {
+ hierarchyBoundsListener =
+ AWTEventMulticaster.add(hierarchyBoundsListener, listener);
+ if (hierarchyBoundsListener != null)
+ enableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see HierarchyEvent
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #getHierarchyBoundsListeners()
+ * @since 1.3
+ */
+ public synchronized void
+ removeHierarchyBoundsListener(HierarchyBoundsListener listener)
+ {
+ hierarchyBoundsListener =
+ AWTEventMulticaster.remove(hierarchyBoundsListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
+ * @since 1.4
+ */
+ public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()
+ {
+ return (HierarchyBoundsListener[])
+ AWTEventMulticaster.getListeners(hierarchyBoundsListener,
+ HierarchyBoundsListener.class);
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see KeyEvent
+ * @see #removeKeyListener(KeyListener)
+ * @see #getKeyListeners()
+ * @since 1.1
+ */
+ public synchronized void addKeyListener(KeyListener listener)
+ {
+ keyListener = AWTEventMulticaster.add(keyListener, listener);
+ if (keyListener != null)
+ enableEvents(AWTEvent.KEY_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see KeyEvent
+ * @see #addKeyListener(KeyListener)
+ * @see #getKeyListeners()
+ * @since 1.1
+ */
+ public synchronized void removeKeyListener(KeyListener listener)
+ {
+ keyListener = AWTEventMulticaster.remove(keyListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addKeyListener(KeyListener)
+ * @see #removeKeyListener(KeyListener)
+ * @since 1.4
+ */
+ public synchronized KeyListener[] getKeyListeners()
+ {
+ return (KeyListener[])
+ AWTEventMulticaster.getListeners(keyListener, KeyListener.class);
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see #removeMouseListener(MouseListener)
+ * @see #getMouseListeners()
+ * @since 1.1
+ */
+ public synchronized void addMouseListener(MouseListener listener)
+ {
+ mouseListener = AWTEventMulticaster.add(mouseListener, listener);
+ if (mouseListener != null)
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see #addMouseListener(MouseListener)
+ * @see #getMouseListeners()
+ * @since 1.1
+ */
+ public synchronized void removeMouseListener(MouseListener listener)
+ {
+ mouseListener = AWTEventMulticaster.remove(mouseListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseListener(MouseListener)
+ * @see #removeMouseListener(MouseListener)
+ * @since 1.4
+ */
+ public synchronized MouseListener[] getMouseListeners()
+ {
+ return (MouseListener[])
+ AWTEventMulticaster.getListeners(mouseListener, MouseListener.class);
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see #removeMouseMotionListener(MouseMotionListener)
+ * @see #getMouseMotionListeners()
+ * @since 1.1
+ */
+ public synchronized void addMouseMotionListener(MouseMotionListener listener)
+ {
+ mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener);
+ if (mouseMotionListener != null)
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #getMouseMotionListeners()
+ * @since 1.1
+ */
+ public synchronized void removeMouseMotionListener(MouseMotionListener listener)
+ {
+ mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #removeMouseMotionListener(MouseMotionListener)
+ * @since 1.4
+ */
+ public synchronized MouseMotionListener[] getMouseMotionListeners()
+ {
+ return (MouseMotionListener[])
+ AWTEventMulticaster.getListeners(mouseMotionListener,
+ MouseMotionListener.class);
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see MouseWheelEvent
+ * @see #removeMouseWheelListener(MouseWheelListener)
+ * @see #getMouseWheelListeners()
+ * @since 1.4
+ */
+ public synchronized void addMouseWheelListener(MouseWheelListener listener)
+ {
+ mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, listener);
+ if (mouseWheelListener != null)
+ enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see MouseWheelEvent
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #getMouseWheelListeners()
+ * @since 1.4
+ */
+ public synchronized void removeMouseWheelListener(MouseWheelListener listener)
+ {
+ mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #removeMouseWheelListener(MouseWheelListener)
+ * @since 1.4
+ */
+ public synchronized MouseWheelListener[] getMouseWheelListeners()
+ {
+ return (MouseWheelListener[])
+ AWTEventMulticaster.getListeners(mouseWheelListener,
+ MouseWheelListener.class);
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener to add
+ * @see InputMethodEvent
+ * @see #removeInputMethodListener(InputMethodListener)
+ * @see #getInputMethodListeners()
+ * @see #getInputMethodRequests()
+ * @since 1.2
+ */
+ public synchronized void addInputMethodListener(InputMethodListener listener)
+ {
+ inputMethodListener = AWTEventMulticaster.add(inputMethodListener, listener);
+ if (inputMethodListener != null)
+ enableEvents(AWTEvent.INPUT_METHOD_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see InputMethodEvent
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #getInputMethodRequests()
+ * @since 1.2
+ */
+ public synchronized void removeInputMethodListener(InputMethodListener listener)
+ {
+ inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #removeInputMethodListener(InputMethodListener)
+ * @since 1.4
+ */
+ public synchronized InputMethodListener[] getInputMethodListeners()
+ {
+ return (InputMethodListener[])
+ AWTEventMulticaster.getListeners(inputMethodListener,
+ InputMethodListener.class);
+ }
+
+ /**
+ * Returns all registered EventListers of the given listenerType.
+ *
+ * @param listenerType the class of listeners to filter
+ * @return an array of registered listeners
+ * @see #getComponentListeners()
+ * @see #getFocusListeners()
+ * @see #getHierarchyListeners()
+ * @see #getHierarchyBoundsListeners()
+ * @see #getKeyListeners()
+ * @see #getMouseListeners()
+ * @see #getMouseMotionListeners()
+ * @see #getMouseWheelListeners()
+ * @see #getInputMethodListeners()
+ * @see #getPropertyChangeListeners()
+ * @since 1.3
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ if (listenerType == ComponentListener.class)
+ return getComponentListeners();
+ if (listenerType == FocusListener.class)
+ return getFocusListeners();
+ if (listenerType == HierarchyListener.class)
+ return getHierarchyListeners();
+ if (listenerType == HierarchyBoundsListener.class)
+ return getHierarchyBoundsListeners();
+ if (listenerType == KeyListener.class)
+ return getKeyListeners();
+ if (listenerType == MouseListener.class)
+ return getMouseListeners();
+ if (listenerType == MouseMotionListener.class)
+ return getMouseMotionListeners();
+ if (listenerType == MouseWheelListener.class)
+ return getMouseWheelListeners();
+ if (listenerType == InputMethodListener.class)
+ return getInputMethodListeners();
+ if (listenerType == PropertyChangeListener.class)
+ return getPropertyChangeListeners();
+ return (EventListener[]) Array.newInstance(listenerType, 0);
+ }
+
+ /**
+ * Returns the input method request handler, for subclasses which support
+ * on-the-spot text input. By default, input methods are handled by AWT,
+ * and this returns null.
+ *
+ * @return the input method handler, null by default
+ * @since 1.2
+ */
+ public InputMethodRequests getInputMethodRequests()
+ {
+ return null;
+ }
+
+ /**
+ * Gets the input context of this component, which is inherited from the
+ * parent unless this is overridden.
+ *
+ * @return the text input context
+ * @since 1.2
+ */
+ public InputContext getInputContext()
+ {
+ return parent == null ? null : parent.getInputContext();
+ }
+
+ /**
+ * Enables the specified events. The events to enable are specified
+ * by OR-ing together the desired masks from <code>AWTEvent</code>.
+ *
+ * <p>Events are enabled by default when a listener is attached to the
+ * component for that event type. This method can be used by subclasses
+ * to ensure the delivery of a specified event regardless of whether
+ * or not a listener is attached.
+ *
+ * @param eventsToEnable the desired events to enable
+ * @see #processEvent(AWTEvent)
+ * @see #disableEvents(long)
+ * @see AWTEvent
+ * @since 1.1
+ */
+ protected final void enableEvents(long eventsToEnable)
+ {
+ 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);
+ }
+
+ /**
+ * Disables the specified events. The events to disable are specified
+ * by OR-ing together the desired masks from <code>AWTEvent</code>.
+ *
+ * @param eventsToDisable the desired events to disable
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected final void disableEvents(long eventsToDisable)
+ {
+ eventMask &= ~eventsToDisable;
+ // forward new event mask to peer?
+ }
+
+ /**
+ * This is called by the EventQueue if two events with the same event id
+ * and owner component are queued. Returns a new combined event, or null if
+ * no combining is done. The coelesced events are currently mouse moves
+ * (intermediate ones are discarded) and paint events (a merged paint is
+ * created in place of the two events).
+ *
+ * @param existingEvent the event on the queue
+ * @param newEvent the new event that might be entered on the queue
+ * @return null if both events are kept, or the replacement coelesced event
+ */
+ protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
+ {
+ switch (existingEvent.id)
+ {
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ // Just drop the old (intermediate) event and return the new one.
+ return newEvent;
+ case PaintEvent.PAINT:
+ case PaintEvent.UPDATE:
+ return coalescePaintEvents((PaintEvent) existingEvent,
+ (PaintEvent) newEvent);
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Processes the specified event. In this class, this method simply
+ * calls one of the more specific event handlers.
+ *
+ * @param e the event to process
+ * @throws NullPointerException if e is null
+ * @see #processComponentEvent(ComponentEvent)
+ * @see #processFocusEvent(FocusEvent)
+ * @see #processKeyEvent(KeyEvent)
+ * @see #processMouseEvent(MouseEvent)
+ * @see #processMouseMotionEvent(MouseEvent)
+ * @see #processInputMethodEvent(InputMethodEvent)
+ * @see #processHierarchyEvent(HierarchyEvent)
+ * @see #processMouseWheelEvent(MouseWheelEvent)
+ * @since 1.1
+ */
+ protected void processEvent(AWTEvent e)
+ {
+ /* Note: the order of these if statements are
+ important. Subclasses must be checked first. Eg. MouseEvent
+ must be checked before ComponentEvent, since a MouseEvent
+ object is also an instance of a ComponentEvent. */
+
+ if (e instanceof FocusEvent)
+ processFocusEvent((FocusEvent) e);
+ else if (e instanceof MouseWheelEvent)
+ processMouseWheelEvent((MouseWheelEvent) e);
+ else if (e instanceof MouseEvent)
+ {
+ if (e.id == MouseEvent.MOUSE_MOVED
+ || e.id == MouseEvent.MOUSE_DRAGGED)
+ processMouseMotionEvent((MouseEvent) e);
+ else
+ processMouseEvent((MouseEvent) e);
+ }
+ else if (e instanceof KeyEvent)
+ processKeyEvent((KeyEvent) e);
+ else if (e instanceof InputMethodEvent)
+ processInputMethodEvent((InputMethodEvent) e);
+ else if (e instanceof ComponentEvent)
+ processComponentEvent((ComponentEvent) e);
+ else if (e instanceof HierarchyEvent)
+ {
+ if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
+ processHierarchyEvent((HierarchyEvent) e);
+ else
+ processHierarchyBoundsEvent((HierarchyEvent) e);
+ }
+ }
+
+ /**
+ * Called when a component event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>ComponentEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see ComponentListener
+ * @see #addComponentListener(ComponentListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processComponentEvent(ComponentEvent e)
+ {
+ if (componentListener == null)
+ return;
+ switch (e.id)
+ {
+ case ComponentEvent.COMPONENT_HIDDEN:
+ componentListener.componentHidden(e);
+ break;
+ case ComponentEvent.COMPONENT_MOVED:
+ componentListener.componentMoved(e);
+ break;
+ case ComponentEvent.COMPONENT_RESIZED:
+ componentListener.componentResized(e);
+ break;
+ case ComponentEvent.COMPONENT_SHOWN:
+ componentListener.componentShown(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a focus event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>FocusEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see FocusListener
+ * @see #addFocusListener(FocusListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processFocusEvent(FocusEvent e)
+ {
+ if (focusListener == null)
+ return;
+
+ switch (e.id)
+ {
+ case FocusEvent.FOCUS_GAINED:
+ focusListener.focusGained(e);
+ break;
+ case FocusEvent.FOCUS_LOST:
+ focusListener.focusLost(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a key event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>KeyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see KeyListener
+ * @see #addKeyListener(KeyListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processKeyEvent(KeyEvent e)
+ {
+ if (keyListener == null)
+ return;
+ switch (e.id)
+ {
+ case KeyEvent.KEY_PRESSED:
+ keyListener.keyPressed(e);
+ break;
+ case KeyEvent.KEY_RELEASED:
+ keyListener.keyReleased(e);
+ break;
+ case KeyEvent.KEY_TYPED:
+ keyListener.keyTyped(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a regular mouse event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>MouseEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseListener
+ * @see #addMouseListener(MouseListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processMouseEvent(MouseEvent e)
+ {
+ if (mouseListener == null)
+ return;
+ switch (e.id)
+ {
+ case MouseEvent.MOUSE_CLICKED:
+ mouseListener.mouseClicked(e);
+ break;
+ case MouseEvent.MOUSE_ENTERED:
+ mouseListener.mouseEntered(e);
+ break;
+ case MouseEvent.MOUSE_EXITED:
+ mouseListener.mouseExited(e);
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ mouseListener.mousePressed(e);
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ mouseListener.mouseReleased(e);
+ break;
+ }
+ e.consume();
+ }
+
+ /**
+ * Called when a mouse motion event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>MouseMotionEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseMotionListener
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processMouseMotionEvent(MouseEvent e)
+ {
+ if (mouseMotionListener == null)
+ return;
+ switch (e.id)
+ {
+ case MouseEvent.MOUSE_DRAGGED:
+ mouseMotionListener.mouseDragged(e);
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ mouseMotionListener.mouseMoved(e);
+ break;
+ }
+ e.consume();
+ }
+
+ /**
+ * Called when a mouse wheel event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>MouseWheelEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseWheelListener
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #enableEvents(long)
+ * @since 1.4
+ */
+ protected void processMouseWheelEvent(MouseWheelEvent e)
+ {
+ if (mouseWheelListener != null
+ && e.id == MouseEvent.MOUSE_WHEEL)
+ {
+ mouseWheelListener.mouseWheelMoved(e);
+ e.consume();
+ }
+ }
+
+ /**
+ * Called when an input method event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>InputMethodEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see InputMethodListener
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #enableEvents(long)
+ * @since 1.2
+ */
+ protected void processInputMethodEvent(InputMethodEvent e)
+ {
+ if (inputMethodListener == null)
+ return;
+ switch (e.id)
+ {
+ case InputMethodEvent.CARET_POSITION_CHANGED:
+ inputMethodListener.caretPositionChanged(e);
+ break;
+ case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+ inputMethodListener.inputMethodTextChanged(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a hierarchy change event is dispatched and component events
+ * are enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>HierarchyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see HierarchyListener
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #enableEvents(long)
+ * @since 1.3
+ */
+ protected void processHierarchyEvent(HierarchyEvent e)
+ {
+ if (hierarchyListener == null)
+ return;
+ if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
+ hierarchyListener.hierarchyChanged(e);
+ }
+
+ /**
+ * Called when a hierarchy bounds event is dispatched and component events
+ * are enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>HierarchyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see HierarchyBoundsListener
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #enableEvents(long)
+ * @since 1.3
+ */
+ protected void processHierarchyBoundsEvent(HierarchyEvent e)
+ {
+ if (hierarchyBoundsListener == null)
+ return;
+ switch (e.id)
+ {
+ case HierarchyEvent.ANCESTOR_MOVED:
+ hierarchyBoundsListener.ancestorMoved(e);
+ break;
+ case HierarchyEvent.ANCESTOR_RESIZED:
+ hierarchyBoundsListener.ancestorResized(e);
+ break;
+ }
+ }
+
+ /**
+ * AWT 1.0 event handler.
+ *
+ * This method calls one of the event-specific handler methods. For
+ * example for key events, either {@link #keyDown(Event,int)}
+ * or {@link #keyUp(Event,int)} is called. A derived
+ * component can override one of these event-specific methods if it
+ * only needs to handle certain event types. Otherwise it can
+ * override handleEvent itself and handle any event.
+ *
+ * @param evt the event to handle
+ * @return true if the event was handled, false otherwise
+ * @deprecated use {@link #processEvent(AWTEvent)} instead
+ */
+ public boolean handleEvent (Event evt)
+ {
+ switch (evt.id)
+ {
+ // Handle key events.
+ case Event.KEY_ACTION:
+ case Event.KEY_PRESS:
+ return keyDown (evt, evt.key);
+ case Event.KEY_ACTION_RELEASE:
+ case Event.KEY_RELEASE:
+ return keyUp (evt, evt.key);
+
+ // Handle mouse events.
+ case Event.MOUSE_DOWN:
+ return mouseDown (evt, evt.x, evt.y);
+ case Event.MOUSE_UP:
+ return mouseUp (evt, evt.x, evt.y);
+ case Event.MOUSE_MOVE:
+ return mouseMove (evt, evt.x, evt.y);
+ case Event.MOUSE_DRAG:
+ return mouseDrag (evt, evt.x, evt.y);
+ case Event.MOUSE_ENTER:
+ return mouseEnter (evt, evt.x, evt.y);
+ case Event.MOUSE_EXIT:
+ return mouseExit (evt, evt.x, evt.y);
+
+ // Handle focus events.
+ case Event.GOT_FOCUS:
+ return gotFocus (evt, evt.arg);
+ case Event.LOST_FOCUS:
+ return lostFocus (evt, evt.arg);
+
+ // Handle action event.
+ case Event.ACTION_EVENT:
+ return action (evt, evt.arg);
+ }
+ // Unknown event.
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_DOWN event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_DOWN handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseDown(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_DRAG event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_DRAG handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
+ */
+ public boolean mouseDrag(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_UP event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_UP handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseUp(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_MOVE event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_MOVE handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
+ */
+ public boolean mouseMove(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_ENTER event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_ENTER handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseEnter(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_EXIT event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_EXIT handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseExit(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 KEY_PRESS and KEY_ACTION event handler. This method is
+ * meant to be overridden by components providing their own key
+ * press handler. The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param key the key pressed, ignored
+ * @return false
+ * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
+ */
+ public boolean keyDown(Event evt, int key)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 KEY_RELEASE and KEY_ACTION_RELEASE event handler. This
+ * method is meant to be overridden by components providing their
+ * own key release handler. The default implementation simply
+ * returns false.
+ *
+ * @param evt the event to handle
+ * @param key the key pressed, ignored
+ * @return false
+ * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
+ */
+ public boolean keyUp(Event evt, int key)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 ACTION_EVENT event handler. This method is meant to be
+ * overridden by components providing their own action event
+ * handler. The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the object acted on, ignored
+ * @return false
+ * @deprecated in classes which support actions, use
+ * <code>processActionEvent(ActionEvent)</code> instead
+ */
+ public boolean action(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * Called to inform this component it has been added to a container.
+ * A native peer - if any - is created at this time. This method is
+ * called automatically by the AWT system and should not be called by
+ * user level code.
+ *
+ * @see #isDisplayable()
+ * @see #removeNotify()
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createComponent(this);
+ /* Now that all the children has gotten their peers, we should
+ have the event mask needed for this component and its
+ lightweight subcomponents. */
+ peer.setEventMask(eventMask);
+ /* We do not invalidate here, but rather leave that job up to
+ the peer. For efficiency, the peer can choose not to
+ invalidate if it is happy with the current dimensions,
+ etc. */
+ }
+
+ /**
+ * Called to inform this component is has been removed from its
+ * container. Its native peer - if any - is destroyed at this time.
+ * This method is called automatically by the AWT system and should
+ * not be called by user level code.
+ *
+ * @see #isDisplayable()
+ * @see #addNotify()
+ */
+ 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)
+ tmp.dispose();
+ }
+
+ /**
+ * AWT 1.0 GOT_FOCUS event handler. This method is meant to be
+ * overridden by components providing their own GOT_FOCUS handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the Object focused, ignored
+ * @return false
+ * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
+ */
+ public boolean gotFocus(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 LOST_FOCUS event handler. This method is meant to be
+ * overridden by components providing their own LOST_FOCUS handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the Object focused, ignored
+ * @return false
+ * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
+ */
+ public boolean lostFocus(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * Tests whether or not this component is in the group that can be
+ * traversed using the keyboard traversal mechanism (such as the TAB key).
+ *
+ * @return true if the component is traversed via the TAB key
+ * @see #setFocusable(boolean)
+ * @since 1.1
+ * @deprecated use {@link #isFocusable()} instead
+ */
+ public boolean isFocusTraversable()
+ {
+ return enabled && visible && (peer == null || isLightweight() || peer.isFocusTraversable());
+ }
+
+ /**
+ * Tests if this component can receive focus.
+ *
+ * @return true if this component can receive focus
+ * @since 1.4
+ */
+ public boolean isFocusable()
+ {
+ return focusable;
+ }
+
+ /**
+ * Specify whether this component can receive focus. This method also
+ * sets the {@link #isFocusTraversableOverridden} field to 1, which
+ * appears to be the undocumented way {@link
+ * DefaultFocusTraversalPolicy#accept(Component)} determines whether to
+ * respect the {@link #isFocusable()} method of the component.
+ *
+ * @param focusable the new focusable status
+ * @since 1.4
+ */
+ public void setFocusable(boolean focusable)
+ {
+ firePropertyChange("focusable", this.focusable, focusable);
+ this.focusable = focusable;
+ this.isFocusTraversableOverridden = 1;
+ }
+
+ /**
+ * Sets the focus traversal keys for one of the three focus
+ * traversal directions supported by Components:
+ * {@link KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS},
+ * {@link KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS}, or
+ * {@link KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS}. Normally, the
+ * default values should match the operating system's native
+ * choices. To disable a given traversal, use
+ * <code>Collections.EMPTY_SET</code>. The event dispatcher will
+ * consume PRESSED, RELEASED, and TYPED events for the specified
+ * key, although focus can only transfer on PRESSED or RELEASED.
+ *
+ * <p>The defaults are:
+ * <table>
+ * <th><td>Identifier</td><td>Meaning</td><td>Default</td></th>
+ * <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
+ * <td>Normal forward traversal</td>
+ * <td>TAB on KEY_PRESSED, Ctrl-TAB on KEY_PRESSED</td></tr>
+ * <tr><td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
+ * <td>Normal backward traversal</td>
+ * <td>Shift-TAB on KEY_PRESSED, Ctrl-Shift-TAB on KEY_PRESSED</td></tr>
+ * <tr><td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
+ * <td>Go up a traversal cycle</td><td>None</td></tr>
+ * </table>
+ *
+ * If keystrokes is null, this component's focus traversal key set
+ * is inherited from one of its ancestors. If none of its ancestors
+ * has its own set of focus traversal keys, the focus traversal keys
+ * are set to the defaults retrieved from the current
+ * KeyboardFocusManager. If not null, the set must contain only
+ * AWTKeyStrokes that are not already focus keys and are not
+ * KEY_TYPED events.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, or
+ * UP_CYCLE_TRAVERSAL_KEYS
+ * @param keystrokes a set of keys, or null
+ * @throws IllegalArgumentException if id or keystrokes is invalid
+ * @see #getFocusTraversalKeys(int)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ * @since 1.4
+ */
+ public void setFocusTraversalKeys(int id, Set keystrokes)
+ {
+ if (keystrokes == null)
+ {
+ Container parent = getParent ();
+
+ while (parent != null)
+ {
+ if (parent.areFocusTraversalKeysSet (id))
+ {
+ keystrokes = parent.getFocusTraversalKeys (id);
+ break;
+ }
+ parent = parent.getParent ();
+ }
+
+ if (keystrokes == null)
+ keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
+ getDefaultFocusTraversalKeys (id);
+ }
+
+ Set sa;
+ Set sb;
+ String name;
+ switch (id)
+ {
+ case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ name = "forwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ name = "backwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ name = "upCycleFocusTraversalKeys";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+
+ int i = keystrokes.size ();
+ Iterator iter = keystrokes.iterator ();
+
+ while (--i >= 0)
+ {
+ Object o = iter.next ();
+ if (!(o instanceof AWTKeyStroke)
+ || sa.contains (o) || sb.contains (o)
+ || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
+ throw new IllegalArgumentException ();
+ }
+
+ if (focusTraversalKeys == null)
+ focusTraversalKeys = new Set[3];
+
+ keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
+ firePropertyChange (name, focusTraversalKeys[id], keystrokes);
+
+ focusTraversalKeys[id] = keystrokes;
+ }
+
+ /**
+ * Returns the set of keys for a given focus traversal action, as
+ * defined in <code>setFocusTraversalKeys</code>. If not set, this
+ * is inherited from the parent component, which may have gotten it
+ * from the KeyboardFocusManager.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
+ * or UP_CYCLE_TRAVERSAL_KEYS
+ *
+ * @return set of traversal keys
+ *
+ * @throws IllegalArgumentException if id is invalid
+ *
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ *
+ * @since 1.4
+ */
+ public Set getFocusTraversalKeys (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException();
+
+ Set s = null;
+
+ if (focusTraversalKeys != null)
+ s = focusTraversalKeys[id];
+
+ if (s == null && parent != null)
+ s = parent.getFocusTraversalKeys (id);
+
+ return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .getDefaultFocusTraversalKeys(id)) : s;
+ }
+
+ /**
+ * Tests whether the focus traversal keys for a given action are explicitly
+ * set or inherited.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
+ * or UP_CYCLE_TRAVERSAL_KEYS
+ * @return true if that set is explicitly specified
+ * @throws IllegalArgumentException if id is invalid
+ * @see #getFocusTraversalKeys (int)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ * @since 1.4
+ */
+ public boolean areFocusTraversalKeysSet (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ return focusTraversalKeys != null && focusTraversalKeys[id] != null;
+ }
+
+ /**
+ * Enable or disable focus traversal keys on this Component. If
+ * they are, then the keyboard focus manager consumes and acts on
+ * key press and release events that trigger focus traversal, and
+ * discards the corresponding key typed events. If focus traversal
+ * keys are disabled, then all key events that would otherwise
+ * trigger focus traversal are sent to this Component.
+ *
+ * @param focusTraversalKeysEnabled the new value of the flag
+ * @see #getFocusTraversalKeysEnabled ()
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see #getFocusTraversalKeys (int)
+ * @since 1.4
+ */
+ public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled)
+ {
+ firePropertyChange ("focusTraversalKeysEnabled",
+ this.focusTraversalKeysEnabled,
+ focusTraversalKeysEnabled);
+ this.focusTraversalKeysEnabled = focusTraversalKeysEnabled;
+ }
+
+ /**
+ * Check whether or not focus traversal keys are enabled on this
+ * Component. If they are, then the keyboard focus manager consumes
+ * and acts on key press and release events that trigger focus
+ * traversal, and discards the corresponding key typed events. If
+ * focus traversal keys are disabled, then all key events that would
+ * otherwise trigger focus traversal are sent to this Component.
+ *
+ * @return true if focus traversal keys are enabled
+ * @see #setFocusTraversalKeysEnabled (boolean)
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see #getFocusTraversalKeys (int)
+ * @since 1.4
+ */
+ public boolean getFocusTraversalKeysEnabled ()
+ {
+ return focusTraversalKeysEnabled;
+ }
+
+ /**
+ * Request that this Component be given the keyboard input focus and
+ * that its top-level ancestor become the focused Window.
+ *
+ * For the request to be granted, the Component must be focusable,
+ * displayable and showing and the top-level Window to which it
+ * belongs must be focusable. If the request is initially denied on
+ * the basis that the top-level Window is not focusable, the request
+ * will be remembered and granted when the Window does become
+ * focused.
+ *
+ * Never assume that this Component is the focus owner until it
+ * receives a FOCUS_GAINED event.
+ *
+ * The behaviour of this method is platform-dependent.
+ * {@link #requestFocusInWindow()} should be used instead.
+ *
+ * @see #requestFocusInWindow ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ */
+ public void requestFocus ()
+ {
+ 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,
+ 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);
+ }
+ }
+ }
+
+ /**
+ * Request that this Component be given the keyboard input focus and
+ * that its top-level ancestor become the focused Window.
+ *
+ * For the request to be granted, the Component must be focusable,
+ * displayable and showing and the top-level Window to which it
+ * belongs must be focusable. If the request is initially denied on
+ * the basis that the top-level Window is not focusable, the request
+ * will be remembered and granted when the Window does become
+ * focused.
+ *
+ * Never assume that this Component is the focus owner until it
+ * receives a FOCUS_GAINED event.
+ *
+ * The behaviour of this method is platform-dependent.
+ * {@link #requestFocusInWindow()} should be used instead.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused. This method is meant to be called by derived
+ * lightweight Components that want to avoid unnecessary repainting
+ * when they know a given focus transfer need only be temporary.
+ *
+ * @param temporary true if the focus request is temporary
+ * @return true if the request has a chance of success
+ * @see #requestFocusInWindow ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ 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;
+ }
+
+ /**
+ * Request that this component be given the keyboard input focus, if
+ * its top-level ancestor is the currently focused Window. A
+ * <code>FOCUS_GAINED</code> event will be fired if and only if this
+ * request is successful. To be successful, the component must be
+ * displayable, showing, and focusable, and its ancestor top-level
+ * Window must be focused.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused.
+ *
+ * @return true if the request has a chance of success
+ * @see #requestFocus ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ public boolean requestFocusInWindow ()
+ {
+ return requestFocusInWindow (false);
+ }
+
+ /**
+ * Request that this component be given the keyboard input focus, if
+ * its top-level ancestor is the currently focused Window. A
+ * <code>FOCUS_GAINED</code> event will be fired if and only if this
+ * request is successful. To be successful, the component must be
+ * displayable, showing, and focusable, and its ancestor top-level
+ * Window must be focused.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused. This method is meant to be called by derived
+ * lightweight Components that want to avoid unnecessary repainting
+ * when they know a given focus transfer need only be temporary.
+ *
+ * @param temporary true if the focus request is temporary
+ * @return true if the request has a chance of success
+ * @see #requestFocus ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ protected boolean requestFocusInWindow (boolean temporary)
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ Window focusedWindow = manager.getFocusedWindow ();
+
+ if (isDisplayable ()
+ && isShowing ()
+ && isFocusable ())
+ {
+ if (focusedWindow != null)
+ {
+ synchronized (getTreeLock ())
+ {
+ 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 (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
+ {
+ // 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)
+ {
+ 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
+ return false;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Transfers focus to the next component in the focus traversal
+ * order, as though this were the current focus owner.
+ *
+ * @see #requestFocus()
+ * @since 1.1
+ */
+ public void transferFocus ()
+ {
+ nextFocus ();
+ }
+
+ /**
+ * Returns the root container that owns the focus cycle where this
+ * component resides. A focus cycle root is in two cycles, one as
+ * the ancestor, and one as the focusable element; this call always
+ * returns the ancestor.
+ *
+ * @return the ancestor container that owns the focus cycle
+ * @since 1.4
+ */
+ public Container getFocusCycleRootAncestor ()
+ {
+ if (this instanceof Window
+ && ((Container) this).isFocusCycleRoot ())
+ return (Container) this;
+
+ Container parent = getParent ();
+
+ while (parent != null
+ && !parent.isFocusCycleRoot ())
+ parent = parent.getParent ();
+
+ return parent;
+ }
+
+ /**
+ * Tests if the container is the ancestor of the focus cycle that
+ * this component belongs to.
+ *
+ * @param c the container to test
+ * @return true if c is the focus cycle root
+ * @since 1.4
+ */
+ public boolean isFocusCycleRoot (Container c)
+ {
+ return c == getFocusCycleRootAncestor ();
+ }
+
+ /**
+ * AWT 1.0 focus event processor. Transfers focus to the next
+ * component in the focus traversal order, as though this were the
+ * current focus owner.
+ *
+ * @deprecated use {@link #transferFocus ()} instead
+ */
+ public void nextFocus ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ manager.focusNextComponent (this);
+ }
+
+ /**
+ * Transfers focus to the previous component in the focus traversal
+ * order, as though this were the current focus owner.
+ *
+ * @see #requestFocus ()
+ * @since 1.4
+ */
+ public void transferFocusBackward ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ manager.focusPreviousComponent (this);
+ }
+
+ /**
+ * Transfers focus to the focus cycle root of this component.
+ * However, if this is a Window, the default focus owner in the
+ * window in the current focus cycle is focused instead.
+ *
+ * @see #requestFocus()
+ * @see #isFocusCycleRoot(Container)
+ * @since 1.4
+ */
+ public void transferFocusUpCycle ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ manager.upFocusCycle (this);
+ }
+
+ /**
+ * Tests if this component is the focus owner. Use {@link
+ * #isFocusOwner ()} instead.
+ *
+ * @return true if this component owns focus
+ * @since 1.2
+ */
+ public boolean hasFocus ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ Component focusOwner = manager.getFocusOwner ();
+
+ return this == focusOwner;
+ }
+
+ /**
+ * Tests if this component is the focus owner.
+ *
+ * @return true if this component owns focus
+ * @since 1.4
+ */
+ public boolean isFocusOwner()
+ {
+ return hasFocus ();
+ }
+
+ /**
+ * Adds the specified popup menu to this component.
+ *
+ * @param popup the popup menu to be added
+ *
+ * @see #remove(MenuComponent)
+ *
+ * @since 1.1
+ */
+ public synchronized void add(PopupMenu popup)
+ {
+ if (popups == null)
+ popups = new Vector();
+ popups.add(popup);
+
+ if (popup.parent != null)
+ popup.parent.remove(popup);
+ popup.parent = this;
+ if (peer != null)
+ popup.addNotify();
+ }
+
+ /**
+ * Removes the specified popup menu from this component.
+ *
+ * @param popup the popup menu to remove
+ * @see #add(PopupMenu)
+ * @since 1.1
+ */
+ public synchronized void remove(MenuComponent popup)
+ {
+ if (popups != null)
+ popups.remove(popup);
+ }
+
+ /**
+ * Returns a debugging string representing this component. The string may
+ * be empty but not null.
+ *
+ * @return a string representing this component
+ */
+ protected String paramString()
+ {
+ StringBuffer param = new StringBuffer();
+ String name = getName();
+ if (name != null)
+ param.append(name).append(",");
+ param.append(x).append(",").append(y).append(",").append(width)
+ .append("x").append(height);
+ if (! isValid())
+ param.append(",invalid");
+ if (! isVisible())
+ param.append(",invisible");
+ if (! isEnabled())
+ param.append(",disabled");
+ if (! isOpaque())
+ param.append(",translucent");
+ if (isDoubleBuffered())
+ param.append(",doublebuffered");
+ return param.toString();
+ }
+
+ /**
+ * Returns a string representation of this component. This is implemented
+ * as <code>getClass().getName() + '[' + paramString() + ']'</code>.
+ *
+ * @return a string representation of this component
+ */
+ public String toString()
+ {
+ return getClass().getName() + '[' + paramString() + ']';
+ }
+
+ /**
+ * Prints a listing of this component to <code>System.out</code>.
+ *
+ * @see #list(PrintStream)
+ */
+ public void list()
+ {
+ list(System.out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print stream.
+ *
+ * @param out the <code>PrintStream</code> to print to
+ */
+ public void list(PrintStream out)
+ {
+ list(out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print stream,
+ * starting at the specified indentation point.
+ *
+ * @param out the <code>PrintStream</code> to print to
+ * @param indent the indentation point
+ */
+ public void list(PrintStream out, int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ out.print(' ');
+ out.println(toString());
+ }
+
+ /**
+ * Prints a listing of this component to the specified print writer.
+ *
+ * @param out the <code>PrintWrinter</code> to print to
+ * @since 1.1
+ */
+ public void list(PrintWriter out)
+ {
+ list(out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print writer,
+ * starting at the specified indentation point.
+ *
+ * @param out the <code>PrintWriter</code> to print to
+ * @param indent the indentation point
+ * @since 1.1
+ */
+ public void list(PrintWriter out, int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ out.print(' ');
+ out.println(toString());
+ }
+
+ /**
+ * Adds the specified property 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. The property listener ignores inherited
+ * properties. Recognized properties include:<br>
+ * <ul>
+ * <li>the font (<code>"font"</code>)</li>
+ * <li>the background color (<code>"background"</code>)</li>
+ * <li>the foreground color (<code>"foreground"</code>)</li>
+ * <li>the focusability (<code>"focusable"</code>)</li>
+ * <li>the focus key traversal enabled state
+ * (<code>"focusTraversalKeysEnabled"</code>)</li>
+ * <li>the set of forward traversal keys
+ * (<code>"forwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of backward traversal keys
+ * (<code>"backwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of up-cycle traversal keys
+ * (<code>"upCycleFocusTraversalKeys"</code>)</li>
+ * </ul>
+ *
+ * @param listener the new listener to add
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @since 1.1
+ */
+ public void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (changeSupport == null)
+ changeSupport = new PropertyChangeSupport(this);
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * Removes the specified property listener from the component. This is
+ * harmless if the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @since 1.1
+ */
+ public void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (changeSupport != null)
+ changeSupport.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return changeSupport == null ? new PropertyChangeListener[0]
+ : changeSupport.getPropertyChangeListeners();
+ }
+
+ /**
+ * Adds the specified property 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. The property listener ignores inherited
+ * properties. The listener is keyed to a single property. Recognized
+ * properties include:<br>
+ * <ul>
+ * <li>the font (<code>"font"</code>)</li>
+ * <li>the background color (<code>"background"</code>)</li>
+ * <li>the foreground color (<code>"foreground"</code>)</li>
+ * <li>the focusability (<code>"focusable"</code>)</li>
+ * <li>the focus key traversal enabled state
+ * (<code>"focusTraversalKeysEnabled"</code>)</li>
+ * <li>the set of forward traversal keys
+ * (<code>"forwardFocusTraversalKeys"</code>)</li>
+p * <li>the set of backward traversal keys
+ * (<code>"backwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of up-cycle traversal keys
+ * (<code>"upCycleFocusTraversalKeys"</code>)</li>
+ * </ul>
+ *
+ * @param propertyName the property name to filter on
+ * @param listener the new listener to add
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @since 1.1
+ */
+ public void addPropertyChangeListener(String propertyName,
+ PropertyChangeListener listener)
+ {
+ if (changeSupport == null)
+ changeSupport = new PropertyChangeSupport(this);
+ changeSupport.addPropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Removes the specified property listener on a particular property from
+ * the component. This is harmless if the listener was not previously
+ * registered.
+ *
+ * @param propertyName the property name to filter on
+ * @param listener the listener to remove
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @since 1.1
+ */
+ public void removePropertyChangeListener(String propertyName,
+ PropertyChangeListener listener)
+ {
+ if (changeSupport != null)
+ changeSupport.removePropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners on the named property that
+ * are registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners(String property)
+ {
+ return changeSupport == null ? new PropertyChangeListener[0]
+ : changeSupport.getPropertyChangeListeners(property);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, Object oldValue,
+ Object newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, boolean oldValue,
+ boolean newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, int oldValue,
+ int newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Sets the text layout orientation of this component. New components default
+ * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects only
+ * the current component, while
+ * {@link #applyComponentOrientation(ComponentOrientation)} affects the
+ * entire hierarchy.
+ *
+ * @param o the new orientation
+ * @throws NullPointerException if o is null
+ * @see #getComponentOrientation()
+ */
+ public void setComponentOrientation(ComponentOrientation o)
+ {
+ if (o == null)
+ throw new NullPointerException();
+ ComponentOrientation oldOrientation = orientation;
+ orientation = o;
+ firePropertyChange("componentOrientation", oldOrientation, o);
+ }
+
+ /**
+ * Determines the text layout orientation used by this component.
+ *
+ * @return the component orientation
+ * @see #setComponentOrientation(ComponentOrientation)
+ */
+ public ComponentOrientation getComponentOrientation()
+ {
+ return orientation;
+ }
+
+ /**
+ * Sets the text layout orientation of this component. New components default
+ * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects the
+ * entire hierarchy, while
+ * {@link #setComponentOrientation(ComponentOrientation)} affects only the
+ * current component.
+ *
+ * @param o the new orientation
+ * @throws NullPointerException if o is null
+ * @see #getComponentOrientation()
+ * @since 1.4
+ */
+ public void applyComponentOrientation(ComponentOrientation o)
+ {
+ setComponentOrientation(o);
+ }
+
+ /**
+ * Returns the accessibility framework context of this class. Component is
+ * not accessible, so the default implementation returns null. Subclasses
+ * must override this behavior, and return an appropriate subclass of
+ * {@link AccessibleAWTComponent}.
+ *
+ * @return the accessibility context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return null;
+ }
+
+
+ // Helper methods; some are package visible for use by subclasses.
+
+ /**
+ * Subclasses should override this to return unique component names like
+ * "menuitem0".
+ *
+ * @return the generated name for this component
+ */
+ String generateName()
+ {
+ // Component is abstract.
+ return null;
+ }
+
+ /**
+ * Sets the peer for this component.
+ *
+ * @param peer the new peer
+ */
+ final void setPeer(ComponentPeer peer)
+ {
+ this.peer = peer;
+ }
+
+ /**
+ * Implementation method that allows classes such as Canvas and Window to
+ * override the graphics configuration without violating the published API.
+ *
+ * @return the graphics configuration
+ */
+ GraphicsConfiguration getGraphicsConfigurationImpl()
+ {
+ if (peer != null)
+ {
+ GraphicsConfiguration config = peer.getGraphicsConfiguration();
+ if (config != null)
+ return config;
+ }
+
+ if (parent != null)
+ return parent.getGraphicsConfiguration();
+
+ return null;
+ }
+
+ /**
+ * Translate an AWT 1.1 event ({@link AWTEvent}) into an AWT 1.0
+ * event ({@link Event}).
+ *
+ * @param e an AWT 1.1 event to translate
+ *
+ * @return an AWT 1.0 event representing e
+ */
+ static Event translateEvent (AWTEvent e)
+ {
+ Component target = (Component) e.getSource ();
+ Event translated = null;
+
+ if (e instanceof InputEvent)
+ {
+ InputEvent ie = (InputEvent) e;
+ long when = ie.getWhen ();
+
+ int oldID = 0;
+ int id = e.getID ();
+
+ int oldMods = 0;
+ int mods = ie.getModifiersEx ();
+
+ if ((mods & InputEvent.BUTTON2_DOWN_MASK) != 0)
+ oldMods |= Event.META_MASK;
+ else if ((mods & InputEvent.BUTTON3_DOWN_MASK) != 0)
+ oldMods |= Event.ALT_MASK;
+
+ if ((mods & InputEvent.SHIFT_DOWN_MASK) != 0)
+ oldMods |= Event.SHIFT_MASK;
+
+ if ((mods & InputEvent.CTRL_DOWN_MASK) != 0)
+ oldMods |= Event.CTRL_MASK;
+
+ if ((mods & InputEvent.META_DOWN_MASK) != 0)
+ oldMods |= Event.META_MASK;
+
+ if ((mods & InputEvent.ALT_DOWN_MASK) != 0)
+ oldMods |= Event.ALT_MASK;
+
+ if (e instanceof MouseEvent)
+ {
+ if (id == MouseEvent.MOUSE_PRESSED)
+ oldID = Event.MOUSE_DOWN;
+ else if (id == MouseEvent.MOUSE_RELEASED)
+ oldID = Event.MOUSE_UP;
+ else if (id == MouseEvent.MOUSE_MOVED)
+ oldID = Event.MOUSE_MOVE;
+ else if (id == MouseEvent.MOUSE_DRAGGED)
+ oldID = Event.MOUSE_DRAG;
+ else if (id == MouseEvent.MOUSE_ENTERED)
+ oldID = Event.MOUSE_ENTER;
+ else if (id == MouseEvent.MOUSE_EXITED)
+ oldID = Event.MOUSE_EXIT;
+ else
+ // No analogous AWT 1.0 mouse event.
+ return null;
+
+ MouseEvent me = (MouseEvent) e;
+
+ translated = new Event (target, when, oldID,
+ me.getX (), me.getY (), 0, oldMods);
+ }
+ else if (e instanceof KeyEvent)
+ {
+ if (id == KeyEvent.KEY_PRESSED)
+ oldID = Event.KEY_PRESS;
+ else if (e.getID () == KeyEvent.KEY_RELEASED)
+ oldID = Event.KEY_RELEASE;
+ else
+ // No analogous AWT 1.0 key event.
+ return null;
+
+ int oldKey = 0;
+ int newKey = ((KeyEvent) e).getKeyCode ();
+ switch (newKey)
+ {
+ case KeyEvent.VK_BACK_SPACE:
+ oldKey = Event.BACK_SPACE;
+ break;
+ case KeyEvent.VK_CAPS_LOCK:
+ oldKey = Event.CAPS_LOCK;
+ break;
+ case KeyEvent.VK_DELETE:
+ oldKey = Event.DELETE;
+ break;
+ case KeyEvent.VK_DOWN:
+ case KeyEvent.VK_KP_DOWN:
+ oldKey = Event.DOWN;
+ break;
+ case KeyEvent.VK_END:
+ oldKey = Event.END;
+ break;
+ case KeyEvent.VK_ENTER:
+ oldKey = Event.ENTER;
+ break;
+ case KeyEvent.VK_ESCAPE:
+ oldKey = Event.ESCAPE;
+ break;
+ case KeyEvent.VK_F1:
+ oldKey = Event.F1;
+ break;
+ case KeyEvent.VK_F10:
+ oldKey = Event.F10;
+ break;
+ case KeyEvent.VK_F11:
+ oldKey = Event.F11;
+ break;
+ case KeyEvent.VK_F12:
+ oldKey = Event.F12;
+ break;
+ case KeyEvent.VK_F2:
+ oldKey = Event.F2;
+ break;
+ case KeyEvent.VK_F3:
+ oldKey = Event.F3;
+ break;
+ case KeyEvent.VK_F4:
+ oldKey = Event.F4;
+ break;
+ case KeyEvent.VK_F5:
+ oldKey = Event.F5;
+ break;
+ case KeyEvent.VK_F6:
+ oldKey = Event.F6;
+ break;
+ case KeyEvent.VK_F7:
+ oldKey = Event.F7;
+ break;
+ case KeyEvent.VK_F8:
+ oldKey = Event.F8;
+ break;
+ case KeyEvent.VK_F9:
+ oldKey = Event.F9;
+ break;
+ case KeyEvent.VK_HOME:
+ oldKey = Event.HOME;
+ break;
+ case KeyEvent.VK_INSERT:
+ oldKey = Event.INSERT;
+ break;
+ case KeyEvent.VK_LEFT:
+ case KeyEvent.VK_KP_LEFT:
+ oldKey = Event.LEFT;
+ break;
+ case KeyEvent.VK_NUM_LOCK:
+ oldKey = Event.NUM_LOCK;
+ break;
+ case KeyEvent.VK_PAUSE:
+ oldKey = Event.PAUSE;
+ break;
+ case KeyEvent.VK_PAGE_DOWN:
+ oldKey = Event.PGDN;
+ break;
+ case KeyEvent.VK_PAGE_UP:
+ oldKey = Event.PGUP;
+ break;
+ case KeyEvent.VK_PRINTSCREEN:
+ oldKey = Event.PRINT_SCREEN;
+ break;
+ case KeyEvent.VK_RIGHT:
+ case KeyEvent.VK_KP_RIGHT:
+ oldKey = Event.RIGHT;
+ break;
+ case KeyEvent.VK_SCROLL_LOCK:
+ oldKey = Event.SCROLL_LOCK;
+ break;
+ case KeyEvent.VK_TAB:
+ oldKey = Event.TAB;
+ break;
+ case KeyEvent.VK_UP:
+ case KeyEvent.VK_KP_UP:
+ oldKey = Event.UP;
+ break;
+ default:
+ oldKey = newKey;
+ }
+
+ translated = new Event (target, when, oldID,
+ 0, 0, oldKey, oldMods);
+ }
+ }
+ else if (e instanceof ActionEvent)
+ translated = new Event (target, Event.ACTION_EVENT,
+ ((ActionEvent) e).getActionCommand ());
+
+ return translated;
+ }
+
+ /**
+ * Implementation of dispatchEvent. Allows trusted package classes
+ * to dispatch additional events first. This implementation first
+ * translates <code>e</code> to an AWT 1.0 event and sends the
+ * result to {@link #postEvent}. If the AWT 1.0 event is not
+ * handled, and events of type <code>e</code> are enabled for this
+ * component, e is passed on to {@link #processEvent}.
+ *
+ * @param e the event to dispatch
+ */
+
+ void dispatchEventImpl (AWTEvent e)
+ {
+ Event oldEvent = translateEvent (e);
+
+ if (oldEvent != null)
+ postEvent (oldEvent);
+
+ if (eventTypeEnabled (e.id))
+ {
+ // 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))
+ {
+ 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:
+ if (isLightweight())
+ requestFocus();
+ break;
+ }
+ }
+ processEvent (e);
+ }
+ }
+
+ /**
+ * Tells whether or not an event type is enabled.
+ */
+ boolean eventTypeEnabled (int type)
+ {
+ if (type > AWTEvent.RESERVED_ID_MAX)
+ return true;
+
+ switch (type)
+ {
+ case ComponentEvent.COMPONENT_HIDDEN:
+ case ComponentEvent.COMPONENT_MOVED:
+ case ComponentEvent.COMPONENT_RESIZED:
+ case ComponentEvent.COMPONENT_SHOWN:
+ return (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0);
+
+ case KeyEvent.KEY_PRESSED:
+ case KeyEvent.KEY_RELEASED:
+ case KeyEvent.KEY_TYPED:
+ return (keyListener != null
+ || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0);
+
+ case MouseEvent.MOUSE_CLICKED:
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ return (mouseListener != null
+ || mouseMotionListener != null
+ || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
+
+ case FocusEvent.FOCUS_GAINED:
+ case FocusEvent.FOCUS_LOST:
+ return (focusListener != null
+ || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0);
+
+ case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+ case InputMethodEvent.CARET_POSITION_CHANGED:
+ return (inputMethodListener != null
+ || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0);
+
+ case PaintEvent.PAINT:
+ case PaintEvent.UPDATE:
+ return (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0;
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Coalesce paint events. Current heuristic is: Merge if the union of
+ * areas is less than twice that of the sum of the areas. The X server
+ * tend to create a lot of paint events that are adjacent but not
+ * overlapping.
+ *
+ * <pre>
+ * +------+
+ * | +-----+ ...will be merged
+ * | | |
+ * | | |
+ * +------+ |
+ * +-----+
+ *
+ * +---------------+--+
+ * | | | ...will not be merged
+ * +---------------+ |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * +--+
+ * </pre>
+ *
+ * @param queuedEvent the first paint event
+ * @param newEvent the second paint event
+ * @return the combined paint event, or null
+ */
+ private PaintEvent coalescePaintEvents(PaintEvent queuedEvent,
+ PaintEvent newEvent)
+ {
+ Rectangle r1 = queuedEvent.getUpdateRect();
+ Rectangle r2 = newEvent.getUpdateRect();
+ Rectangle union = r1.union(r2);
+
+ int r1a = r1.width * r1.height;
+ int r2a = r2.width * r2.height;
+ int ua = union.width * union.height;
+
+ if (ua > (r1a+r2a)*2)
+ return null;
+ /* The 2 factor should maybe be reconsidered. Perhaps 3/2
+ would be better? */
+
+ newEvent.setUpdateRect(union);
+ return newEvent;
+ }
+
+ /**
+ * This method is used to implement transferFocus(). CHILD is the child
+ * making the request. This is overridden by Container; when called for an
+ * ordinary component there is no child and so we always return null.
+ *
+ * FIXME: is this still needed, in light of focus traversal policies?
+ *
+ * @param child the component making the request
+ * @return the next component to focus on
+ */
+ Component findNextFocusComponent(Component child)
+ {
+ return null;
+ }
+
+ /**
+ * Deserializes this component. This regenerates all serializable listeners
+ * which were registered originally.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if deserialization fails
+ * @throws IOException if the stream fails
+ */
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject();
+ String key = (String) s.readObject();
+ while (key != null)
+ {
+ Object listener = s.readObject();
+ if ("componentL".equals(key))
+ addComponentListener((ComponentListener) listener);
+ else if ("focusL".equals(key))
+ addFocusListener((FocusListener) listener);
+ else if ("keyL".equals(key))
+ addKeyListener((KeyListener) listener);
+ else if ("mouseL".equals(key))
+ addMouseListener((MouseListener) listener);
+ else if ("mouseMotionL".equals(key))
+ addMouseMotionListener((MouseMotionListener) listener);
+ else if ("inputMethodL".equals(key))
+ addInputMethodListener((InputMethodListener) listener);
+ else if ("hierarchyL".equals(key))
+ addHierarchyListener((HierarchyListener) listener);
+ else if ("hierarchyBoundsL".equals(key))
+ addHierarchyBoundsListener((HierarchyBoundsListener) listener);
+ else if ("mouseWheelL".equals(key))
+ addMouseWheelListener((MouseWheelListener) listener);
+ key = (String) s.readObject();
+ }
+ }
+
+ /**
+ * Serializes this component. This ignores all listeners which do not
+ * implement Serializable, but includes those that do.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the stream fails
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ AWTEventMulticaster.save(s, "componentL", componentListener);
+ AWTEventMulticaster.save(s, "focusL", focusListener);
+ AWTEventMulticaster.save(s, "keyL", keyListener);
+ AWTEventMulticaster.save(s, "mouseL", mouseListener);
+ AWTEventMulticaster.save(s, "mouseMotionL", mouseMotionListener);
+ AWTEventMulticaster.save(s, "inputMethodL", inputMethodListener);
+ AWTEventMulticaster.save(s, "hierarchyL", hierarchyListener);
+ AWTEventMulticaster.save(s, "hierarchyBoundsL", hierarchyBoundsListener);
+ AWTEventMulticaster.save(s, "mouseWheelL", mouseWheelListener);
+ s.writeObject(null);
+ }
+
+
+ // Nested classes.
+
+ /**
+ * This class provides accessibility support for subclasses of container.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected abstract class AccessibleAWTComponent extends AccessibleContext
+ implements Serializable, AccessibleComponent
+ {
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = 642321655757800191L;
+
+ /**
+ * Converts show/hide events to PropertyChange events, and is registered
+ * as a component listener on this component.
+ *
+ * @serial the component handler
+ */
+ protected ComponentListener accessibleAWTComponentHandler
+ = new AccessibleAWTComponentHandler();
+
+ /**
+ * Converts focus events to PropertyChange events, and is registered
+ * as a focus listener on this component.
+ *
+ * @serial the focus handler
+ */
+ protected FocusListener accessibleAWTFocusHandler
+ = new AccessibleAWTFocusHandler();
+
+ /**
+ * The default constructor.
+ */
+ protected AccessibleAWTComponent()
+ {
+ Component.this.addComponentListener(accessibleAWTComponentHandler);
+ Component.this.addFocusListener(accessibleAWTFocusHandler);
+ }
+
+ /**
+ * Adds a global property change listener to the accessible component.
+ *
+ * @param l the listener to add
+ * @see #ACCESSIBLE_NAME_PROPERTY
+ * @see #ACCESSIBLE_DESCRIPTION_PROPERTY
+ * @see #ACCESSIBLE_STATE_PROPERTY
+ * @see #ACCESSIBLE_VALUE_PROPERTY
+ * @see #ACCESSIBLE_SELECTION_PROPERTY
+ * @see #ACCESSIBLE_TEXT_PROPERTY
+ * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ Component.this.addPropertyChangeListener(l);
+ super.addPropertyChangeListener(l);
+ }
+
+ /**
+ * Removes a global property change listener from this accessible
+ * component.
+ *
+ * @param l the listener to remove
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ Component.this.removePropertyChangeListener(l);
+ super.removePropertyChangeListener(l);
+ }
+
+ /**
+ * Returns the accessible name of this component. It is almost always
+ * wrong to return getName(), since it is not localized. In fact, for
+ * things like buttons, this should be the text of the button, not the
+ * name of the object. The tooltip text might also be appropriate.
+ *
+ * @return the name
+ * @see #setAccessibleName(String)
+ */
+ public String getAccessibleName()
+ {
+ return accessibleName == null ? getName() : accessibleName;
+ }
+
+ /**
+ * Returns a brief description of this accessible context. This should
+ * be localized.
+ *
+ * @return a description of this component
+ * @see #setAccessibleDescription(String)
+ */
+ public String getAccessibleDescription()
+ {
+ return accessibleDescription;
+ }
+
+ /**
+ * Returns the role of this component.
+ *
+ * @return the accessible role
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.AWT_COMPONENT;
+ }
+
+ /**
+ * Returns a state set describing this component's state.
+ *
+ * @return a new state set
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet s = new AccessibleStateSet();
+ if (Component.this.isEnabled())
+ s.add(AccessibleState.ENABLED);
+ if (isFocusable())
+ s.add(AccessibleState.FOCUSABLE);
+ if (isFocusOwner())
+ s.add(AccessibleState.FOCUSED);
+ if (isOpaque())
+ s.add(AccessibleState.OPAQUE);
+ if (Component.this.isShowing())
+ s.add(AccessibleState.SHOWING);
+ if (Component.this.isVisible())
+ s.add(AccessibleState.VISIBLE);
+ return s;
+ }
+
+ /**
+ * Returns the parent of this component, if it is accessible.
+ *
+ * @return the accessible parent
+ */
+ public Accessible getAccessibleParent()
+ {
+ if (accessibleParent == null)
+ {
+ Container parent = getParent();
+ accessibleParent = parent instanceof Accessible
+ ? (Accessible) parent : null;
+ }
+ return accessibleParent;
+ }
+
+ /**
+ * Returns the index of this component in its accessible parent.
+ *
+ * @return the index, or -1 if the parent is not accessible
+ * @see #getAccessibleParent()
+ */
+ public int getAccessibleIndexInParent()
+ {
+ if (getAccessibleParent() == null)
+ return -1;
+ AccessibleContext context
+ = ((Component) accessibleParent).getAccessibleContext();
+ if (context == null)
+ return -1;
+ for (int i = context.getAccessibleChildrenCount(); --i >= 0; )
+ if (context.getAccessibleChild(i) == Component.this)
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the number of children of this component which implement
+ * Accessible. Subclasses must override this if they can have children.
+ *
+ * @return the number of accessible children, default 0
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the ith accessible child. Subclasses must override this if
+ * they can have children.
+ *
+ * @return the ith accessible child, or null
+ * @see #getAccessibleChildrenCount()
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the locale of this component.
+ *
+ * @return the locale
+ * @throws IllegalComponentStateException if the locale is unknown
+ */
+ public Locale getLocale()
+ {
+ return Component.this.getLocale();
+ }
+
+ /**
+ * Returns this, since it is an accessible component.
+ *
+ * @return the accessible component
+ */
+ public AccessibleComponent getAccessibleComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Gets the background color.
+ *
+ * @return the background color
+ * @see #setBackground(Color)
+ */
+ public Color getBackground()
+ {
+ return Component.this.getBackground();
+ }
+
+ /**
+ * Sets the background color.
+ *
+ * @param c the background color
+ * @see #getBackground()
+ * @see #isOpaque()
+ */
+ public void setBackground(Color c)
+ {
+ Component.this.setBackground(c);
+ }
+
+ /**
+ * Gets the foreground color.
+ *
+ * @return the foreground color
+ * @see #setForeground(Color)
+ */
+ public Color getForeground()
+ {
+ return Component.this.getForeground();
+ }
+
+ /**
+ * Sets the foreground color.
+ *
+ * @param c the foreground color
+ * @see #getForeground()
+ */
+ public void setForeground(Color c)
+ {
+ Component.this.setForeground(c);
+ }
+
+ /**
+ * Gets the cursor.
+ *
+ * @return the cursor
+ * @see #setCursor(Cursor)
+ */
+ public Cursor getCursor()
+ {
+ return Component.this.getCursor();
+ }
+
+ /**
+ * Sets the cursor.
+ *
+ * @param cursor the cursor
+ * @see #getCursor()
+ */
+ public void setCursor(Cursor cursor)
+ {
+ Component.this.setCursor(cursor);
+ }
+
+ /**
+ * Gets the font.
+ *
+ * @return the font
+ * @see #setFont(Font)
+ */
+ public Font getFont()
+ {
+ return Component.this.getFont();
+ }
+
+ /**
+ * Sets the font.
+ *
+ * @param f the font
+ * @see #getFont()
+ */
+ public void setFont(Font f)
+ {
+ Component.this.setFont(f);
+ }
+
+ /**
+ * Gets the font metrics for a font.
+ *
+ * @param f the font to look up
+ * @return its metrics
+ * @throws NullPointerException if f is null
+ * @see #getFont()
+ */
+ public FontMetrics getFontMetrics(Font f)
+ {
+ return Component.this.getFontMetrics(f);
+ }
+
+ /**
+ * Tests if the component is enabled.
+ *
+ * @return true if the component is enabled
+ * @see #setEnabled(boolean)
+ * @see #getAccessibleStateSet()
+ * @see AccessibleState#ENABLED
+ */
+ public boolean isEnabled()
+ {
+ return Component.this.isEnabled();
+ }
+
+ /**
+ * Set whether the component is enabled.
+ *
+ * @param b the new enabled status
+ * @see #isEnabled()
+ */
+ public void setEnabled(boolean b)
+ {
+ Component.this.setEnabled(b);
+ }
+
+ /**
+ * Test whether the component is visible (not necesarily showing).
+ *
+ * @return true if it is visible
+ * @see #setVisible(boolean)
+ * @see #getAccessibleStateSet()
+ * @see AccessibleState#VISIBLE
+ */
+ public boolean isVisible()
+ {
+ return Component.this.isVisible();
+ }
+
+ /**
+ * Sets the visibility of this component.
+ *
+ * @param b the desired visibility
+ * @see #isVisible()
+ */
+ public void setVisible(boolean b)
+ {
+ Component.this.setVisible(b);
+ }
+
+ /**
+ * Tests if the component is showing.
+ *
+ * @return true if this is showing
+ */
+ public boolean isShowing()
+ {
+ return Component.this.isShowing();
+ }
+
+ /**
+ * Tests if the point is contained in this component.
+ *
+ * @param p the point to check
+ * @return true if it is contained
+ * @throws NullPointerException if p is null
+ */
+ public boolean contains(Point p)
+ {
+ return Component.this.contains(p.x, p.y);
+ }
+
+ /**
+ * Returns the location of this object on the screen, or null if it is
+ * not showing.
+ *
+ * @return the location relative to screen coordinates, if showing
+ * @see #getBounds()
+ * @see #getLocation()
+ */
+ public Point getLocationOnScreen()
+ {
+ return Component.this.isShowing() ? Component.this.getLocationOnScreen()
+ : null;
+ }
+
+ /**
+ * Returns the location of this object relative to its parent's coordinate
+ * system, or null if it is not showing.
+ *
+ * @return the location
+ * @see #getBounds()
+ * @see #getLocationOnScreen()
+ */
+ public Point getLocation()
+ {
+ return Component.this.isShowing() ? Component.this.getLocation() : null;
+ }
+
+ /**
+ * Sets the location of this relative to its parent's coordinate system.
+ *
+ * @param p the location
+ * @throws NullPointerException if p is null
+ * @see #getLocation()
+ */
+ public void setLocation(Point p)
+ {
+ Component.this.setLocation(p.x, p.y);
+ }
+
+ /**
+ * Gets the bounds of this component, or null if it is not on screen.
+ *
+ * @return the bounds
+ * @see #contains(Point)
+ * @see #setBounds(Rectangle)
+ */
+ public Rectangle getBounds()
+ {
+ return Component.this.isShowing() ? Component.this.getBounds() : null;
+ }
+
+ /**
+ * Sets the bounds of this component.
+ *
+ * @param r the bounds
+ * @throws NullPointerException if r is null
+ * @see #getBounds()
+ */
+ public void setBounds(Rectangle r)
+ {
+ Component.this.setBounds(r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Gets the size of this component, or null if it is not showing.
+ *
+ * @return the size
+ * @see #setSize(Dimension)
+ */
+ public Dimension getSize()
+ {
+ return Component.this.isShowing() ? Component.this.getSize() : null;
+ }
+
+ /**
+ * Sets the size of this component.
+ *
+ * @param d the size
+ * @throws NullPointerException if d is null
+ * @see #getSize()
+ */
+ public void setSize(Dimension d)
+ {
+ Component.this.setSize(d.width, d.height);
+ }
+
+ /**
+ * Returns the Accessible child at a point relative to the coordinate
+ * system of this component, if one exists, or null. Since components
+ * have no children, subclasses must override this to get anything besides
+ * null.
+ *
+ * @param p the point to check
+ * @return the accessible child at that point
+ * @throws NullPointerException if p is null
+ */
+ public Accessible getAccessibleAt(Point p)
+ {
+ return null;
+ }
+
+ /**
+ * Tests whether this component can accept focus.
+ *
+ * @return true if this is focus traversable
+ * @see #getAccessibleStateSet ()
+ * @see AccessibleState#FOCUSABLE
+ * @see AccessibleState#FOCUSED
+ */
+ public boolean isFocusTraversable ()
+ {
+ return Component.this.isFocusTraversable ();
+ }
+
+ /**
+ * Requests focus for this component.
+ *
+ * @see #isFocusTraversable ()
+ */
+ public void requestFocus ()
+ {
+ Component.this.requestFocus ();
+ }
+
+ /**
+ * Adds a focus listener.
+ *
+ * @param l the listener to add
+ */
+ public void addFocusListener(FocusListener l)
+ {
+ Component.this.addFocusListener(l);
+ }
+
+ /**
+ * Removes a focus listener.
+ *
+ * @param l the listener to remove
+ */
+ public void removeFocusListener(FocusListener l)
+ {
+ Component.this.removeFocusListener(l);
+ }
+
+ /**
+ * Converts component changes into property changes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected class AccessibleAWTComponentHandler implements ComponentListener
+ {
+ /**
+ * Default constructor.
+ */
+ protected AccessibleAWTComponentHandler()
+ {
+ }
+
+ /**
+ * Convert a component hidden to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void componentHidden(ComponentEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, AccessibleState.VISIBLE, null);
+ }
+
+ /**
+ * Convert a component shown to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void componentShown(ComponentEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.VISIBLE);
+ }
+
+ /**
+ * Moving a component does not affect properties.
+ *
+ * @param e ignored
+ */
+ public void componentMoved(ComponentEvent e)
+ {
+ }
+
+ /**
+ * Resizing a component does not affect properties.
+ *
+ * @param e ignored
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ }
+ } // class AccessibleAWTComponentHandler
+
+ /**
+ * Converts focus changes into property changes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected class AccessibleAWTFocusHandler implements FocusListener
+ {
+ /**
+ * Default constructor.
+ */
+ protected AccessibleAWTFocusHandler()
+ {
+ }
+
+ /**
+ * Convert a focus gained to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void focusGained(FocusEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.FOCUSED);
+ }
+
+ /**
+ * Convert a focus lost to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void focusLost(FocusEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null);
+ }
+ } // class AccessibleAWTComponentHandler
+ } // class AccessibleAWTComponent
+
+ /**
+ * This class provides support for blitting offscreen surfaces to a
+ * component.
+ *
+ * @see BufferStrategy
+ *
+ * @since 1.4
+ */
+ protected class BltBufferStrategy extends BufferStrategy
+ {
+ /**
+ * The capabilities of the image buffer.
+ */
+ protected BufferCapabilities caps;
+
+ /**
+ * The back buffers used in this strategy.
+ */
+ protected VolatileImage[] backBuffers;
+
+ /**
+ * Whether or not the image buffer resources are allocated and
+ * ready to be drawn into.
+ */
+ protected boolean validatedContents;
+
+ /**
+ * The width of the back buffers.
+ */
+ protected int width;
+
+ /**
+ * The height of the back buffers.
+ */
+ protected int height;
+
+ /**
+ * The front buffer.
+ */
+ private VolatileImage frontBuffer;
+
+ /**
+ * Creates a blitting buffer strategy.
+ *
+ * @param numBuffers the number of buffers, including the front
+ * buffer
+ * @param caps the capabilities of this strategy
+ */
+ protected BltBufferStrategy(int numBuffers, BufferCapabilities caps)
+ {
+ this.caps = caps;
+ createBackBuffers(numBuffers - 1);
+ width = getWidth();
+ height = getHeight();
+ }
+
+ /**
+ * Initializes the backBuffers field with an array of numBuffers
+ * VolatileImages.
+ *
+ * @param numBuffers the number of backbuffers to create
+ */
+ protected void createBackBuffers(int numBuffers)
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ backBuffers = new VolatileImage[numBuffers];
+
+ for (int i = 0; i < numBuffers; i++)
+ backBuffers[i] = c.createCompatibleVolatileImage(width, height);
+ }
+
+ /**
+ * Retrieves the capabilities of this buffer strategy.
+ *
+ * @return the capabilities of this buffer strategy
+ */
+ public BufferCapabilities getCapabilities()
+ {
+ return caps;
+ }
+
+ /**
+ * Retrieves a graphics object that can be used to draw into this
+ * strategy's image buffer.
+ *
+ * @return a graphics object
+ */
+ public Graphics getDrawGraphics()
+ {
+ // Return the backmost buffer's graphics.
+ return backBuffers[0].getGraphics();
+ }
+
+ /**
+ * Bring the contents of the back buffer to the front buffer.
+ */
+ public void show()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ // draw the front buffer.
+ getGraphics().drawImage(backBuffers[backBuffers.length - 1],
+ width, height, null);
+
+ BufferCapabilities.FlipContents f = getCapabilities().getFlipContents();
+
+ // blit the back buffers.
+ for (int i = backBuffers.length - 1; i > 0 ; i--)
+ backBuffers[i] = backBuffers[i - 1];
+
+ // create new backmost buffer.
+ if (f == BufferCapabilities.FlipContents.UNDEFINED)
+ backBuffers[0] = c.createCompatibleVolatileImage(width, height);
+
+ // create new backmost buffer and clear it to the background
+ // color.
+ if (f == BufferCapabilities.FlipContents.BACKGROUND)
+ {
+ backBuffers[0] = c.createCompatibleVolatileImage(width, height);
+ backBuffers[0].getGraphics().clearRect(0, 0, width, height);
+ }
+
+ // FIXME: set the backmost buffer to the prior contents of the
+ // front buffer. How do we retrieve the contents of the front
+ // buffer?
+ //
+ // if (f == BufferCapabilities.FlipContents.PRIOR)
+
+ // set the backmost buffer to a copy of the new front buffer.
+ if (f == BufferCapabilities.FlipContents.COPIED)
+ backBuffers[0] = backBuffers[backBuffers.length - 1];
+ }
+
+ /**
+ * Re-create the image buffer resources if they've been lost.
+ */
+ protected void revalidate()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ int result = backBuffers[i].validate(c);
+ if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ backBuffers[i] = c.createCompatibleVolatileImage(width, height);
+ }
+ validatedContents = true;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * lost.
+ *
+ * @return true if the resources have been lost, false otherwise
+ */
+ public boolean contentsLost()
+ {
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ if (backBuffers[i].contentsLost())
+ {
+ validatedContents = false;
+ return true;
+ }
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return false;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * restored.
+ *
+ * @return true if the resources have been restored, false
+ * otherwise
+ */
+ public boolean contentsRestored()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ boolean imageRestored = false;
+
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ int result = backBuffers[i].validate(c);
+ if (result == VolatileImage.IMAGE_RESTORED)
+ imageRestored = true;
+ else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ return false;
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return imageRestored;
+ }
+ }
+
+ /**
+ * This class provides support for flipping component buffers. It
+ * can only be used on Canvases and Windows.
+ *
+ * @since 1.4
+ */
+ protected class FlipBufferStrategy extends BufferStrategy
+ {
+ /**
+ * The number of buffers.
+ */
+ protected int numBuffers;
+
+ /**
+ * The capabilities of this buffering strategy.
+ */
+ protected BufferCapabilities caps;
+
+ /**
+ * An Image reference to the drawing buffer.
+ */
+ protected Image drawBuffer;
+
+ /**
+ * A VolatileImage reference to the drawing buffer.
+ */
+ protected VolatileImage drawVBuffer;
+
+ /**
+ * Whether or not the image buffer resources are allocated and
+ * ready to be drawn into.
+ */
+ protected boolean validatedContents;
+
+ /**
+ * The width of the back buffer.
+ */
+ private int width;
+
+ /**
+ * The height of the back buffer.
+ */
+ private int height;
+
+ /**
+ * Creates a flipping buffer strategy. The only supported
+ * strategy for FlipBufferStrategy itself is a double-buffer page
+ * flipping strategy. It forms the basis for more complex derived
+ * strategies.
+ *
+ * @param numBuffers the number of buffers
+ * @param caps the capabilities of this buffering strategy
+ *
+ * @throws AWTException if the requested
+ * number-of-buffers/capabilities combination is not supported
+ */
+ protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ this.caps = caps;
+ width = getWidth();
+ height = getHeight();
+
+ if (numBuffers > 1)
+ createBuffers(numBuffers, caps);
+ else
+ {
+ drawVBuffer = peer.createVolatileImage(width, height);
+ drawBuffer = drawVBuffer;
+ }
+ }
+
+ /**
+ * Creates a multi-buffer flipping strategy. The number of
+ * buffers must be greater than one and the buffer capabilities
+ * must specify page flipping.
+ *
+ * @param numBuffers the number of flipping buffers; must be
+ * greater than one
+ * @param caps the buffering capabilities; caps.isPageFlipping()
+ * must return true
+ *
+ * @throws IllegalArgumentException if numBuffers is not greater
+ * than one or if the page flipping capability is not requested
+ *
+ * @throws AWTException if the requested flipping strategy is not
+ * supported
+ */
+ protected void createBuffers(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ if (numBuffers <= 1)
+ throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
+ + " numBuffers must be greater than"
+ + " one.");
+
+ if (!caps.isPageFlipping())
+ throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
+ + " flipping must be a specified"
+ + " capability.");
+
+ peer.createBuffers(numBuffers, caps);
+ }
+
+ /**
+ * Return a direct reference to the back buffer image.
+ *
+ * @return a direct reference to the back buffer image.
+ */
+ protected Image getBackBuffer()
+ {
+ return peer.getBackBuffer();
+ }
+
+ /**
+ * Perform a flip operation to transfer the contents of the back
+ * buffer to the front buffer.
+ */
+ protected void flip(BufferCapabilities.FlipContents flipAction)
+ {
+ peer.flip(flipAction);
+ }
+
+ /**
+ * Release the back buffer's resources.
+ */
+ protected void destroyBuffers()
+ {
+ peer.destroyBuffers();
+ }
+
+ /**
+ * Retrieves the capabilities of this buffer strategy.
+ *
+ * @return the capabilities of this buffer strategy
+ */
+ public BufferCapabilities getCapabilities()
+ {
+ return caps;
+ }
+
+ /**
+ * Retrieves a graphics object that can be used to draw into this
+ * strategy's image buffer.
+ *
+ * @return a graphics object
+ */
+ public Graphics getDrawGraphics()
+ {
+ return drawVBuffer.getGraphics();
+ }
+
+ /**
+ * Re-create the image buffer resources if they've been lost.
+ */
+ protected void revalidate()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ if (drawVBuffer.validate(c) == VolatileImage.IMAGE_INCOMPATIBLE)
+ drawVBuffer = peer.createVolatileImage(width, height);
+ validatedContents = true;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * lost.
+ *
+ * @return true if the resources have been lost, false otherwise
+ */
+ public boolean contentsLost()
+ {
+ if (drawVBuffer.contentsLost())
+ {
+ validatedContents = false;
+ return true;
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return false;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * restored.
+ *
+ * @return true if the resources have been restored, false
+ * otherwise
+ */
+ public boolean contentsRestored()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ int result = drawVBuffer.validate(c);
+
+ boolean imageRestored = false;
+
+ if (result == VolatileImage.IMAGE_RESTORED)
+ imageRestored = true;
+ else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ return false;
+
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return imageRestored;
+ }
+
+ /**
+ * Bring the contents of the back buffer to the front buffer.
+ */
+ public void show()
+ {
+ flip(caps.getFlipContents());
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/ComponentOrientation.java b/libjava/classpath/java/awt/ComponentOrientation.java
new file mode 100644
index 00000000000..69b14c7553f
--- /dev/null
+++ b/libjava/classpath/java/awt/ComponentOrientation.java
@@ -0,0 +1,215 @@
+/* ComponentOrientation.java -- describes a component's orientation
+ Copyright (C) 2000, 2001, 2002 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 java.io.Serializable;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * This class is used to differentiate different orientations for text layout.
+ * It controls whether text flows left-to-right or right-to-left, and whether
+ * lines are horizontal or vertical, as in this table:<br>
+ * <pre>
+ * LT RT TL TR
+ * A B C C B A A D G G D A
+ * D E F F E D B E H H E B
+ * G H I I H G C F I I F C
+ * </pre>
+ * <b>LT</b> languages are most common (left-to-right lines, top-to-bottom).
+ * This includes Western European languages, and optionally includes Japanese,
+ * Chinese, and Korean. <b>RT</b> languages (right-to-left lines,
+ * top-to-bottom) are mainly middle eastern, such as Hebrew and Arabic.
+ * <b>TR</b> languages flow top-to-bottom in a line, right-to-left, and are
+ * the basis of Japanese, Chinese, and Korean. Finally, <b>TL</b> languages
+ * flow top-to-bottom in a line, left-to-right, as in Mongolian.
+ *
+ * <p>This is a pretty poor excuse for a type-safe enum, since it is not
+ * guaranteed that orientation objects are unique (thanks to serialization),
+ * yet there is no equals() method. You would be wise to compare the output
+ * of isHorizontal() and isLeftToRight() rather than comparing objects with
+ * ==, especially since more constants may be added in the future.
+ *
+ * @author Bryce McKinlay (bryce@albatross.co.nz)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public final class ComponentOrientation implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4113291392143563828L;
+
+ /** Constant for unknown orientation. */
+ private static final int UNKNOWN_ID = 1;
+
+ /** Constant for horizontal line orientation. */
+ private static final int HORIZONTAL_ID = 2;
+
+ /** Constant for left-to-right orientation. */
+ private static final int LEFT_TO_RIGHT_ID = 4;
+
+ /**
+ * Items run left to right, and lines flow top to bottom. Examples: English,
+ * French.
+ */
+ public static final ComponentOrientation LEFT_TO_RIGHT
+ = new ComponentOrientation(HORIZONTAL_ID | LEFT_TO_RIGHT_ID);
+
+ /**
+ * Items run right to left, and lines flow top to bottom. Examples: Arabic,
+ * Hebrew.
+ */
+ public static final ComponentOrientation RIGHT_TO_LEFT
+ = new ComponentOrientation(HORIZONTAL_ID);
+
+ /**
+ * The orientation is unknown for the locale. For backwards compatibility,
+ * this behaves like LEFT_TO_RIGHT in the instance methods.
+ */
+ public static final ComponentOrientation UNKNOWN
+ = new ComponentOrientation(UNKNOWN_ID | HORIZONTAL_ID | LEFT_TO_RIGHT_ID);
+
+ /**
+ * The orientation of this object; bitwise-or of unknown (1), horizontal (2),
+ * and left-to-right (4).
+ *
+ * @serial the orientation
+ */
+ private final int orientation;
+
+ /**
+ * Construct a given orientation.
+ *
+ * @param orientation the orientation
+ */
+ private ComponentOrientation(int orientation)
+ {
+ this.orientation = orientation;
+ }
+
+ /**
+ * Returns true if the lines are horizontal, in which case lines flow
+ * top-to-bottom. For example, English, Hebrew. Counterexamples: Japanese,
+ * Chinese, Korean, Mongolian.
+ *
+ * @return true if this orientation has horizontal lines
+ */
+ public boolean isHorizontal()
+ {
+ return (orientation & HORIZONTAL_ID) != 0;
+ }
+
+ /**
+ * If isHorizontal() returns true, then this determines whether items in
+ * the line flow left-to-right. If isHorizontal() returns false, items in
+ * a line flow top-to-bottom, and this determines if lines flow
+ * left-to-right.
+ *
+ * @return true if this orientation flows left-to-right
+ */
+ public boolean isLeftToRight()
+ {
+ return (orientation & LEFT_TO_RIGHT_ID) != 0;
+ }
+
+ /**
+ * Gets an orientation appropriate for the locale.
+ *
+ * @param locale the locale
+ * @return the orientation for that locale
+ * @throws NullPointerException if locale is null
+ */
+ public static ComponentOrientation getOrientation(Locale locale)
+ {
+ // Based on iterating over all languages defined in JDK 1.4, this behavior
+ // matches Sun's. However, it makes me wonder if any non-horizontal
+ // orientations even exist, as it sure contradicts their documentation.
+ String language = locale.getLanguage();
+ if ("ar".equals(language) || "fa".equals(language) || "iw".equals(language)
+ || "ur".equals(language))
+ return RIGHT_TO_LEFT;
+ return LEFT_TO_RIGHT;
+ }
+
+ /**
+ * Gets an orientation from a resource bundle. This tries the following:
+ *
+ * <ul>
+ * <li>Use the key "Orientation" to find an instance of ComponentOrientation
+ * in the bundle.</li>
+ * <li>Get the locale of the resource bundle, and get the orientation of
+ * that locale.</li>
+ * <li>Give up and get the orientation of the default locale.</li>
+ * </ul>
+ *
+ * @param bdl the bundle to use
+ * @return the orientation
+ * @throws NullPointerException if bdl is null
+ * @deprecated use {@link #getOrientation(Locale)} instead
+ */
+ public static ComponentOrientation getOrientation(ResourceBundle bdl)
+ {
+ ComponentOrientation r;
+ try
+ {
+ r = (ComponentOrientation) bdl.getObject("Orientation");
+ if (r != null)
+ return r;
+ }
+ catch (MissingResourceException ignored)
+ {
+ }
+ catch (ClassCastException ignored)
+ {
+ }
+ try
+ {
+ r = getOrientation(bdl.getLocale());
+ if (r != null)
+ return r;
+ }
+ catch (Exception ignored)
+ {
+ }
+ return getOrientation(Locale.getDefault());
+ }
+} // class ComponentOrientation
diff --git a/libjava/classpath/java/awt/Composite.java b/libjava/classpath/java/awt/Composite.java
new file mode 100644
index 00000000000..ca3abe4d1ee
--- /dev/null
+++ b/libjava/classpath/java/awt/Composite.java
@@ -0,0 +1,73 @@
+/* Composite.java -- graphics formed from composite layers
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ColorModel;
+
+/**
+ * This interface is for graphics which are formed as composites of others.
+ * It combines {@link Graphics2D} shapes according to defined rules to form
+ * the new image. Implementations of this interface must be immutable, because
+ * they are not cloned when a Graphics2D container is cloned.
+ *
+ * <p>Since this can expose pixels to untrusted code, there is a security
+ * check on custom objects, <code>readDisplayPixels</code>, to prevent leaking
+ * restricted information graphically.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see AlphaComposite
+ * @see CompositeContext
+ * @see Graphics2D#setComposite(Composite)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Composite
+{
+ /**
+ * Create a context state for performing the compositing operation. Several
+ * contexts may exist for this object, in a multi-threaded environment.
+ *
+ * @param srcColorModel the color model of the source
+ * @param dstColorModel the color model of the destination
+ * @param hints hints for choosing between rendering alternatives
+ */
+ CompositeContext createContext(ColorModel srcColorModel,
+ ColorModel dstColorModel,
+ RenderingHints hints);
+} // interface Composite
diff --git a/libjava/classpath/java/awt/CompositeContext.java b/libjava/classpath/java/awt/CompositeContext.java
new file mode 100644
index 00000000000..018a27071dd
--- /dev/null
+++ b/libjava/classpath/java/awt/CompositeContext.java
@@ -0,0 +1,71 @@
+/* Composite.java -- the context for compositing graphics layers
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+/**
+ * This interface provides an optimized environment for compositing graphics.
+ * Several such contexts may exist for a given <code>Composite</code> object.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Composite
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface CompositeContext
+{
+ /**
+ * Release resources allocated for the compositing.
+ */
+ void dispose();
+
+ /**
+ * Compose the two source images into the composite image. The destination
+ * can be the same as one of the two inputs, and the destination must be
+ * compatible with the ColorModel chosen in {@link Composite#createContext}.
+ *
+ * @param src the lower image source in compositing
+ * @param dstIn the upper image source in compositing
+ * @param dstOut the destination for the composite
+ * @see Composite
+ */
+ void compose(Raster src, Raster dstIn, WritableRaster dstOut);
+} // interface CompositeContext
diff --git a/libjava/classpath/java/awt/Container.java b/libjava/classpath/java/awt/Container.java
new file mode 100644
index 00000000000..303d13b2eb9
--- /dev/null
+++ b/libjava/classpath/java/awt/Container.java
@@ -0,0 +1,2026 @@
+/* Container.java -- parent container class in AWT
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ContainerEvent;
+import java.awt.event.ContainerListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ContainerPeer;
+import java.awt.peer.LightweightPeer;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.accessibility.Accessible;
+import javax.swing.SwingUtilities;
+
+/**
+ * A generic window toolkit object that acts as a container for other objects.
+ * Components are tracked in a list, and new elements are at the end of the
+ * list or bottom of the stacking order.
+ *
+ * @author original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.0
+ *
+ * @status still missing 1.4 support
+ */
+public class Container extends Component
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 4613797578919906343L;
+
+ /* Serialized fields from the serialization spec. */
+ int ncomponents;
+ Component[] component;
+ LayoutManager layoutMgr;
+
+ LightweightDispatcher dispatcher;
+
+ Dimension maxSize;
+
+ /**
+ * @since 1.4
+ */
+ boolean focusCycleRoot;
+
+ int containerSerializedDataVersion;
+
+ /* Anything else is non-serializable, and should be declared "transient". */
+ transient ContainerListener containerListener;
+ transient PropertyChangeSupport changeSupport;
+
+ /** The focus traversal policy that determines how focus is
+ transferred between this Container and its children. */
+ private FocusTraversalPolicy focusTraversalPolicy;
+
+ /**
+ * The focus traversal keys, if not inherited from the parent or default
+ * keyboard manager. These sets will contain only AWTKeyStrokes that
+ * represent press and release events to use as focus control.
+ *
+ * @see #getFocusTraversalKeys(int)
+ * @see #setFocusTraversalKeys(int, Set)
+ * @since 1.4
+ */
+ transient Set[] focusTraversalKeys;
+
+ /**
+ * Default constructor for subclasses.
+ */
+ public Container()
+ {
+ }
+
+ /**
+ * Returns the number of components in this container.
+ *
+ * @return The number of components in this container.
+ */
+ public int getComponentCount()
+ {
+ return countComponents ();
+ }
+
+ /**
+ * Returns the number of components in this container.
+ *
+ * @return The number of components in this container.
+ *
+ * @deprecated use {@link #getComponentCount()} instead
+ */
+ public int countComponents()
+ {
+ return ncomponents;
+ }
+
+ /**
+ * Returns the component at the specified index.
+ *
+ * @param n The index of the component to retrieve.
+ *
+ * @return The requested component.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the specified index is invalid
+ */
+ public Component getComponent(int n)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (n < 0 || n >= ncomponents)
+ throw new ArrayIndexOutOfBoundsException("no such component");
+
+ return component[n];
+ }
+ }
+
+ /**
+ * Returns an array of the components in this container.
+ *
+ * @return The components in this container.
+ */
+ public Component[] getComponents()
+ {
+ synchronized (getTreeLock ())
+ {
+ Component[] result = new Component[ncomponents];
+
+ if (ncomponents > 0)
+ System.arraycopy(component, 0, result, 0, ncomponents);
+
+ return result;
+ }
+ }
+
+ /**
+ * Swaps the components at position i and j, in the container.
+ */
+
+ protected void swapComponents (int i, int j)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (i < 0
+ || i >= component.length
+ || j < 0
+ || j >= component.length)
+ throw new ArrayIndexOutOfBoundsException ();
+ Component tmp = component[i];
+ component[i] = component[j];
+ component[j] = tmp;
+ }
+ }
+
+ /**
+ * Returns the insets for this container, which is the space used for
+ * borders, the margin, etc.
+ *
+ * @return The insets for this container.
+ */
+ public Insets getInsets()
+ {
+ return insets ();
+ }
+
+ /**
+ * Returns the insets for this container, which is the space used for
+ * borders, the margin, etc.
+ *
+ * @return The insets for this container.
+ * @deprecated use {@link #getInsets()} instead
+ */
+ public Insets insets()
+ {
+ if (peer == null)
+ return new Insets (0, 0, 0, 0);
+
+ return ((ContainerPeer) peer).getInsets ();
+ }
+
+ /**
+ * Adds the specified component to this container at the end of the
+ * component list.
+ *
+ * @param comp The component to add to the container.
+ *
+ * @return The same component that was added.
+ */
+ public Component add(Component comp)
+ {
+ addImpl(comp, null, -1);
+ return comp;
+ }
+
+ /**
+ * Adds the specified component to the container at the end of the
+ * component list. This method should not be used. Instead, use
+ * <code>add(Component, Object)</code>.
+ *
+ * @param name The name of the component to be added.
+ * @param comp The component to be added.
+ *
+ * @return The same component that was added.
+ *
+ * @see #add(Component,Object)
+ */
+ public Component add(String name, Component comp)
+ {
+ addImpl(comp, name, -1);
+ return comp;
+ }
+
+ /**
+ * Adds the specified component to this container at the specified index
+ * in the component list.
+ *
+ * @param comp The component to be added.
+ * @param index The index in the component list to insert this child
+ * at, or -1 to add at the end of the list.
+ *
+ * @return The same component that was added.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
+ */
+ public Component add(Component comp, int index)
+ {
+ addImpl(comp, null, index);
+ return comp;
+ }
+
+ /**
+ * Adds the specified component to this container at the end of the
+ * component list. The layout manager will use the specified constraints
+ * when laying out this component.
+ *
+ * @param comp The component to be added to this container.
+ * @param constraints The layout constraints for this component.
+ */
+ public void add(Component comp, Object constraints)
+ {
+ addImpl(comp, constraints, -1);
+ }
+
+ /**
+ * Adds the specified component to this container at the specified index
+ * in the component list. The layout manager will use the specified
+ * constraints when layout out this component.
+ *
+ * @param comp The component to be added.
+ * @param constraints The layout constraints for this component.
+ * @param index The index in the component list to insert this child
+ * at, or -1 to add at the end of the list.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
+ */
+ public void add(Component comp, Object constraints, int index)
+ {
+ addImpl(comp, constraints, index);
+ }
+
+ /**
+ * This method is called by all the <code>add()</code> methods to perform
+ * the actual adding of the component. Subclasses who wish to perform
+ * their own processing when a component is added should override this
+ * method. Any subclass doing this must call the superclass version of
+ * this method in order to ensure proper functioning of the container.
+ *
+ * @param comp The component to be added.
+ * @param constraints The layout constraints for this component, or
+ * <code>null</code> if there are no constraints.
+ * @param index The index in the component list to insert this child
+ * at, or -1 to add at the end of the list.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
+ */
+ protected void addImpl(Component comp, Object constraints, int index)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (index > ncomponents
+ || (index < 0 && index != -1)
+ || comp instanceof Window
+ || (comp instanceof Container
+ && ((Container) comp).isAncestorOf(this)))
+ throw new IllegalArgumentException();
+
+ // Reparent component, and make sure component is instantiated if
+ // we are.
+ if (comp.parent != null)
+ comp.parent.remove(comp);
+ comp.parent = this;
+ if (peer != null)
+ {
+ if (comp.isLightweight ())
+ {
+ enableEvents (comp.eventMask);
+ if (!isLightweight ())
+ enableEvents (AWTEvent.PAINT_EVENT_MASK);
+ }
+ }
+
+ invalidate();
+
+ if (component == null)
+ component = new Component[4]; // FIXME, better initial size?
+
+ // This isn't the most efficient implementation. We could do less
+ // copying when growing the array. It probably doesn't matter.
+ if (ncomponents >= component.length)
+ {
+ int nl = component.length * 2;
+ Component[] c = new Component[nl];
+ System.arraycopy(component, 0, c, 0, ncomponents);
+ component = c;
+ }
+
+ if (index == -1)
+ component[ncomponents++] = comp;
+ else
+ {
+ System.arraycopy(component, index, component, index + 1,
+ ncomponents - index);
+ component[index] = comp;
+ ++ncomponents;
+ }
+
+ // Notify the layout manager.
+ if (layoutMgr != null)
+ {
+ if (layoutMgr instanceof LayoutManager2)
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
+ lm2.addLayoutComponent(comp, constraints);
+ }
+ else if (constraints instanceof String)
+ layoutMgr.addLayoutComponent((String) constraints, comp);
+ else
+ layoutMgr.addLayoutComponent(null, comp);
+ }
+
+ if (isShowing ())
+ {
+ // Post event to notify of adding the component.
+ ContainerEvent ce = new ContainerEvent(this,
+ ContainerEvent.COMPONENT_ADDED,
+ comp);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+ }
+
+ /**
+ * Removes the component at the specified index from this container.
+ *
+ * @param index The index of the component to remove.
+ */
+ public void remove(int index)
+ {
+ synchronized (getTreeLock ())
+ {
+ Component r = component[index];
+
+ r.removeNotify();
+
+ System.arraycopy(component, index + 1, component, index,
+ ncomponents - index - 1);
+ component[--ncomponents] = null;
+
+ invalidate();
+
+ if (layoutMgr != null)
+ layoutMgr.removeLayoutComponent(r);
+
+ r.parent = null;
+
+ if (isShowing ())
+ {
+ // Post event to notify of removing the component.
+ ContainerEvent ce = new ContainerEvent(this,
+ ContainerEvent.COMPONENT_REMOVED,
+ r);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+ }
+
+ /**
+ * Removes the specified component from this container.
+ *
+ * @param comp The component to remove from this container.
+ */
+ public void remove(Component comp)
+ {
+ synchronized (getTreeLock ())
+ {
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ if (component[i] == comp)
+ {
+ remove(i);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes all components from this container.
+ */
+ public void removeAll()
+ {
+ synchronized (getTreeLock ())
+ {
+ while (ncomponents > 0)
+ remove(0);
+ }
+ }
+
+ /**
+ * Returns the current layout manager for this container.
+ *
+ * @return The layout manager for this container.
+ */
+ public LayoutManager getLayout()
+ {
+ return layoutMgr;
+ }
+
+ /**
+ * Sets the layout manager for this container to the specified layout
+ * manager.
+ *
+ * @param mgr The new layout manager for this container.
+ */
+ public void setLayout(LayoutManager mgr)
+ {
+ layoutMgr = mgr;
+ invalidate();
+ }
+
+ /**
+ * Layout the components in this container.
+ */
+ public void doLayout()
+ {
+ layout ();
+ }
+
+ /**
+ * Layout the components in this container.
+ *
+ * @deprecated use {@link #doLayout()} instead
+ */
+ public void layout()
+ {
+ if (layoutMgr != null)
+ layoutMgr.layoutContainer (this);
+ }
+
+ /**
+ * Invalidates this container to indicate that it (and all parent
+ * containers) need to be laid out.
+ */
+ public void invalidate()
+ {
+ super.invalidate();
+ }
+
+ /**
+ * Re-lays out the components in this container.
+ */
+ public void validate()
+ {
+ synchronized (getTreeLock ())
+ {
+ if (! isValid() && peer != null)
+ {
+ validateTree();
+ }
+ }
+ }
+
+ /**
+ * Recursively invalidates the container tree.
+ */
+ void invalidateTree()
+ {
+ for (int i = 0; i < ncomponents; i++)
+ {
+ Component comp = component[i];
+ comp.invalidate();
+ if (comp instanceof Container)
+ ((Container) comp).invalidateTree();
+ }
+ }
+
+ /**
+ * Recursively validates the container tree, recomputing any invalid
+ * layouts.
+ */
+ protected void validateTree()
+ {
+ if (valid)
+ return;
+
+ ContainerPeer cPeer = null;
+ if (peer != null && ! (peer instanceof LightweightPeer))
+ {
+ cPeer = (ContainerPeer) peer;
+ cPeer.beginValidate();
+ }
+
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ Component comp = component[i];
+
+ if (comp.getPeer () == null)
+ comp.addNotify();
+ }
+
+ doLayout ();
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ Component comp = component[i];
+
+ if (! comp.isValid())
+ {
+ if (comp instanceof Container)
+ {
+ ((Container) comp).validateTree();
+ }
+ else
+ {
+ component[i].validate();
+ }
+ }
+ }
+
+ /* children will call invalidate() when they are layed out. It
+ is therefore important that valid is not set to true
+ until after the children have been layed out. */
+ valid = true;
+
+ if (cPeer != null)
+ cPeer.endValidate();
+ }
+
+ public void setFont(Font f)
+ {
+ super.setFont(f);
+ // FIXME: Although it might make more sense to invalidate only
+ // those children whose font == null, Sun invalidates all children.
+ // So we'll do the same.
+ invalidateTree();
+ }
+
+ /**
+ * Returns the preferred size of this container.
+ *
+ * @return The preferred size of this container.
+ */
+ public Dimension getPreferredSize()
+ {
+ return preferredSize ();
+ }
+
+ /**
+ * Returns the preferred size of this container.
+ *
+ * @return The preferred size of this container.
+ *
+ * @deprecated use {@link #getPreferredSize()} instead
+ */
+ public Dimension preferredSize()
+ {
+ if (layoutMgr != null)
+ return layoutMgr.preferredLayoutSize (this);
+ else
+ return super.preferredSize ();
+ }
+
+ /**
+ * Returns the minimum size of this container.
+ *
+ * @return The minimum size of this container.
+ */
+ public Dimension getMinimumSize()
+ {
+ return minimumSize ();
+ }
+
+ /**
+ * Returns the minimum size of this container.
+ *
+ * @return The minimum size of this container.
+ *
+ * @deprecated use {@link #getMinimumSize()} instead
+ */
+ public Dimension minimumSize()
+ {
+ if (layoutMgr != null)
+ return layoutMgr.minimumLayoutSize (this);
+ else
+ return super.minimumSize ();
+ }
+
+ /**
+ * Returns the maximum size of this container.
+ *
+ * @return The maximum size of this container.
+ */
+ public Dimension getMaximumSize()
+ {
+ if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
+ return lm2.maximumLayoutSize(this);
+ }
+ else
+ return super.getMaximumSize();
+ }
+
+ /**
+ * Returns the preferred alignment along the X axis. This is a value
+ * between 0 and 1 where 0 represents alignment flush left and
+ * 1 means alignment flush right, and 0.5 means centered.
+ *
+ * @return The preferred alignment along the X axis.
+ */
+ public float getAlignmentX()
+ {
+ if (layoutMgr instanceof LayoutManager2)
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
+ return lm2.getLayoutAlignmentX(this);
+ }
+ else
+ return super.getAlignmentX();
+ }
+
+ /**
+ * Returns the preferred alignment along the Y axis. This is a value
+ * between 0 and 1 where 0 represents alignment flush top and
+ * 1 means alignment flush bottom, and 0.5 means centered.
+ *
+ * @return The preferred alignment along the Y axis.
+ */
+ public float getAlignmentY()
+ {
+ if (layoutMgr instanceof LayoutManager2)
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
+ return lm2.getLayoutAlignmentY(this);
+ }
+ else
+ return super.getAlignmentY();
+ }
+
+ /**
+ * Paints this container. The implementation of this method in this
+ * class forwards to any lightweight components in this container. If
+ * this method is subclassed, this method should still be invoked as
+ * a superclass method so that lightweight components are properly
+ * drawn.
+ *
+ * @param g The graphics context for this paint job.
+ */
+ public void paint(Graphics g)
+ {
+ if (!isShowing())
+ return;
+ // Paint self first.
+ super.paint(g);
+ // Visit heavyweights as well, in case they were
+ // erased when we cleared the background for this container.
+ visitChildren(g, GfxPaintVisitor.INSTANCE, false);
+ }
+
+ /**
+ * Updates this container. The implementation of this method in this
+ * class forwards to any lightweight components in this container. If
+ * this method is subclassed, this method should still be invoked as
+ * a superclass method so that lightweight components are properly
+ * drawn.
+ *
+ * @param g The graphics context for this update.
+ */
+ public void update(Graphics g)
+ {
+ super.update(g);
+ }
+
+ /**
+ * Prints this container. The implementation of this method in this
+ * class forwards to any lightweight components in this container. If
+ * this method is subclassed, this method should still be invoked as
+ * a superclass method so that lightweight components are properly
+ * drawn.
+ *
+ * @param g The graphics context for this print job.
+ */
+ public void print(Graphics g)
+ {
+ super.print(g);
+ visitChildren(g, GfxPrintVisitor.INSTANCE, true);
+ }
+
+ /**
+ * Paints all of the components in this container.
+ *
+ * @param g The graphics context for this paint job.
+ */
+ public void paintComponents(Graphics g)
+ {
+ super.paint(g);
+ visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
+ }
+
+ /**
+ * Prints all of the components in this container.
+ *
+ * @param g The graphics context for this print job.
+ */
+ public void printComponents(Graphics g)
+ {
+ super.paint(g);
+ visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
+ }
+
+ /**
+ * Adds the specified container listener to this object's list of
+ * container listeners.
+ *
+ * @param listener The listener to add.
+ */
+ public synchronized void addContainerListener(ContainerListener listener)
+ {
+ containerListener = AWTEventMulticaster.add(containerListener, listener);
+ }
+
+ /**
+ * Removes the specified container listener from this object's list of
+ * container listeners.
+ *
+ * @param listener The listener to remove.
+ */
+ public synchronized void removeContainerListener(ContainerListener listener)
+ {
+ containerListener = AWTEventMulticaster.remove(containerListener, listener);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public synchronized ContainerListener[] getContainerListeners()
+ {
+ return (ContainerListener[])
+ AWTEventMulticaster.getListeners(containerListener,
+ ContainerListener.class);
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this Container. FooListeners are registered using the addFooListener
+ * method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements @see java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ if (listenerType == ContainerListener.class)
+ return getContainerListeners();
+ return super.getListeners(listenerType);
+ }
+
+ /**
+ * Processes the specified event. This method calls
+ * <code>processContainerEvent()</code> if this method is a
+ * <code>ContainerEvent</code>, otherwise it calls the superclass
+ * method.
+ *
+ * @param e The event to be processed.
+ */
+ protected void processEvent(AWTEvent e)
+ {
+ if (e instanceof ContainerEvent)
+ processContainerEvent((ContainerEvent) e);
+ else
+ super.processEvent(e);
+ }
+
+ /**
+ * Called when a container event occurs if container events are enabled.
+ * This method calls any registered listeners.
+ *
+ * @param e The event that occurred.
+ */
+ protected void processContainerEvent(ContainerEvent e)
+ {
+ if (containerListener == null)
+ return;
+ switch (e.id)
+ {
+ case ContainerEvent.COMPONENT_ADDED:
+ containerListener.componentAdded(e);
+ break;
+
+ case ContainerEvent.COMPONENT_REMOVED:
+ containerListener.componentRemoved(e);
+ break;
+ }
+ }
+
+ /**
+ * AWT 1.0 event processor.
+ *
+ * @param e The event that occurred.
+ *
+ * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
+ */
+ public void deliverEvent(Event e)
+ {
+ if (!handleEvent (e))
+ {
+ synchronized (getTreeLock ())
+ {
+ Component parent = getParent ();
+
+ if (parent != null)
+ parent.deliverEvent (e);
+ }
+ }
+ }
+
+ /**
+ * Returns the component located at the specified point. This is done
+ * by checking whether or not a child component claims to contain this
+ * point. The first child component that does is returned. If no
+ * child component claims the point, the container itself is returned,
+ * unless the point does not exist within this container, in which
+ * case <code>null</code> is returned.
+ *
+ * @param x The X coordinate of the point.
+ * @param y The Y coordinate of the point.
+ *
+ * @return The component containing the specified point, or
+ * <code>null</code> if there is no such point.
+ */
+ public Component getComponentAt(int x, int y)
+ {
+ return locate (x, y);
+ }
+
+ /**
+ * Returns the component located at the specified point. This is done
+ * by checking whether or not a child component claims to contain this
+ * point. The first child component that does is returned. If no
+ * child component claims the point, the container itself is returned,
+ * unless the point does not exist within this container, in which
+ * case <code>null</code> is returned.
+ *
+ * @param x The x position of the point to return the component at.
+ * @param y The y position of the point to return the component at.
+ *
+ * @return The component containing the specified point, or <code>null</code>
+ * if there is no such point.
+ *
+ * @deprecated use {@link #getComponentAt(int, int)} instead
+ */
+ public Component locate(int x, int y)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (!contains (x, y))
+ return null;
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ // Ignore invisible children...
+ if (!component[i].isVisible ())
+ continue;
+
+ int x2 = x - component[i].x;
+ int y2 = y - component[i].y;
+ if (component[i].contains (x2, y2))
+ return component[i];
+ }
+ return this;
+ }
+ }
+
+ /**
+ * Returns the component located at the specified point. This is done
+ * by checking whether or not a child component claims to contain this
+ * point. The first child component that does is returned. If no
+ * child component claims the point, the container itself is returned,
+ * unless the point does not exist within this container, in which
+ * case <code>null</code> is returned.
+ *
+ * @param p The point to return the component at.
+ * @return The component containing the specified point, or <code>null</code>
+ * if there is no such point.
+ */
+ public Component getComponentAt(Point p)
+ {
+ return getComponentAt (p.x, p.y);
+ }
+
+ public Component findComponentAt(int x, int y)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (! contains(x, y))
+ return null;
+
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ // Ignore invisible children...
+ if (!component[i].isVisible())
+ continue;
+
+ int x2 = x - component[i].x;
+ int y2 = y - component[i].y;
+ // We don't do the contains() check right away because
+ // findComponentAt would redundantly do it first thing.
+ if (component[i] instanceof Container)
+ {
+ Container k = (Container) component[i];
+ Component r = k.findComponentAt(x2, y2);
+ if (r != null)
+ return r;
+ }
+ else if (component[i].contains(x2, y2))
+ return component[i];
+ }
+
+ return this;
+ }
+ }
+
+ public Component findComponentAt(Point p)
+ {
+ return findComponentAt(p.x, p.y);
+ }
+
+ /**
+ * Called when this container is added to another container to inform it
+ * to create its peer. Peers for any child components will also be
+ * created.
+ */
+ public void addNotify()
+ {
+ super.addNotify();
+ addNotifyContainerChildren();
+ }
+
+ /**
+ * Called when this container is removed from its parent container to
+ * inform it to destroy its peer. This causes the peers of all child
+ * component to be destroyed as well.
+ */
+ public void removeNotify()
+ {
+ synchronized (getTreeLock ())
+ {
+ for (int i = 0; i < ncomponents; ++i)
+ component[i].removeNotify();
+ super.removeNotify();
+ }
+ }
+
+ /**
+ * Tests whether or not the specified component is contained within
+ * this components subtree.
+ *
+ * @param comp The component to test.
+ *
+ * @return <code>true</code> if this container is an ancestor of the
+ * specified component, <code>false</code> otherwise.
+ */
+ public boolean isAncestorOf(Component comp)
+ {
+ synchronized (getTreeLock ())
+ {
+ while (true)
+ {
+ if (comp == null)
+ return false;
+ if (comp == this)
+ return true;
+ comp = comp.getParent();
+ }
+ }
+ }
+
+ /**
+ * Returns a string representing the state of this container for
+ * debugging purposes.
+ *
+ * @return A string representing the state of this container.
+ */
+ protected String paramString()
+ {
+ if (layoutMgr == null)
+ return super.paramString();
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(super.paramString());
+ sb.append(",layout=");
+ sb.append(layoutMgr.getClass().getName());
+ return sb.toString();
+ }
+
+ /**
+ * Writes a listing of this container to the specified stream starting
+ * at the specified indentation point.
+ *
+ * @param out The <code>PrintStream</code> to write to.
+ * @param indent The indentation point.
+ */
+ public void list(PrintStream out, int indent)
+ {
+ synchronized (getTreeLock ())
+ {
+ super.list(out, indent);
+ for (int i = 0; i < ncomponents; ++i)
+ component[i].list(out, indent + 2);
+ }
+ }
+
+ /**
+ * Writes a listing of this container to the specified stream starting
+ * at the specified indentation point.
+ *
+ * @param out The <code>PrintWriter</code> to write to.
+ * @param indent The indentation point.
+ */
+ public void list(PrintWriter out, int indent)
+ {
+ synchronized (getTreeLock ())
+ {
+ super.list(out, indent);
+ for (int i = 0; i < ncomponents; ++i)
+ component[i].list(out, indent + 2);
+ }
+ }
+
+ /**
+ * Sets the focus traversal keys for a given traversal operation for this
+ * Container.
+ *
+ * @exception IllegalArgumentException If id is not one of
+ * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
+ * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS,
+ * or if keystrokes contains null, or if any Object in keystrokes is not an
+ * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any
+ * keystroke already maps to another focus traversal operation for this
+ * Container.
+ *
+ * @since 1.4
+ */
+ public void setFocusTraversalKeys(int id, Set keystrokes)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ if (keystrokes == null)
+ {
+ Container parent = getParent ();
+
+ while (parent != null)
+ {
+ if (parent.areFocusTraversalKeysSet (id))
+ {
+ keystrokes = parent.getFocusTraversalKeys (id);
+ break;
+ }
+ parent = parent.getParent ();
+ }
+
+ if (keystrokes == null)
+ keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
+ getDefaultFocusTraversalKeys (id);
+ }
+
+ Set sa;
+ Set sb;
+ Set sc;
+ String name;
+ switch (id)
+ {
+ case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ sc = getFocusTraversalKeys
+ (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
+ name = "forwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ sc = getFocusTraversalKeys
+ (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
+ name = "backwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sc = getFocusTraversalKeys
+ (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
+ name = "upCycleFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sc = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ name = "downCycleFocusTraversalKeys";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+
+ int i = keystrokes.size ();
+ Iterator iter = keystrokes.iterator ();
+
+ while (--i >= 0)
+ {
+ Object o = iter.next ();
+ if (!(o instanceof AWTKeyStroke)
+ || sa.contains (o) || sb.contains (o) || sc.contains (o)
+ || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
+ throw new IllegalArgumentException ();
+ }
+
+ if (focusTraversalKeys == null)
+ focusTraversalKeys = new Set[3];
+
+ keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
+ firePropertyChange (name, focusTraversalKeys[id], keystrokes);
+
+ focusTraversalKeys[id] = keystrokes;
+ }
+
+ /**
+ * Returns the Set of focus traversal keys for a given traversal operation for
+ * this Container.
+ *
+ * @exception IllegalArgumentException If id is not one of
+ * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
+ * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
+ *
+ * @since 1.4
+ */
+ public Set getFocusTraversalKeys (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ Set s = null;
+
+ if (focusTraversalKeys != null)
+ s = focusTraversalKeys[id];
+
+ if (s == null && parent != null)
+ s = parent.getFocusTraversalKeys (id);
+
+ return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .getDefaultFocusTraversalKeys(id)) : s;
+ }
+
+ /**
+ * Returns whether the Set of focus traversal keys for the given focus
+ * traversal operation has been explicitly defined for this Container.
+ * If this method returns false, this Container is inheriting the Set from
+ * an ancestor, or from the current KeyboardFocusManager.
+ *
+ * @exception IllegalArgumentException If id is not one of
+ * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
+ * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
+ *
+ * @since 1.4
+ */
+ public boolean areFocusTraversalKeysSet (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ return focusTraversalKeys != null && focusTraversalKeys[id] != null;
+ }
+
+ /**
+ * Check whether the given Container is the focus cycle root of this
+ * Container's focus traversal cycle. If this Container is a focus
+ * cycle root itself, then it will be in two different focus cycles
+ * -- it's own, and that of its ancestor focus cycle root's. In
+ * that case, if <code>c</code> is either of those containers, this
+ * method will return true.
+ *
+ * @param c the candidate Container
+ *
+ * @return true if c is the focus cycle root of the focus traversal
+ * cycle to which this Container belongs, false otherwise
+ *
+ * @since 1.4
+ */
+ public boolean isFocusCycleRoot (Container c)
+ {
+ if (this == c
+ && isFocusCycleRoot ())
+ return true;
+
+ Container ancestor = getFocusCycleRootAncestor ();
+
+ if (c == ancestor)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * If this Container is a focus cycle root, set the focus traversal
+ * policy that determines the focus traversal order for its
+ * children. If non-null, this policy will be inherited by all
+ * inferior focus cycle roots. If <code>policy</code> is null, this
+ * Container will inherit its policy from the closest ancestor focus
+ * cycle root that's had its policy set.
+ *
+ * @param policy the new focus traversal policy for this Container or null
+ *
+ * @since 1.4
+ */
+ public void setFocusTraversalPolicy (FocusTraversalPolicy policy)
+ {
+ focusTraversalPolicy = policy;
+ }
+
+ /**
+ * Return the focus traversal policy that determines the focus
+ * traversal order for this Container's children. This method
+ * returns null if this Container is not a focus cycle root. If the
+ * focus traversal policy has not been set explicitly, then this
+ * method will return an ancestor focus cycle root's policy instead.
+ *
+ * @return this Container's focus traversal policy or null
+ *
+ * @since 1.4
+ */
+ public FocusTraversalPolicy getFocusTraversalPolicy ()
+ {
+ if (!isFocusCycleRoot ())
+ return null;
+
+ if (focusTraversalPolicy == null)
+ {
+ Container ancestor = getFocusCycleRootAncestor ();
+
+ if (ancestor != this)
+ return ancestor.getFocusTraversalPolicy ();
+ else
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ return manager.getDefaultFocusTraversalPolicy ();
+ }
+ }
+ else
+ return focusTraversalPolicy;
+ }
+
+ /**
+ * Check whether this Container's focus traversal policy has been
+ * explicitly set. If it has not, then this Container will inherit
+ * its focus traversal policy from one of its ancestor focus cycle
+ * roots.
+ *
+ * @return true if focus traversal policy is set, false otherwise
+ */
+ public boolean isFocusTraversalPolicySet ()
+ {
+ return focusTraversalPolicy == null;
+ }
+
+ /**
+ * Set whether or not this Container is the root of a focus
+ * traversal cycle. This Container's focus traversal policy
+ * determines the order of focus traversal. Some policies prevent
+ * the focus from being transferred between two traversal cycles
+ * until an up or down traversal operation is performed. In that
+ * case, normal traversal (not up or down) is limited to this
+ * Container and all of this Container's descendents that are not
+ * descendents of inferior focus cycle roots. In the default case
+ * however, ContainerOrderFocusTraversalPolicy is in effect, and it
+ * supports implicit down-cycle traversal operations.
+ *
+ * @param focusCycleRoot true if this is a focus cycle root, false otherwise
+ *
+ * @since 1.4
+ */
+ public void setFocusCycleRoot (boolean focusCycleRoot)
+ {
+ this.focusCycleRoot = focusCycleRoot;
+ }
+
+ /**
+ * Check whether this Container is a focus cycle root.
+ *
+ * @return true if this is a focus cycle root, false otherwise
+ *
+ * @since 1.4
+ */
+ public boolean isFocusCycleRoot ()
+ {
+ return focusCycleRoot;
+ }
+
+ /**
+ * Transfer focus down one focus traversal cycle. If this Container
+ * is a focus cycle root, then its default component becomes the
+ * focus owner, and this Container becomes the current focus cycle
+ * root. No traversal will occur if this Container is not a focus
+ * cycle root.
+ *
+ * @since 1.4
+ */
+ public void transferFocusDownCycle ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ manager.downFocusCycle (this);
+ }
+
+ /**
+ * Sets the ComponentOrientation property of this container and all components
+ * contained within it.
+ *
+ * @exception NullPointerException If orientation is null
+ *
+ * @since 1.4
+ */
+ public void applyComponentOrientation (ComponentOrientation orientation)
+ {
+ if (orientation == null)
+ throw new NullPointerException ();
+ }
+
+ public void addPropertyChangeListener (PropertyChangeListener listener)
+ {
+ if (listener == null)
+ return;
+
+ if (changeSupport == null)
+ changeSupport = new PropertyChangeSupport (this);
+
+ changeSupport.addPropertyChangeListener (listener);
+ }
+
+ public void addPropertyChangeListener (String name,
+ PropertyChangeListener listener)
+ {
+ if (listener == null)
+ return;
+
+ if (changeSupport == null)
+ changeSupport = new PropertyChangeSupport (this);
+
+ changeSupport.addPropertyChangeListener (name, listener);
+ }
+
+ // Hidden helper methods.
+
+ /**
+ * Perform a graphics operation on the children of this container.
+ * For each applicable child, the visitChild() method will be called
+ * to perform the graphics operation.
+ *
+ * @param gfx The graphics object that will be used to derive new
+ * graphics objects for the children.
+ *
+ * @param visitor Object encapsulating the graphics operation that
+ * should be performed.
+ *
+ * @param lightweightOnly If true, only lightweight components will
+ * be visited.
+ */
+ private void visitChildren(Graphics gfx, GfxVisitor visitor,
+ boolean lightweightOnly)
+ {
+ synchronized (getTreeLock ())
+ {
+ for (int i = ncomponents - 1; i >= 0; --i)
+ {
+ Component comp = component[i];
+ // If we're visiting heavyweights as well,
+ // don't recurse into Containers here. This avoids
+ // painting the same nested child multiple times.
+ boolean applicable = comp.isVisible()
+ && (comp.isLightweight()
+ || !lightweightOnly && ! (comp instanceof Container));
+
+ if (applicable)
+ visitChild(gfx, visitor, comp);
+ }
+ }
+ }
+
+ /**
+ * Perform a graphics operation on a child. A translated and clipped
+ * graphics object will be created, and the visit() method of the
+ * visitor will be called to perform the operation.
+ *
+ * @param gfx The graphics object that will be used to derive new
+ * graphics objects for the child.
+ *
+ * @param visitor Object encapsulating the graphics operation that
+ * should be performed.
+ *
+ * @param comp The child component that should be visited.
+ */
+ private void visitChild(Graphics gfx, GfxVisitor visitor,
+ Component comp)
+ {
+ Rectangle bounds = comp.getBounds();
+ Rectangle oldClip = gfx.getClipBounds();
+ if (oldClip == null)
+ oldClip = bounds;
+
+ Rectangle clip = oldClip.intersection(bounds);
+
+ if (clip.isEmpty()) return;
+
+ boolean clipped = false;
+ boolean translated = false;
+ try
+ {
+ gfx.setClip(clip.x, clip.y, clip.width, clip.height);
+ clipped = true;
+ gfx.translate(bounds.x, bounds.y);
+ translated = true;
+ visitor.visit(comp, gfx);
+ }
+ finally
+ {
+ if (translated)
+ gfx.translate (-bounds.x, -bounds.y);
+ if (clipped)
+ gfx.setClip (oldClip.x, oldClip.y, oldClip.width, oldClip.height);
+ }
+ }
+
+ void dispatchEventImpl(AWTEvent e)
+ {
+ // Give lightweight dispatcher a chance to handle it.
+ if (eventTypeEnabled (e.id)
+ && dispatcher != null
+ && dispatcher.handleEvent (e))
+ return;
+
+ if ((e.id <= ContainerEvent.CONTAINER_LAST
+ && e.id >= ContainerEvent.CONTAINER_FIRST)
+ && (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+ }
+
+ // This is used to implement Component.transferFocus.
+ Component findNextFocusComponent(Component child)
+ {
+ synchronized (getTreeLock ())
+ {
+ int start, end;
+ if (child != null)
+ {
+ for (start = 0; start < ncomponents; ++start)
+ {
+ if (component[start] == child)
+ break;
+ }
+ end = start;
+ // This special case lets us be sure to terminate.
+ if (end == 0)
+ end = ncomponents;
+ ++start;
+ }
+ else
+ {
+ start = 0;
+ end = ncomponents;
+ }
+
+ for (int j = start; j != end; ++j)
+ {
+ if (j >= ncomponents)
+ {
+ // The JCL says that we should wrap here. However, that
+ // seems wrong. To me it seems that focus order should be
+ // global within in given window. So instead if we reach
+ // the end we try to look in our parent, if we have one.
+ if (parent != null)
+ return parent.findNextFocusComponent(this);
+ j -= ncomponents;
+ }
+ if (component[j] instanceof Container)
+ {
+ Component c = component[j];
+ c = c.findNextFocusComponent(null);
+ if (c != null)
+ return c;
+ }
+ else if (component[j].isFocusTraversable())
+ return component[j];
+ }
+
+ return null;
+ }
+ }
+
+ private void addNotifyContainerChildren()
+ {
+ synchronized (getTreeLock ())
+ {
+ for (int i = ncomponents; --i >= 0; )
+ {
+ component[i].addNotify();
+ if (component[i].isLightweight ())
+ {
+
+ // If we're not lightweight, and we just got a lightweight
+ // child, we need a lightweight dispatcher to feed it events.
+ if (! this.isLightweight())
+ {
+ if (dispatcher == null)
+ dispatcher = new LightweightDispatcher (this);
+ }
+
+
+ enableEvents(component[i].eventMask);
+ if (peer != null && !isLightweight ())
+ enableEvents (AWTEvent.PAINT_EVENT_MASK);
+ }
+ }
+ }
+ }
+
+ /**
+ * Deserialize this Container:
+ * <ol>
+ * <li>Read from the stream the default serializable fields.</li>
+ * <li>Read a list of serializable ContainerListeners as optional
+ * data. If the list is null, no listeners will be registered.</li>
+ * <li>Read this Container's FocusTraversalPolicy as optional data.
+ * If this is null, then this Container will use a
+ * DefaultFocusTraversalPolicy.</li>
+ * </ol>
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if deserialization fails
+ * @throws IOException if the stream fails
+ */
+ private void readObject (ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject ();
+ String key = (String) s.readObject ();
+ while (key != null)
+ {
+ Object object = s.readObject ();
+ if ("containerL".equals (key))
+ addContainerListener((ContainerListener) object);
+ // FIXME: under what key is the focus traversal policy stored?
+ else if ("focusTraversalPolicy".equals (key))
+ setFocusTraversalPolicy ((FocusTraversalPolicy) object);
+
+ key = (String) s.readObject();
+ }
+ }
+
+ /**
+ * Serialize this Container:
+ * <ol>
+ * <li>Write to the stream the default serializable fields.</li>
+ * <li>Write the list of serializable ContainerListeners as optional
+ * data.</li>
+ * <li>Write this Container's FocusTraversalPolicy as optional data.</li>
+ * </ol>
+ *
+ * @param s the stream to write to
+ * @throws IOException if the stream fails
+ */
+ private void writeObject (ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject ();
+ AWTEventMulticaster.save (s, "containerL", containerListener);
+ if (focusTraversalPolicy instanceof Serializable)
+ s.writeObject (focusTraversalPolicy);
+ else
+ s.writeObject (null);
+ }
+
+ // Nested classes.
+
+ /* The following classes are used in concert with the
+ visitChildren() method to implement all the graphics operations
+ that requires traversal of the containment hierarchy. */
+
+ abstract static class GfxVisitor
+ {
+ public abstract void visit(Component c, Graphics gfx);
+ }
+
+ static class GfxPaintVisitor extends GfxVisitor
+ {
+ public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
+
+ public void visit(Component c, Graphics gfx)
+ {
+ c.paint(gfx);
+ }
+ }
+
+ static class GfxPrintVisitor extends GfxVisitor
+ {
+ public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
+
+ public void visit(Component c, Graphics gfx)
+ {
+ c.print(gfx);
+ }
+ }
+
+ static class GfxPaintAllVisitor extends GfxVisitor
+ {
+ public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
+
+ public void visit(Component c, Graphics gfx)
+ {
+ c.paintAll(gfx);
+ }
+ }
+
+ static class GfxPrintAllVisitor extends GfxVisitor
+ {
+ public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
+
+ public void visit(Component c, Graphics gfx)
+ {
+ c.printAll(gfx);
+ }
+ }
+
+ /**
+ * This class provides accessibility support for subclasses of container.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.3
+ */
+ protected class AccessibleAWTContainer extends AccessibleAWTComponent
+ {
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 5081320404842566097L;
+
+ /**
+ * The handler to fire PropertyChange when children are added or removed.
+ *
+ * @serial the handler for property changes
+ */
+ protected ContainerListener accessibleContainerHandler
+ = new AccessibleContainerHandler();
+
+ /**
+ * The default constructor.
+ */
+ protected AccessibleAWTContainer()
+ {
+ Container.this.addContainerListener(accessibleContainerHandler);
+ }
+
+ /**
+ * Return the number of accessible children of the containing accessible
+ * object (at most the total number of its children).
+ *
+ * @return the number of accessible children
+ */
+ public int getAccessibleChildrenCount()
+ {
+ synchronized (getTreeLock ())
+ {
+ int count = 0;
+ int i = component == null ? 0 : component.length;
+ while (--i >= 0)
+ if (component[i] instanceof Accessible)
+ count++;
+ return count;
+ }
+ }
+
+ /**
+ * Return the nth accessible child of the containing accessible object.
+ *
+ * @param i the child to grab, zero-based
+ * @return the accessible child, or null
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (component == null)
+ return null;
+ int index = -1;
+ while (i >= 0 && ++index < component.length)
+ if (component[index] instanceof Accessible)
+ i--;
+ if (i < 0)
+ return (Accessible) component[index];
+ return null;
+ }
+ }
+
+ /**
+ * Return the accessible child located at point (in the parent's
+ * coordinates), if one exists.
+ *
+ * @param p the point to look at
+ *
+ * @return an accessible object at that point, or null
+ *
+ * @throws NullPointerException if p is null
+ */
+ public Accessible getAccessibleAt(Point p)
+ {
+ Component c = getComponentAt(p.x, p.y);
+ return c != Container.this && c instanceof Accessible ? (Accessible) c
+ : null;
+ }
+
+ /**
+ * This class fires a <code>PropertyChange</code> listener, if registered,
+ * when children are added or removed from the enclosing accessible object.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.3
+ */
+ protected class AccessibleContainerHandler implements ContainerListener
+ {
+ /**
+ * Default constructor.
+ */
+ protected AccessibleContainerHandler()
+ {
+ }
+
+ /**
+ * Fired when a component is added; forwards to the PropertyChange
+ * listener.
+ *
+ * @param e the container event for adding
+ */
+ public void componentAdded(ContainerEvent e)
+ {
+ AccessibleAWTContainer.this.firePropertyChange
+ (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
+ }
+
+ /**
+ * Fired when a component is removed; forwards to the PropertyChange
+ * listener.
+ *
+ * @param e the container event for removing
+ */
+ public void componentRemoved(ContainerEvent e)
+ {
+ AccessibleAWTContainer.this.firePropertyChange
+ (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
+ }
+ } // class AccessibleContainerHandler
+ } // class AccessibleAWTContainer
+} // class Container
+
+/**
+ * There is a helper class implied from stack traces called
+ * LightweightDispatcher, but since it is not part of the public API,
+ * rather than mimic it exactly we write something which does "roughly
+ * the same thing".
+ */
+
+class LightweightDispatcher implements Serializable
+{
+ private static final long serialVersionUID = 5184291520170872969L;
+ private Container nativeContainer;
+ private Cursor nativeCursor;
+ private long eventMask;
+
+ private transient Component mouseEventTarget;
+ private transient Component pressedComponent;
+ private transient Component lastComponentEntered;
+ private transient Component tempComponent;
+ private transient int pressCount;
+
+ LightweightDispatcher(Container c)
+ {
+ nativeContainer = c;
+ }
+
+ void acquireComponentForMouseEvent(MouseEvent me)
+ {
+ int x = me.getX ();
+ int y = me.getY ();
+
+ // Find the candidate which should receive this event.
+ Component parent = nativeContainer;
+ Component candidate = null;
+ Point p = me.getPoint();
+ while (candidate == null && parent != null)
+ {
+ candidate =
+ SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
+ if (candidate == null || (candidate.eventMask & me.getID()) == 0)
+ {
+ candidate = null;
+ p = SwingUtilities.convertPoint(parent, p.x, p.y, parent.parent);
+ parent = parent.parent;
+ }
+ }
+
+ // 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 == nativeContainer)
+ candidate = null;
+
+ // If our candidate is new, inform the old target we're leaving.
+ if (lastComponentEntered != null
+ && lastComponentEntered.isShowing()
+ && lastComponentEntered != candidate)
+ {
+ // Old candidate could have been removed from
+ // the nativeContainer so we check first.
+ if (SwingUtilities.isDescendingFrom(lastComponentEntered, nativeContainer))
+ {
+ Point tp =
+ SwingUtilities.convertPoint(nativeContainer,
+ 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);
+ }
+ lastComponentEntered = null;
+ }
+ // If we have a candidate, maybe enter it.
+ if (candidate != null)
+ {
+ mouseEventTarget = candidate;
+ if (candidate.isLightweight()
+ && candidate.isShowing()
+ && candidate != nativeContainer
+ && candidate != lastComponentEntered)
+ {
+ lastComponentEntered = mouseEventTarget;
+ Point cp = SwingUtilities.convertPoint(nativeContainer,
+ 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
+ if (SwingUtilities.isDescendingFrom(pressedComponent, nativeContainer))
+ 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;
+ }
+ }
+
+ boolean handleEvent(AWTEvent e)
+ {
+ if (e instanceof MouseEvent)
+ {
+ MouseEvent me = (MouseEvent) e;
+
+ acquireComponentForMouseEvent(me);
+
+ // Avoid dispatching ENTERED and EXITED events twice.
+ if (mouseEventTarget != null
+ && mouseEventTarget.isShowing()
+ && e.getID() != MouseEvent.MOUSE_ENTERED
+ && e.getID() != MouseEvent.MOUSE_EXITED)
+ {
+ MouseEvent newEvt =
+ SwingUtilities.convertMouseEvent(nativeContainer, 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;
+ }
+ if (newEvt.isConsumed())
+ e.consume();
+ }
+ }
+
+ return e.isConsumed();
+ }
+
+} // class LightweightDispatcher
diff --git a/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java b/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java
new file mode 100644
index 00000000000..152482c887b
--- /dev/null
+++ b/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java
@@ -0,0 +1,413 @@
+/* ContainerOrderFocusTraversalPolicy.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * ContainerOrderFocusTraversalPolicy defines a focus traversal order
+ * based on the order in which Components were packed in a Container.
+ * This policy performs a pre-order traversal of the Component
+ * hierarchy starting from a given focus cycle root. Portions of the
+ * hierarchy that are not visible and displayable are skipped.
+ *
+ * By default, this policy transfers focus down-cycle implicitly.
+ * That is, if a forward traversal is requested on a focus cycle root
+ * and the focus cycle root has focusable children, the focus will
+ * automatically be transfered down to the lower focus cycle.
+ *
+ * The default implementation of accept accepts only Components that
+ * are visible, displayable, enabled and focusable. Derived classes
+ * can override these acceptance criteria by overriding accept.
+ *
+ * @author Michael Koch
+ * @author Thomas Fitzsimmons (fitzsim@redhat.com)
+ * @since 1.4
+ */
+public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
+ implements Serializable
+{
+ /**
+ * Compatible to JDK 1.4+
+ */
+ static final long serialVersionUID = 486933713763926351L;
+
+ /**
+ * True if implicit down cycling is enabled.
+ */
+ private boolean implicitDownCycleTraversal = true;
+
+ /**
+ * Creates the <code>ContainerOrderFocusTraversalPolicy</code> object.
+ */
+ public ContainerOrderFocusTraversalPolicy ()
+ {
+ // Nothing to do here
+ }
+
+ /**
+ * Returns the Component that should receive the focus after current.
+ * root must be a focus cycle root of current.
+ *
+ * @param root a focus cycle root of current
+ * @param current a (possibly indirect) child of root, or root itself
+ *
+ * @return the next Component in the focus traversal order for root,
+ * or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is not a focus cycle
+ * root of current, or if either root or current is null.
+ */
+ public Component getComponentAfter (Container root, Component current)
+ {
+ if (root == null)
+ throw new IllegalArgumentException ("focus cycle root is null");
+ if (current == null)
+ throw new IllegalArgumentException ("current component is null");
+
+ if (!root.isFocusCycleRoot ())
+ throw new IllegalArgumentException ("root is not a focus cycle root");
+
+ Container ancestor = current.getFocusCycleRootAncestor ();
+ Container prevAncestor = ancestor;
+ while (ancestor != root)
+ {
+ ancestor = current.getFocusCycleRootAncestor ();
+ if (ancestor == prevAncestor)
+ {
+ // We've reached the top focus cycle root ancestor. Check
+ // if it is root.
+ if (ancestor != root)
+ throw new IllegalArgumentException ("the given container is not"
+ + " a focus cycle root of the"
+ + " current component");
+ else
+ break;
+ }
+ prevAncestor = ancestor;
+ }
+
+ // FIXME: is this the right thing to do here? It moves the context
+ // for traversal up one focus traversal cycle. We'll need a test
+ // for this.
+ if ((Component) root == current)
+ root = current.getFocusCycleRootAncestor ();
+
+ // Check if we've reached the top of the component hierarchy. If
+ // so then we want to loop around to the first component in the
+ // focus traversal cycle.
+ if (current instanceof Window)
+ return getFirstComponent ((Container) current);
+
+ Container parent = current.getParent ();
+
+ synchronized (parent.getTreeLock ())
+ {
+ Component[] components = parent.getComponents ();
+ int componentIndex = 0;
+ int numComponents = parent.getComponentCount ();
+
+ // Find component's index.
+ for (int i = 0; i < numComponents; i++)
+ {
+ if (components[i] == current)
+ componentIndex = i;
+ }
+
+ // Search forward for the next acceptable component.
+ for (int i = componentIndex + 1; i < numComponents; i++)
+ {
+ if (accept (components[i]))
+ return components[i];
+
+ if (components[i] instanceof Container)
+ {
+ Component result = getFirstComponent ((Container) components[i]);
+
+ if (result != null
+ && implicitDownCycleTraversal)
+ return result;
+ }
+ }
+
+ // No focusable components after current in its Container. So go
+ // to the next Component after current's Container (parent).
+ Component result = getComponentAfter (root, parent);
+
+ return result;
+ }
+ }
+
+ /**
+ * Returns the Component that should receive the focus before
+ * <code>current</code>. <code>root</code> must be a focus cycle
+ * root of current.
+ *
+ * @param root a focus cycle root of current
+ * @param current a (possibly indirect) child of root, or root itself
+ *
+ * @return the previous Component in the focus traversal order for
+ * root, or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is not a focus cycle
+ * root of current, or if either root or current is null.
+ */
+ public Component getComponentBefore (Container root, Component current)
+ {
+ if (root == null)
+ throw new IllegalArgumentException ("focus cycle root is null");
+ if (current == null)
+ throw new IllegalArgumentException ("current component is null");
+
+ if (!root.isFocusCycleRoot ())
+ throw new IllegalArgumentException ("root is not a focus cycle root");
+
+ Container ancestor = current.getFocusCycleRootAncestor ();
+ Container prevAncestor = ancestor;
+ while (ancestor != root)
+ {
+ ancestor = current.getFocusCycleRootAncestor ();
+ if (ancestor == prevAncestor)
+ {
+ // We've reached the top focus cycle root ancestor. Check
+ // if it is root.
+ if (ancestor != root)
+ throw new IllegalArgumentException ("the given container is not"
+ + " a focus cycle root of the"
+ + " current component");
+ else
+ break;
+ }
+ prevAncestor = ancestor;
+ }
+
+ // FIXME: is this the right thing to do here? It moves the context
+ // for traversal up one focus traversal cycle. We'll need a test
+ // for this.
+ if ((Component) root == current)
+ root = current.getFocusCycleRootAncestor ();
+
+ // Check if we've reached the top of the component hierarchy. If
+ // so then we want to loop around to the last component in the
+ // focus traversal cycle.
+ if (current instanceof Window)
+ return getLastComponent ((Container) current);
+
+ Container parent = current.getParent ();
+
+ synchronized (parent.getTreeLock ())
+ {
+ Component[] components = parent.getComponents ();
+ int componentIndex = 0;
+ int numComponents = parent.getComponentCount ();
+
+ // Find component's index.
+ for (int i = 0; i < numComponents; i++)
+ {
+ if (components[i] == current)
+ componentIndex = i;
+ }
+
+ // Search backward for the next acceptable component.
+ for (int i = componentIndex - 1; i >= 0; i--)
+ {
+ if (accept (components[i]))
+ return components[i];
+
+ if (components[i] instanceof Container)
+ {
+ Component result = getLastComponent ((Container) components[i]);
+
+ if (result != null)
+ return result;
+ }
+ }
+
+ // No focusable components before current in its Container. So go
+ // to the previous Component before current's Container (parent).
+ Component result = getComponentBefore (root, parent);
+
+ return result;
+ }
+ }
+
+ /**
+ * Returns the first Component of root that should receive the focus.
+ *
+ * @param root a focus cycle root
+ *
+ * @return the first Component in the focus traversal order for
+ * root, or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public Component getFirstComponent(Container root)
+ {
+ if (root == null)
+ throw new IllegalArgumentException ();
+
+ if (!root.isVisible ()
+ || !root.isDisplayable ())
+ return null;
+
+ if (accept (root))
+ return root;
+
+ Component[] componentArray = root.getComponents ();
+
+ for (int i = 0; i < componentArray.length; i++)
+ {
+ Component component = componentArray [i];
+
+ if (accept (component))
+ return component;
+
+ if (component instanceof Container)
+ {
+ Component result = getFirstComponent ((Container) component);
+
+ if (result != null)
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the last Component of root that should receive the focus.
+ *
+ * @param root a focus cycle root
+ *
+ * @return the last Component in the focus traversal order for
+ * root, or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public Component getLastComponent (Container root)
+ {
+ if (root == null)
+ throw new IllegalArgumentException ();
+
+ if (!root.isVisible ()
+ || !root.isDisplayable ())
+ return null;
+
+ if (accept (root))
+ return root;
+
+ Component[] componentArray = root.getComponents ();
+
+ for (int i = componentArray.length - 1; i >= 0; i--)
+ {
+ Component component = componentArray [i];
+
+ if (accept (component))
+ return component;
+
+ if (component instanceof Container)
+ {
+ Component result = getLastComponent ((Container) component);
+
+ if (result != null)
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the default Component of root that should receive the focus.
+ *
+ * @param root a focus cycle root
+ *
+ * @return the default Component in the focus traversal order for
+ * root, or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public Component getDefaultComponent (Container root)
+ {
+ return getFirstComponent (root);
+ }
+
+ /**
+ * Set whether or not implicit down cycling is enabled. If it is,
+ * then initiating a forward focus traversal operation onto a focus
+ * cycle root, the focus will be implicitly transferred into the
+ * root container's focus cycle.
+ *
+ * @param value the setting for implicit down cycling
+ */
+ public void setImplicitDownCycleTraversal (boolean value)
+ {
+ implicitDownCycleTraversal = value;
+ }
+
+ /**
+ * Check whether or not implicit down cycling is enabled. If it is,
+ * then initiating a forward focus traversal operation onto a focus
+ * cycle root, the focus will be implicitly transferred into the
+ * root container's focus cycle.
+ *
+ * @return true if the focus will be transferred down-cycle
+ * implicitly
+ */
+ public boolean getImplicitDownCycleTraversal ()
+ {
+ return implicitDownCycleTraversal;
+ }
+
+ /**
+ * Check whether the given Component is an acceptable target for the
+ * keyboard input focus.
+ *
+ * @param current the Component to check
+ *
+ * @return true if current is acceptable, false otherwise
+ */
+ protected boolean accept (Component current)
+ {
+ return (current.visible
+ && current.isDisplayable ()
+ && current.enabled
+ && current.focusable);
+ }
+}
diff --git a/libjava/classpath/java/awt/Cursor.java b/libjava/classpath/java/awt/Cursor.java
new file mode 100644
index 00000000000..48a63f06f4f
--- /dev/null
+++ b/libjava/classpath/java/awt/Cursor.java
@@ -0,0 +1,224 @@
+/* Copyright (C) 1999, 2000, 2002 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;
+
+/**
+ * This class represents various predefined cursor types.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Cursor implements java.io.Serializable
+{
+ static final long serialVersionUID = 8028237497568985504L;
+
+ /**
+ * Constant for the system default cursor type
+ */
+ public static final int DEFAULT_CURSOR = 0;
+
+ /**
+ * Constant for a cross-hair cursor.
+ */
+ public static final int CROSSHAIR_CURSOR = 1;
+
+ /**
+ * Constant for a cursor over a text field.
+ */
+ public static final int TEXT_CURSOR = 2;
+
+ /**
+ * Constant for a cursor to display while waiting for an action to complete.
+ */
+ public static final int WAIT_CURSOR = 3;
+
+ /**
+ * Cursor used over SW corner of window decorations.
+ */
+ public static final int SW_RESIZE_CURSOR = 4;
+
+ /**
+ * Cursor used over SE corner of window decorations.
+ */
+ public static final int SE_RESIZE_CURSOR = 5;
+
+ /**
+ * Cursor used over NW corner of window decorations.
+ */
+ public static final int NW_RESIZE_CURSOR = 6;
+
+ /**
+ * Cursor used over NE corner of window decorations.
+ */
+ public static final int NE_RESIZE_CURSOR = 7;
+
+ /**
+ * Cursor used over N edge of window decorations.
+ */
+ public static final int N_RESIZE_CURSOR = 8;
+
+ /**
+ * Cursor used over S edge of window decorations.
+ */
+ public static final int S_RESIZE_CURSOR = 9;
+
+ /**
+ * Cursor used over W edge of window decorations.
+ */
+ public static final int W_RESIZE_CURSOR = 10;
+
+ /**
+ * Cursor used over E edge of window decorations.
+ */
+ public static final int E_RESIZE_CURSOR = 11;
+
+ /**
+ * Constant for a hand cursor.
+ */
+ public static final int HAND_CURSOR = 12;
+
+ /**
+ * Constant for a cursor used during window move operations.
+ */
+ public static final int MOVE_CURSOR = 13;
+
+ public static final int CUSTOM_CURSOR = 0xFFFFFFFF;
+
+ private static final int PREDEFINED_COUNT = 14;
+
+ protected static Cursor[] predefined = new Cursor[PREDEFINED_COUNT];
+ protected String name;
+
+ /**
+ * @serial The numeric id of this cursor.
+ */
+ int type;
+
+ /**
+ * Initializes a new instance of <code>Cursor</code> with the specified
+ * type.
+ *
+ * @param type The cursor type.
+ *
+ * @exception IllegalArgumentException If the specified cursor type is invalid
+ */
+ public Cursor(int type)
+ {
+ if (type < 0 || type >= PREDEFINED_COUNT)
+ throw new IllegalArgumentException ("invalid cursor " + type);
+
+ this.type = type;
+ // FIXME: lookup and set name?
+ }
+
+ /** This constructor is used internally only.
+ * Application code should call Toolkit.createCustomCursor().
+ */
+ protected Cursor(String name)
+ {
+ this.name = name;
+ this.type = CUSTOM_CURSOR;
+ }
+
+ /**
+ * Returns an instance of <code>Cursor</code> for one of the specified
+ * predetermined types.
+ *
+ * @param type The type contant from this class.
+ *
+ * @return The requested predefined cursor.
+ *
+ * @exception IllegalArgumentException If the constant is not one of the
+ * predefined cursor type constants from this class.
+ */
+ public static Cursor getPredefinedCursor(int type)
+ {
+ if (type < 0 || type >= PREDEFINED_COUNT)
+ throw new IllegalArgumentException ("invalid cursor " + type);
+ if (predefined[type] == null)
+ predefined[type] = new Cursor(type);
+ return predefined[type];
+ }
+
+ /**
+ * Retrieves the system specific custom Cursor named Cursor names are,
+ * for example: "Invalid.16x16".
+ *
+ * @exception AWTException
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public static Cursor getSystemCustomCursor(String name)
+ throws AWTException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+
+ // FIXME
+ return null;
+ }
+
+ /**
+ * Returns an instance of the system default cursor type.
+ *
+ * @return The system default cursor.
+ */
+ public static Cursor getDefaultCursor()
+ {
+ return getPredefinedCursor(DEFAULT_CURSOR);
+ }
+
+ /**
+ * Returns the numeric type identifier for this cursor.
+ *
+ * @return The cursor id.
+ */
+ public int getType()
+ {
+ return type;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String toString()
+ {
+ return (this.getClass() + "[" + getName() + "]");
+ }
+}
diff --git a/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java b/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java
new file mode 100644
index 00000000000..46b56d3fc29
--- /dev/null
+++ b/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java
@@ -0,0 +1,109 @@
+/* DefaultFocusTraversalPolicy.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * DefaultFocusTraversalPolicy is the default focus traversal policy
+ * used by Containers.
+ *
+ * This policy sharpens ContainerOrderFocusTraversalPolicy's
+ * acceptance criteria, to reject those Components that have
+ * unfocusable peers. Despite this extra strictness, this policy will
+ * always accept a Component that has explicitly been set focusable by
+ * any means.
+ *
+ * This AWT implementation assumes that the peers of the following
+ * Components are not focusable: Canvas, Panel, Label, ScrollPane,
+ * Scrollbar, Window, and any lightweight Component.
+ *
+ * A Component's focusability is independent of the focusability of
+ * its peer.
+ *
+ * @author Thomas Fitzsimmons (fitzsim@redhat.com)
+ * @since 1.4
+ */
+public class DefaultFocusTraversalPolicy
+ extends ContainerOrderFocusTraversalPolicy
+{
+ /**
+ * Construct a default focus traversal policy.
+ */
+ public DefaultFocusTraversalPolicy ()
+ {
+ }
+
+ /**
+ * Check whether a given Component would be acceptable as a focus
+ * owner. The Component must be displayable, visible and enabled to
+ * be acceptable. If the Component's focus traversability has been
+ * overridden, by overriding Component.isFocusTraversable or
+ * Component.isFocusable, or by calling Component.setFocusable, then
+ * the Component will be accepted if it is focusable. If the
+ * Component uses the default focus traversable behaviour, then
+ * <code>comp</code> will always be rejected if it is a Canvas,
+ * Panel, Label, ScrollPane, Scrollbar, Window or lightweight
+ * Component.
+ *
+ * @param comp the Component to check
+ *
+ * @return true if the Component is an acceptable target for
+ * keyboard input focus, false otherwise
+ */
+ protected boolean accept (Component comp)
+ {
+ if (comp.visible
+ && comp.isDisplayable ()
+ && comp.enabled)
+ {
+ if (comp.isFocusTraversableOverridden != 0
+ && (comp.isFocusTraversable () || comp.isFocusable()))
+ return true;
+
+ if (!(comp instanceof Canvas
+ || comp instanceof Panel
+ || comp instanceof Label
+ || comp instanceof ScrollPane
+ || comp instanceof Scrollbar
+ || comp instanceof Window
+ || comp.isLightweight ()))
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java b/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java
new file mode 100644
index 00000000000..f53cc5ef04d
--- /dev/null
+++ b/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java
@@ -0,0 +1,536 @@
+/* DefaultKeyboardFocusManager.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+// FIXME: finish documentation
+public class DefaultKeyboardFocusManager extends KeyboardFocusManager
+{
+ /**
+ * This class models a request to delay the dispatch of events that
+ * arrive after a certain time, until a certain component becomes
+ * the focus owner.
+ */
+ private class EventDelayRequest implements Comparable
+ {
+ /** A {@link java.util.List} of {@link java.awt.event.KeyEvent}s
+ that are being delayed, pending this request's {@link
+ Component} receiving the keyboard focus. */
+ private LinkedList enqueuedKeyEvents = new LinkedList ();
+
+ /** An event timestamp. All events that arrive after this time
+ should be queued in the {@link #enqueuedKeyEvents} {@link
+ java.util.List}. */
+ public long timestamp;
+ /** When this {@link Component} becomes focused, all events
+ between this EventDelayRequest and the next one in will be
+ dispatched from {@link #enqueuedKeyEvents}. */
+ public Component focusedComp;
+
+ /**
+ * Construct a new EventDelayRequest.
+ *
+ * @param timestamp events that arrive after this time will be
+ * delayed
+ * @param focusedComp the Component that needs to receive focus
+ * before events are dispatched
+ */
+ public EventDelayRequest (long timestamp, Component focusedComp)
+ {
+ this.timestamp = timestamp;
+ this.focusedComp = focusedComp;
+ }
+
+ public int compareTo (Object o)
+ {
+ if (!(o instanceof EventDelayRequest))
+ throw new ClassCastException ();
+
+ EventDelayRequest request = (EventDelayRequest) o;
+
+ if (request.timestamp < timestamp)
+ return -1;
+ else if (request.timestamp == timestamp)
+ return 0;
+ else
+ return 1;
+ }
+
+ public boolean equals (Object o)
+ {
+ if (!(o instanceof EventDelayRequest) || o == null)
+ return false;
+
+ EventDelayRequest request = (EventDelayRequest) o;
+
+ return (request.timestamp == timestamp
+ && request.focusedComp == focusedComp);
+ }
+
+ public void enqueueEvent (KeyEvent e)
+ {
+ KeyEvent last = (KeyEvent) enqueuedKeyEvents.getLast ();
+ if (last != null && e.getWhen () < last.getWhen ())
+ throw new RuntimeException ("KeyEvents enqueued out-of-order");
+
+ if (e.getWhen () <= timestamp)
+ throw new RuntimeException ("KeyEvents enqueued before starting timestamp");
+
+ enqueuedKeyEvents.add (e);
+ }
+
+ public void dispatchEvents ()
+ {
+ int size = enqueuedKeyEvents.size ();
+ for (int i = 0; i < size; i++)
+ {
+ KeyEvent e = (KeyEvent) enqueuedKeyEvents.remove (0);
+ dispatchKeyEvent (e);
+ }
+ }
+
+ public void discardEvents ()
+ {
+ enqueuedKeyEvents.clear ();
+ }
+ }
+
+ /**
+ * This flag indicates for which focus traversal key release event we
+ * possibly wait, before letting any more KEY_TYPED events through.
+ */
+ private AWTKeyStroke waitForKeyStroke = null;
+
+ /** The {@link java.util.SortedSet} of current {@link
+ #EventDelayRequest}s. */
+ private SortedSet delayRequests = new TreeSet ();
+
+ public DefaultKeyboardFocusManager ()
+ {
+ }
+
+ public boolean dispatchEvent (AWTEvent e)
+ {
+ if (e instanceof WindowEvent)
+ {
+ Window target = (Window) e.getSource ();
+
+ if (e.id == WindowEvent.WINDOW_ACTIVATED)
+ setGlobalActiveWindow (target);
+ else if (e.id == WindowEvent.WINDOW_GAINED_FOCUS)
+ setGlobalFocusedWindow (target);
+ else if (e.id != WindowEvent.WINDOW_LOST_FOCUS
+ && e.id != WindowEvent.WINDOW_DEACTIVATED)
+ return false;
+
+ redispatchEvent(target, e);
+ return true;
+ }
+ else if (e instanceof FocusEvent)
+ {
+ Component target = (Component) e.getSource ();
+
+ 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);
+ }
+ }
+ else if (e.id == FocusEvent.FOCUS_LOST)
+ {
+ if (((FocusEvent) e).isTemporary ())
+ setGlobalFocusOwner (null);
+ else
+ setGlobalPermanentFocusOwner (null);
+ }
+
+ redispatchEvent(target, e);
+
+ return true;
+ }
+ else if (e instanceof KeyEvent)
+ {
+ // Loop through all registered KeyEventDispatchers, giving
+ // each a chance to handle this event.
+ Iterator i = getKeyEventDispatchers().iterator();
+
+ while (i.hasNext ())
+ {
+ KeyEventDispatcher dispatcher = (KeyEventDispatcher) i.next ();
+ if (dispatcher.dispatchKeyEvent ((KeyEvent) e))
+ return true;
+ }
+
+ // processKeyEvent checks if this event represents a focus
+ // traversal key stroke.
+ Component focusOwner = getGlobalPermanentFocusOwner ();
+
+ if (focusOwner != null)
+ processKeyEvent (focusOwner, (KeyEvent) e);
+
+ if (e.isConsumed ())
+ return true;
+
+ if (enqueueKeyEvent ((KeyEvent) e))
+ // This event was enqueued for dispatch at a later time.
+ return true;
+ else
+ // This event wasn't handled by any of the registered
+ // KeyEventDispatchers, and wasn't enqueued for dispatch
+ // later, so send it to the default dispatcher.
+ return dispatchKeyEvent ((KeyEvent) e);
+ }
+
+ return false;
+ }
+
+ private boolean enqueueKeyEvent (KeyEvent e)
+ {
+ Iterator i = delayRequests.iterator ();
+ boolean oneEnqueued = false;
+ while (i.hasNext ())
+ {
+ EventDelayRequest request = (EventDelayRequest) i.next ();
+ if (e.getWhen () > request.timestamp)
+ {
+ request.enqueueEvent (e);
+ oneEnqueued = true;
+ }
+ }
+ return oneEnqueued;
+ }
+
+ public boolean dispatchKeyEvent (KeyEvent e)
+ {
+ Component focusOwner = getGlobalPermanentFocusOwner ();
+
+ if (focusOwner != null)
+ redispatchEvent(focusOwner, e);
+
+ // Loop through all registered KeyEventPostProcessors, giving
+ // each a chance to process this event.
+ Iterator i = getKeyEventPostProcessors().iterator();
+
+ while (i.hasNext ())
+ {
+ KeyEventPostProcessor processor = (KeyEventPostProcessor) i.next ();
+ if (processor.postProcessKeyEvent ((KeyEvent) e))
+ return true;
+ }
+
+ // The event hasn't been consumed yet. Check if it is an
+ // MenuShortcut.
+ if (postProcessKeyEvent (e))
+ return true;
+
+ // Always return true.
+ return true;
+ }
+
+ public boolean postProcessKeyEvent (KeyEvent e)
+ {
+ // Check if this event represents a menu shortcut.
+
+ // MenuShortcuts are activated by Ctrl- KeyEvents, only on KEY_PRESSED.
+ int modifiers = e.getModifiersEx ();
+ if (e.getID() == KeyEvent.KEY_PRESSED
+ && (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0)
+ {
+ Window focusedWindow = getGlobalFocusedWindow ();
+ if (focusedWindow instanceof Frame)
+ {
+ MenuBar menubar = ((Frame) focusedWindow).getMenuBar ();
+
+ if (menubar != null)
+ {
+ // If there's a menubar, loop through all menu items,
+ // checking whether each one has a shortcut, and if
+ // so, whether this key event should activate it.
+ int numMenus = menubar.getMenuCount ();
+
+ for (int i = 0; i < numMenus; i++)
+ {
+ Menu menu = menubar.getMenu (i);
+ int numItems = menu.getItemCount ();
+
+ for (int j = 0; j < numItems; j++)
+ {
+ MenuItem item = menu.getItem (j);
+ MenuShortcut shortcut = item.getShortcut ();
+
+ if (item.isEnabled() && shortcut != null)
+ {
+ // Dispatch a new ActionEvent if:
+ //
+ // a) this is a Shift- KeyEvent, and the
+ // shortcut requires the Shift modifier
+ //
+ // or, b) this is not a Shift- KeyEvent, and the
+ // shortcut does not require the Shift
+ // modifier.
+ if (shortcut.getKey () == e.getKeyCode ()
+ && ((shortcut.usesShiftModifier ()
+ && (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0)
+ || (! shortcut.usesShiftModifier ()
+ && (modifiers & KeyEvent.SHIFT_DOWN_MASK) == 0)))
+ {
+ item.dispatchEvent (new ActionEvent (item,
+ ActionEvent.ACTION_PERFORMED,
+ item.getActionCommand (),
+ modifiers));
+ // The event was dispatched.
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public void processKeyEvent (Component comp, KeyEvent e)
+ {
+ AWTKeyStroke eventKeystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e);
+ // For every focus traversal keystroke, we need to also consume
+ // the other two key event types for the same key (e.g. if
+ // KEY_PRESSED TAB is a focus traversal keystroke, we also need to
+ // consume KEY_RELEASED and KEY_TYPED TAB key events).
+ // consuming KEY_RELEASED is easy, because their keyCodes matches
+ // the KEY_PRESSED event. Consuming the intermediate KEY_TYPED is
+ // very difficult because their is no clean way that we can know
+ // which KEY_TYPED belongs to a focusTraversalKey and which not.
+ // To address this problem we swallow every KEY_TYPE between the
+ // KEY_PRESSED event that matches a focusTraversalKey and the
+ // corresponding KEY_RELEASED.
+ AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
+ e.getModifiersEx (),
+ !(e.id == KeyEvent.KEY_RELEASED));
+
+ // Here we check if we are currently waiting for a KEY_RELEASED and
+ // swallow all KeyEvents that are to be delivered in between. This
+ // should only be the KEY_TYPED events that correspond to the
+ // focusTraversalKey's KEY_PRESSED event
+ if (waitForKeyStroke != null)
+ {
+ if (eventKeystroke.equals(waitForKeyStroke))
+ // release this lock
+ waitForKeyStroke = null;
+
+ // as long as we are waiting for the KEY_RELEASED, we swallow every
+ // KeyEvent, including the KEY_RELEASED
+ e.consume();
+ return;
+ }
+
+ Set forwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ Set backwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ Set upKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ Set downKeystrokes = null;
+ if (comp instanceof Container)
+ downKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
+
+ if (forwardKeystrokes.contains (eventKeystroke))
+ {
+ waitForKeyStroke = oppositeKeystroke;
+ focusNextComponent (comp);
+ e.consume ();
+ }
+ else if (backwardKeystrokes.contains (eventKeystroke))
+ {
+ waitForKeyStroke = oppositeKeystroke;
+ focusPreviousComponent (comp);
+ e.consume ();
+ }
+ else if (upKeystrokes.contains (eventKeystroke))
+ {
+ waitForKeyStroke = oppositeKeystroke;
+ upFocusCycle (comp);
+ e.consume ();
+ }
+ else if (comp instanceof Container
+ && downKeystrokes.contains (eventKeystroke))
+ {
+ waitForKeyStroke = oppositeKeystroke;
+ downFocusCycle ((Container) comp);
+ e.consume ();
+ }
+ }
+
+ protected void enqueueKeyEvents (long after, Component untilFocused)
+ {
+ delayRequests.add (new EventDelayRequest (after, untilFocused));
+ }
+
+ protected void dequeueKeyEvents (long after, Component untilFocused)
+ {
+ // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
+
+ // Remove the KeyEvent with the oldest timestamp, which should be
+ // the first element in the SortedSet.
+ if (after < 0)
+ {
+ int size = delayRequests.size ();
+ if (size > 0)
+ delayRequests.remove (delayRequests.first ());
+ }
+ else
+ {
+ EventDelayRequest template = new EventDelayRequest (after, untilFocused);
+ if (delayRequests.contains (template))
+ {
+ EventDelayRequest actual = (EventDelayRequest) delayRequests.tailSet (template).first ();
+ delayRequests.remove (actual);
+ actual.dispatchEvents ();
+ }
+ }
+ }
+
+ protected void discardKeyEvents (Component comp)
+ {
+ // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
+
+ Iterator i = delayRequests.iterator ();
+
+ while (i.hasNext ())
+ {
+ EventDelayRequest request = (EventDelayRequest) i.next ();
+
+ if (request.focusedComp == comp
+ || (comp instanceof Container
+ && ((Container) comp).isAncestorOf (request.focusedComp)))
+ request.discardEvents ();
+ }
+ }
+
+ public void focusPreviousComponent (Component comp)
+ {
+ Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
+ Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
+ FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
+
+ Component previous = policy.getComponentBefore (focusCycleRoot, focusComp);
+ if (previous != null)
+ previous.requestFocusInWindow ();
+ }
+
+ public void focusNextComponent (Component comp)
+ {
+ Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
+ Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
+ FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
+
+ Component next = policy.getComponentAfter (focusCycleRoot, focusComp);
+ if (next != null)
+ next.requestFocusInWindow ();
+ }
+
+ public void upFocusCycle (Component comp)
+ {
+ Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
+ Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
+
+ if (focusCycleRoot instanceof Window)
+ {
+ FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
+ Component defaultComponent = policy.getDefaultComponent (focusCycleRoot);
+ if (defaultComponent != null)
+ defaultComponent.requestFocusInWindow ();
+ }
+ else
+ {
+ Container parentFocusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor ();
+
+ focusCycleRoot.requestFocusInWindow ();
+ setGlobalCurrentFocusCycleRoot (parentFocusCycleRoot);
+ }
+ }
+
+ public void downFocusCycle (Container cont)
+ {
+ if (cont == null)
+ return;
+
+ if (cont.isFocusCycleRoot (cont))
+ {
+ FocusTraversalPolicy policy = cont.getFocusTraversalPolicy ();
+ Component defaultComponent = policy.getDefaultComponent (cont);
+ if (defaultComponent != null)
+ defaultComponent.requestFocusInWindow ();
+ setGlobalCurrentFocusCycleRoot (cont);
+ }
+ }
+} // class DefaultKeyboardFocusManager
diff --git a/libjava/classpath/java/awt/Dialog.java b/libjava/classpath/java/awt/Dialog.java
new file mode 100644
index 00000000000..d3eb975a86d
--- /dev/null
+++ b/libjava/classpath/java/awt/Dialog.java
@@ -0,0 +1,553 @@
+/* Dialog.java -- An AWT dialog box
+ Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.DialogPeer;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * A dialog box widget class.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class Dialog extends Window
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization constant
+private static final long serialVersionUID = 5920926903803293709L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial Indicates whether or not this dialog box is modal.
+ */
+private boolean modal;
+
+/**
+ * @serial Indicates whether or not this dialog box is resizable.
+ */
+private boolean resizable = true;
+
+/**
+ * @serial The title string for this dialog box, which can be
+ * <code>null</code>.
+ */
+private String title;
+
+/**
+ * This field indicates whether the dialog is undecorated or not.
+ */
+private boolean undecorated = false;
+
+/**
+ * Indicates that we are blocked for modality in show
+ */
+private boolean blocked = false;
+
+/**
+ * Secondary EventQueue to handle AWT events while
+ * we are blocked for modality in show
+ */
+private EventQueue eq2 = null;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified
+ * parent, that is resizable and not modal, and which has no title.
+ *
+ * @param parent The parent frame of this dialog box.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null. This exception is always
+ * thrown when GraphicsEnvironment.isHeadless() returns true.
+ */
+public
+Dialog(Frame parent)
+{
+ this(parent, "", false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified
+ * parent and modality, that is resizable and which has no title.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param modal <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null. This exception is always
+ * thrown when GraphicsEnvironment.isHeadless() returns true.
+ */
+public
+Dialog(Frame parent, boolean modal)
+{
+ this(parent, "", modal);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified
+ * parent, that is resizable and not modal, and which has the specified
+ * title.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null. This exception is always
+ * thrown when GraphicsEnvironment.isHeadless() returns true.
+ */
+public
+Dialog(Frame parent, String title)
+{
+ this(parent, title, false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, title, and modality, that is resizable.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ * @param modal <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException If owner is null or
+ * GraphicsEnvironment.isHeadless() returns true.
+ */
+public
+Dialog(Frame parent, String title, boolean modal)
+{
+ this (parent, title, modal, parent.getGraphicsConfiguration ());
+}
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, title, modality and <code>GraphicsConfiguration</code>,
+ * that is resizable.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ * @param modal <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ * @param gc The <code>GraphicsConfiguration</code> object to use.
+ *
+ * @exception IllegalArgumentException If owner is null, the
+ * GraphicsConfiguration is not a screen device or
+ * GraphicsEnvironment.isHeadless() returns true.
+ *
+ * @since 1.4
+ */
+public
+Dialog (Frame parent, String title, boolean modal, GraphicsConfiguration gc)
+{
+ super (parent, gc);
+
+ // A null title is equivalent to an empty title
+ this.title = (title != null) ? title : "";
+ this.modal = modal;
+ visible = false;
+
+ setLayout(new BorderLayout());
+}
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, that is resizable.
+ *
+ * @exception IllegalArgumentException If parent is null. This exception is
+ * always thrown when GraphicsEnvironment.isHeadless() returns true.
+ *
+ * @since 1.2
+ */
+public
+Dialog (Dialog owner)
+{
+ this (owner, "", false, owner.getGraphicsConfiguration ());
+}
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent and title, that is resizable.
+ *
+ * @exception IllegalArgumentException If parent is null. This exception is
+ * always thrown when GraphicsEnvironment.isHeadless() returns true.
+ *
+ * @since 1.2
+ */
+public
+Dialog (Dialog owner, String title)
+{
+ this (owner, title, false, owner.getGraphicsConfiguration ());
+}
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, title and modality, that is resizable.
+ *
+ * @exception IllegalArgumentException If parent is null. This exception is
+ * always thrown when GraphicsEnvironment.isHeadless() returns true.
+ *
+ * @since 1.2
+ */
+public
+Dialog (Dialog owner, String title, boolean modal)
+{
+ this (owner, title, modal, owner.getGraphicsConfiguration ());
+}
+
+/**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, title, modality and <code>GraphicsConfiguration</code>,
+ * that is resizable.
+ *
+ * @exception IllegalArgumentException If parent is null, the
+ * GraphicsConfiguration is not a screen device or
+ * GraphicsEnvironment.isHeadless() returns true.
+ *
+ * @since 1.4
+ */
+public
+Dialog (Dialog parent, String title, boolean modal, GraphicsConfiguration gc)
+{
+ super (parent, parent.getGraphicsConfiguration ());
+
+ // A null title is equivalent to an empty title
+ this.title = (title != null) ? title : "";
+ this.modal = modal;
+ visible = false;
+
+ setLayout (new BorderLayout ());
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the title of this dialog box.
+ *
+ * @return The title of this dialog box.
+ */
+public String
+getTitle()
+{
+ return(title);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the title of this dialog box to the specified string.
+ *
+ * @param title The new title.
+ */
+public synchronized void
+setTitle(String title)
+{
+ // A null title is equivalent to an empty title
+ this.title = (title != null) ? title : "";
+
+ if (peer != null)
+ {
+ DialogPeer d = (DialogPeer) peer;
+ d.setTitle (title);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this dialog box is modal.
+ *
+ * @return <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ */
+public boolean
+isModal()
+{
+ return(modal);
+}
+
+/*************************************************************************/
+
+/**
+ * Changes the modality of this dialog box. This can only be done before
+ * the peer is created.
+ *
+ * @param modal <code>true</code> to make this dialog box modal,
+ * <code>false</code> to make it non-modal.
+ */
+public void
+setModal(boolean modal)
+{
+ this.modal = modal;
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this dialog box is resizable.
+ *
+ * @return <code>true</code> if this dialog is resizable, <code>false</code>,
+ * otherwise.
+ */
+public boolean
+isResizable()
+{
+ return(resizable);
+}
+
+/*************************************************************************/
+
+/**
+ * Changes the resizability of this dialog box.
+ *
+ * @param resizable <code>true</code> to make this dialog resizable,
+ * <code>false</code> to make it non-resizable.
+ */
+public synchronized void
+setResizable(boolean resizable)
+{
+ this.resizable = resizable;
+ if (peer != null)
+ {
+ DialogPeer d = (DialogPeer) peer;
+ d.setResizable (resizable);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Creates this object's native peer.
+ */
+public synchronized void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createDialog (this);
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Makes this dialog visible and brings it to the front.
+ * If the dialog is modal and is not already visible, this call will not
+ * return until the dialog is hidden by someone calling hide or dispose.
+ * If this is the event dispatching thread we must ensure that another event
+ * thread runs while the one which invoked this method is blocked.
+ */
+public synchronized void
+show()
+{
+ super.show();
+
+ if (isModal())
+ {
+ // If already shown (and blocked) just return
+ if (blocked)
+ return;
+
+ /* If show is called in the dispatch thread for a modal dialog it will
+ block so we must run another thread so the events keep being
+ dispatched.*/
+ if (EventQueue.isDispatchThread ())
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ eq2 = new EventQueue ();
+ eq.push (eq2);
+ }
+
+ try
+ {
+ blocked = true;
+ wait ();
+ blocked = false;
+ }
+ catch (InterruptedException e)
+ {
+ blocked = false;
+ }
+
+ if (eq2 != null)
+ {
+ eq2.pop ();
+ eq2 = null;
+ }
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Hides the Dialog and then
+ * causes show() to return if it is currently blocked.
+ */
+
+public synchronized void
+hide ()
+{
+ if (blocked)
+ {
+ notifyAll ();
+ }
+
+ super.hide();
+}
+
+/*************************************************************************/
+
+/**
+ * Disposes the Dialog and then causes show() to return
+ * if it is currently blocked.
+ */
+
+public synchronized void
+dispose ()
+{
+ if (blocked)
+ {
+ notifyAll ();
+ }
+
+ super.dispose();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this component.
+ *
+ * @return A debugging string for this component.
+ */
+protected String
+paramString()
+{
+ return ("title+" + title + ",modal=" + modal +
+ ",resizable=" + resizable + "," + super.paramString());
+}
+
+ /**
+ * Returns whether this frame is undecorated or not.
+ *
+ * @since 1.4
+ */
+ public boolean isUndecorated ()
+ {
+ return undecorated;
+ }
+
+ /**
+ * Disables or enables decorations for this frame. This method can only be
+ * called while the frame is not displayable.
+ *
+ * @exception IllegalComponentStateException If this frame is displayable.
+ *
+ * @since 1.4
+ */
+ public void setUndecorated (boolean undecorated)
+ {
+ if (isDisplayable ())
+ throw new IllegalComponentStateException ();
+
+ this.undecorated = undecorated;
+ }
+
+ protected class AccessibleAWTDialog extends AccessibleAWTWindow
+ {
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.DIALOG;
+ }
+
+ public AccessibleStateSet getAccessibleState()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (isResizable())
+ states.add(AccessibleState.RESIZABLE);
+ if (isModal())
+ states.add(AccessibleState.MODAL);
+ return states;
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Dialog</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTDialog();
+ return accessibleContext;
+ }
+
+} // class Dialog
+
diff --git a/libjava/classpath/java/awt/Dimension.java b/libjava/classpath/java/awt/Dimension.java
new file mode 100644
index 00000000000..4c1a07bf920
--- /dev/null
+++ b/libjava/classpath/java/awt/Dimension.java
@@ -0,0 +1,234 @@
+/* Dimension.java -- represents a 2-dimensional span
+ Copyright (C) 1999, 2000, 2002 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 java.awt.geom.Dimension2D;
+import java.io.Serializable;
+
+/**
+ * This class holds a width and height value pair. This is used in plenty
+ * of windowing classes, but also has geometric meaning.
+ *
+ * <p>It is valid for a dimension to have negative width or height; but it
+ * is considered to have no area. Therefore, the behavior in various methods
+ * is undefined in such a case.
+ *
+ * <p>There are some public fields; if you mess with them in an inconsistent
+ * manner, it is your own fault when you get invalid results. Also, this
+ * class is not threadsafe.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Component
+ * @see LayoutManager
+ * @since 1.0
+ * @status updated to 1.14
+ */
+public class Dimension extends Dimension2D implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 4723952579491349524L;
+
+ /**
+ * The width of this object.
+ *
+ * @see #getSize()
+ * @see #setSize(double, double)
+ * @serial the width
+ */
+ public int width;
+
+ /**
+ * The height of this object.
+ *
+ * @see #getSize()
+ * @see #setSize(double, double)
+ * @serial the height
+ */
+ public int height;
+
+ /**
+ * Create a new Dimension with a width and height of zero.
+ */
+ public Dimension()
+ {
+ }
+
+ /**
+ * Create a new Dimension with width and height identical to that of the
+ * specified dimension.
+ *
+ * @param d the Dimension to copy
+ * @throws NullPointerException if d is null
+ */
+ public Dimension(Dimension d)
+ {
+ width = d.width;
+ height = d.height;
+ }
+
+ /**
+ * Create a new Dimension with the specified width and height.
+ *
+ * @param w the width of this object
+ * @param h the height of this object
+ */
+ public Dimension(int w, int h)
+ {
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Gets the width of this dimension.
+ *
+ * @return the width, as a double
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Gets the height of this dimension.
+ *
+ * @return the height, as a double
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Sets the size of this dimension. The values are rounded to int.
+ *
+ * @param w the new width
+ * @param h the new height
+ * @since 1.2
+ */
+ public void setSize(double w, double h)
+ {
+ width = (int) w;
+ height = (int) h;
+ }
+
+ /**
+ * Returns the size of this dimension. A pretty useless method, as this is
+ * already a dimension.
+ *
+ * @return a copy of this dimension
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public Dimension getSize()
+ {
+ return new Dimension(width, height);
+ }
+
+ /**
+ * Sets the width and height of this object to match that of the
+ * specified object.
+ *
+ * @param d the Dimension to get the new width and height from
+ * @throws NullPointerException if d is null
+ * @see #getSize()
+ * @since 1.1
+ */
+ public void setSize(Dimension d)
+ {
+ width = d.width;
+ height = d.height;
+ }
+
+ /**
+ * Sets the width and height of this object to the specified values.
+ *
+ * @param w the new width value
+ * @param h the new height value
+ */
+ public void setSize(int w, int h)
+ {
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Tests this object for equality against the specified object. This will
+ * be true if and only if the specified object is an instance of
+ * Dimension2D, and has the same width and height.
+ *
+ * @param obj the object to test against
+ * @return true if the object is equal to this
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Dimension))
+ return false;
+ Dimension dim = (Dimension) obj;
+ return height == dim.height && width == dim.width;
+ }
+
+ /**
+ * Return the hashcode for this object. It is not documented, but appears
+ * to be <code>((width + height) * (width + height + 1) / 2) + width</code>.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // Reverse engineering this was fun!
+ return (width + height) * (width + height + 1) / 2 + width;
+ }
+
+ /**
+ * Returns a string representation of this object. The format is:
+ * <code>getClass().getName() + "[width=" + width + ",height=" + height
+ * + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return getClass().getName()
+ + "[width=" + width + ",height=" + height + ']';
+ }
+} // class Dimension
diff --git a/libjava/classpath/java/awt/DisplayMode.java b/libjava/classpath/java/awt/DisplayMode.java
new file mode 100644
index 00000000000..d41d4a87f57
--- /dev/null
+++ b/libjava/classpath/java/awt/DisplayMode.java
@@ -0,0 +1,164 @@
+/* DisplayMode.java -- a description of display mode configurations
+ Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This encapsulates information about the display mode for a graphics
+ * device configuration. They are device dependent, and may not always be
+ * available.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see GraphicsDevice
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public final class DisplayMode
+{
+ /**
+ * Value of the bit depth if multiple depths are supported.
+ *
+ * @see #getBitDepth()
+ */
+ public static final int BIT_DEPTH_MULTI = -1;
+
+ /**
+ * Value of an unknown refresh rate.
+ *
+ * @see #getRefreshRate()
+ */
+ public static final int REFRESH_RATE_UNKNOWN = 0;
+
+ /** The width. */
+ private final int width;
+
+ /** The height. */
+ private final int height;
+
+ /** The bit depth. */
+ private final int bitDepth;
+
+ /** The refresh rate. */
+ private final int refreshRate;
+
+ /**
+ * Create a mode with the given parameters.
+ *
+ * @param width the width
+ * @param height the height
+ * @param bitDepth the bitDepth
+ * @param refreshRate the refreshRate
+ * @see #BIT_DEPTH_MULTI
+ * @see #REFRESH_RATE_UNKNOWN
+ */
+ public DisplayMode(int width, int height, int bitDepth, int refreshRate)
+ {
+ this.width = width;
+ this.height = height;
+ this.bitDepth = bitDepth;
+ this.refreshRate = refreshRate;
+ }
+
+ /**
+ * Returns the height, in pixels.
+ *
+ * @return the height
+ */
+ public int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the width, in pixels.
+ *
+ * @return the width
+ */
+ public int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns the bit depth, in bits per pixel. This may be BIT_DEPTH_MULTI.
+ *
+ * @return the bit depth
+ * @see #BIT_DEPTH_MULTI
+ */
+ public int getBitDepth()
+ {
+ return bitDepth;
+ }
+
+ /**
+ * Returns the refresh rate, in hertz. This may be REFRESH_RATE_UNKNOWN.
+ *
+ * @return the refresh rate
+ * @see #REFRESH_RATE_UNKNOWN
+ */
+ public int getRefreshRate()
+ {
+ return refreshRate;
+ }
+
+ /**
+ * Test for equality. This returns true for two modes with identical
+ * parameters.
+ *
+ * @param dm The display mode to compare to
+ *
+ * @return true if it is equal
+ */
+ public boolean equals (DisplayMode dm)
+ {
+ return (width == dm.width
+ && height == dm.height
+ && bitDepth == dm.bitDepth
+ && refreshRate == dm.refreshRate);
+ }
+
+ /**
+ * Returns a hash code for the display mode.
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return width + height + bitDepth + refreshRate;
+ }
+} // class DisplayMode
diff --git a/libjava/classpath/java/awt/Event.java b/libjava/classpath/java/awt/Event.java
new file mode 100644
index 00000000000..648139cc850
--- /dev/null
+++ b/libjava/classpath/java/awt/Event.java
@@ -0,0 +1,185 @@
+/* Copyright (C) 1999, 2000, 2002 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;
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class Event implements java.io.Serializable
+{
+ static final long serialVersionUID = 5488922509400504703L;
+
+ public static final int SHIFT_MASK = 1;
+ public static final int CTRL_MASK = 2;
+ public static final int META_MASK = 4;
+ public static final int ALT_MASK = 8;
+
+ public static final int ACTION_EVENT = 1001;
+ public static final int BACK_SPACE = 8;
+ public static final int CAPS_LOCK = 1022;
+ public static final int DELETE = 127;
+ public static final int DOWN = 1005;
+ public static final int END = 1001;
+ public static final int ENTER = 10;
+ public static final int ESCAPE = 27;
+ public static final int F1 = 1008;
+ public static final int F10 = 1017;
+ public static final int F11 = 1018;
+ public static final int F12 = 1019;
+ public static final int F2 = 1009;
+ public static final int F3 = 1010;
+ public static final int F4 = 1011;
+ public static final int F5 = 1012;
+ public static final int F6 = 1013;
+ public static final int F7 = 1014;
+ public static final int F8 = 1015;
+ public static final int F9 = 1016;
+ public static final int GOT_FOCUS = 1004;
+ public static final int HOME = 1000;
+ public static final int INSERT = 1025;
+ public static final int KEY_ACTION = 403;
+ public static final int KEY_ACTION_RELEASE = 404;
+ public static final int KEY_PRESS = 401;
+ public static final int KEY_RELEASE = 402;
+ public static final int LEFT = 1006;
+ public static final int LIST_DESELECT = 702;
+ public static final int LIST_SELECT = 701;
+ public static final int LOAD_FILE = 1002;
+ public static final int LOST_FOCUS = 1005;
+ public static final int MOUSE_DOWN = 501;
+ public static final int MOUSE_DRAG = 506;
+ public static final int MOUSE_ENTER = 504;
+ public static final int MOUSE_EXIT = 505;
+ public static final int MOUSE_MOVE = 503;
+ public static final int MOUSE_UP = 502;
+ public static final int NUM_LOCK = 1023;
+ public static final int PAUSE = 1024;
+ public static final int PGDN = 1003;
+ public static final int PGUP = 1002;
+ public static final int PRINT_SCREEN = 1020;
+ public static final int RIGHT = 1007;
+ public static final int SAVE_FILE = 1003;
+ public static final int SCROLL_ABSOLUTE = 605;
+ public static final int SCROLL_BEGIN = 606;
+ public static final int SCROLL_END = 607;
+ public static final int SCROLL_LINE_DOWN = 602;
+ public static final int SCROLL_LINE_UP = 601;
+ public static final int SCROLL_LOCK = 1021;
+ public static final int SCROLL_PAGE_DOWN = 604;
+ public static final int SCROLL_PAGE_UP = 603;
+ public static final int TAB = 9;
+ public static final int UP = 1004;
+ public static final int WINDOW_DEICONIFY = 204;
+ public static final int WINDOW_DESTROY = 201;
+ public static final int WINDOW_EXPOSE = 202;
+ public static final int WINDOW_ICONIFY = 203;
+ public static final int WINDOW_MOVED = 205;
+
+ public Object arg;
+ public int clickCount;
+ boolean consumed; // Required by serialization spec.
+ public Event evt;
+ public int id;
+ public int key;
+ public int modifiers;
+ public Object target;
+ public long when;
+ public int x;
+ public int y;
+
+ public Event (Object target, int id, Object arg)
+ {
+ this.id = id;
+ this.target = target;
+ this.arg = arg;
+ }
+
+ public Event (Object target, long when, int id, int x, int y, int key,
+ int modifiers)
+ {
+ this.target = target;
+ this.when = when;
+ this.id = id;
+ this.x = x;
+ this.y = y;
+ this.key = key;
+ this.modifiers = modifiers;
+ }
+
+ public Event (Object target, long when, int id, int x, int y, int key,
+ int modifiers, Object arg)
+ {
+ this (target, when, id, x, y, key, modifiers);
+ this.arg = arg;
+ }
+
+ public boolean controlDown ()
+ {
+ return ((modifiers & CTRL_MASK) == 0 ? false : true);
+ }
+
+ public boolean metaDown ()
+ {
+ return ((modifiers & META_MASK) == 0 ? false : true);
+ }
+
+ protected String paramString ()
+ {
+ return "id=" + id + ",x=" + x + ",y=" + y
+ + ",target=" + target + ",arg=" + arg;
+ }
+
+ public boolean shiftDown()
+ {
+ return ((modifiers & SHIFT_MASK) == 0 ? false : true);
+ }
+
+ public String toString()
+ {
+ return getClass().getName() + "[" + paramString() + "]";
+ }
+
+ public void translate (int x, int y)
+ {
+ this.x += x;
+ this.y += y;
+ }
+}
diff --git a/libjava/classpath/java/awt/EventDispatchThread.java b/libjava/classpath/java/awt/EventDispatchThread.java
new file mode 100644
index 00000000000..a64cdae8567
--- /dev/null
+++ b/libjava/classpath/java/awt/EventDispatchThread.java
@@ -0,0 +1,94 @@
+/* EventDispatchThread.java -
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt;
+
+/**
+ * @author Bryce McKinlay
+ * @status believed complete, but untested.
+ */
+class EventDispatchThread extends Thread
+{
+ private static int dispatchThreadNum;
+
+ private EventQueue queue;
+
+ EventDispatchThread(EventQueue queue)
+ {
+ super();
+ setName("AWT-EventQueue-" + ++dispatchThreadNum);
+ this.queue = queue;
+ setPriority(NORM_PRIORITY + 1);
+ }
+
+ public void run()
+ {
+ while (true)
+ {
+ 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);
+ }
+ catch (ThreadDeath death)
+ {
+ // If someone wants to kill us, let them.
+ return;
+ }
+ catch (InterruptedException ie)
+ {
+ // We are interrupted when we should finish executing
+ return;
+ }
+ catch (Throwable x)
+ {
+ System.err.println("Exception during event dispatch:");
+ x.printStackTrace(System.err);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/EventQueue.java b/libjava/classpath/java/awt/EventQueue.java
new file mode 100644
index 00000000000..a8b00781321
--- /dev/null
+++ b/libjava/classpath/java/awt/EventQueue.java
@@ -0,0 +1,552 @@
+/* EventQueue.java --
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InvocationEvent;
+import java.awt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.util.EmptyStackException;
+
+/* Written using on-line Java 2 Platform Standard Edition v1.3 API
+ * Specification, as well as "The Java Class Libraries", 2nd edition
+ * (Addison-Wesley, 1998).
+ * Status: Believed complete, but untested.
+ */
+
+/**
+ * This class manages a queue of <code>AWTEvent</code> objects that
+ * are posted to it. The AWT system uses only one event queue for all
+ * events.
+ *
+ * @author Bryce McKinlay
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class EventQueue
+{
+ private static final int INITIAL_QUEUE_DEPTH = 8;
+ private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH];
+
+ private int next_in = 0; // Index where next event will be added to queue
+ private int next_out = 0; // Index of next event to be removed from queue
+
+ private EventQueue next;
+ private EventQueue prev;
+ private AWTEvent currentEvent;
+ private long lastWhen = System.currentTimeMillis();
+
+ private EventDispatchThread dispatchThread = new EventDispatchThread(this);
+ private boolean shutdown = false;
+
+ private long lastNativeQueueAccess = 0;
+ private long humanLatencyThreshold = 100;
+
+ synchronized void setShutdown (boolean b)
+ {
+ shutdown = b;
+ }
+
+ synchronized boolean isShutdown ()
+ {
+ if (shutdown)
+ return true;
+
+ // This is the exact self-shutdown condition specified in J2SE:
+ // http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html
+
+ if (peekEvent() == null
+ && ((ClasspathToolkit) Toolkit.getDefaultToolkit()).nativeQueueEmpty())
+ {
+ Frame[] frames = Frame.getFrames();
+ for (int i = 0; i < frames.length; ++i)
+ if (frames[i].isDisplayable())
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Initializes a new instance of <code>EventQueue</code>.
+ */
+ public EventQueue()
+ {
+ }
+
+ /**
+ * Returns the next event in the queue. This method will block until
+ * an event is available or until the thread is interrupted.
+ *
+ * @return The next event in the queue.
+ *
+ * @exception InterruptedException If this thread is interrupted while
+ * waiting for an event to be posted to the queue.
+ */
+ public synchronized AWTEvent getNextEvent()
+ throws InterruptedException
+ {
+ if (next != null)
+ return next.getNextEvent();
+
+ ClasspathToolkit tk = ((ClasspathToolkit) Toolkit.getDefaultToolkit());
+ long curr = System.currentTimeMillis();
+
+ if (! tk.nativeQueueEmpty() &&
+ (curr - lastNativeQueueAccess > humanLatencyThreshold))
+ {
+ tk.iterateNativeQueue(this, false);
+ lastNativeQueueAccess = curr;
+ }
+
+ while (next_in == next_out)
+ {
+ // Only the EventDispatchThread associated with the top of the stack is
+ // allowed to get events from the native source; everyone else just
+ // waits on the head of the queue.
+
+ if (isDispatchThread())
+ {
+ // We are not allowed to return null from this method, yet it
+ // is possible that we actually have run out of native events
+ // in the enclosing while() loop, and none of the native events
+ // happened to cause AWT events. We therefore ought to check
+ // the isShutdown() condition here, before risking a "native
+ // wait". If we check it before entering this function we may
+ // wait forever for events after the shutdown condition has
+ // arisen.
+
+ if (isShutdown())
+ throw new InterruptedException();
+
+ tk.iterateNativeQueue(this, true);
+ lastNativeQueueAccess = System.currentTimeMillis();
+ }
+ else
+ {
+ try
+ {
+ wait();
+ }
+ catch (InterruptedException ie)
+ {
+ }
+ }
+ }
+
+ AWTEvent res = queue[next_out];
+
+ if (++next_out == queue.length)
+ next_out = 0;
+ return res;
+ }
+
+ /**
+ * Returns the next event in the queue without removing it from the queue.
+ * This method will block until an event is available or until the thread
+ * is interrupted.
+ *
+ * @return The next event in the queue.
+ * @specnote Does not block. Returns null if there are no events on the
+ * queue.
+ */
+ public synchronized AWTEvent peekEvent()
+ {
+ if (next != null)
+ return next.peekEvent();
+
+ if (next_in != next_out)
+ return queue[next_out];
+ else
+ return null;
+ }
+
+ /**
+ * Returns the next event in the queue that has the specified id
+ * without removing it from the queue.
+ * This method will block until an event is available or until the thread
+ * is interrupted.
+ *
+ * @param id The event id to return.
+ *
+ * @return The next event in the queue.
+ *
+ * @specnote Does not block. Returns null if there are no matching events
+ * on the queue.
+ */
+ public synchronized AWTEvent peekEvent(int id)
+ {
+ if (next != null)
+ return next.peekEvent(id);
+
+ int i = next_out;
+ while (i != next_in)
+ {
+ AWTEvent qevt = queue[i];
+ if (qevt.id == id)
+ return qevt;
+ }
+ return null;
+ }
+
+ /**
+ * Posts a new event to the queue.
+ *
+ * @param evt The event to post to the queue.
+ *
+ * @exception NullPointerException If event is null.
+ */
+ public synchronized void postEvent(AWTEvent evt)
+ {
+ if (evt == null)
+ throw new NullPointerException();
+
+ if (next != null)
+ {
+ next.postEvent(evt);
+ return;
+ }
+
+ /* Check for any events already on the queue with the same source
+ and ID. */
+ int i = next_out;
+ while (i != next_in)
+ {
+ AWTEvent qevt = queue[i];
+ Object src;
+ if (qevt.id == evt.id
+ && (src = qevt.getSource()) == evt.getSource()
+ && src instanceof Component)
+ {
+ /* If there are, call coalesceEvents on the source component
+ to see if they can be combined. */
+ Component srccmp = (Component) src;
+ AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt);
+ if (coalesced_evt != null)
+ {
+ /* Yes. Replace the existing event with the combined event. */
+ queue[i] = coalesced_evt;
+ return;
+ }
+ break;
+ }
+ if (++i == queue.length)
+ i = 0;
+ }
+
+ queue[next_in] = evt;
+ if (++next_in == queue.length)
+ next_in = 0;
+
+ if (next_in == next_out)
+ {
+ /* Queue is full. Extend it. */
+ AWTEvent[] oldQueue = queue;
+ queue = new AWTEvent[queue.length * 2];
+
+ int len = oldQueue.length - next_out;
+ System.arraycopy(oldQueue, next_out, queue, 0, len);
+ if (next_out != 0)
+ System.arraycopy(oldQueue, 0, queue, len, next_out);
+
+ next_out = 0;
+ next_in = oldQueue.length;
+ }
+
+ if (dispatchThread == null || !dispatchThread.isAlive())
+ {
+ dispatchThread = new EventDispatchThread(this);
+ dispatchThread.start();
+ }
+
+ // Window events might represent the closing of a window, which
+ // might cause the end of the dispatch thread's life, so we'll wake
+ // it up here to give it a chance to check for shutdown.
+
+ if (!isDispatchThread()
+ || (evt.getID() == WindowEvent.WINDOW_CLOSED)
+ || (evt.getID() == WindowEvent.WINDOW_CLOSING))
+ ((ClasspathToolkit) Toolkit.getDefaultToolkit()).wakeNativeQueue();
+
+ notify();
+ }
+
+ /**
+ * Causes runnable to have its run method called in the dispatch thread of the
+ * EventQueue. This will happen after all pending events are processed. The
+ * call blocks until this has happened. This method will throw an Error if
+ * called from the event dispatcher thread.
+ *
+ * @exception InterruptedException If another thread has interrupted
+ * this thread.
+ * @exception InvocationTargetException If an exception is thrown when running
+ * runnable.
+ *
+ * @since 1.2
+ */
+ public static void invokeAndWait(Runnable runnable)
+ throws InterruptedException, InvocationTargetException
+ {
+ if (isDispatchThread ())
+ throw new Error("Can't call invokeAndWait from event dispatch thread");
+
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ Thread current = Thread.currentThread();
+
+ InvocationEvent ie =
+ new InvocationEvent(eq, runnable, current, true);
+
+ synchronized (current)
+ {
+ eq.postEvent(ie);
+ current.wait();
+ }
+
+ Exception exception;
+
+ if ((exception = ie.getException()) != null)
+ throw new InvocationTargetException(exception);
+ }
+
+ /**
+ * This arranges for runnable to have its run method called in the
+ * dispatch thread of the EventQueue. This will happen after all
+ * pending events are processed.
+ *
+ * @since 1.2
+ */
+ public static void invokeLater(Runnable runnable)
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+
+ InvocationEvent ie =
+ new InvocationEvent(eq, runnable, null, false);
+
+ eq.postEvent(ie);
+ }
+
+ /**
+ * Return true if the current thread is the current AWT event dispatch
+ * thread.
+ */
+ public static boolean isDispatchThread()
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+
+ /* Find last EventQueue in chain */
+ while (eq.next != null)
+ eq = eq.next;
+
+ return (Thread.currentThread() == eq.dispatchThread);
+ }
+
+ /**
+ * Return the event currently being dispatched by the event
+ * dispatch thread. If the current thread is not the event
+ * dispatch thread, this method returns null.
+ *
+ * @since 1.4
+ */
+ public static AWTEvent getCurrentEvent()
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ Thread ct = Thread.currentThread();
+
+ /* Find out if this thread is the dispatch thread for any of the
+ EventQueues in the chain */
+ while (ct != eq.dispatchThread)
+ {
+ // Try next EventQueue, if any
+ if (eq.next == null)
+ return null; // Not an event dispatch thread
+ eq = eq.next;
+ }
+
+ return eq.currentEvent;
+ }
+
+ /**
+ * Allows a custom EventQueue implementation to replace this one.
+ * All pending events are transferred to the new queue. Calls to postEvent,
+ * getNextEvent, and peekEvent and others are forwarded to the pushed queue
+ * until it is removed with a pop().
+ *
+ * @exception NullPointerException if newEventQueue is null.
+ */
+ public synchronized void push(EventQueue newEventQueue)
+ {
+ if (newEventQueue == null)
+ throw new NullPointerException ();
+
+ /* Make sure we are at the top of the stack because callers can
+ only get a reference to the one at the bottom using
+ Toolkit.getDefaultToolkit().getSystemEventQueue() */
+ if (next != null)
+ {
+ next.push (newEventQueue);
+ return;
+ }
+
+ /* Make sure we have a live dispatch thread to drive the queue */
+ if (dispatchThread == null)
+ dispatchThread = new EventDispatchThread(this);
+
+ int i = next_out;
+ while (i != next_in)
+ {
+ newEventQueue.postEvent(queue[i]);
+ next_out = i;
+ if (++i == queue.length)
+ i = 0;
+ }
+
+ next = newEventQueue;
+ newEventQueue.prev = this;
+ }
+
+ /** Transfer any pending events from this queue back to the parent queue that
+ * was previously push()ed. Event dispatch from this queue is suspended.
+ *
+ * @exception EmptyStackException If no previous push was made on this
+ * EventQueue.
+ */
+ protected void pop() throws EmptyStackException
+ {
+ if (prev == null)
+ throw new EmptyStackException();
+
+ /* The order is important here, we must get the prev lock first,
+ or deadlock could occur as callers usually get here following
+ prev's next pointer, and thus obtain prev's lock before trying
+ to get this lock. */
+ synchronized (prev)
+ {
+ prev.next = next;
+ if (next != null)
+ next.prev = prev;
+
+ synchronized (this)
+ {
+ int i = next_out;
+ while (i != next_in)
+ {
+ prev.postEvent(queue[i]);
+ next_out = i;
+ if (++i == queue.length)
+ i = 0;
+ }
+ // Empty the queue so it can be reused
+ next_in = 0;
+ next_out = 0;
+
+ ((ClasspathToolkit) Toolkit.getDefaultToolkit()).wakeNativeQueue();
+ setShutdown(true);
+ dispatchThread = null;
+ this.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Dispatches an event. The manner in which the event is dispatched depends
+ * upon the type of the event and the type of the event's source object.
+ *
+ * @exception NullPointerException If event is null.
+ */
+ protected void dispatchEvent(AWTEvent evt)
+ {
+ currentEvent = evt;
+
+ if (evt instanceof InputEvent)
+ lastWhen = ((InputEvent) evt).getWhen();
+ else if (evt instanceof ActionEvent)
+ lastWhen = ((ActionEvent) evt).getWhen();
+ else if (evt instanceof InvocationEvent)
+ lastWhen = ((InvocationEvent) evt).getWhen();
+
+ if (evt instanceof ActiveEvent)
+ {
+ ActiveEvent active_evt = (ActiveEvent) evt;
+ active_evt.dispatch();
+ }
+ else
+ {
+ Object source = evt.getSource();
+
+ if (source instanceof Component)
+ {
+ Component srccmp = (Component) source;
+ srccmp.dispatchEvent(evt);
+ }
+ else if (source instanceof MenuComponent)
+ {
+ MenuComponent srccmp = (MenuComponent) source;
+ srccmp.dispatchEvent(evt);
+ }
+ }
+ }
+
+ /**
+ * Returns the timestamp of the most recent event that had a timestamp, or
+ * the initialization time of the event queue if no events have been fired.
+ * At present, only <code>InputEvent</code>s, <code>ActionEvent</code>s,
+ * <code>InputMethodEvent</code>s, and <code>InvocationEvent</code>s have
+ * timestamps, but this may be added to other events in future versions.
+ * If this is called by the event dispatching thread, it can be any
+ * (sequential) value, but to other threads, the safest bet is to return
+ * System.currentTimeMillis().
+ *
+ * @return the most recent timestamp
+ * @see InputEvent#getWhen()
+ * @see ActionEvent#getWhen()
+ * @see InvocationEvent#getWhen()
+ * @see InputMethodEvent#getWhen()
+ * @since 1.4
+ */
+ public static long getMostRecentEventTime()
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ if (Thread.currentThread() != eq.dispatchThread)
+ return System.currentTimeMillis();
+ return eq.lastWhen;
+ }
+}
diff --git a/libjava/classpath/java/awt/FileDialog.java b/libjava/classpath/java/awt/FileDialog.java
new file mode 100644
index 00000000000..7f2723e7e9a
--- /dev/null
+++ b/libjava/classpath/java/awt/FileDialog.java
@@ -0,0 +1,318 @@
+/* FileDialog.java -- A filename selection dialog box
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.FileDialogPeer;
+import java.io.FilenameFilter;
+import java.io.Serializable;
+
+/**
+ * This class implements a file selection dialog box widget.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class FileDialog extends Dialog implements Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * Indicates that the purpose of the dialog is for opening a file.
+ */
+public static final int LOAD = 0;
+
+/**
+ * Indicates that the purpose of the dialog is for saving a file.
+ */
+public static final int SAVE = 1;
+
+// Serialization constant
+private static final long serialVersionUID = 5035145889651310422L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The directory for this file dialog.
+ */
+private String dir;
+
+/**
+ * @serial The filename for this file dialog
+ */
+private String file;
+
+/**
+ * @serial The filter for selecting filenames to display
+ */
+private FilenameFilter filter;
+
+/**
+ * @serial The mode of this dialog, either <code>LOAD</code> or
+ * <code>SAVE</code>.
+ */
+private int mode;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>FileDialog</code> with the
+ * specified parent. This dialog will have no title and will be for
+ * loading a file.
+ *
+ * @param parent The parent frame for this dialog.
+ */
+public
+FileDialog(Frame parent)
+{
+ this(parent, "", LOAD);
+}
+
+/*************************************************************************/
+
+/**
+ * Initialized a new instance of <code>FileDialog</code> with the
+ * specified parent and title. This dialog will be for opening a file.
+ *
+ * @param parent The parent frame for this dialog.
+ * @param title The title for this dialog.
+ */
+public
+FileDialog(Frame parent, String title)
+{
+ this(parent, title, LOAD);
+}
+
+/*************************************************************************/
+
+/**
+ * Initialized a new instance of <code>FileDialog</code> with the
+ * specified parent, title, and mode.
+ *
+ * @param parent The parent frame for this dialog.
+ * @param title The title for this dialog.
+ * @param mode The mode of the dialog, either <code>LOAD</code> or
+ * <code>SAVE</code>.
+ *
+ * @exception IllegalArgumentException If an illegal file dialog mode
+ * is supplied.
+ */
+public
+FileDialog(Frame parent, String title, int mode)
+{
+ super(parent, title, true);
+
+ if ((mode != LOAD) && (mode != SAVE))
+ throw new IllegalArgumentException (
+ "Mode argument must be either LOAD or SAVE");
+
+ setMode (mode);
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the mode of this dialog, either <code>LOAD</code> or
+ * <code>SAVE</code>.
+ *
+ * @return The mode of this dialog.
+ */
+public int
+getMode()
+{
+ return(mode);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the mode of this dialog to either <code>LOAD</code> or
+ * <code>SAVE</code>. This method is only effective before the native
+ * peer is created.
+ *
+ * @param mode The new mode of this file dialog.
+ *
+ * @exception IllegalArgumentException If an illegal file dialog mode
+ * is supplied.
+ */
+public void
+setMode(int mode)
+{
+ if ((mode != LOAD) && (mode != SAVE))
+ throw new IllegalArgumentException("Bad mode: " + mode);
+
+ this.mode = mode;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the directory for this file dialog.
+ *
+ * @return The directory for this file dialog.
+ */
+public String
+getDirectory()
+{
+ return(dir);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the directory for this file dialog.
+ *
+ * @param dir The new directory for this file dialog.
+ */
+public synchronized void
+setDirectory(String dir)
+{
+ this.dir = dir;
+ if (peer != null)
+ {
+ FileDialogPeer f = (FileDialogPeer) peer;
+ f.setDirectory (dir);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the file that is selected in this dialog.
+ *
+ * @return The file that is selected in this dialog.
+ */
+public String
+getFile()
+{
+ return(file);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the selected file for this dialog.
+ *
+ * @param file The selected file for this dialog.
+ */
+public synchronized void
+setFile(String file)
+{
+ this.file = file;
+ if (peer != null)
+ {
+ FileDialogPeer f = (FileDialogPeer) peer;
+ f.setFile (file);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the filename filter being used by this dialog.
+ *
+ * @return The filename filter being used by this dialog.
+ */
+public FilenameFilter
+getFilenameFilter()
+{
+ return(filter);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the filename filter used by this dialog.
+ *
+ * @param filter The new filename filter for this file dialog box.
+ */
+public synchronized void
+setFilenameFilter(FilenameFilter filter)
+{
+ this.filter = filter;
+ if (peer != null)
+ {
+ FileDialogPeer f = (FileDialogPeer) peer;
+ f.setFilenameFilter (filter);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Creates the native peer for this file dialog box.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createFileDialog (this);
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+protected String
+paramString()
+{
+ return ("dir=" + dir + ",file=" + file +
+ ",mode=" + mode + "," + super.paramString());
+}
+
+} // class FileDialog
+
diff --git a/libjava/classpath/java/awt/FlowLayout.java b/libjava/classpath/java/awt/FlowLayout.java
new file mode 100644
index 00000000000..4674990ac52
--- /dev/null
+++ b/libjava/classpath/java/awt/FlowLayout.java
@@ -0,0 +1,364 @@
+/* FlowLayout.java -- Grid-based layout engine
+ Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/** This class implements a flow-based layout. Components are laid
+ * out in order from left to right. When a component cannot be placed
+ * without horizontal clipping, a new row is started. This class
+ * supports horizontal and vertical gaps. These are used for spacing
+ * between components.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class FlowLayout implements LayoutManager, Serializable
+{
+ /** Constant that specifies left alignment. */
+ public static final int LEFT = 0;
+ /** Constant that specifies center alignment. */
+ public static final int CENTER = 1;
+ /** Constant that specifies right alignment. */
+ public static final int RIGHT = 2;
+
+ /** Constant that specifies alignment to leading edge of container's
+ * orientation. */
+ public static final int LEADING = 3;
+ /** Constant that specifies alignment to trailing edge of container's
+ * orientation. */
+ public static final int TRAILING = 4;
+
+ // Serialization constant
+ private static final long serialVersionUID = -7262534875583282631L;
+
+ /**
+ * Add a new component to the layout. This particular implementation
+ * does nothing.
+ *
+ * @param name the name
+ * @param comp the component
+ */
+ public void addLayoutComponent (String name, Component comp)
+ {
+ // Nothing.
+ }
+
+ /**
+ * Returns the current justification value for this object.
+ *
+ * @return The current justification value for this object.
+ */
+ public int getAlignment ()
+ {
+ return align;
+ }
+
+ /**
+ * Returns the horizontal gap between components.
+ *
+ * @return The horizontal gap between components.
+ */
+ public int getHgap ()
+ {
+ return hgap;
+ }
+
+ /**
+ * Returns the vertical gap between lines of components.
+ *
+ * @return The vertical gap between lines of components.
+ */
+ public int getVgap ()
+ {
+ return vgap;
+ }
+
+ /**
+ * Initializes a new instance of <code>FlowLayout</code> with a center
+ * justification and a default horizontal and vertical gap of 5.
+ */
+ public FlowLayout ()
+ {
+ this (CENTER, 5, 5);
+ }
+
+ /**
+ * Initializes a new instance of <code>FlowLayout</code> with the specified
+ * justification and a default horizontal and vertical gap of 5.
+ *
+ * @param align The justification setting, which should be one of the
+ * contants in this class.
+ */
+ public FlowLayout (int align)
+ {
+ this (align, 5, 5);
+ }
+
+ /**
+ * Initializes a new instance of <code>FlowLayout</code> with the specified
+ * justification and gap values
+ * @param align Alignment
+ * @param hgap The horizontal gap
+ * @param vgap The vertical gap
+ * @exception IllegalArgumentException If either gap is negative
+ */
+ public FlowLayout (int align, int hgap, int vgap)
+ {
+ // Use methods to set fields so that we can have all the checking
+ // in one place.
+ setVgap (vgap);
+ setHgap (hgap);
+ setAlignment (align);
+ }
+
+ /** Lay out the container's components based on current settings.
+ * @param parent The parent container
+ */
+ public void layoutContainer (Container parent)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int num = parent.getComponentCount ();
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ Dimension d = parent.getSize ();
+ Insets ins = parent.getInsets ();
+
+ ComponentOrientation orient = parent.getComponentOrientation ();
+ boolean left_to_right = orient.isLeftToRight ();
+
+ int y = ins.top + vgap;
+ int i = 0;
+ while (i < num)
+ {
+ // Find the components which go in the current row.
+ int new_w = ins.left + hgap + ins.right;
+ int new_h = 0;
+ int j;
+ boolean found_one = false;
+ for (j = i; j < num; ++j)
+ {
+ // Skip invisible items.
+ if (! comps[j].visible)
+ continue;
+
+ Dimension c = comps[j].getPreferredSize ();
+
+ int next_w = new_w + hgap + c.width;
+ if (next_w <= d.width || ! found_one)
+ {
+ new_w = next_w;
+ new_h = Math.max (new_h, c.height);
+ found_one = true;
+ }
+ else
+ {
+ // Must start a new row, and we already found an item
+ break;
+ }
+ }
+
+ // Set the location of each component for this row.
+ int x;
+
+ int myalign = align;
+ if (align == LEADING)
+ myalign = left_to_right ? LEFT : RIGHT;
+ else if (align == TRAILING)
+ myalign = left_to_right ? RIGHT : LEFT;
+
+ if (myalign == LEFT)
+ x = ins.left + hgap;
+ else if (myalign == CENTER)
+ x = ins.left + (d.width - new_w) / 2 + hgap;
+ else
+ x = ins.left + (d.width - new_w) + hgap;
+
+ for (int k = i; k < j; ++k)
+ {
+ if (comps[k].visible)
+ {
+ Dimension c = comps[k].getPreferredSize ();
+ comps[k].setBounds (x, y + (new_h - c.height) / 2,
+ c.width, c.height);
+ x += c.width + hgap;
+ }
+ }
+
+ // Advance to next row.
+ i = j;
+ y += new_h + vgap;
+ }
+ }
+ }
+
+ /**
+ * Returns the minimum layout size for the specified container using
+ * this layout.
+ * @param cont The parent container
+ * @return The minimum layout size.
+ */
+ public Dimension minimumLayoutSize (Container cont)
+ {
+ return getSize (cont, true);
+ }
+
+ /**
+ * Returns the preferred layout size for the specified container using
+ * this layout.
+ * @param cont The parent container
+ * @return The preferred layout size.
+ */
+ public Dimension preferredLayoutSize (Container cont)
+ {
+ return getSize (cont, false);
+ }
+
+ /** Remove the indicated component from this layout manager.
+ * This particular implementation does nothing.
+ * @param comp The component to remove
+ */
+ public void removeLayoutComponent (Component comp)
+ {
+ // Nothing.
+ }
+
+ /**
+ * Sets the justification value for this object to the specified value.
+ *
+ * @param align The new justification value for this object, which must
+ * be one of the constants in this class.
+ */
+ public void setAlignment (int align)
+ {
+ if (align != LEFT && align != RIGHT && align != CENTER
+ && align != LEADING && align != TRAILING)
+ throw new IllegalArgumentException ("invalid alignment: " + align);
+ this.align = align;
+ }
+
+ /**
+ * Sets the horizontal gap between components to the specified value.
+ *
+ * @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.
+ *
+ * @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;
+ }
+
+ /** Return String description of this object.
+ * @return A string representation of this object.
+ */
+ public String toString ()
+ {
+ return ("[" + getClass ().getName () + ",hgap=" + hgap + ",vgap=" + vgap
+ + ",align=" + align + "]");
+ }
+
+ // This method is used to compute the various sizes.
+ private Dimension getSize (Container parent, boolean is_min)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int w, h, num = parent.getComponentCount ();
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ w = 0;
+ h = 0;
+ for (int i = 0; i < num; ++i)
+ {
+ if (! comps[i].visible)
+ continue;
+
+ // FIXME: can we just directly read the fields in Component?
+ // Or will that not work with subclassing?
+ Dimension d;
+
+ if (is_min)
+ d = comps[i].getMinimumSize ();
+ else
+ d = comps[i].getPreferredSize ();
+
+ w += d.width;
+ h = Math.max (d.height, h);
+ }
+
+ Insets ins = parent.getInsets ();
+
+ w += (num + 1) * hgap + ins.left + ins.right;
+ h += 2 * vgap + ins.top + ins.bottom;
+
+ return new Dimension (w, h);
+ }
+ }
+
+ /**
+ * @serial The justification alignment of the lines of components, which
+ * will be one of the constants defined in this class.
+ */
+ private int align;
+
+ /**
+ * @serial The horizontal gap between components.
+ */
+ private int hgap;
+
+ /**
+ * @serial The vertical gap between lines of components.
+ */
+ private int vgap;
+}
diff --git a/libjava/classpath/java/awt/FocusTraversalPolicy.java b/libjava/classpath/java/awt/FocusTraversalPolicy.java
new file mode 100644
index 00000000000..a7f1558dde9
--- /dev/null
+++ b/libjava/classpath/java/awt/FocusTraversalPolicy.java
@@ -0,0 +1,103 @@
+/* FocusTraversalPolicy.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * @since 1.4
+ */
+public abstract class FocusTraversalPolicy
+{
+ /**
+ * Creates a <code>FocusTraversalPolicy</code> object.
+ */
+ public FocusTraversalPolicy()
+ {
+ // Do nothing in here.
+ }
+
+ /**
+ * Returns the Component that should receive the focus after a Component.
+ *
+ * @exception IllegalArgumentException If root or current is null,
+ * or if root is not a focus cycle root of current.
+ */
+ public abstract Component getComponentAfter(Container root,
+ Component current);
+
+ /**
+ * Returns the Component that should receive the focus before a Component.
+ *
+ * @exception IllegalArgumentException If root or current is null,
+ * or if root is not a focus cycle root of current.
+ */
+ public abstract Component getComponentBefore(Container root,
+ Component current);
+
+ /**
+ * Returns the first Component in the traversal cycle.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public abstract Component getFirstComponent(Container root);
+
+ /**
+ * Returns the last Component in the traversal cycle.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public abstract Component getLastComponent(Container root);
+
+ /**
+ * Returns the default Component to focus.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public abstract Component getDefaultComponent(Container root);
+
+ /**
+ * Returns the Component that should receive the focus when a Window is made
+ * visible for the first time.
+ *
+ * @exception IllegalArgumentException If window is null.
+ */
+ public Component getInitialComponent(Window window)
+ {
+ return getDefaultComponent(window);
+ }
+} // class FocusTraversalPolicy
diff --git a/libjava/classpath/java/awt/Font.java b/libjava/classpath/java/awt/Font.java
new file mode 100644
index 00000000000..30961ab2fa4
--- /dev/null
+++ b/libjava/classpath/java/awt/Font.java
@@ -0,0 +1,1336 @@
+/* Font.java -- Font object
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.peer.ClasspathFontPeer;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.peer.FontPeer;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * This class represents a windowing system font.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Graydon Hoare (graydon@redhat.com)
+ */
+public class Font implements Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * Constant indicating a "plain" font.
+ */
+public static final int PLAIN = 0;
+
+/**
+ * Constant indicating a "bold" font.
+ */
+public static final int BOLD = 1;
+
+/**
+ * Constant indicating an "italic" font.
+ */
+public static final int ITALIC = 2;
+
+/**
+ * Constant indicating the baseline mode characteristic of Roman.
+ */
+public static final int ROMAN_BASELINE = 0;
+
+/**
+ * Constant indicating the baseline mode characteristic of Chinese.
+ */
+public static final int CENTER_BASELINE = 1;
+
+/**
+ * Constant indicating the baseline mode characteristic of Devanigri.
+ */
+public static final int HANGING_BASELINE = 2;
+
+
+ /**
+ * Indicates to <code>createFont</code> that the supplied font data
+ * is in TrueType format.
+ *
+ * <p><em>Specification Note:</em> The Sun JavaDoc for J2SE 1.4 does
+ * not indicate whether this value also subsumes OpenType. OpenType
+ * is essentially the same format as TrueType, but allows to define
+ * glyph shapes in the same way as PostScript, using cubic bezier
+ * curves.
+ *
+ * @since 1.3
+ */
+ public static final int TRUETYPE_FONT = 0;
+
+
+ /**
+ * A flag for <code>layoutGlyphVector</code>, indicating that the
+ * orientation of a text run is from left to right.
+ *
+ * @since 1.4
+ */
+ public static final int LAYOUT_LEFT_TO_RIGHT = 0;
+
+
+ /**
+ * A flag for <code>layoutGlyphVector</code>, indicating that the
+ * orientation of a text run is from right to left.
+ *
+ * @since 1.4
+ */
+ public static final int LAYOUT_RIGHT_TO_LEFT = 1;
+
+
+ /**
+ * A flag for <code>layoutGlyphVector</code>, indicating that the
+ * text does not contain valid characters before the
+ * <code>start</code> position. If this flag is set,
+ * <code>layoutGlyphVector</code> does not examine the text before
+ * <code>start</code>, even if this would be necessary to select the
+ * correct glyphs (e.g., for Arabic text).
+ *
+ * @since 1.4
+ */
+ public static final int LAYOUT_NO_START_CONTEXT = 2;
+
+
+ /**
+ * A flag for <code>layoutGlyphVector</code>, indicating that the
+ * text does not contain valid characters after the
+ * <code>limit</code> position. If this flag is set,
+ * <code>layoutGlyphVector</code> does not examine the text after
+ * <code>limit</code>, even if this would be necessary to select the
+ * correct glyphs (e.g., for Arabic text).
+ *
+ * @since 1.4
+ */
+ public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
+
+ /**
+ * The logical name of this font.
+ *
+ * @since 1.0
+ */
+ protected String name;
+
+ /**
+ * The size of this font in pixels.
+ *
+ * @since 1.0
+ */
+ protected int size;
+
+ /**
+ * The style of this font -- PLAIN, BOLD, ITALIC or BOLD+ITALIC.
+ *
+ * @since 1.0
+ */
+ protected int style;
+
+// Serialization constant
+private static final long serialVersionUID = -4206021311591459213L;
+
+
+ // The ClasspathToolkit-provided peer which implements this font
+ private ClasspathFontPeer peer;
+
+/*************************************************************************/
+
+/*
+ * Static Methods
+ */
+
+/**
+ * Creates a <code>Font</code> object from the specified string, which
+ * is in one of the following formats:
+ * <p>
+ * <ul>
+ * <li>fontname-style-pointsize
+ * <li>fontname-style
+ * <li>fontname-pointsize
+ * <li>fontname
+ * </ul>
+ * <p>
+ * The style should be one of BOLD, ITALIC, or BOLDITALIC. The default
+ * style if none is specified is PLAIN. The default size if none
+ * is specified is 12.
+ *
+ * @param fontspec a string specifying the required font (<code>null</code>
+ * permitted, interpreted as 'Dialog-PLAIN-12').
+ *
+ * @return A font.
+ */
+ public static Font decode (String fontspec)
+{
+ if (fontspec == null)
+ fontspec = "Dialog-PLAIN-12";
+ String name = null;
+ int style = PLAIN;
+ int size = 12;
+
+ StringTokenizer st = new StringTokenizer(fontspec, "- ");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if (name == null)
+ {
+ name = token;
+ continue;
+ }
+
+ if (token.toUpperCase().equals("BOLD"))
+ {
+ style = BOLD;
+ continue;
+ }
+ if (token.toUpperCase().equals("ITALIC"))
+ {
+ style = ITALIC;
+ continue;
+ }
+ if (token.toUpperCase().equals("BOLDITALIC"))
+ {
+ style = BOLD | ITALIC;
+ continue;
+ }
+
+ int tokenval = 0;
+ try
+ {
+ tokenval = Integer.parseInt(token);
+ }
+ catch(NumberFormatException e)
+ {
+ // Ignored.
+ }
+
+ if (tokenval != 0)
+ size = tokenval;
+ }
+
+ HashMap attrs = new HashMap();
+ ClasspathFontPeer.copyStyleToAttrs (style, attrs);
+ ClasspathFontPeer.copySizeToAttrs (size, attrs);
+
+ return getFontFromToolkit (name, attrs);
+}
+
+ /* These methods delegate to the toolkit. */
+
+ protected static ClasspathToolkit tk ()
+ {
+ return (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
+ }
+
+ /* Every factory method in Font should eventually call this. */
+ protected static Font getFontFromToolkit (String name, Map attribs)
+ {
+ return tk ().getFont (name, attribs);
+ }
+
+ /* Every Font constructor should eventually call this. */
+ protected static ClasspathFontPeer getPeerFromToolkit (String name, Map attrs)
+ {
+ return tk ().getClasspathFontPeer (name, attrs);
+ }
+
+
+/*************************************************************************/
+
+/**
+ * Returns a <code>Font</code> object from the passed property name.
+ *
+ * @param propname The name of the system property.
+ * @param defval Value to use if the property is not found.
+ *
+ * @return The requested font, or <code>default</code> if the property
+ * not exist or is malformed.
+ */
+ public static Font getFont (String propname, Font defval)
+{
+ String propval = System.getProperty(propname);
+ if (propval != null)
+ return decode (propval);
+ return defval;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a <code>Font</code> object from the passed property name.
+ *
+ * @param propname The name of the system property.
+ *
+ * @return The requested font, or <code>null</code> if the property
+ * not exist or is malformed.
+ */
+ public static Font getFont (String propname)
+{
+ return getFont (propname, (Font)null);
+}
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>Font</code> with the specified
+ * attributes.
+ *
+ * @param name The name of the font.
+ * @param style The font style.
+ * @param size The font point size.
+ */
+
+ public Font (String name, int style, int size)
+ {
+ HashMap attrs = new HashMap();
+ ClasspathFontPeer.copyStyleToAttrs (style, attrs);
+ ClasspathFontPeer.copySizeToAttrs (size, attrs);
+ this.peer = getPeerFromToolkit (name, attrs);
+ }
+
+ public Font (Map attrs)
+ {
+ this(null, attrs);
+ }
+
+ /* This extra constructor is here to permit ClasspathToolkit and to build
+ a font with a "logical name" as well as attrs. */
+ public Font (String name, Map attrs)
+ {
+ // If attrs is null, setting it to an empty HashMap will give this
+ // Font default attributes.
+ if (attrs == null)
+ attrs = new HashMap();
+ this.peer = getPeerFromToolkit (name, attrs);
+ }
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the logical name of the font. A logical name is the name the
+ * font was constructed with. It may be the name of a logical font (one
+ * of 6 required names in all java environments) or it may be a face
+ * name.
+ *
+ * @return The logical name of the font.
+ *
+ * @see #getFamily()
+ * @see #getFontName()
+ */
+ public String getName ()
+{
+ return peer.getName (this);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the style of the font.
+ *
+ * @return The font style.
+ */
+ public int getSize ()
+{
+ return (int) peer.getSize (this);
+}
+
+ public float getSize2D ()
+{
+ return peer.getSize (this);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this is a plain font. This will be true if
+ * and only if neither the bold nor the italics style is set.
+ *
+ * @return <code>true</code> if this is a plain font, <code>false</code>
+ * otherwise.
+ */
+ public boolean isPlain ()
+{
+ return peer.isPlain (this);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this font is bold.
+ *
+ * @return <code>true</code> if this font is bold, <code>false</code>
+ * otherwise.
+ */
+ public boolean isBold ()
+{
+ return peer.isBold (this);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this font is italic.
+ *
+ * @return <code>true</code> if this font is italic, <code>false</code>
+ * otherwise.
+ */
+ public boolean isItalic ()
+{
+ return peer.isItalic (this);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the family name of this font. A family name describes a design
+ * or "brand name" (such as Helvetica or Palatino). It is less specific
+ * than a font face name (such as Helvetica Bold).
+ *
+ * @return A string containing the font family name.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFontName()
+ * @see GraphicsEnvironment#getAvailableFontFamilyNames()
+ */
+ public String getFamily ()
+{
+ return peer.getFamily (this);
+}
+
+/**
+ * Returns integer code representing the sum of style flags of this font, a
+ * combination of either {@link #PLAIN}, {@link #BOLD}, or {@link #ITALIC}.
+ *
+ * @return code representing the style of this font.
+ *
+ * @see #isPlain()
+ * @see #isBold()
+ * @see #isItalic()
+ */
+ public int getStyle ()
+{
+ return peer.getStyle (this);
+}
+
+/**
+ * Checks if specified character maps to a glyph in this font.
+ *
+ * @param c The character to check.
+ *
+ * @return Whether the character has a corresponding glyph in this font.
+ *
+ * @since 1.2
+ */
+ public boolean canDisplay (char c)
+{
+ return peer.canDisplay (this, c);
+}
+
+/**
+ * Checks how much of a given string can be mapped to glyphs in
+ * this font.
+ *
+ * @param s The string to check.
+ *
+ * @return The index of the first character in <code>s</code> which cannot
+ * be converted to a glyph by this font, or <code>-1</code> if all
+ * characters can be mapped to glyphs.
+ *
+ * @since 1.2
+ */
+ public int canDisplayUpTo (String s)
+{
+ return peer.canDisplayUpTo (this, new StringCharacterIterator (s),
+ 0, s.length () - 1);
+}
+
+/**
+ * Checks how much of a given sequence of text can be mapped to glyphs in
+ * this font.
+ *
+ * @param text Array containing the text to check.
+ * @param start Position of first character to check in <code>text</code>.
+ * @param limit Position of last character to check in <code>text</code>.
+ *
+ * @return The index of the first character in the indicated range which
+ * cannot be converted to a glyph by this font, or <code>-1</code> if all
+ * characters can be mapped to glyphs.
+ *
+ * @since 1.2
+ *
+ * @throws IndexOutOfBoundsException if the range [start, limit] is
+ * invalid in <code>text</code>.
+ */
+ public int canDisplayUpTo (char[] text, int start, int limit)
+{
+ return peer.canDisplayUpTo
+ (this, new StringCharacterIterator (new String (text)), start, limit);
+}
+
+/**
+ * Checks how much of a given sequence of text can be mapped to glyphs in
+ * this font.
+ *
+ * @param i Iterator over the text to check.
+ * @param start Position of first character to check in <code>i</code>.
+ * @param limit Position of last character to check in <code>i</code>.
+ *
+ * @return The index of the first character in the indicated range which
+ * cannot be converted to a glyph by this font, or <code>-1</code> if all
+ * characters can be mapped to glyphs.
+ *
+ * @since 1.2
+ *
+ * @throws IndexOutOfBoundsException if the range [start, limit] is
+ * invalid in <code>i</code>.
+ */
+ public int canDisplayUpTo (CharacterIterator i, int start, int limit)
+{
+ return peer.canDisplayUpTo (this, i, start, limit);
+}
+
+/**
+ * Creates a new font with point size 1 and {@link #PLAIN} style,
+ * reading font data from the provided input stream. The resulting font
+ * can have further fonts derived from it using its
+ * <code>deriveFont</code> method.
+ *
+ * @param fontFormat Integer code indicating the format the font data is
+ * in.Currently this can only be {@link #TRUETYPE_FONT}.
+ * @param is {@link InputStream} from which font data will be read. This
+ * stream is not closed after font data is extracted.
+ *
+ * @return A new {@link Font} of the format indicated.
+ *
+ * @throws IllegalArgumentException if <code>fontType</code> is not
+ * recognized.
+ * @throws FontFormatException if data in InputStream is not of format
+ * indicated.
+ * @throws IOException if insufficient data is present on InputStream.
+ *
+ * @since 1.3
+ */
+ public static Font createFont (int fontFormat, InputStream is)
+ throws FontFormatException, IOException
+{
+ return tk().createFont (fontFormat, is);
+}
+
+/**
+ * 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
+ * is inappropriate for scripts with special shaping or contextual layout
+ * requirements such as Arabic, Indic, Hebrew or Thai.
+ *
+ * @param ctx The rendering context used for precise glyph placement.
+ * @param str The string to convert to Glyphs.
+ *
+ * @return A new {@link GlyphVector} containing glyphs mapped from str,
+ * through the font's cmap table.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ */
+ public GlyphVector createGlyphVector (FontRenderContext ctx, String str)
+{
+ return peer.createGlyphVector (this, ctx, new StringCharacterIterator (str));
+}
+
+/**
+ * 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
+ * is inappropriate for scripts with special shaping or contextual layout
+ * requirements such as Arabic, Indic, Hebrew or Thai.
+ *
+ * @param ctx The rendering context used for precise glyph placement.
+ * @param i Iterator over the text to convert to glyphs.
+ *
+ * @return A new {@link GlyphVector} containing glyphs mapped from str,
+ * through the font's cmap table.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ */
+ public GlyphVector createGlyphVector (FontRenderContext ctx, CharacterIterator i)
+{
+ return peer.createGlyphVector (this, ctx, i);
+}
+
+/**
+ * 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
+ * is inappropriate for scripts with special shaping or contextual layout
+ * requirements such as Arabic, Indic, Hebrew or Thai.
+ *
+ * @param ctx The rendering context used for precise glyph placement.
+ * @param chars Array of characters to convert to glyphs.
+ *
+ * @return A new {@link GlyphVector} containing glyphs mapped from str,
+ * through the font's cmap table.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ */
+ public GlyphVector createGlyphVector (FontRenderContext ctx, char[] chars)
+{
+ return peer.createGlyphVector
+ (this, ctx, new StringCharacterIterator (new String (chars)));
+}
+
+/**
+ * Extracts a sequence of glyphs from a font, returning a new {@link
+ * GlyphVector} with a mapped glyph for each input glyph code.
+ *
+ * @param ctx The rendering context used for precise glyph placement.
+ * @param glyphCodes Array of characters to convert to glyphs.
+ *
+ * @return A new {@link GlyphVector} containing glyphs mapped from str,
+ * through the font's cmap table.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ *
+ * @specnote This method is documented to perform character-to-glyph
+ * conversions, in the Sun documentation, but its second parameter name is
+ * "glyphCodes" and it is not clear to me why it would exist if its
+ * purpose was to transport character codes inside integers. I assume it
+ * is mis-documented in the Sun documentation.
+ */
+
+ public GlyphVector createGlyphVector (FontRenderContext ctx, int[] glyphCodes)
+{
+ return peer.createGlyphVector (this, ctx, glyphCodes);
+}
+
+/**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new size and style.
+ *
+ * @param style The style of the newly created font.
+ * @param size The size of the newly created font.
+ *
+ * @return A clone of the current font, with the specified size and style.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont (int style, float size)
+{
+ return peer.deriveFont (this, style, size);
+}
+
+/**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new size.
+ *
+ * @param size The size of the newly created font.
+ *
+ * @return A clone of the current font, with the specified size.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont (float size)
+{
+ return peer.deriveFont (this, size);
+}
+
+/**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new style.
+ *
+ * @param style The style of the newly created font.
+ *
+ * @return A clone of the current font, with the specified style.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont (int style)
+{
+ return peer.deriveFont (this, style);
+}
+
+/**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new style and subjected to a new affine transformation.
+ *
+ * @param style The style of the newly created font.
+ * @param a The transformation to apply.
+ *
+ * @return A clone of the current font, with the specified style and
+ * transform.
+ *
+ * @throws IllegalArgumentException If transformation is
+ * <code>null</code>.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont (int style, AffineTransform a)
+{
+ if (a == null)
+ throw new IllegalArgumentException ("Affine transformation is null");
+
+ return peer.deriveFont (this, style, a);
+}
+
+/**
+ * Produces a new {@link Font} based on the current font, subjected
+ * to a new affine transformation.
+ *
+ * @param a The transformation to apply.
+ *
+ * @return A clone of the current font, with the specified transform.
+ *
+ * @throws IllegalArgumentException If transformation is
+ * <code>null</code>.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont (AffineTransform a)
+{
+ if (a == null)
+ throw new IllegalArgumentException ("Affine transformation is null");
+
+ return peer.deriveFont (this, a);
+}
+
+/**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new set of attributes.
+ *
+ * @param attributes Attributes of the newly created font.
+ *
+ * @return A clone of the current font, with the specified attributes.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont (Map attributes)
+{
+ return peer.deriveFont (this, attributes);
+}
+
+/**
+ * Returns a map of chracter attributes which this font currently has set.
+ *
+ * @return A map of chracter attributes which this font currently has set.
+ *
+ * @see #getAvailableAttributes()
+ * @see java.text.AttributedCharacterIterator.Attribute
+ * @see java.awt.font.TextAttribute
+ */
+ public Map getAttributes ()
+{
+ return peer.getAttributes (this);
+}
+
+/**
+ * Returns an array of chracter attribute keys which this font understands.
+ *
+ * @return An array of chracter attribute keys which this font understands.
+ *
+ * @see #getAttributes()
+ * @see java.text.AttributedCharacterIterator.Attribute
+ * @see java.awt.font.TextAttribute
+ */
+ public AttributedCharacterIterator.Attribute[] getAvailableAttributes()
+{
+ return peer.getAvailableAttributes (this);
+}
+
+/**
+ * Returns a baseline code (one of {@link #ROMAN_BASELINE}, {@link
+ * #CENTER_BASELINE} or {@link #HANGING_BASELINE}) indicating which baseline
+ * this font will measure baseline offsets for, when presenting glyph
+ * metrics for a given character.
+ *
+ * Baseline offsets describe the position of a glyph relative to an
+ * invisible line drawn under, through the center of, or over a line of
+ * rendered text, respectively. Different scripts use different baseline
+ * modes, so clients should not assume all baseline offsets in a glyph
+ * vector are from a common baseline.
+ *
+ * @param c The character code to select a baseline mode for.
+ *
+ * @return The baseline mode which would be used in a glyph associated
+ * with the provided character.
+ *
+ * @since 1.2
+ *
+ * @see LineMetrics#getBaselineOffsets()
+ */
+ public byte getBaselineFor (char c)
+{
+ return peer.getBaselineFor (this, c);
+}
+
+/**
+ * Returns the family name of this font. A family name describes a
+ * typographic style (such as Helvetica or Palatino). It is more specific
+ * than a logical font name (such as Sans Serif) but less specific than a
+ * font face name (such as Helvetica Bold).
+ *
+ * @param lc The locale in which to describe the name of the font family.
+ *
+ * @return A string containing the font family name, localized for the
+ * provided locale.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFontName()
+ * @see GraphicsEnvironment#getAvailableFontFamilyNames()
+ * @see Locale
+ */
+ public String getFamily (Locale lc)
+{
+ return peer.getFamily (this, lc);
+}
+
+/**
+ * Returns a font appropriate for the given attribute set.
+ *
+ * @param attributes The attributes required for the new font.
+ *
+ * @return A new Font with the given attributes.
+ *
+ * @since 1.2
+ *
+ * @see java.awt.font.TextAttribute
+ */
+ public static Font getFont (Map attributes)
+{
+ return getFontFromToolkit (null, attributes);
+}
+
+/**
+ * Returns the font face name of the font. A font face name describes a
+ * specific variant of a font family (such as Helvetica Bold). It is more
+ * specific than both a font family name (such as Helvetica) and a logical
+ * font name (such as Sans Serif).
+ *
+ * @return The font face name of the font.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFamily()
+ */
+ public String getFontName ()
+{
+ return peer.getFontName (this);
+}
+
+/**
+ * Returns the font face name of the font. A font face name describes a
+ * specific variant of a font family (such as Helvetica Bold). It is more
+ * specific than both a font family name (such as Helvetica).
+ *
+ * @param lc The locale in which to describe the name of the font face.
+ *
+ * @return A string containing the font face name, localized for the
+ * provided locale.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFamily()
+ */
+ public String getFontName (Locale lc)
+{
+ return peer.getFontName (this, lc);
+}
+
+/**
+ * Returns the italic angle of this font, a measurement of its slant when
+ * style is {@link #ITALIC}. The precise meaning is the inverse slope of a
+ * caret line which "best measures" the font's italic posture.
+ *
+ * @return The italic angle.
+ *
+ * @see java.awt.font.TextAttribute#POSTURE
+ */
+ public float getItalicAngle ()
+{
+ return peer.getItalicAngle (this);
+}
+
+/**
+ * Returns a {@link LineMetrics} object constructed with the specified
+ * text and {@link FontRenderContext}.
+ *
+ * @param text The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param rc Context for calculating precise glyph placement and hints.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>text</code>.
+ */
+ public LineMetrics getLineMetrics(String text, int begin,
+ int limit, FontRenderContext rc)
+{
+ return peer.getLineMetrics (this, new StringCharacterIterator (text),
+ begin, limit, rc);
+}
+
+/**
+ * Returns a {@link LineMetrics} object constructed with the specified
+ * text and {@link FontRenderContext}.
+ *
+ * @param chars The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param rc Context for calculating precise glyph placement and hints.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>chars</code>.
+ */
+ public LineMetrics getLineMetrics(char[] chars, int begin,
+ int limit, FontRenderContext rc)
+{
+ return peer.getLineMetrics (this, new StringCharacterIterator (new String(chars)),
+ begin, limit, rc);
+}
+
+/**
+ * Returns a {@link LineMetrics} object constructed with the specified
+ * text and {@link FontRenderContext}.
+ *
+ * @param ci The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param rc Context for calculating precise glyph placement and hints.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>ci</code>.
+ */
+ public LineMetrics getLineMetrics (CharacterIterator ci, int begin,
+ int limit, FontRenderContext rc)
+{
+ return peer.getLineMetrics (this, ci, begin, limit, rc);
+}
+
+/**
+ * Returns the maximal bounding box of all the bounding boxes in this
+ * font, when the font's bounding boxes are evaluated in a given {@link
+ * FontRenderContext}
+ *
+ * @param rc Context in which to evaluate bounding boxes.
+ *
+ * @return The maximal bounding box.
+ */
+ public Rectangle2D getMaxCharBounds (FontRenderContext rc)
+{
+ return peer.getMaxCharBounds (this, rc);
+}
+
+/**
+ * Returns the glyph code this font uses to represent missing glyphs. This
+ * code will be present in glyph vectors when the font was unable to
+ * locate a glyph to represent a particular character code.
+ *
+ * @return The missing glyph code.
+ *
+ * @since 1.2
+ */
+ public int getMissingGlyphCode ()
+{
+ return peer.getMissingGlyphCode (this);
+}
+
+/**
+ * Returns the overall number of glyphs in this font. This number is one
+ * more than the greatest glyph code used in any glyph vectors this font
+ * produces. In other words, glyph codes are taken from the range
+ * <code>[ 0, getNumGlyphs() - 1 ]</code>.
+ *
+ * @return The number of glyphs in this font.
+ *
+ * @since 1.2
+ */
+ public int getNumGlyphs ()
+{
+ return peer.getMissingGlyphCode (this);
+}
+
+/**
+ * Returns the PostScript Name of this font.
+ *
+ * @return The PostScript Name of this font.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFamily()
+ * @see #getFontName()
+ */
+ public String getPSName ()
+{
+ return peer.getPostScriptName (this);
+}
+
+/**
+ * Returns the logical bounds of the specified string when rendered with this
+ * font in the specified {@link FontRenderContext}. This box will include the
+ * glyph origin, ascent, advance, height, and leading, but may not include all
+ * diacritics or accents. To get the complete visual bounding box of all the
+ * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
+ * {@link TextLayout}.
+ *
+ * @param str The string to measure.
+ * @param frc The context in which to make the precise glyph measurements.
+ *
+ * @return A bounding box covering the logical bounds of the specified text.
+ *
+ * @see #createGlyphVector(FontRenderContext, String)
+ */
+ public Rectangle2D getStringBounds (String str, FontRenderContext frc)
+{
+ return getStringBounds (str, 0, str.length () - 1, frc);
+}
+
+/**
+ * Returns the logical bounds of the specified string when rendered with this
+ * font in the specified {@link FontRenderContext}. This box will include the
+ * glyph origin, ascent, advance, height, and leading, but may not include all
+ * diacritics or accents. To get the complete visual bounding box of all the
+ * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
+ * {@link TextLayout}.
+ *
+ * @param str The string to measure.
+ * @param begin Index of the first character in <code>str</code> to measure.
+ * @param limit Index of the last character in <code>str</code> to measure.
+ * @param frc The context in which to make the precise glyph measurements.
+ *
+ * @return A bounding box covering the logical bounds of the specified text.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>str</code>.
+ *
+ * @since 1.2
+ *
+ * @see #createGlyphVector(FontRenderContext, String)
+ */
+ public Rectangle2D getStringBounds (String str, int begin,
+ int limit, FontRenderContext frc)
+{
+ return peer.getStringBounds (this, new StringCharacterIterator(str), begin, limit, frc);
+}
+
+/**
+ * Returns the logical bounds of the specified string when rendered with this
+ * font in the specified {@link FontRenderContext}. This box will include the
+ * glyph origin, ascent, advance, height, and leading, but may not include all
+ * diacritics or accents. To get the complete visual bounding box of all the
+ * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
+ * {@link TextLayout}.
+ *
+ * @param ci The text to measure.
+ * @param begin Index of the first character in <code>ci</code> to measure.
+ * @param limit Index of the last character in <code>ci</code> to measure.
+ * @param frc The context in which to make the precise glyph measurements.
+ *
+ * @return A bounding box covering the logical bounds of the specified text.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>ci</code>.
+ *
+ * @since 1.2
+ *
+ * @see #createGlyphVector(FontRenderContext, CharacterIterator)
+ */
+ public Rectangle2D getStringBounds (CharacterIterator ci, int begin,
+ int limit, FontRenderContext frc)
+{
+ return peer.getStringBounds (this, ci, begin, limit, frc);
+}
+
+/**
+ * Returns the logical bounds of the specified string when rendered with this
+ * font in the specified {@link FontRenderContext}. This box will include the
+ * glyph origin, ascent, advance, height, and leading, but may not include all
+ * diacritics or accents. To get the complete visual bounding box of all the
+ * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
+ * {@link TextLayout}.
+ *
+ * @param chars The text to measure.
+ * @param begin Index of the first character in <code>ci</code> to measure.
+ * @param limit Index of the last character in <code>ci</code> to measure.
+ * @param frc The context in which to make the precise glyph measurements.
+ *
+ * @return A bounding box covering the logical bounds of the specified text.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>chars</code>.
+ *
+ * @since 1.2
+ *
+ * @see #createGlyphVector(FontRenderContext, char[])
+ */
+ public Rectangle2D getStringBounds (char[] chars, int begin,
+ int limit, FontRenderContext frc)
+{
+ return peer.getStringBounds (this, new StringCharacterIterator (new String (chars)),
+ begin, limit, frc);
+}
+
+/**
+ * Returns a copy of the affine transformation this font is currently
+ * subject to, if any.
+ *
+ * @return The current transformation.
+ */
+ public AffineTransform getTransform ()
+{
+ return peer.getTransform (this);
+}
+
+/**
+ * Indicates whether this font's line metrics are uniform. A font may be
+ * composed of several "subfonts", each covering a different code range,
+ * and each with their own line metrics. A font with no subfonts, or
+ * subfonts with identical line metrics, is said to have "uniform" line
+ * metrics.
+ *
+ * @return Whether this font has uniform line metrics.
+ *
+ * @see LineMetrics
+ * @see #getLineMetrics(String, FontRenderContext)
+ */
+ public boolean hasUniformLineMetrics ()
+{
+ return peer.hasUniformLineMetrics (this);
+}
+
+/**
+ * Indicates whether this font is subject to a non-identity affine
+ * transformation.
+ *
+ * @return <code>true</code> iff the font has a non-identity affine
+ * transformation applied to it.
+ */
+ public boolean isTransformed ()
+{
+ return peer.isTransformed (this);
+}
+
+/**
+ * Produces a glyph vector representing a full layout fo the specified
+ * text in this font. Full layouts may include complex shaping and
+ * reordering operations, for scripts such as Arabic or Hindi.
+ *
+ * Bidirectional (bidi) layout is not performed in this method; text
+ * should have its bidi direction specified with one of the flags {@link
+ * #LAYOUT_LEFT_TO_RIGHT} or {@link #LAYOUT_RIGHT_TO_LEFT}.
+ *
+ * Some types of layout (notably Arabic glyph shaping) may examine context
+ * characters beyond the bounds of the indicated range, in order to select
+ * an appropriate shape. The flags {@link #LAYOUT_NO_START_CONTEXT} and
+ * {@link #LAYOUT_NO_LIMIT_CONTEXT} can be provided to prevent these extra
+ * context areas from being examined, for instance if they contain invalid
+ * characters.
+ *
+ * @param frc Context in which to perform the layout.
+ * @param chars Text to perform layout on.
+ * @param start Index of first character to perform layout on.
+ * @param limit Index of last character to perform layout on.
+ * @param flags Combination of flags controlling layout.
+ *
+ * @return A new {@link GlyphVector} representing the specified text.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>chars</code>.
+ */
+ public GlyphVector layoutGlyphVector (FontRenderContext frc,
+ char[] chars, int start,
+ int limit, int flags)
+{
+ return peer.layoutGlyphVector (this, frc, chars, start, limit, flags);
+}
+
+
+/**
+ * Returns a native peer object for this font.
+ *
+ * @return A native peer object for this font.
+ *
+ * @deprecated
+ */
+ public FontPeer getPeer ()
+{
+ return peer;
+}
+
+
+/**
+ * Returns a hash value for this font.
+ *
+ * @return A hash for this font.
+ */
+ public int hashCode()
+{
+ return this.toString().hashCode();
+}
+
+
+/**
+ * Tests whether or not the specified object is equal to this font. This
+ * will be true if and only if:
+ * <P>
+ * <ul>
+ * <li>The object is not <code>null</code>.
+ * <li>The object is an instance of <code>Font</code>.
+ * <li>The object has the same names, style, size, and transform as this object.
+ * </ul>
+ *
+ * @return <code>true</code> if the specified object is equal to this
+ * object, <code>false</code> otherwise.
+ */
+public boolean
+equals(Object obj)
+{
+ if (obj == null)
+ return(false);
+
+ if (!(obj instanceof Font))
+ return(false);
+
+ Font f = (Font)obj;
+
+ return (f.getName ().equals (this.getName ()) &&
+ f.getFamily ().equals (this.getFamily ()) &&
+ f.getFontName ().equals (this.getFontName ()) &&
+ f.getTransform ().equals (this.getTransform ()) &&
+ f.getSize() == this.getSize() &&
+ f.getStyle() == this.getStyle());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this font.
+ *
+ * @return A string representation of this font.
+ */
+public String
+toString()
+{
+ String styleString = "";
+
+ switch (getStyle ())
+ {
+ case 0:
+ styleString = "plain";
+ break;
+ case 1:
+ styleString = "bold";
+ break;
+ case 2:
+ styleString = "italic";
+ break;
+ default:
+ styleString = "unknown";
+ }
+
+ return getClass ().getName ()
+ + "[family=" + getFamily ()
+ + ",name=" + getFontName ()
+ + ",style=" + styleString
+ + ",size=" + getSize () + "]";
+}
+
+
+ /**
+ * Determines the line metrics for a run of text.
+ *
+ * @param str the text run to be measured.
+ *
+ * @param frc the font rendering parameters that are used for the
+ * measurement. The exact placement and size of text slightly
+ * depends on device-specific characteristics, for instance
+ * the device resolution or anti-aliasing. For this reason,
+ * the returned measurement will only be accurate if the
+ * passed <code>FontRenderContext</code> correctly reflects
+ * the relevant parameters. Hence, <code>frc</code> should be
+ * obtained from the same <code>Graphics2D</code> that will
+ * be used for drawing, and any rendering hints should be set
+ * to the desired values before obtaining <code>frc</code>.
+ *
+ * @see java.awt.Graphics2D#getFontRenderContext()
+ */
+ public LineMetrics getLineMetrics(String str, FontRenderContext frc)
+ {
+ return getLineMetrics (str, 0, str.length () - 1, frc);
+ }
+
+} // class Font
+
diff --git a/libjava/classpath/java/awt/FontFormatException.java b/libjava/classpath/java/awt/FontFormatException.java
new file mode 100644
index 00000000000..6ec8757fb5b
--- /dev/null
+++ b/libjava/classpath/java/awt/FontFormatException.java
@@ -0,0 +1,65 @@
+/* FontFormatException.java -- the specified font is bad
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * Thrown when a specified font is bad.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Font
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public class FontFormatException extends Exception
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -4481290147811361272L;
+
+ /**
+ * Create a new instance with the specified detailed error message.
+ *
+ * @param message the detailed error message
+ */
+ public FontFormatException(String message)
+ {
+ super(message);
+ }
+} // class FontFormatException
diff --git a/libjava/classpath/java/awt/FontMetrics.java b/libjava/classpath/java/awt/FontMetrics.java
new file mode 100644
index 00000000000..e702a625766
--- /dev/null
+++ b/libjava/classpath/java/awt/FontMetrics.java
@@ -0,0 +1,425 @@
+/* FontMetrics.java -- Information about about a fonts display characteristics
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineMetrics;
+import java.awt.geom.Rectangle2D;
+import java.text.CharacterIterator;
+
+// FIXME: I leave many methods basically unimplemented. This
+// should be reviewed.
+
+/**
+ * This class returns information about the display characteristics of
+ * a font. It is abstract, and concrete subclasses should implement at
+ * least the following methods:
+ *
+ * <ul>
+ * <li>getAscent()</li>
+ * <li>getDescent()</li>
+ * <li>getLeading()</li>
+ * <li>getMaxAdvance()</li>
+ * <li>charWidth(char)</li>
+ * <li>charsWidth(char[], int, int)</li>
+ * </ul>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class FontMetrics implements java.io.Serializable
+{
+ // Serialization constant.
+ private static final long serialVersionUID = 1681126225205050147L;
+
+ /**
+ * This is the font for which metrics will be returned.
+ */
+ protected Font font;
+
+ /**
+ * Initializes a new instance of <code>FontMetrics</code> for the
+ * specified font.
+ *
+ * @param font The font to return metric information for.
+ */
+ protected FontMetrics(Font font)
+ {
+ this.font = font;
+ }
+
+ /**
+ * Returns the font that this object is creating metric information fo.
+ *
+ * @return The font for this object.
+ */
+ public Font getFont()
+ {
+ return font;
+ }
+
+ /**
+ * Returns the leading, or spacing between lines, for this font.
+ *
+ * @return The font leading.
+ */
+ public int getLeading()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the ascent of the font, which is the distance from the base
+ * to the top of the majority of characters in the set. Some characters
+ * can exceed this value however.
+ *
+ * @return The font ascent.
+ */
+ public int getAscent()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns the descent of the font, which is the distance from the base
+ * to the bottom of the majority of characters in the set. Some characters
+ * can exceed this value however.
+ *
+ * @return The font descent.
+ */
+ public int getDescent()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns the height of a line in this font. This will be the sum
+ * of the leading, the ascent, and the descent.
+ *
+ * @return The height of the font.
+ */
+ public int getHeight()
+ {
+ return getAscent() + getDescent() + getLeading();
+ }
+
+ /**
+ * Returns the maximum ascent value. This is the maximum distance any
+ * character in the font rised above the baseline.
+ *
+ * @return The maximum ascent for this font.
+ */
+ public int getMaxAscent()
+ {
+ return getAscent();
+ }
+
+ /**
+ * Returns the maximum descent value. This is the maximum distance any
+ * character in the font extends below the baseline.
+ *
+ * @return The maximum descent for this font.
+ */
+ public int getMaxDescent()
+ {
+ return getMaxDecent();
+ }
+
+ /**
+ * Returns the maximum descent value. This is the maximum distance any
+ * character in the font extends below the baseline.
+ *
+ * @return The maximum descent for this font.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMaxDescent()</code>.
+ */
+ public int getMaxDecent()
+ {
+ return getDescent();
+ }
+
+ /**
+ * Returns the width of the widest character in the font.
+ *
+ * @return The width of the widest character in the font.
+ */
+ public int getMaxAdvance()
+ {
+ return -1;
+ }
+
+ /**
+ * Returns the width of the specified character.
+ *
+ * @param ch The character to return the width of.
+ *
+ * @return The width of the specified character.
+ */
+ public int charWidth(int ch)
+ {
+ return charWidth((char) ch);
+ }
+
+ /**
+ * Returns the width of the specified character.
+ *
+ * @param ch The character to return the width of.
+ *
+ * @return The width of the specified character.
+ */
+ public int charWidth(char ch)
+ {
+ return 1;
+ }
+
+ /**
+ * Returns the total width of the specified string
+ *
+ * @param str The string to return the width of.
+ *
+ * @return The width of the string.
+ */
+ public int stringWidth(String str)
+ {
+ char[] buf = new char[str.length()];
+ str.getChars(0, str.length(), buf, 0);
+
+ return charsWidth(buf, 0, buf.length);
+ }
+
+ /**
+ * Returns the total width of the specified character array.
+ *
+ * @param buf The character array containing the data.
+ * @param offset The offset into the array to start calculating from.
+ * @param len The total number of bytes to process.
+ *
+ * @return The width of the requested characters.
+ */
+ public int charsWidth(char[] buf, int offset, int len)
+ {
+ int total_width = 0;
+ for (int i = offset; i < len; i++)
+ total_width += charWidth(buf[i]);
+ return total_width;
+ }
+
+ /**
+ * Returns the total width of the specified byte array.
+ *
+ * @param buf The byte array containing the data.
+ * @param offset The offset into the array to start calculating from.
+ * @param len The total number of bytes to process.
+ *
+ * @return The width of the requested characters.
+ */
+ public int bytesWidth(byte[] buf, int offset, int len)
+ {
+ int total_width = 0;
+ for (int i = offset; i < len; i++)
+ total_width = charWidth((char) buf[i]);
+
+ return total_width;
+ }
+
+ /**
+ * Returns the widths of the first 256 characters in the font.
+ *
+ * @return The widths of the first 256 characters in the font.
+ */
+ public int[] getWidths()
+ {
+ int[] result = new int[256];
+ for (char i = 0; i < 256; i++)
+ result[i] = charWidth(i);
+ return result;
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return A string representation of this object.
+ */
+ public String toString()
+ {
+ return (this.getClass() + "[font=" + font + ",ascent=" + getAscent()
+ + ",descent=" + getDescent() + ",height=" + getHeight() + "]");
+ }
+
+ // Generic FontRenderContext used when getLineMetrics is called with a
+ // plain Graphics object.
+ private static final FontRenderContext gRC = new FontRenderContext(null,
+ false,
+ false);
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the
+ * specified text and the {@link FontRenderContext} of the Graphics
+ * object when it is an instance of Graphics2D or a generic
+ * FontRenderContext with a null transform, not anti-aliased and not
+ * using fractional metrics.
+ *
+ * @param text The string to calculate metrics from.
+ * @param g The Graphics object that will be used.
+ *
+ * @return A new {@link LineMetrics} object.
+ */
+ public LineMetrics getLineMetrics(String text, Graphics g)
+ {
+ return getLineMetrics(text, 0, text.length(), g);
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the
+ * specified text and the {@link FontRenderContext} of the Graphics
+ * object when it is an instance of Graphics2D or a generic
+ * FontRenderContext with a null transform, not anti-aliased and not
+ * using fractional metrics.
+ *
+ * @param text The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param g The Graphics object that will be used.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>text</code>.
+ */
+ public LineMetrics getLineMetrics(String text, int begin, int limit,
+ Graphics g)
+ {
+ FontRenderContext rc;
+ if (g instanceof Graphics2D)
+ rc = ((Graphics2D) g).getFontRenderContext();
+ else
+ rc = gRC;
+ return font.getLineMetrics(text, begin, limit, rc);
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the
+ * specified text and the {@link FontRenderContext} of the Graphics
+ * object when it is an instance of Graphics2D or a generic
+ * FontRenderContext with a null transform, not anti-aliased and not
+ * using fractional metrics.
+ *
+ * @param chars The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param g The Graphics object that will be used.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>text</code>.
+ */
+ public LineMetrics getLineMetrics(char[] chars, int begin, int limit,
+ Graphics g)
+ {
+ FontRenderContext rc;
+ if (g instanceof Graphics2D)
+ rc = ((Graphics2D) g).getFontRenderContext();
+ else
+ rc = gRC;
+ return font.getLineMetrics(chars, begin, limit, rc);
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the
+ * specified text and the {@link FontRenderContext} of the Graphics
+ * object when it is an instance of Graphics2D or a generic
+ * FontRenderContext with a null transform, not anti-aliased and not
+ * using fractional metrics.
+ *
+ * @param ci An iterator over the string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param g The Graphics object that will be used.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>text</code>.
+ */
+ public LineMetrics getLineMetrics(CharacterIterator ci, int begin,
+ int limit, Graphics g)
+ {
+ FontRenderContext rc;
+ if (g instanceof Graphics2D)
+ rc = ((Graphics2D) g).getFontRenderContext();
+ else
+ rc = gRC;
+ return font.getLineMetrics(ci, begin, limit, rc);
+ }
+
+ public Rectangle2D getStringBounds(String str, Graphics context)
+ {
+ return font.getStringBounds(str, getFontRenderContext(context));
+ }
+
+ public Rectangle2D getStringBounds(String str, int beginIndex, int limit,
+ Graphics context)
+ {
+ return font.getStringBounds(str, beginIndex, limit,
+ getFontRenderContext(context));
+ }
+
+ public Rectangle2D getStringBounds(char[] chars, int beginIndex, int limit,
+ Graphics context)
+ {
+ return font.getStringBounds(chars, beginIndex, limit,
+ getFontRenderContext(context));
+ }
+
+ public Rectangle2D getStringBounds(CharacterIterator ci, int beginIndex,
+ int limit, Graphics context)
+ {
+ return font.getStringBounds(ci, beginIndex, limit,
+ getFontRenderContext(context));
+ }
+
+ private FontRenderContext getFontRenderContext(Graphics context)
+ {
+ if (context instanceof Graphics2D)
+ return ((Graphics2D) context).getFontRenderContext();
+
+ return gRC;
+ }
+}
diff --git a/libjava/classpath/java/awt/Frame.java b/libjava/classpath/java/awt/Frame.java
new file mode 100644
index 00000000000..0cb97f8b596
--- /dev/null
+++ b/libjava/classpath/java/awt/Frame.java
@@ -0,0 +1,649 @@
+/* Frame.java -- AWT toplevel window
+ Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.FramePeer;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This class is a top-level window with a title bar and window
+ * decorations.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Frame extends Window implements MenuContainer
+{
+/**
+ * Constant for the default cursor.
+ * @deprecated Replaced by <code>Cursor.DEFAULT_CURSOR</code> instead.
+ */
+public static final int DEFAULT_CURSOR = Cursor.DEFAULT_CURSOR;
+
+/**
+ * Constant for a cross-hair cursor.
+ * @deprecated Use <code>Cursor.CROSSHAIR_CURSOR</code> instead.
+ */
+public static final int CROSSHAIR_CURSOR = Cursor.CROSSHAIR_CURSOR;
+
+/**
+ * Constant for a cursor over a text field.
+ * @deprecated Use <code>Cursor.TEXT_CURSOR</code> instead.
+ */
+public static final int TEXT_CURSOR = Cursor.TEXT_CURSOR;
+
+/**
+ * Constant for a cursor to display while waiting for an action to complete.
+ * @deprecated Use <code>Cursor.WAIT_CURSOR</code>.
+ */
+public static final int WAIT_CURSOR = Cursor.WAIT_CURSOR;
+
+/**
+ * Cursor used over SW corner of window decorations.
+ * @deprecated Use <code>Cursor.SW_RESIZE_CURSOR</code> instead.
+ */
+public static final int SW_RESIZE_CURSOR = Cursor.SW_RESIZE_CURSOR;
+
+/**
+ * Cursor used over SE corner of window decorations.
+ * @deprecated Use <code>Cursor.SE_RESIZE_CURSOR</code> instead.
+ */
+public static final int SE_RESIZE_CURSOR = Cursor.SE_RESIZE_CURSOR;
+
+/**
+ * Cursor used over NW corner of window decorations.
+ * @deprecated Use <code>Cursor.NW_RESIZE_CURSOR</code> instead.
+ */
+public static final int NW_RESIZE_CURSOR = Cursor.NW_RESIZE_CURSOR;
+
+/**
+ * Cursor used over NE corner of window decorations.
+ * @deprecated Use <code>Cursor.NE_RESIZE_CURSOR</code> instead.
+ */
+public static final int NE_RESIZE_CURSOR = Cursor.NE_RESIZE_CURSOR;
+
+/**
+ * Cursor used over N edge of window decorations.
+ * @deprecated Use <code>Cursor.N_RESIZE_CURSOR</code> instead.
+ */
+public static final int N_RESIZE_CURSOR = Cursor.N_RESIZE_CURSOR;
+
+/**
+ * Cursor used over S edge of window decorations.
+ * @deprecated Use <code>Cursor.S_RESIZE_CURSOR</code> instead.
+ */
+public static final int S_RESIZE_CURSOR = Cursor.S_RESIZE_CURSOR;
+
+/**
+ * Cursor used over E edge of window decorations.
+ * @deprecated Use <code>Cursor.E_RESIZE_CURSOR</code> instead.
+ */
+public static final int E_RESIZE_CURSOR = Cursor.E_RESIZE_CURSOR;
+
+/**
+ * Cursor used over W edge of window decorations.
+ * @deprecated Use <code>Cursor.W_RESIZE_CURSOR</code> instead.
+ */
+public static final int W_RESIZE_CURSOR = Cursor.W_RESIZE_CURSOR;
+
+/**
+ * Constant for a hand cursor.
+ * @deprecated Use <code>Cursor.HAND_CURSOR</code> instead.
+ */
+public static final int HAND_CURSOR = Cursor.HAND_CURSOR;
+
+/**
+ * Constant for a cursor used during window move operations.
+ * @deprecated Use <code>Cursor.MOVE_CURSOR</code> instead.
+ */
+public static final int MOVE_CURSOR = Cursor.MOVE_CURSOR;
+
+public static final int ICONIFIED = 1;
+public static final int MAXIMIZED_BOTH = 6;
+public static final int MAXIMIZED_HORIZ = 2;
+public static final int MAXIMIZED_VERT = 4;
+public static final int NORMAL = 0;
+
+// Serialization version constant
+private static final long serialVersionUID = 2673458971256075116L;
+
+/**
+ * @serial The version of the class data being serialized
+ * // FIXME: what is this value?
+ */
+private int frameSerializedDataVersion;
+
+/**
+ * @serial Image used as the icon when this frame is minimized.
+ */
+private Image icon;
+
+/**
+ * @serial Constant used by the JDK Motif peer set. Not used in
+ * this implementation.
+ */
+private boolean mbManagement;
+
+/**
+ * @serial The menu bar for this frame.
+ */
+//private MenuBar menuBar = new MenuBar();
+private MenuBar menuBar;
+
+/**
+ * @serial A list of other top-level windows owned by this window.
+ */
+Vector ownedWindows = new Vector();
+
+/**
+ * @serial Indicates whether or not this frame is resizable.
+ */
+private boolean resizable = true;
+
+/**
+ * @serial The state of this frame.
+ * // FIXME: What are the values here?
+ * This is package-private to avoid an accessor method.
+ */
+int state;
+
+/**
+ * @serial The title of the frame.
+ */
+private String title = "";
+
+ /**
+ * Maximized bounds for this frame.
+ */
+ private Rectangle maximizedBounds;
+
+ /**
+ * This field indicates whether the frame is undecorated or not.
+ */
+ private boolean undecorated = false;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_frame_number;
+
+/**
+ * Initializes a new instance of <code>Frame</code> that is not visible
+ * and has no title.
+ */
+public
+Frame()
+{
+ this("");
+ noteFrame(this);
+}
+
+/**
+ * Initializes a new instance of <code>Frame</code> that is not visible
+ * and has the specified title.
+ *
+ * @param title The title of this frame.
+ */
+public
+Frame(String title)
+{
+ super();
+ this.title = title;
+ // Top-level frames are initially invisible.
+ visible = false;
+ noteFrame(this);
+}
+
+public
+Frame(GraphicsConfiguration gc)
+{
+ super(gc);
+ visible = false;
+ noteFrame(this);
+}
+
+public
+Frame(String title, GraphicsConfiguration gc)
+{
+ super(gc);
+ setTitle(title);
+ visible = false;
+ noteFrame(this);
+}
+
+/**
+ * Returns this frame's title string.
+ *
+ * @return This frame's title string.
+ */
+public String
+getTitle()
+{
+ return(title);
+}
+
+/*
+ * Sets this frame's title to the specified value.
+ *
+ * @param title The new frame title.
+ */
+public synchronized void
+setTitle(String title)
+{
+ this.title = title;
+ if (peer != null)
+ ((FramePeer) peer).setTitle(title);
+}
+
+/**
+ * Returns this frame's icon.
+ *
+ * @return This frame's icon, or <code>null</code> if this frame does not
+ * have an icon.
+ */
+public Image
+getIconImage()
+{
+ return(icon);
+}
+
+/**
+ * Sets this frame's icon to the specified value.
+ *
+ * @icon The new icon for this frame.
+ */
+public synchronized void
+setIconImage(Image icon)
+{
+ this.icon = icon;
+ if (peer != null)
+ ((FramePeer) peer).setIconImage(icon);
+}
+
+/**
+ * Returns this frame's menu bar.
+ *
+ * @return This frame's menu bar, or <code>null</code> if this frame
+ * does not have a menu bar.
+ */
+public MenuBar
+getMenuBar()
+{
+ return(menuBar);
+}
+
+/**
+ * Sets this frame's menu bar.
+ *
+ * @param menuBar The new menu bar for this frame.
+ */
+public synchronized void
+setMenuBar(MenuBar menuBar)
+{
+ if (peer != null)
+ {
+ if (this.menuBar != null)
+ this.menuBar.removeNotify();
+ if (menuBar != null)
+ menuBar.addNotify();
+ invalidateTree ();
+ ((FramePeer) peer).setMenuBar(menuBar);
+ }
+ this.menuBar = menuBar;
+}
+
+/**
+ * Tests whether or not this frame is resizable. This will be
+ * <code>true</code> by default.
+ *
+ * @return <code>true</code> if this frame is resizable, <code>false</code>
+ * otherwise.
+ */
+public boolean
+isResizable()
+{
+ return(resizable);
+}
+
+/**
+ * Sets the resizability of this frame to the specified value.
+ *
+ * @param resizable <code>true</code> to make the frame resizable,
+ * <code>false</code> to make it non-resizable.
+ */
+public synchronized void
+setResizable(boolean resizable)
+{
+ this.resizable = resizable;
+ if (peer != null)
+ ((FramePeer) peer).setResizable(resizable);
+}
+
+/**
+ * Returns the cursor type of the cursor for this window. This will
+ * be one of the constants in this class.
+ *
+ * @return The cursor type for this frame.
+ *
+ * @deprecated Use <code>Component.getCursor()</code> instead.
+ */
+public int
+getCursorType()
+{
+ return(getCursor().getType());
+}
+
+/**
+ * Sets the cursor for this window to the specified type. The specified
+ * type should be one of the constants in this class.
+ *
+ * @param type The cursor type.
+ *
+ * @deprecated Use <code>Component.setCursor(Cursor)</code> instead.
+ */
+public void
+setCursor(int type)
+{
+ setCursor(new Cursor(type));
+}
+
+/**
+ * Removes the specified component from this frame's menu.
+ *
+ * @param menu The menu component to remove.
+ */
+public void
+remove(MenuComponent menu)
+{
+ menuBar.remove(menu);
+}
+
+/**
+ * Notifies this frame that it should create its native peer.
+ */
+private static void fireDummyEvent()
+{
+ EventQueue.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ // Do nothing here.
+ }
+ });
+}
+
+public void
+addNotify()
+{
+ if (menuBar != null)
+ menuBar.addNotify();
+ if (peer == null)
+ peer = getToolkit ().createFrame (this);
+
+ // We now know there's a Frame (us) with a live peer, so we can start the
+ // fundamental queue and dispatch thread, by inserting a dummy event.
+ if (parent != null && parent.isDisplayable())
+ fireDummyEvent();
+
+ super.addNotify();
+}
+
+public void removeNotify()
+{
+ if (menuBar != null)
+ menuBar.removeNotify();
+ super.removeNotify();
+
+ // By now we've been disconnected from the peer, and the peer set to
+ // null. This is formally the same as saying "we just became
+ // un-displayable", so we wake up the event queue with a dummy event to
+ // see if it's time to shut down.
+ fireDummyEvent();
+}
+
+ /**
+ * Returns a debugging string describing this window.
+ *
+ * @return A debugging string describing this window.
+ */
+ protected String paramString ()
+ {
+ String title = getTitle ();
+
+ String resizable = "";
+ if (isResizable ())
+ resizable = ",resizable";
+
+ String state = "";
+ switch (getState ())
+ {
+ case NORMAL:
+ state = ",normal";
+ break;
+ case ICONIFIED:
+ state = ",iconified";
+ break;
+ case MAXIMIZED_BOTH:
+ state = ",maximized-both";
+ break;
+ case MAXIMIZED_HORIZ:
+ state = ",maximized-horiz";
+ break;
+ case MAXIMIZED_VERT:
+ state = ",maximized-vert";
+ break;
+ }
+
+ return super.paramString () + ",title=" + title + resizable + state;
+ }
+
+private static ArrayList weakFrames = new ArrayList();
+
+private static void noteFrame(Frame f)
+{
+ weakFrames.add(new WeakReference(f));
+}
+
+public static Frame[] getFrames()
+{
+ int n = 0;
+ synchronized (weakFrames)
+ {
+ Iterator i = weakFrames.iterator();
+ while (i.hasNext())
+ {
+ WeakReference wr = (WeakReference) i.next();
+ if (wr.get() != null)
+ ++n;
+ }
+ if (n == 0)
+ return new Frame[0];
+ else
+ {
+ Frame[] frames = new Frame[n];
+ n = 0;
+ i = weakFrames.iterator();
+ while (i.hasNext())
+ {
+ WeakReference wr = (WeakReference) i.next();
+ if (wr.get() != null)
+ frames[n++] = (Frame) wr.get();
+ }
+ return frames;
+ }
+ }
+}
+
+ public void setState (int state)
+ {
+ int current_state = getExtendedState ();
+
+ if (state == NORMAL
+ && (current_state & ICONIFIED) != 0)
+ setExtendedState (current_state | ICONIFIED);
+
+ if (state == ICONIFIED
+ && (current_state & ~ICONIFIED) == 0)
+ setExtendedState (current_state & ~ICONIFIED);
+ }
+
+ public int getState ()
+ {
+ /* FIXME: State might have changed in the peer... Must check. */
+
+ return (state & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void setExtendedState (int state)
+ {
+ this.state = state;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public int getExtendedState ()
+ {
+ return state;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void setMaximizedBounds (Rectangle maximizedBounds)
+ {
+ this.maximizedBounds = maximizedBounds;
+ }
+
+ /**
+ * Returns the maximized bounds of this frame.
+ *
+ * @return the maximized rectangle, may be null.
+ *
+ * @since 1.4
+ */
+ public Rectangle getMaximizedBounds ()
+ {
+ return maximizedBounds;
+ }
+
+ /**
+ * Returns whether this frame is undecorated or not.
+ *
+ * @since 1.4
+ */
+ public boolean isUndecorated ()
+ {
+ return undecorated;
+ }
+
+ /**
+ * Disables or enables decorations for this frame. This method can only be
+ * called while the frame is not displayable.
+ *
+ * @exception IllegalComponentStateException If this frame is displayable.
+ *
+ * @since 1.4
+ */
+ public void setUndecorated (boolean undecorated)
+ {
+ if (isDisplayable ())
+ throw new IllegalComponentStateException ();
+
+ this.undecorated = undecorated;
+ }
+
+ /**
+ * Generate a unique name for this frame.
+ *
+ * @return A unique name for this frame.
+ */
+ String generateName ()
+ {
+ return "frame" + getUniqueLong ();
+ }
+
+ private static synchronized long getUniqueLong ()
+ {
+ return next_frame_number++;
+ }
+
+ protected class AccessibleAWTFrame extends AccessibleAWTWindow
+ {
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.FRAME;
+ }
+
+ public AccessibleStateSet getAccessibleState()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (isResizable())
+ states.add(AccessibleState.RESIZABLE);
+ if ((state & ICONIFIED) != 0)
+ states.add(AccessibleState.ICONIFIED);
+ return states;
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Frame</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTFrame();
+ return accessibleContext;
+ }
+
+}
diff --git a/libjava/classpath/java/awt/GradientPaint.java b/libjava/classpath/java/awt/GradientPaint.java
new file mode 100644
index 00000000000..74067f49e86
--- /dev/null
+++ b/libjava/classpath/java/awt/GradientPaint.java
@@ -0,0 +1,229 @@
+/* GradientPaint.java --
+ Copyright (C) 2002, 2005, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+import gnu.java.awt.GradientPaintContext;
+
+/**
+ * A paint object that can be used to color a region by blending two colors.
+ * Instances of this class are immutable.
+ */
+public class GradientPaint implements Paint
+{
+ private final float x1;
+ private final float y1;
+ private final Color c1;
+ private final float x2;
+ private final float y2;
+ private final Color c2;
+ private final boolean cyclic;
+
+ /**
+ * Creates a new acyclic <code>GradientPaint</code>.
+ *
+ * @param x1 the x-coordinate of the anchor point for color 1.
+ * @param y1 the y-coordinate of the anchor point for color 1.
+ * @param c1 color 1 (<code>null</code> not permitted).
+ * @param x2 the x-coordinate of the anchor point for color 2.
+ * @param y2 the y-coordinate of the anchor point for color 2.
+ * @param c2 the second color (<code>null</code> not permitted).
+ */
+ public GradientPaint(float x1, float y1, Color c1,
+ float x2, float y2, Color c2)
+ {
+ this(x1, y1, c1, x2, y2, c2, false);
+ }
+
+ /**
+ * Creates a new acyclic <code>GradientPaint</code>.
+ *
+ * @param p1 anchor point 1 (<code>null</code> not permitted).
+ * @param c1 color 1 (<code>null</code> not permitted).
+ * @param p2 anchor point 2 (<code>null</code> not permitted).
+ * @param c2 color 2 (<code>null</code> not permitted).
+ */
+ public GradientPaint(Point2D p1, Color c1, Point2D p2, Color c2)
+ {
+ this((float) p1.getX(), (float) p1.getY(), c1,
+ (float) p2.getX(), (float) p2.getY(), c2, false);
+ }
+
+ /**
+ * Creates a new cyclic or acyclic <code>GradientPaint</code>.
+ *
+ * @param x1 the x-coordinate of the anchor point for color 1.
+ * @param y1 the y-coordinate of the anchor point for color 1.
+ * @param c1 color 1 (<code>null</code> not permitted).
+ * @param x2 the x-coordinate of the anchor point for color 2.
+ * @param y2 the y-coordinate of the anchor point for color 2.
+ * @param c2 the second color (<code>null</code> not permitted).
+ * @param cyclic a flag that controls whether the gradient is cyclic or
+ * acyclic.
+ */
+ public GradientPaint(float x1, float y1, Color c1,
+ float x2, float y2, Color c2, boolean cyclic)
+ {
+ if (c1 == null || c2 == null)
+ throw new NullPointerException();
+ this.x1 = x1;
+ this.y1 = y1;
+ this.c1 = c1;
+ this.x2 = x2;
+ this.y2 = y2;
+ this.c2 = c2;
+ this.cyclic = cyclic;
+ }
+
+ /**
+ * Creates a new cyclic or acyclic <code>GradientPaint</code>.
+ *
+ * @param p1 anchor point 1 (<code>null</code> not permitted).
+ * @param c1 color 1 (<code>null</code> not permitted).
+ * @param p2 anchor point 2 (<code>null</code> not permitted).
+ * @param c2 color 2 (<code>null</code> not permitted).
+ * @param cyclic a flag that controls whether the gradient is cyclic or
+ * acyclic.
+ */
+ public GradientPaint(Point2D p1, Color c1, Point2D p2, Color c2,
+ boolean cyclic)
+ {
+ this((float) p1.getX(), (float) p1.getY(), c1,
+ (float) p2.getX(), (float) p2.getY(), c2, cyclic);
+ }
+
+ /**
+ * Returns a point with the same coordinates as the anchor point for color 1.
+ * Note that if you modify this point, the <code>GradientPaint</code> remains
+ * unchanged.
+ *
+ * @return A point with the same coordinates as the anchor point for color 1.
+ */
+ public Point2D getPoint1()
+ {
+ return new Point2D.Float(x1, y1);
+ }
+
+ /**
+ * Returns the first color.
+ *
+ * @return The color (never <code>null</code>).
+ */
+ public Color getColor1()
+ {
+ return c1;
+ }
+
+ /**
+ * Returns a point with the same coordinates as the anchor point for color 2.
+ * Note that if you modify this point, the <code>GradientPaint</code> remains
+ * unchanged.
+ *
+ * @return A point with the same coordinates as the anchor point for color 2.
+ */
+ public Point2D getPoint2()
+ {
+ return new Point2D.Float(x2, y2);
+ }
+
+ /**
+ * Returns the second color.
+ *
+ * @return The color (never <code>null</code>).
+ */
+ public Color getColor2()
+ {
+ return c2;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>GradientPaint</code> instance is
+ * cyclic, and <code>false</code> otherwise.
+ *
+ * @return A boolean.
+ */
+ public boolean isCyclic()
+ {
+ return cyclic;
+ }
+
+ /**
+ * Returns the {@link PaintContext} used to generate the color pattern.
+ *
+ * @param cm the color model, used as a hint (ignored in this
+ * implementation).
+ * @param deviceBounds the device space bounding box of the painted area.
+ * @param userBounds the user space bounding box of the painted area.
+ * @param xform the transformation from user space to device space.
+ * @param hints any hints for choosing between rendering alternatives.
+ *
+ * @return The context for performing the paint
+ */
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds,
+ AffineTransform xform,
+ RenderingHints hints)
+ {
+ Point2D xp1 = xform.transform(getPoint1(), null);
+ Point2D xp2 = xform.transform(getPoint2(), null);
+ return new GradientPaintContext((float) xp1.getX(), (float) xp1.getY(), c1,
+ (float) xp2.getX(), (float) xp2.getY(), c2, cyclic);
+ }
+
+ /**
+ * Returns the transparency code for this <code>GradientPaint</code> instance.
+ * This is derived from the two {@link Color} objects used in creating this
+ * object: if both colors are opaque, this method returns
+ * {@link Transparency#OPAQUE}, otherwise it returns
+ * {@link Transparency#TRANSLUCENT}.
+ *
+ * @return {@link Transparency#OPAQUE} or {@link Transparency#TRANSLUCENT}.
+ */
+ public int getTransparency()
+ {
+ if (c1.getAlpha() == 255 && c2.getAlpha() == 255)
+ return Transparency.OPAQUE;
+ else
+ return Transparency.TRANSLUCENT;
+ }
+
+} // class GradientPaint
diff --git a/libjava/classpath/java/awt/Graphics.java b/libjava/classpath/java/awt/Graphics.java
new file mode 100644
index 00000000000..ff26190e5f0
--- /dev/null
+++ b/libjava/classpath/java/awt/Graphics.java
@@ -0,0 +1,767 @@
+/* Graphics.java -- Abstract Java drawing class
+ Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ImageObserver;
+import java.text.AttributedCharacterIterator;
+
+/**
+ * This is the abstract superclass of classes for drawing to graphics
+ * devices such as the screen or printers.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public abstract class Graphics
+{
+
+/*
+ * Instance Variables
+ */
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Default constructor for subclasses.
+ */
+protected
+Graphics()
+{
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns a copy of this <code>Graphics</code> object.
+ *
+ * @return A copy of this object.
+ */
+public abstract Graphics
+create();
+
+/*************************************************************************/
+
+/**
+ * Returns a copy of this <code>Graphics</code> object. The origin point
+ * will be translated to the point (x, y) and the cliping rectangle set
+ * to the intersection of the clipping rectangle in this object and the
+ * rectangle specified by the parameters to this method.
+ *
+ * @param x The new X coordinate of the clipping region rect.
+ * @param y The new Y coordinate of the clipping region rect.
+ * @param width The width of the clipping region intersect rectangle.
+ * @param height The height of the clipping region intersect rectangle.
+ *
+ * @return A copy of this object, modified as specified.
+ */
+public Graphics
+create(int x, int y, int width, int height)
+{
+ Graphics g = create();
+
+ g.translate(x, y);
+ // FIXME: I'm not sure if this will work. Are the old clip rect bounds
+ // translated above?
+ g.clipRect(0, 0, width, height);
+
+ return(g);
+}
+
+/*************************************************************************/
+
+/**
+ * Translates this context so that its new origin point is the point
+ * (x, y).
+ *
+ * @param x The new X coordinate of the origin.
+ * @param y The new Y coordinate of the origin.
+ */
+public abstract void
+translate(int x, int y);
+
+/*************************************************************************/
+
+/**
+ * Returns the current color for this object.
+ *
+ * @return The color for this object.
+ */
+public abstract Color
+getColor();
+
+/*************************************************************************/
+
+/**
+ * Sets the current color for this object.
+ *
+ * @param color The new color.
+ */
+public abstract void
+setColor(Color color);
+
+/*************************************************************************/
+
+/**
+ * Sets this context into "paint" mode, where the target pixels are
+ * completely overwritten when drawn on.
+ */
+public abstract void
+setPaintMode();
+
+/*************************************************************************/
+
+/**
+ * Sets this context info "XOR" mode, where the targe pixles are
+ * XOR-ed when drawn on.
+ *
+ * @param color The color to XOR against.
+ */
+public abstract void
+setXORMode(Color color);
+
+/*************************************************************************/
+
+/**
+ * Returns the current font for this graphics context.
+ *
+ * @return The current font.
+ */
+public abstract Font
+getFont();
+
+/*************************************************************************/
+
+/**
+ * Sets the font for this graphics context to the specified value.
+ *
+ * @param font The new font.
+ */
+public abstract void
+setFont(Font font);
+
+/*************************************************************************/
+
+/**
+ * Returns the font metrics for the current font.
+ *
+ * @return The font metrics for the current font.
+ */
+public FontMetrics
+getFontMetrics()
+{
+ return(getFontMetrics(getFont()));
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the font metrics for the specified font.
+ *
+ * @param font The font to return metrics for.
+ *
+ * @return The requested font metrics.
+ */
+public abstract FontMetrics
+getFontMetrics(Font font);
+
+/*************************************************************************/
+
+/**
+ * Returns the bounding rectangle of the clipping region for this
+ * graphics context.
+ *
+ * @return The bounding rectangle for the clipping region.
+ */
+public abstract Rectangle
+getClipBounds();
+
+/*************************************************************************/
+
+/**
+ * Returns the bounding rectangle of the clipping region for this
+ * graphics context.
+ *
+ * @return The bounding rectangle for the clipping region.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getClipBounds()</code>.
+ */
+public Rectangle
+getClipRect()
+{
+ return(getClipBounds());
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the clipping region to the intersection of the current clipping
+ * region and the rectangle determined by the specified parameters.
+ *
+ * @param x The X coordinate of the upper left corner of the intersect rect.
+ * @param y The Y coordinate of the upper left corner of the intersect rect.
+ * @param width The width of the intersect rect.
+ * @param height The height of the intersect rect.
+ */
+public abstract void
+clipRect(int x, int y, int width, int height);
+
+/*************************************************************************/
+
+/**
+ * Sets the clipping region to the rectangle determined by the specified
+ * parameters.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ */
+public abstract void
+setClip(int x, int y, int width, int height);
+
+/*************************************************************************/
+
+/**
+ * Returns the current clipping region as a <code>Shape</code> object.
+ *
+ * @return The clipping region as a <code>Shape</code>.
+ */
+public abstract Shape
+getClip();
+
+/*************************************************************************/
+
+/**
+ * Sets the clipping region to the specified <code>Shape</code>.
+ *
+ * @param clip The new clipping region.
+ */
+public abstract void
+setClip(Shape clip);
+
+/*************************************************************************/
+
+/**
+ * Copies the specified rectangle to the specified offset location.
+ *
+ * @param x The X coordinate of the upper left corner of the copy rect.
+ * @param y The Y coordinate of the upper left corner of the copy rect.
+ * @param width The width of the copy rect.
+ * @param height The height of the copy rect.
+ * @param dx The offset from the X value to start drawing.
+ * @param dy The offset from the Y value to start drawing.
+ */
+public abstract void
+copyArea(int x, int y, int width, int height, int dx, int dy);
+
+/*************************************************************************/
+
+/**
+ * Draws a line between the two specified points.
+ *
+ * @param x1 The X coordinate of the first point.
+ * @param y1 The Y coordinate of the first point.
+ * @param x2 The X coordinate of the second point.
+ * @param y2 The Y coordinate of the second point.
+ */
+public abstract void
+drawLine(int x1, int y1, int x2, int y2);
+
+/*************************************************************************/
+
+/**
+ * Fills the area bounded by the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the fill rect.
+ * @param y The Y coordinate of the upper left corner of the fill rect.
+ * @param width The width of the fill rect.
+ * @param height The height of the fill rect.
+ */
+public abstract void
+fillRect(int x, int y, int width, int height);
+
+/*************************************************************************/
+
+/**
+ * Draws the outline of the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the draw rect.
+ * @param y The Y coordinate of the upper left corner of the draw rect.
+ * @param width The width of the draw rect.
+ * @param height The height of the draw rect.
+ */
+public void
+drawRect(int x, int y, int width, int height)
+{
+ int x1 = x;
+ int y1 = y;
+ int x2 = x + width;
+ int y2 = y + height;
+ drawLine(x1, y1, x2, y1);
+ drawLine(x2, y1, x2, y2);
+ drawLine(x2, y2, x1, y2);
+ drawLine(x1, y2, x1, y1);
+}
+
+/*************************************************************************/
+
+/**
+ * Clears the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the clear rect.
+ * @param y The Y coordinate of the upper left corner of the clear rect.
+ * @param width The width of the clear rect.
+ * @param height The height of the clear rect.
+ */
+public abstract void
+clearRect(int x, int y, int width, int height);
+
+/*************************************************************************/
+
+/**
+ * Draws the outline of the specified rectangle with rounded cornders.
+ *
+ * @param x The X coordinate of the upper left corner of the draw rect.
+ * @param y The Y coordinate of the upper left corner of the draw rect.
+ * @param width The width of the draw rect.
+ * @param height The height of the draw rect.
+ * @param arcWidth The width of the corner arcs.
+ * @param arcHeight The height of the corner arcs.
+ */
+public abstract void
+drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight);
+
+/*************************************************************************/
+
+/**
+ * Fills the specified rectangle with rounded cornders.
+ *
+ * @param x The X coordinate of the upper left corner of the fill rect.
+ * @param y The Y coordinate of the upper left corner of the fill rect.
+ * @param width The width of the fill rect.
+ * @param height The height of the fill rect.
+ * @param arcWidth The width of the corner arcs.
+ * @param arcHeight The height of the corner arcs.
+ */
+public abstract void
+fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight);
+
+/*************************************************************************/
+
+public void
+draw3DRect(int x, int y, int width, int height, boolean raised)
+{
+ Color color = getColor();
+ Color tl = color.brighter();
+ Color br = color.darker();
+
+ if (!raised)
+ {
+ Color tmp = tl;
+ tl = br;
+ br = tmp;
+ }
+
+ int x1 = x;
+ int y1 = y;
+ int x2 = x + width;
+ int y2 = y + height;
+
+ setColor(tl);
+ drawLine(x1, y1, x2, y1);
+ drawLine(x1, y2, x1, y1);
+ setColor(br);
+ drawLine(x2, y1, x2, y2);
+ drawLine(x2, y2, x1, y2);
+ setColor(color);
+}
+
+/**
+ * Fills the specified rectangle with a 3D effect
+ *
+ * @param x The X coordinate of the upper left corner of the fill rect.
+ * @param y The Y coordinate of the upper left corner of the fill rect.
+ * @param width The width of the fill rect.
+ * @param height The height of the fill rect.
+ * @param raised <code>true</code> if the rectangle appears raised,
+ * <code>false</code> if it should appear etched.
+ */
+public void
+fill3DRect(int x, int y, int width, int height, boolean raised)
+{
+ fillRect(x, y, width, height);
+ draw3DRect(x, y, width-1, height-1, raised);
+}
+
+/*************************************************************************/
+
+/**
+ * Draws an oval that just fits within the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ */
+public abstract void
+drawOval(int x, int y, int width, int height);
+
+/*************************************************************************/
+
+/**
+ * Fills an oval that just fits within the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ */
+public abstract void
+fillOval(int x, int y, int width, int height);
+
+/*************************************************************************/
+
+/**
+ * Draws an arc using the specified bounding rectangle and the specified
+ * angle parameter. The arc is centered at the center of the rectangle.
+ * The arc starts at the arcAngle position and extend for arcAngle
+ * degrees. The degree origin is at the 3 o'clock position.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ * @param arcStart The beginning angle of the arc.
+ * @param arcAngle The extent of the arc.
+ */
+public abstract void
+drawArc(int x, int y, int width, int height, int arcStart, int arcAngle);
+
+/*************************************************************************/
+
+/**
+ * Fills the arc define by the specified bounding rectangle and the specified
+ * angle parameter. The arc is centered at the center of the rectangle.
+ * The arc starts at the arcAngle position and extend for arcAngle
+ * degrees. The degree origin is at the 3 o'clock position.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ * @param arcStart The beginning angle of the arc.
+ * @param arcAngle The extent of the arc.
+ */
+public abstract void
+fillArc(int x, int y, int width, int height, int arcStart, int arcAngle);
+
+/*************************************************************************/
+
+/**
+ * Draws a series of interconnected lines determined by the arrays
+ * of corresponding x and y coordinates.
+ *
+ * @param xPoints The X coordinate array.
+ * @param yPoints The Y coordinate array.
+ * @param npoints The number of points to draw.
+ */
+public abstract void
+drawPolyline(int xPoints[], int yPoints[], int npoints);
+
+/*************************************************************************/
+
+/**
+ * Draws a series of interconnected lines determined by the arrays
+ * of corresponding x and y coordinates. The figure is closed if necessary
+ * by connecting the first and last points.
+ *
+ * @param xPoints The X coordinate array.
+ * @param yPoints The Y coordinate array.
+ * @param npoints The number of points to draw.
+ */
+public abstract void
+drawPolygon(int xPoints[], int yPoints[], int npoints);
+
+/*************************************************************************/
+
+/**
+ * Draws the specified polygon.
+ *
+ * @param polygon The polygon to draw.
+ */
+public void
+drawPolygon(Polygon polygon)
+{
+ drawPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints);
+}
+
+/*************************************************************************/
+
+/**
+ * Fills the polygon determined by the arrays
+ * of corresponding x and y coordinates.
+ *
+ * @param xPoints The X coordinate array.
+ * @param yPoints The Y coordinate array.
+ * @param npoints The number of points to draw.
+ */
+public abstract void
+fillPolygon(int xPoints[], int yPoints[], int npoints);
+
+/*************************************************************************/
+
+/**
+ * Fills the specified polygon
+ *
+ * @param polygon The polygon to fill.
+ */
+public void
+fillPolygon(Polygon polygon)
+{
+ fillPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints);
+}
+
+/*************************************************************************/
+
+/**
+ * Draws the specified string starting at the specified point.
+ *
+ * @param string The string to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ */
+public abstract void
+drawString(String string, int x, int y);
+
+public abstract void drawString (AttributedCharacterIterator ci, int x, int y);
+
+/*************************************************************************/
+
+/**
+ * Draws the specified characters starting at the specified point.
+ *
+ * @param data The array of characters to draw.
+ * @param offset The offset into the array to start drawing characters from.
+ * @param length The number of characters to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ */
+public void
+drawChars(char data[], int offset, int length, int x, int y)
+{
+ drawString(new String(data, offset, length), x, y);
+}
+
+public void
+drawBytes(byte[] data, int offset, int length, int x, int y)
+{
+ String str = new String(data, offset, length);
+ drawString(str, x, y);
+}
+
+/*************************************************************************/
+
+/**
+ * Draws all of the image that is available and returns. If the image
+ * is not completely loaded, <code>false</code> is returned and
+ * the specified iamge observer is notified as more data becomes
+ * available.
+ *
+ * @param image The image to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ * @param observer The image observer to notify as data becomes available.
+ *
+ * @return <code>true</code> if all the image data is available,
+ * <code>false</code> otherwise.
+ */
+public abstract boolean
+drawImage(Image image, int x, int y, ImageObserver observer);
+
+/*************************************************************************/
+
+/**
+ * Draws all of the image that is available and returns. The image
+ * is scaled to fit in the specified rectangle. If the image
+ * is not completely loaded, <code>false</code> is returned and
+ * the specified iamge observer is notified as more data becomes
+ * available.
+ *
+ * @param image The image to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ * @param width The width of the rectangle to draw in.
+ * @param height The height of the rectangle to draw in.
+ * @param observer The image observer to notify as data becomes available.
+ *
+ * @return <code>true</code> if all the image data is available,
+ * <code>false</code> otherwise.
+ */
+public abstract boolean
+drawImage(Image image, int x, int y, int width, int height,
+ ImageObserver observer);
+
+/*************************************************************************/
+
+/**
+ * Draws all of the image that is available and returns. If the image
+ * is not completely loaded, <code>false</code> is returned and
+ * the specified iamge observer is notified as more data becomes
+ * available.
+ *
+ * @param image The image to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ * @param bgcolor The background color to use for the image.
+ * @param observer The image observer to notify as data becomes available.
+ *
+ * @return <code>true</code> if all the image data is available,
+ * <code>false</code> otherwise.
+ */
+public abstract boolean
+drawImage(Image image, int x, int y, Color bgcolor, ImageObserver observer);
+
+/*************************************************************************/
+
+/**
+ * Draws all of the image that is available and returns. The image
+ * is scaled to fit in the specified rectangle. If the image
+ * is not completely loaded, <code>false</code> is returned and
+ * the specified iamge observer is notified as more data becomes
+ * available.
+ *
+ * @param image The image to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ * @param width The width of the rectangle to draw in.
+ * @param height The height of the rectangle to draw in.
+ * @param bgcolor The background color to use for the image.
+ * @param observer The image observer to notify as data becomes available.
+ *
+ * @return <code>true</code> if all the image data is available,
+ * <code>false</code> otherwise.
+ */
+public abstract boolean
+drawImage(Image image, int x, int y, int width, int height, Color bgcolor,
+ ImageObserver observer);
+
+/*************************************************************************/
+
+/**
+ * FIXME: Write Javadocs for this when you understand it.
+ */
+public abstract boolean
+drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
+ int sx2, int sy2, ImageObserver observer);
+
+/*************************************************************************/
+
+/**
+ * FIXME: Write Javadocs for this when you understand it.
+ */
+public abstract boolean
+drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
+ int sx2, int sy2, Color bgcolor, ImageObserver observer);
+
+/*************************************************************************/
+
+/**
+ * Free any resources held by this graphics context immediately instead
+ * of waiting for the object to be garbage collected and finalized.
+ */
+public abstract void
+dispose();
+
+/*************************************************************************/
+
+/**
+ * Frees the resources held by this graphics context when it is
+ * garbage collected.
+ */
+public void
+finalize()
+{
+ dispose();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this object.
+ *
+ * @return A string representation of this object.
+ */
+public String
+toString()
+{
+ return getClass ().getName () + "[font=" + getFont () + ",color=" + getColor () + "]";
+}
+
+public boolean
+hitClip(int x, int y, int width, int height)
+{
+ throw new UnsupportedOperationException("not implemented yet");
+}
+
+public Rectangle
+getClipBounds(Rectangle r)
+{
+ Rectangle clipBounds = getClipBounds();
+
+ if (r == null)
+ return clipBounds;
+
+ r.x = clipBounds.x;
+ r.y = clipBounds.y;
+ r.width = clipBounds.width;
+ r.height = clipBounds.height;
+ return r;
+}
+
+} // class Graphics
+
diff --git a/libjava/classpath/java/awt/Graphics2D.java b/libjava/classpath/java/awt/Graphics2D.java
new file mode 100644
index 00000000000..3faa9dc0c66
--- /dev/null
+++ b/libjava/classpath/java/awt/Graphics2D.java
@@ -0,0 +1,158 @@
+/* Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+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;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public abstract class Graphics2D extends Graphics
+{
+
+ protected Graphics2D()
+ {
+ }
+
+ public void draw3DRect(int x, int y, int width, int height,
+ boolean raised)
+ {
+ super.draw3DRect(x, y, width, height, raised);
+ }
+
+ public void fill3DRect(int x, int y, int width, int height,
+ boolean raised)
+ {
+ super.fill3DRect(x, y, width, height, raised);
+ }
+
+ public abstract void draw(Shape shape);
+
+ public abstract boolean drawImage(Image image, AffineTransform xform,
+ ImageObserver obs);
+
+ public abstract void drawImage(BufferedImage image,
+ BufferedImageOp op,
+ int x,
+ int y);
+
+ public abstract void drawRenderedImage(RenderedImage image,
+ AffineTransform xform);
+
+ public abstract void drawRenderableImage(RenderableImage image,
+ AffineTransform xform);
+
+ public abstract void drawString(String text, int x, int y);
+
+ public abstract void drawString(String text, float x, float y);
+
+ public abstract void drawString(AttributedCharacterIterator iterator,
+ int x, int y);
+
+ public abstract void drawString(AttributedCharacterIterator iterator,
+ float x, float y);
+
+ // public abstract void drawGlyphVector(GlyphVector g, float x, float y);
+
+ public abstract void fill(Shape shape);
+
+ public abstract boolean hit(Rectangle rect, Shape text,
+ boolean onStroke);
+
+ public abstract GraphicsConfiguration getDeviceConfiguration();
+
+ public abstract void setComposite(Composite comp);
+
+ public abstract void setPaint(Paint paint);
+
+ public abstract void setStroke(Stroke stroke);
+
+ public abstract void setRenderingHint(RenderingHints.Key hintKey,
+ Object hintValue);
+
+ public abstract Object getRenderingHint(RenderingHints.Key hintKey);
+
+ public abstract void setRenderingHints(Map hints);
+
+ public abstract void addRenderingHints(Map hints);
+
+ public abstract RenderingHints getRenderingHints();
+
+ public abstract void translate(int x, int y);
+
+ public abstract void translate(double tx, double ty);
+
+ public abstract void rotate(double theta);
+
+ public abstract void rotate(double theta, double x, double y);
+
+ public abstract void scale(double scaleX, double scaleY);
+
+ public abstract void shear(double shearX, double shearY);
+
+ public abstract void transform(AffineTransform Tx);
+
+ public abstract void setTransform(AffineTransform Tx);
+
+ public abstract AffineTransform getTransform();
+
+ public abstract Paint getPaint();
+
+ public abstract Composite getComposite();
+
+ public abstract void setBackground(Color color);
+
+ public abstract Color getBackground();
+
+ public abstract Stroke getStroke();
+
+ public abstract void clip(Shape s);
+
+ public abstract FontRenderContext getFontRenderContext ();
+
+ public abstract void drawGlyphVector (GlyphVector g, float x, float y);
+}
diff --git a/libjava/classpath/java/awt/GraphicsConfigTemplate.java b/libjava/classpath/java/awt/GraphicsConfigTemplate.java
new file mode 100644
index 00000000000..e46888378fe
--- /dev/null
+++ b/libjava/classpath/java/awt/GraphicsConfigTemplate.java
@@ -0,0 +1,106 @@
+/* GraphicsConfigTemplate.java -- a template for selecting configurations
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * This allows filtering an array of GraphicsConfigurations for the best
+ * one based on various requirements. The resulting configuration has had
+ * all non-default attributes set as required to meet or exceed the request.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see GraphicsConfiguration
+ * @see GraphicsDevice
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class GraphicsConfigTemplate implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -8061369279557787079L;
+
+ /** States that a feature is required to select a configuration. */
+ public static final int REQUIRED = 1;
+
+ /**
+ * States that a feature is preferred, but not required, to select a
+ * configuration. In the case of multiple valid configurations, the tie
+ * breaks in favor of the one with the feature.
+ */
+ public static final int PREFERRED = 2;
+
+ /**
+ * States that a feature is not necessary in the configuration. In the case
+ * of multiple valid configurations, the tie breaks in favor of the one
+ * without the feature, to reduce overhead.
+ */
+ public static final int UNNECESSARY = 3;
+
+ /**
+ * The default constructor.
+ */
+ public GraphicsConfigTemplate()
+ {
+ }
+
+ /**
+ * Returns the "best" match among the array of possible configurations, given
+ * the criteria of this template.
+ *
+ * @param array the array to choose from
+ * @return the best match
+ * @throws NullPointerException if array is null
+ */
+ public abstract GraphicsConfiguration getBestConfiguration
+ (GraphicsConfiguration[] array);
+
+ /**
+ * Returns true if the given configuration supports all the features required
+ * by this template.
+ *
+ * @param config the configuration to test
+ * @return true if it is a match
+ * @throws NullPointerException if config is null
+ */
+ public abstract boolean isGraphicsConfigSupported
+ (GraphicsConfiguration config);
+} // class GraphicsConfigTemplate
diff --git a/libjava/classpath/java/awt/GraphicsConfiguration.java b/libjava/classpath/java/awt/GraphicsConfiguration.java
new file mode 100644
index 00000000000..6dc27793d43
--- /dev/null
+++ b/libjava/classpath/java/awt/GraphicsConfiguration.java
@@ -0,0 +1,218 @@
+/* GraphicsConfiguration.java -- describes characteristics of graphics
+ Copyright (C) 2000, 2001, 2002 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 java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.VolatileImage;
+
+/**
+ * This class describes the configuration of various graphics devices, such
+ * as a monitor or printer. Different configurations may exist for the same
+ * device, according to the different native modes supported.
+ *
+ * <p>Virtual devices are supported (for example, in a multiple screen
+ * environment, a virtual device covers all screens simultaneously); the
+ * configuration will have a non-zero relative coordinate system in such
+ * a case.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Window
+ * @see Frame
+ * @see GraphicsEnvironment
+ * @see GraphicsDevice
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class GraphicsConfiguration
+{
+ /**
+ * The default constructor.
+ *
+ * @see GraphicsDevice#getConfigurations()
+ * @see GraphicsDevice#getDefaultConfiguration()
+ * @see GraphicsDevice#getBestConfiguration(GraphicsConfigTemplate)
+ * @see Graphics2D#getDeviceConfiguration()
+ */
+ protected GraphicsConfiguration ()
+ {
+ }
+
+ /**
+ * Gets the associated device that this configuration describes.
+ *
+ * @return the device
+ */
+ public abstract GraphicsDevice getDevice();
+
+ /**
+ * Returns a buffered image optimized to this device, so that blitting can
+ * be supported in the buffered image.
+ *
+ * @param w the width of the buffer
+ * @param h the height of the buffer
+ * @return the buffered image, or null if none is supported
+ */
+ public abstract BufferedImage createCompatibleImage(int w, int h);
+
+ /**
+ * Returns a buffered volatile image optimized to this device, so that
+ * blitting can be supported in the buffered image. Because the buffer is
+ * volatile, it can be optimized by native graphics accelerators.
+ *
+ * @param w the width of the buffer
+ * @param h the height of the buffer
+ * @return the buffered image, or null if none is supported
+ * @see Component#createVolatileImage(int, int)
+ * @since 1.4
+ */
+ public abstract VolatileImage createCompatibleVolatileImage(int w, int h);
+
+ /**
+ * Returns a buffered volatile image optimized to this device, and with the
+ * given capabilities, so that blitting can be supported in the buffered
+ * image. Because the buffer is volatile, it can be optimized by native
+ * graphics accelerators.
+ *
+ * @param w the width of the buffer
+ * @param h the height of the buffer
+ * @param caps the desired capabilities of the image buffer
+ * @return the buffered image, or null if none is supported
+ * @throws AWTException if the capabilities cannot be met
+ * @since 1.4
+ */
+ public VolatileImage createCompatibleVolatileImage(int w, int h,
+ ImageCapabilities caps)
+ throws AWTException
+ {
+ throw new AWTException("not implemented");
+ }
+
+ /**
+ * Returns a buffered image optimized to this device, and with the specified
+ * transparency, so that blitting can be supported in the buffered image.
+ *
+ * @param w the width of the buffer
+ * @param h the height of the buffer
+ * @param transparency the transparency of the buffer
+ * @return the buffered image, or null if none is supported
+ * @see Transparency#OPAQUE
+ * @see Transparency#BITMASK
+ * @see Transparency#TRANSLUCENT
+ */
+ public abstract BufferedImage createCompatibleImage(int w, int h,
+ int transparency);
+
+ /**
+ * Gets the color model of the corresponding device.
+ *
+ * @return the color model
+ */
+ public abstract ColorModel getColorModel();
+
+ /**
+ * Gets a color model for the corresponding device which supports the desired
+ * transparency level.
+ *
+ * @param transparency the transparency of the model
+ * @return the color model, with transparency
+ * @see Transparency#OPAQUE
+ * @see Transparency#BITMASK
+ * @see Transparency#TRANSLUCENT
+ */
+ public abstract ColorModel getColorModel(int transparency);
+
+ /**
+ * Returns a transform that maps user coordinates to device coordinates. The
+ * preferred mapping is about 72 user units to 1 inch (2.54 cm) of physical
+ * space. This is often the identity transform. The device coordinates have
+ * the origin at the upper left, with increasing x to the right, and
+ * increasing y to the bottom.
+ *
+ * @return the transformation from user space to device space
+ * @see #getNormalizingTransform()
+ */
+ public abstract AffineTransform getDefaultTransform();
+
+ /**
+ * Returns a transform that maps user coordinates to device coordinates. The
+ * exact mapping is 72 user units to 1 inch (2.54 cm) of physical space.
+ * This is often the identity transform. The device coordinates have the
+ * origin at the upper left, with increasing x to the right, and increasing
+ * y to the bottom. Note that this is more accurate (and thus, sometimes more
+ * costly) than the default transform.
+ *
+ * @return the normalized transformation from user space to device space
+ * @see #getDefaultTransform()
+ */
+ public abstract AffineTransform getNormalizingTransform();
+
+ /**
+ * Returns the bounds of the configuration, in device coordinates. If this
+ * is a virtual device (for example, encompassing several screens), the
+ * bounds may have a non-zero origin.
+ *
+ * @return the device bounds
+ * @since 1.3
+ */
+ public abstract Rectangle getBounds();
+
+ /**
+ * Returns the buffering capabilities of this configuration.
+ *
+ * @return the buffer capabilities
+ * @since 1.4
+ */
+ public BufferCapabilities getBufferCapabilities()
+ {
+ throw new Error("not implemented");
+ }
+
+ /**
+ * Returns the imaging capabilities of this configuration.
+ *
+ * @return the image capabilities
+ * @since 1.4
+ */
+ public ImageCapabilities getImageCapabilities()
+ {
+ throw new Error("not implemented");
+ }
+} // class GraphicsConfiguration
diff --git a/libjava/classpath/java/awt/GraphicsDevice.java b/libjava/classpath/java/awt/GraphicsDevice.java
new file mode 100644
index 00000000000..95487a2a1cc
--- /dev/null
+++ b/libjava/classpath/java/awt/GraphicsDevice.java
@@ -0,0 +1,292 @@
+/* GraphicsDevice.java -- information about a graphics device
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.VolatileImage;
+
+/**
+ * This describes a graphics device available to the given environment. This
+ * includes screen and printer devices, and the different configurations for
+ * each device. Also, this allows you to create virtual devices which operate
+ * over a multi-screen environment.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see GraphicsEnvironment
+ * @see GraphicsConfiguration
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public abstract class GraphicsDevice
+{
+ /** Device is a raster screen. */
+ public static final int TYPE_RASTER_SCREEN = 0;
+
+ /** Device is a printer. */
+ public static final int TYPE_PRINTER = 1;
+
+ /** Device is an image buffer not visible to the user. */
+ public static final int TYPE_IMAGE_BUFFER = 2;
+
+ /** The current full-screen window, or null if there is none. */
+ private Window full_screen;
+
+ /**
+ * The bounds of the fullscreen window before it has been switched to full
+ * screen.
+ */
+ private Rectangle fullScreenOldBounds;
+
+ /** The current display mode, or null if unknown. */
+ private DisplayMode mode;
+
+ /**
+ * The default constructor.
+ *
+ * @see GraphicsEnvironment#getScreenDevices()
+ * @see GraphicsEnvironment#getDefaultScreenDevice()
+ * @see GraphicsConfiguration#getDevice()
+ */
+ protected GraphicsDevice()
+ {
+ }
+
+ /**
+ * Returns the type of the device.
+ *
+ * @return the device type
+ * @see #TYPE_RASTER_SCREEN
+ * @see #TYPE_PRINTER
+ * @see #TYPE_IMAGE_BUFFER
+ */
+ public abstract int getType();
+
+ /**
+ * Returns an identification string for the device. This can be
+ * vendor-specific, and may be useful for debugging.
+ *
+ * @return the identification
+ */
+ public abstract String getIDstring();
+
+ /**
+ * Return all configurations valid for this device.
+ *
+ * @return an array of configurations
+ */
+ public abstract GraphicsConfiguration[] getConfigurations();
+
+ /**
+ * Return the default configuration for this device.
+ *
+ * @return the default configuration
+ */
+ public abstract GraphicsConfiguration getDefaultConfiguration();
+
+ /**
+ * Return the best configuration, according to the criteria in the given
+ * template.
+ *
+ * @param template the template to adjust by
+ * @return the best configuration
+ * @throws NullPointerException if template is null
+ */
+ public GraphicsConfiguration getBestConfiguration
+ (GraphicsConfigTemplate template)
+ {
+ return template.getBestConfiguration(getConfigurations());
+ }
+
+ /**
+ * Returns true if the device supports full-screen exclusive mode. The
+ * default implementation returns true; subclass it if this is not the case.
+ *
+ * @return true if full screen support is available
+ * @since 1.4
+ */
+ public boolean isFullScreenSupported()
+ {
+ return true;
+ }
+
+ /**
+ * Toggle the given window between full screen and normal mode. The previous
+ * full-screen window, if different, is restored; if the given window is
+ * null, no window will be full screen. If
+ * <code>isFullScreenSupported()</code> returns true, full screen mode is
+ * considered to be exclusive, which implies:<ul>
+ * <li>Windows cannot overlap the full-screen window. All other application
+ * windows will always appear beneath the full-screen window in the
+ * Z-order.</li>
+ * <li>Input method windows are disabled. It is advisable to call
+ * <code>Component.enableInputMethods(false)</code> to make a component
+ * a non-client of the input method framework.</li>
+ * </ul><br>
+ * If <code>isFullScreenSupported()</code> returns false, full-screen
+ * exclusive mode is simulated by resizing the window to the size of the
+ * screen and positioning it at (0,0). This is also what this method does.
+ * If a device supports real fullscreen mode then it should override this
+ * method as well as #isFullScreenSupported and #getFullScreenWindow.
+ *
+ * @param w the window to toggle
+ * @see #isFullScreenSupported()
+ * @see #getFullScreenWindow()
+ * @see #setDisplayMode(DisplayMode)
+ * @see Component#enableInputMethods(boolean)
+ * @since 1.4
+ */
+ public synchronized void setFullScreenWindow(Window w)
+ {
+ // Restore the previous window to normal mode and release the reference.
+ if (full_screen != null)
+ {
+ full_screen.setBounds(fullScreenOldBounds);
+ }
+
+ full_screen = null;
+
+ // If w != null, make it full-screen.
+ if (w != null)
+ {
+ fullScreenOldBounds = w.getBounds();
+ full_screen = w;
+ DisplayMode dMode = getDisplayMode();
+ full_screen.setBounds(0, 0, dMode.getWidth(), dMode.getHeight());
+ full_screen.requestFocus();
+ full_screen.setLocationRelativeTo(null);
+ }
+ }
+
+ /**
+ * Returns the current full-screen window of the device, or null if no
+ * window is full-screen.
+ *
+ * @return the full-screen window
+ * @see #setFullScreenWindow(Window)
+ * @since 1.4
+ */
+ public Window getFullScreenWindow()
+ {
+ return full_screen;
+ }
+
+ /**
+ * Returns whether this device supports low-level display changes. This may
+ * depend on whether full-screen exclusive mode is available.
+ *
+ * XXX The default implementation returns false for now.
+ *
+ * @return true if display changes are supported
+ * @see #setDisplayMode(DisplayMode)
+ * @since 1.4
+ */
+ public boolean isDisplayChangeSupported()
+ {
+ return false;
+ }
+
+ /**
+ * Sets the display mode. This may be dependent on the availability of
+ * full-screen exclusive mode.
+ *
+ * @param mode the new mode
+ * @throws IllegalArgumentException if the new mode is not in getDisplayModes
+ * @throws UnsupportedOperationException if ! isDisplayChangeSupported()
+ * @see #getDisplayMode()
+ * @see #getDisplayModes()
+ * @see #isDisplayChangeSupported()
+ * @since 1.4
+ */
+ public void setDisplayMode(DisplayMode mode)
+ {
+ DisplayMode[] array = getDisplayModes();
+ if (! isDisplayChangeSupported())
+ throw new UnsupportedOperationException();
+ int i = array == null ? 0 : array.length;
+ while (--i >= 0)
+ if (array[i].equals(mode))
+ break;
+ if (i < 0)
+ throw new IllegalArgumentException();
+ this.mode = mode;
+ }
+
+ /**
+ * Returns the current display mode of this device, or null if unknown.
+ *
+ * @return the current display mode
+ * @see #setDisplayMode(DisplayMode)
+ * @see #getDisplayModes()
+ * @since 1.4
+ */
+ public DisplayMode getDisplayMode()
+ {
+ return mode;
+ }
+
+ /**
+ * Return an array of all available display modes. This implementation
+ * returns a 0-length array, so subclasses must override this.
+ *
+ * @return the array of available modes
+ * @since 1.4
+ */
+ public DisplayMode[] getDisplayModes()
+ {
+ return new DisplayMode[0];
+ }
+
+ /**
+ * Return the number of bytes available in accelerated memory on this
+ * device. The device may support creation or caching on a first-come,
+ * first-served basis, depending on the operating system and driver.
+ * Memory may be a finite resource, and because of multi-threading, you
+ * are not guaranteed that the result of this method ensures your image
+ * will successfully be put in accelerated memory. A negative result means
+ * the memory is unlimited. The default implementation assumes no special
+ * memory is available, and returns 0.
+ *
+ * @return the size of accelerated memory available
+ * @see VolatileImage#flush()
+ * @see ImageCapabilities#isAccelerated()
+ */
+ public int getAvailableAcceleratedMemory()
+ {
+ return 0;
+ }
+} // class GraphicsDevice
diff --git a/libjava/classpath/java/awt/GraphicsEnvironment.java b/libjava/classpath/java/awt/GraphicsEnvironment.java
new file mode 100644
index 00000000000..a82e7a357de
--- /dev/null
+++ b/libjava/classpath/java/awt/GraphicsEnvironment.java
@@ -0,0 +1,244 @@
+/* GraphicsEnvironment.java -- information about the graphics environment
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.classpath.SystemProperties;
+import java.awt.image.BufferedImage;
+import java.util.Locale;
+
+/**
+ * This descibes the collection of GraphicsDevice and Font objects available
+ * on a given platform. The resources might be local or remote, and specify
+ * the valid configurations for displaying graphics.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see GraphicsDevice
+ * @see GraphicsConfiguration
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class GraphicsEnvironment
+{
+ private static GraphicsEnvironment localGraphicsEnvironment;
+
+ /**
+ * The environment must be obtained from a factory or query method, hence
+ * this constructor is protected.
+ */
+ protected GraphicsEnvironment()
+ {
+ }
+
+ /**
+ * Returns the local graphics environment. If the java.awt.graphicsenv
+ * system property is set, it instantiates the specified class,
+ * otherwise it assume that the awt toolkit is a ClasspathToolkit
+ * and delegates to it to create the instance.
+ *
+ * @return the local environment
+ */
+ public static GraphicsEnvironment getLocalGraphicsEnvironment()
+ {
+ if (localGraphicsEnvironment != null)
+ return localGraphicsEnvironment;
+
+ String graphicsenv = SystemProperties.getProperty("java.awt.graphicsenv",
+ null);
+ if (graphicsenv != null)
+ {
+ try
+ {
+ // We intentionally use the bootstrap class loader.
+ localGraphicsEnvironment = (GraphicsEnvironment)
+ Class.forName(graphicsenv).newInstance();
+ return localGraphicsEnvironment;
+ }
+ catch (Exception x)
+ {
+ throw (InternalError)
+ new InternalError("Unable to instantiate java.awt.graphicsenv")
+ .initCause(x);
+ }
+ }
+ else
+ {
+ ClasspathToolkit tk;
+ tk = ((ClasspathToolkit) Toolkit.getDefaultToolkit());
+ localGraphicsEnvironment = tk.getLocalGraphicsEnvironment();
+ return localGraphicsEnvironment;
+ }
+ }
+
+ /**
+ * Check if the local environment is headless, meaning that it does not
+ * support a display, keyboard, or mouse. Many methods in the Abstract
+ * Windows Toolkit (java.awt) throw a {@link HeadlessException} if this
+ * returns true.
+ *
+ * This method returns true if the java.awt.headless property is set
+ * to "true".
+ *
+ * @return true if the environment is headless, meaning that graphics are
+ * unsupported
+ * @since 1.4
+ */
+ public static boolean isHeadless()
+ {
+ String headless = SystemProperties.getProperty("java.awt.headless", null);
+ return "true".equalsIgnoreCase(headless);
+ }
+
+ /**
+ * Check if the given environment is headless, meaning that it does not
+ * support a display, keyboard, or mouse. Many methods in the Abstract
+ * Windows Toolkit (java.awt) throw a {@link HeadlessException} if this
+ * returns true. This default implementation returns isHeadless(), so
+ * subclasses need only override it if they differ.
+ *
+ * @return true if the environment is headless, meaning that graphics are
+ * unsupported
+ * @since 1.4
+ */
+ public boolean isHeadlessInstance()
+ {
+ return isHeadless();
+ }
+
+ /**
+ * Get an array of all the GraphicsDevice objects.
+ *
+ * @return the available graphics devices, may be 0 length
+ * @throws HeadlessException if the environment is headless
+ */
+ public abstract GraphicsDevice[] getScreenDevices();
+
+ /**
+ * Get the default screen GraphicsDevice object.
+ *
+ * @return the default screen device
+ * @throws HeadlessException if the environment is headless
+ */
+ public abstract GraphicsDevice getDefaultScreenDevice();
+
+ /**
+ * Return a Graphics2D object which will render into the specified image.
+ *
+ * @param image the image to render into
+ * @return the object that renders into the image
+ */
+ public abstract Graphics2D createGraphics(BufferedImage image);
+
+ /**
+ * Returns an array of the one-point size fonts available in this
+ * environment. From there, the user can select the font and derive the
+ * correct one of proper size and attributes, using <code>deriveFont</code>.
+ * Only one master version of each font appears in this array; if a font
+ * can be derived from another, it must be created in that way.
+ *
+ * @return the array of available fonts
+ * @see #getAvailableFontFamilyNames()
+ * @see Font#deriveFont(int, float)
+ * @since 1.2
+ */
+ public abstract Font[] getAllFonts();
+
+ /**
+ * Returns an array of the font family names available in this environment.
+ * This allows flexibility in choosing the style of font, while still letting
+ * the Font class decide its best match.
+ *
+ * @return the array of available font families
+ * @see #getAllFonts()
+ * @see Font#getFamily()
+ * @since 1.2
+ */
+ public abstract String[] getAvailableFontFamilyNames();
+
+ /**
+ * Returns an array of the font family names available in this environment,
+ * localized to the current Locale if l is non-null. This allows
+ * flexibility in choosing the style of font, while still letting the Font
+ * class decide its best match.
+ *
+ * @param l the locale to use
+ * @return the array of available font families, localized
+ * @see #getAllFonts()
+ * @see Font#getFamily()
+ * @since 1.2
+ */
+ public abstract String[] getAvailableFontFamilyNames(Locale l);
+
+ /**
+ * Returns the point where a window should be centered. You should probably
+ * also check that the window fits within the screen bounds. The default
+ * simply returns the center of the maximum window bounds; subclasses should
+ * override this if native objects (like scrollbars) make that off-centered.
+ *
+ * @return the centering point
+ * @throws HeadlessException if the environment is headless
+ * @see #getMaximumWindowBounds()
+ * @since 1.4
+ */
+ public Point getCenterPoint()
+ {
+ Rectangle r = getMaximumWindowBounds();
+ return new Point(r.x + r.width / 2, r.y + r.height / 2);
+ }
+
+ /**
+ * Returns the maximum bounds for a centered window object. The default
+ * implementation simply returns the bounds of the default configuration
+ * of the default screen; subclasses should override this to if native
+ * objects (like scrollbars) reduce what is truly available. Also,
+ * subclasses should override this if the window should be centered across
+ * a multi-screen display.
+ *
+ * @return the maximum window bounds
+ * @throws HeadlessException if the environment is headless
+ * @see #getCenterPoint()
+ * @see GraphicsConfiguration#getBounds()
+ * @see Toolkit#getScreenInsets(GraphicsConfiguration)
+ * @since 1.4
+ */
+ public Rectangle getMaximumWindowBounds()
+ {
+ return getDefaultScreenDevice().getDefaultConfiguration().getBounds();
+ }
+} // class GraphicsEnvironment
diff --git a/libjava/classpath/java/awt/GridBagConstraints.java b/libjava/classpath/java/awt/GridBagConstraints.java
new file mode 100644
index 00000000000..8d8b4fae534
--- /dev/null
+++ b/libjava/classpath/java/awt/GridBagConstraints.java
@@ -0,0 +1,195 @@
+/* GridBagConstraints.java -- Constraints for GridBag layout manager
+ Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * This specifies the constraints for a component managed by the
+ * GridBagLayout layout manager.
+ */
+public class GridBagConstraints implements Cloneable, Serializable
+{
+ static final long serialVersionUID = -1000070633030801713L;
+
+ /** Fill in both directions. */
+ public static final int BOTH = 1;
+ /** Don't fill. */
+ public static final int NONE = 0;
+ /** Fill horizontally. */
+ public static final int HORIZONTAL = 2;
+ /** Fill vertically. */
+ public static final int VERTICAL = 3;
+
+ /** Position in the center. */
+ public static final int CENTER = 10;
+ /** Position to the east. */
+ public static final int EAST = 13;
+ /** Position to the north. */
+ public static final int NORTH = 11;
+ /** Position to the northeast. */
+ public static final int NORTHEAST = 12;
+ /** Position to the northwest. */
+ public static final int NORTHWEST = 18;
+ /** Position to the south. */
+ public static final int SOUTH = 15;
+ /** Position to the southeast. */
+ public static final int SOUTHEAST = 14;
+ /** Position to the southwest. */
+ public static final int SOUTHWEST = 16;
+ /** Position to the west. */
+ public static final int WEST = 17;
+
+ /** Occupy all remaining cells except last cell. */
+ public static final int RELATIVE = -1;
+ /** Occupy all remaining cells. */
+ public static final int REMAINDER = 0;
+
+ /**
+ * Position to where the first text line would end. Equals to NORTHEAST for
+ * horizontal left-to-right orientations.
+ */
+ public static final int FIRST_LINE_END = 24;
+
+ /**
+ * Position to where the first text line would start. Equals to NORTHWEST for
+ * horizontal left-to-right orientations.
+ */
+ public static final int FIRST_LINE_START = 23;
+
+ /**
+ * Position to where the last text line would end. Equals to SOUTHEAST for
+ * horizontal left-to-right orientations.
+ */
+ public static final int LAST_LINE_END = 26;
+
+ /**
+ * Position to where the last text line would start. Equals to SOUTHWEST for
+ * horizontal left-to-right orientations.
+ */
+ public static final int LAST_LINE_START = 25;
+
+ /**
+ * Position to where a text line would end. Equals to EAST for
+ * left-to-right orientations.
+ */
+ public static final int LINE_END = 22;
+
+ /**
+ * Position to where a text line would start. Equals to WEST for
+ * left-to-right orientations.
+ */
+ public static final int LINE_START = 21;
+
+ /**
+ * Position to where a page ends. Equals SOUTH for horizontal orientations.
+ */
+ public static final int PAGE_END = 20;
+
+ /**
+ * Position to where a page starts. Equals NORTH for horizontal orientations.
+ */
+ public static final int PAGE_START = 19;
+
+ public int anchor;
+ public int fill;
+ public int gridheight;
+ public int gridwidth;
+ public int gridx;
+ public int gridy;
+ public Insets insets;
+ public int ipadx;
+ public int ipady;
+ public double weightx;
+ public double weighty;
+
+ /** Create a copy of this object. */
+ public Object clone ()
+ {
+ try
+ {
+ GridBagConstraints g = (GridBagConstraints) super.clone ();
+ g.insets = (Insets) insets.clone ();
+ return g;
+ }
+ catch (CloneNotSupportedException _)
+ {
+ // Can't happen.
+ return null;
+ }
+ }
+
+ /** Create a new GridBagConstraints object with the default
+ * parameters. */
+ public GridBagConstraints ()
+ {
+ this.anchor = CENTER;
+ this.fill = NONE;
+ this.gridx = RELATIVE;
+ this.gridy = RELATIVE;
+ this.gridwidth = 1;
+ this.gridheight = 1;
+ this.ipadx = 0;
+ this.ipady = 0;
+ this.insets = new Insets (0, 0, 0, 0);
+ this.weightx = 0;
+ this.weighty = 0;
+ }
+
+ /** Create a new GridBagConstraints object with the indicated
+ * parameters. */
+ public GridBagConstraints (int gridx, int gridy,
+ int gridwidth, int gridheight,
+ double weightx, double weighty,
+ int anchor, int fill,
+ Insets insets, int ipadx, int ipady)
+ {
+ this.anchor = anchor;
+ this.fill = fill;
+ this.gridx = gridx;
+ this.gridy = gridy;
+ this.gridwidth = gridwidth;
+ this.gridheight = gridheight;
+ this.ipadx = ipadx;
+ this.ipady = ipady;
+ this.insets = insets;
+ this.weightx = weightx;
+ this.weighty = weighty;
+ }
+}
diff --git a/libjava/classpath/java/awt/GridBagLayout.java b/libjava/classpath/java/awt/GridBagLayout.java
new file mode 100644
index 00000000000..767610c5693
--- /dev/null
+++ b/libjava/classpath/java/awt/GridBagLayout.java
@@ -0,0 +1,1069 @@
+/* GridBagLayout - Layout manager for components according to GridBagConstraints
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ */
+public class GridBagLayout
+ implements Serializable, LayoutManager2
+{
+ private static final long serialVersionUID = 8838754796412211005L;
+
+ protected static final int MINSIZE = 1;
+ protected static final int PREFERREDSIZE = 2;
+ protected static final int MAXGRIDSIZE = 512;
+
+ // comptable remembers the original contraints given to us.
+ // internalcomptable is used to keep track of modified constraint values
+ // that we calculate, particularly when we are given RELATIVE and
+ // REMAINDER constraints.
+ // Constraints kept in comptable are never modified, and constraints
+ // kept in internalcomptable can be modified internally only.
+ protected Hashtable comptable;
+ private Hashtable internalcomptable;
+ protected GridBagLayoutInfo layoutInfo;
+ protected GridBagConstraints defaultConstraints;
+
+ public double[] columnWeights;
+ public int[] columnWidths;
+ public double[] rowWeights;
+ public int[] rowHeights;
+
+ public GridBagLayout ()
+ {
+ this.comptable = new Hashtable();
+ this.internalcomptable = new Hashtable();
+ this.defaultConstraints= new GridBagConstraints();
+ }
+
+ /**
+ * Helper method to calc the sum of a range of elements in an int array.
+ */
+ private int sumIntArray (int[] array, int upto)
+ {
+ int result = 0;
+
+ for (int i = 0; i < upto; i++)
+ result += array [i];
+
+ return result;
+ }
+
+ /**
+ * Helper method to calc the sum of all elements in an int array.
+ */
+ private int sumIntArray (int[] array)
+ {
+ return sumIntArray(array, array.length);
+ }
+
+ /**
+ * Helper method to calc the sum of all elements in an double array.
+ */
+ private double sumDoubleArray (double[] array)
+ {
+ double result = 0;
+
+ for (int i = 0; i < array.length; i++)
+ result += array [i];
+
+ return result;
+ }
+
+ public void addLayoutComponent (String name, Component component)
+ {
+ // do nothing here.
+ }
+
+ public void removeLayoutComponent (Component component)
+ {
+ // do nothing here
+ }
+
+ public void addLayoutComponent (Component component, Object constraints)
+ {
+ if (constraints == null)
+ return;
+
+ if (!(constraints instanceof GridBagConstraints))
+ throw new IllegalArgumentException("constraints "
+ + constraints
+ + " are not an instance of GridBagConstraints");
+
+ setConstraints (component, (GridBagConstraints) constraints);
+ }
+
+ public Dimension preferredLayoutSize (Container parent)
+ {
+ if (parent == null)
+ return new Dimension (0, 0);
+
+ GridBagLayoutInfo li = getLayoutInfo (parent, PREFERREDSIZE);
+ return getMinSize (parent, li);
+ }
+
+ public Dimension minimumLayoutSize (Container parent)
+ {
+ if (parent == null)
+ return new Dimension (0, 0);
+
+ GridBagLayoutInfo li = getLayoutInfo (parent, MINSIZE);
+ return getMinSize (parent, li);
+ }
+
+ public Dimension maximumLayoutSize (Container target)
+ {
+ return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ public void layoutContainer (Container parent)
+ {
+ arrangeGrid (parent);
+ }
+
+ public float getLayoutAlignmentX (Container target)
+ {
+ return Component.CENTER_ALIGNMENT;
+ }
+
+ public float getLayoutAlignmentY (Container target)
+ {
+ return Component.CENTER_ALIGNMENT;
+ }
+
+ public void invalidateLayout (Container target)
+ {
+ this.layoutInfo = null;
+ }
+
+ public void setConstraints (Component component,
+ GridBagConstraints constraints)
+ {
+ GridBagConstraints clone = (GridBagConstraints) constraints.clone();
+
+ if (clone.gridx < 0)
+ clone.gridx = GridBagConstraints.RELATIVE;
+
+ if (clone.gridy < 0)
+ clone.gridy = GridBagConstraints.RELATIVE;
+
+ if (clone.gridwidth == 0)
+ clone.gridwidth = GridBagConstraints.REMAINDER;
+ else if (clone.gridwidth < 0
+ && clone.gridwidth != GridBagConstraints.REMAINDER
+ && clone.gridwidth != GridBagConstraints.RELATIVE)
+ clone.gridwidth = 1;
+
+ if (clone.gridheight == 0)
+ clone.gridheight = GridBagConstraints.REMAINDER;
+ else if (clone.gridheight < 0
+ && clone.gridheight != GridBagConstraints.REMAINDER
+ && clone.gridheight != GridBagConstraints.RELATIVE)
+ clone.gridheight = 1;
+
+ comptable.put (component, clone);
+ }
+
+ public GridBagConstraints getConstraints (Component component)
+ {
+ return (GridBagConstraints) (lookupConstraints (component).clone());
+ }
+
+ protected GridBagConstraints lookupConstraints (Component component)
+ {
+ GridBagConstraints result = (GridBagConstraints) comptable.get (component);
+
+ if (result == null)
+ {
+ setConstraints (component, defaultConstraints);
+ result = (GridBagConstraints) comptable.get (component);
+ }
+
+ return result;
+ }
+
+ private GridBagConstraints lookupInternalConstraints (Component component)
+ {
+ GridBagConstraints result =
+ (GridBagConstraints) internalcomptable.get (component);
+
+ if (result == null)
+ {
+ result = (GridBagConstraints) lookupConstraints(component).clone();
+ internalcomptable.put (component, result);
+ }
+
+ return result;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public Point getLayoutOrigin ()
+ {
+ if (layoutInfo == null)
+ return new Point (0, 0);
+
+ return new Point (layoutInfo.pos_x, layoutInfo.pos_y);
+ }
+
+ /**
+ * @since 1.1
+ */
+ public int[][] getLayoutDimensions ()
+ {
+ int[][] result = new int [2][];
+ if (layoutInfo == null)
+ {
+ result[0] = new int[0];
+ result[1] = new int[0];
+
+ return result;
+ }
+
+ result [0] = new int [layoutInfo.cols];
+ System.arraycopy (layoutInfo.colWidths, 0, result [0], 0, layoutInfo.cols);
+ result [1] = new int [layoutInfo.rows];
+ System.arraycopy (layoutInfo.rowHeights, 0, result [1], 0, layoutInfo.rows);
+ return result;
+ }
+
+ public double[][] getLayoutWeights ()
+ {
+ double[][] result = new double [2][];
+ if (layoutInfo == null)
+ {
+ result[0] = new double[0];
+ result[1] = new double[0];
+
+ return result;
+ }
+
+ result [0] = new double [layoutInfo.cols];
+ System.arraycopy (layoutInfo.colWeights, 0, result [0], 0, layoutInfo.cols);
+ result [1] = new double [layoutInfo.rows];
+ System.arraycopy (layoutInfo.rowWeights, 0, result [1], 0, layoutInfo.rows);
+ return result;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public Point location (int x, int y)
+ {
+ if (layoutInfo == null)
+ return new Point (0, 0);
+
+ int col;
+ int row;
+ int pixel_x = layoutInfo.pos_x;
+ int pixel_y = layoutInfo.pos_y;
+
+ for (col = 0; col < layoutInfo.cols; col++)
+ {
+ int w = layoutInfo.colWidths [col];
+ if (x < pixel_x + w)
+ break;
+
+ pixel_x += w;
+ }
+
+ for (row = 0; row < layoutInfo.rows; row++)
+ {
+ int h = layoutInfo.rowHeights [row];
+ if (y < pixel_y + h)
+ break;
+
+ pixel_y += h;
+ }
+
+ return new Point (col, row);
+ }
+
+ /**
+ * Obsolete.
+ */
+ protected void AdjustForGravity (GridBagConstraints gbc, Rectangle rect)
+ {
+ // FIXME
+ throw new Error ("Not implemented");
+ }
+
+ /**
+ * Obsolete.
+ */
+ protected void ArrangeGrid (Container parent)
+ {
+ Component[] components = parent.getComponents();
+
+ if (components.length == 0)
+ return;
+
+ GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE);
+ if (info.cols == 0 && info.rows == 0)
+ return;
+ layoutInfo = info;
+
+ // DEBUG
+ //dumpLayoutInfo (layoutInfo);
+
+ for(int i = 0; i < components.length; i++)
+ {
+ Component component = components [i];
+
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ GridBagConstraints constraints =
+ lookupInternalConstraints(component);
+
+ int cellx = sumIntArray(layoutInfo.colWidths, constraints.gridx);
+ int celly = sumIntArray(layoutInfo.rowHeights, constraints.gridy);
+ int cellw = sumIntArray(layoutInfo.colWidths,
+ constraints.gridx + constraints.gridwidth) - cellx;
+ int cellh = sumIntArray(layoutInfo.rowHeights,
+ constraints.gridy + constraints.gridheight) - celly;
+
+ Insets insets = constraints.insets;
+ if (insets != null)
+ {
+ cellx += insets.left;
+ celly += insets.top;
+ cellw -= insets.left + insets.right;
+ cellh -= insets.top + insets.bottom;
+ }
+
+ Dimension dim = component.getPreferredSize();
+
+ // Note: Documentation says that padding is added on both sides, but
+ // visual inspection shows that the Sun implementation only adds it
+ // once, so we do the same.
+ dim.width += constraints.ipadx;
+ dim.height += constraints.ipady;
+
+ switch(constraints.fill)
+ {
+ case GridBagConstraints.HORIZONTAL:
+ dim.width = cellw;
+ break;
+ case GridBagConstraints.VERTICAL:
+ dim.height = cellh;
+ break;
+ case GridBagConstraints.BOTH:
+ dim.width = cellw;
+ dim.height = cellh;
+ break;
+ }
+
+ int x;
+ int y;
+
+ switch(constraints.anchor)
+ {
+ case GridBagConstraints.NORTH:
+ x = cellx + (cellw - dim.width) / 2;
+ y = celly;
+ break;
+ case GridBagConstraints.SOUTH:
+ x = cellx + (cellw - dim.width) / 2;
+ y = celly + cellh - dim.height;
+ break;
+ case GridBagConstraints.WEST:
+ x = cellx;
+ y = celly + (cellh - dim.height) / 2;
+ break;
+ case GridBagConstraints.EAST:
+ x = cellx + cellw - dim.width;
+ y = celly + (cellh - dim.height) / 2;
+ break;
+ case GridBagConstraints.NORTHEAST:
+ x = cellx + cellw - dim.width;
+ y = celly;
+ break;
+ case GridBagConstraints.NORTHWEST:
+ x = cellx;
+ y = celly;
+ break;
+ case GridBagConstraints.SOUTHEAST:
+ x = cellx + cellw - dim.width;
+ y = celly + cellh - dim.height;
+ break;
+ case GridBagConstraints.SOUTHWEST:
+ x = cellx;
+ y = celly + cellh - dim.height;
+ break;
+ default:
+ x = cellx + (cellw - dim.width) / 2;
+ y = celly + (cellh - dim.height) / 2;
+ break;
+ }
+
+ component.setBounds(layoutInfo.pos_x + x, layoutInfo.pos_y + y, dim.width, dim.height);
+ }
+
+ // DEBUG
+ //dumpLayoutInfo (layoutInfo);
+ }
+
+ /**
+ * Obsolete.
+ */
+ protected GridBagLayoutInfo GetLayoutInfo (Container parent, int sizeflag)
+ {
+ if (sizeflag != MINSIZE && sizeflag != PREFERREDSIZE)
+ throw new IllegalArgumentException();
+
+ Dimension parentDim = parent.getSize ();
+ Insets parentInsets = parent.getInsets ();
+ parentDim.width -= parentInsets.left + parentInsets.right;
+ parentDim.height -= parentInsets.top + parentInsets.bottom;
+
+ int current_y = 0;
+ int max_x = 0;
+ int max_y = 0;
+
+ // Guaranteed to contain the last component added to the given row
+ // or column, whose gridwidth/height is not REMAINDER.
+ HashMap lastInRow = new HashMap();
+ HashMap lastInCol = new HashMap();
+
+ Component[] components = parent.getComponents();
+
+ // Components sorted by gridwidths/heights,
+ // smallest to largest, with REMAINDER and RELATIVE at the end.
+ // These are useful when determining sizes and weights.
+ ArrayList sortedByWidth = new ArrayList(components.length);
+ ArrayList sortedByHeight = new ArrayList(components.length);
+
+ // STEP 1: first we figure out how many rows/columns
+ for (int i = 0; i < components.length; i++)
+ {
+ Component component = components [i];
+
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ // When looking up the constraint for the first time, check the
+ // original unmodified constraint. After the first time, always
+ // refer to the internal modified constraint.
+ GridBagConstraints originalConstraints = lookupConstraints (component);
+ GridBagConstraints constraints = (GridBagConstraints) originalConstraints.clone();
+ internalcomptable.put(component, constraints);
+
+ // Cases:
+ //
+ // 1. gridy == RELATIVE, gridx == RELATIVE
+ //
+ // use y as the row number; check for the next
+ // available slot at row y
+ //
+ // 2. only gridx == RELATIVE
+ //
+ // check for the next available slot at row gridy
+ //
+ // 3. only gridy == RELATIVE
+ //
+ // check for the next available slot at column gridx
+ //
+ // 4. neither gridx or gridy == RELATIVE
+ //
+ // nothing to check; just add it
+
+
+ // cases 1 and 2
+ if(constraints.gridx == GridBagConstraints.RELATIVE)
+ {
+ if (constraints.gridy == GridBagConstraints.RELATIVE)
+ constraints.gridy = current_y;
+
+ int x;
+
+ // Check the component that occupies the right-most spot in this
+ // row. We want to add this component after it.
+ // If this row is empty, add to the 0 position.
+ if (!lastInRow.containsKey(new Integer(constraints.gridy)))
+ x = 0;
+ else
+ {
+ Component lastComponent = (Component) lastInRow.get(new Integer(constraints.gridy));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ x = lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth);
+ }
+
+ // Determine if this component will fit in the slot vertically.
+ // If not, bump it over to where it does fit.
+ for (int y = constraints.gridy + 1; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+ {
+ if (lastInRow.containsKey(new Integer(y)))
+ {
+ Component lastComponent = (Component) lastInRow.get(new Integer(y));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ x = Math.max (x,
+ lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth));
+ }
+ }
+
+ constraints.gridx = x;
+ }
+ // case 3
+ else if(constraints.gridy == GridBagConstraints.RELATIVE)
+ {
+ int y;
+ // Check the component that occupies the bottom-most spot in
+ // this column. We want to add this component below it.
+ // If this column is empty, add to the 0 position.
+ if (!lastInCol.containsKey(new Integer(constraints.gridx)))
+ y = 0;
+ else
+ {
+ Component lastComponent = (Component)lastInCol.get(new Integer(constraints.gridx));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ y = lastConstraints.gridy + Math.max(1, lastConstraints.gridheight);
+ }
+
+ // Determine if this component will fit in the slot horizontally.
+ // If not, bump it down to where it does fit.
+ for (int x = constraints.gridx + 1; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+ {
+ if (lastInCol.containsKey(new Integer(x)))
+ {
+ Component lastComponent = (Component) lastInCol.get(new Integer(x));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ y = Math.max (y,
+ lastConstraints.gridy + Math.max(1, lastConstraints.gridheight));
+ }
+ }
+
+ constraints.gridy = y;
+ }
+ // case 4: do nothing
+
+ max_x = Math.max(max_x,
+ constraints.gridx + Math.max(1, constraints.gridwidth));
+ max_y = Math.max(max_y,
+ constraints.gridy + Math.max(1, constraints.gridheight));
+
+ sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
+ sortBySpan(component, constraints.gridheight, sortedByHeight, false);
+
+ // Update our reference points for RELATIVE gridx and gridy.
+ if(constraints.gridwidth == GridBagConstraints.REMAINDER)
+ {
+ current_y = constraints.gridy + Math.max(1, constraints.gridheight);
+ }
+ else if (constraints.gridwidth != GridBagConstraints.REMAINDER)
+ {
+ for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+ {
+ if(lastInRow.containsKey(new Integer(y)))
+ {
+ Component lastComponent = (Component) lastInRow.get(new Integer(y));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ if (constraints.gridx > lastConstraints.gridx)
+ {
+ lastInRow.put(new Integer(y), component);
+ }
+ }
+ else
+ {
+ lastInRow.put(new Integer(y), component);
+ }
+ }
+
+ for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+ {
+ if(lastInCol.containsKey(new Integer(x)))
+ {
+ Component lastComponent = (Component) lastInCol.get(new Integer(x));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ if (constraints.gridy > lastConstraints.gridy)
+ {
+ lastInCol.put(new Integer(x), component);
+ }
+ }
+ else
+ {
+ lastInCol.put(new Integer(x), component);
+ }
+ }
+ }
+ } // end of STEP 1
+
+ GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y);
+
+ // Check if column widths and row heights are overridden.
+
+ for (int x = 0; x < max_x; x++)
+ {
+ if(columnWidths != null && columnWidths.length > x)
+ info.colWidths[x] = columnWidths[x];
+ if(columnWeights != null && columnWeights.length > x)
+ info.colWeights[x] = columnWeights[x];
+ }
+
+ for (int y = 0; y < max_y; y++)
+ {
+ if(rowHeights != null && rowHeights.length > y)
+ info.rowHeights[y] = rowHeights[y];
+ if(rowWeights != null && rowWeights.length > y)
+ info.rowWeights[y] = rowWeights[y];
+ }
+
+ // STEP 2: Fix up any cells with width/height as REMAINDER/RELATIVE.
+ for (int i = 0; i < components.length; i++)
+ {
+ Component component = components [i];
+
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ GridBagConstraints constraints = lookupInternalConstraints (component);
+
+ if(constraints.gridwidth == GridBagConstraints.REMAINDER || constraints.gridwidth == GridBagConstraints.RELATIVE)
+ {
+ if(constraints.gridwidth == GridBagConstraints.REMAINDER)
+ {
+ for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+ {
+ if (lastInRow.containsKey(new Integer(y)))
+ {
+ Component lastComponent = (Component) lastInRow.get(new Integer(y));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+
+ if (lastConstraints.gridwidth == GridBagConstraints.RELATIVE)
+ {
+ constraints.gridx = max_x - 1;
+ break;
+ }
+ else
+ {
+ constraints.gridx = Math.max (constraints.gridx,
+ lastConstraints.gridx + Math.max (1, lastConstraints.gridwidth));
+ }
+ }
+ }
+ constraints.gridwidth = max_x - constraints.gridx;
+ }
+ else if (constraints.gridwidth == GridBagConstraints.RELATIVE)
+ {
+ constraints.gridwidth = max_x - constraints.gridx - 1;
+ }
+
+ // Re-sort
+ sortedByWidth.remove(sortedByWidth.indexOf(component));
+ sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
+ }
+
+ if(constraints.gridheight == GridBagConstraints.REMAINDER || constraints.gridheight == GridBagConstraints.RELATIVE)
+ {
+ if(constraints.gridheight == GridBagConstraints.REMAINDER)
+ {
+ for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+ {
+ if (lastInCol.containsKey(new Integer(x)))
+ {
+ Component lastComponent = (Component) lastInRow.get(new Integer(x));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+
+ if (lastConstraints.gridheight == GridBagConstraints.RELATIVE)
+ {
+ constraints.gridy = max_y - 1;
+ break;
+ }
+ else
+ {
+ constraints.gridy = Math.max (constraints.gridy,
+ lastConstraints.gridy + Math.max (1, lastConstraints.gridheight));
+ }
+ }
+ }
+ constraints.gridheight = max_y - constraints.gridy;
+ }
+ else if (constraints.gridheight == GridBagConstraints.RELATIVE)
+ {
+ constraints.gridheight = max_y - constraints.gridy - 1;
+ }
+
+ // Re-sort
+ sortedByHeight.remove(sortedByHeight.indexOf(component));
+ sortBySpan(component, constraints.gridheight, sortedByHeight, false);
+ }
+ } // end of STEP 2
+
+ // STEP 3: Determine sizes and weights for columns.
+ for (int i = 0; i < sortedByWidth.size(); i++)
+ {
+ Component component = (Component) sortedByWidth.get(i);
+
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ GridBagConstraints constraints = lookupInternalConstraints (component);
+
+ int width = (sizeflag == PREFERREDSIZE) ?
+ component.getPreferredSize().width :
+ component.getMinimumSize().width;
+
+ if(constraints.insets != null)
+ width += constraints.insets.left + constraints.insets.right;
+
+ width += constraints.ipadx;
+
+ distributeSizeAndWeight(width,
+ constraints.weightx,
+ constraints.gridx,
+ constraints.gridwidth,
+ info.colWidths,
+ info.colWeights);
+ } // end of STEP 3
+
+ // STEP 4: Determine sizes and weights for rows.
+ for (int i = 0; i < sortedByHeight.size(); i++)
+ {
+ Component component = (Component) sortedByHeight.get(i);
+
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ GridBagConstraints constraints = lookupInternalConstraints (component);
+
+ int height = (sizeflag == PREFERREDSIZE) ?
+ component.getPreferredSize().height :
+ component.getMinimumSize().height;
+
+ if(constraints.insets != null)
+ height += constraints.insets.top + constraints.insets.bottom;
+
+ height += constraints.ipady;
+
+ distributeSizeAndWeight(height,
+ constraints.weighty,
+ constraints.gridy,
+ constraints.gridheight,
+ info.rowHeights,
+ info.rowWeights);
+ } // end of STEP 4
+
+ // Adjust cell sizes iff parent size not zero.
+ if (parentDim.width > 0 && parentDim.height > 0)
+ {
+ calcCellSizes (info.colWidths, info.colWeights, parentDim.width);
+ calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height);
+ }
+
+ int totalWidth = sumIntArray(info.colWidths);
+ int totalHeight = sumIntArray(info.rowHeights);
+
+ // Make sure pos_x and pos_y are never negative.
+ if (totalWidth >= parentDim.width)
+ info.pos_x = parentInsets.left;
+ else
+ info.pos_x = parentInsets.left + (parentDim.width - totalWidth) / 2;
+
+ if (totalHeight >= parentDim.height)
+ info.pos_y = parentInsets.top;
+ else
+ info.pos_y = parentInsets.top + (parentDim.height - totalHeight) / 2;
+
+ // DEBUG
+ //dumpLayoutInfo (info);
+
+ return info;
+ }
+
+ /**
+ * Obsolete.
+ */
+ protected Dimension GetMinSize (Container parent, GridBagLayoutInfo info)
+ {
+ if (parent == null || info == null)
+ return new Dimension (0, 0);
+
+ Insets insets = parent.getInsets();
+ int width = sumIntArray (info.colWidths) + insets.left + insets.right;
+ int height = sumIntArray (info.rowHeights) + insets.top + insets.bottom;
+ return new Dimension (width, height);
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected Dimension getMinSize (Container parent, GridBagLayoutInfo info)
+ {
+ return GetMinSize (parent, info);
+ }
+
+ /**
+ * Helper method used by GetLayoutInfo to keep components sorted, either
+ * by gridwidth or gridheight.
+ *
+ * @param component Component to add to the sorted list.
+ * @param span Either the component's gridwidth or gridheight.
+ * @param list <code>ArrayList</code> of components, sorted by
+ * their span.
+ * @param sortByWidth Flag indicating sorting index. If true, sort by
+ * width. Otherwise, sort by height.
+ * FIXME: Use a better sorting algorithm.
+ */
+ private void sortBySpan (Component component, int span, ArrayList list, boolean sortByWidth)
+ {
+ if (span == GridBagConstraints.REMAINDER
+ || span == GridBagConstraints.RELATIVE)
+ {
+ // Put all RELATIVE and REMAINDER components at the end.
+ list.add(component);
+ }
+ else
+ {
+ int i = 0;
+ if (list.size() > 0)
+ {
+ GridBagConstraints gbc = lookupInternalConstraints((Component) list.get(i));
+ int otherspan = sortByWidth ?
+ gbc.gridwidth :
+ gbc.gridheight;
+ while (otherspan != GridBagConstraints.REMAINDER
+ && otherspan != GridBagConstraints.RELATIVE
+ && span >= otherspan)
+ {
+ i++;
+ if (i < list.size())
+ {
+ gbc = lookupInternalConstraints((Component) list.get(i));
+ otherspan = sortByWidth ?
+ gbc.gridwidth :
+ gbc.gridheight;
+ }
+ else
+ break;
+ }
+ }
+ list.add(i, component);
+ }
+ }
+
+ /**
+ * Helper method used by GetLayoutInfo to distribute a component's size
+ * and weight.
+ *
+ * @param size Preferred size of component, with inset and padding
+ * already added.
+ * @param weight Weight of component.
+ * @param start Starting position of component. Either
+ * constraints.gridx or gridy.
+ * @param span Span of component. either contraints.gridwidth or
+ * gridheight.
+ * @param sizes Sizes of rows or columns.
+ * @param weights Weights of rows or columns.
+ */
+ private void distributeSizeAndWeight (int size, double weight,
+ int start, int span,
+ int[] sizes, double[] weights)
+ {
+ if (span == 1)
+ {
+ sizes[start] = Math.max(sizes[start], size);
+ weights[start] = Math.max(weights[start], weight);
+ }
+ else
+ {
+ int numOccupied = span;
+ int lastOccupied = -1;
+
+ for(int i = start; i < start + span; i++)
+ {
+ if (sizes[i] == 0.0)
+ numOccupied--;
+ else
+ {
+ size -= sizes[i];
+ lastOccupied = i;
+ }
+ }
+
+ // A component needs to occupy at least one row.
+ if(numOccupied == 0)
+ sizes[start + span - 1] = size;
+ else if (size > 0)
+ sizes[lastOccupied] += size;
+
+ calcCellWeights(weight, weights, start, span);
+ }
+ }
+
+ /**
+ * Helper method used by GetLayoutInfo to calculate weight distribution.
+ * @param weight Weight of component.
+ * @param weights Weights of rows/columns.
+ * @param start Starting position of component in grid (gridx/gridy).
+ * @param span Span of component (gridwidth/gridheight).
+ */
+ private void calcCellWeights (double weight, double[] weights, int start, int span)
+ {
+ double totalWeight = 0.0;
+ for(int k = start; k < start + span; k++)
+ totalWeight += weights[k];
+
+ if(weight > totalWeight)
+ {
+ if (totalWeight == 0.0)
+ {
+ weights[start + span - 1] += weight;
+ }
+ else
+ {
+ double diff = weight - totalWeight ;
+ double remaining = diff;
+
+ for(int k = start; k < start + span; k++)
+ {
+ double extraWeight = diff * weights[k] / totalWeight;
+ weights[k] += extraWeight;
+ remaining -= extraWeight;
+ }
+
+ if (remaining > 0.0 && weights[start + span - 1] != 0.0)
+ {
+ weights[start + span - 1] += remaining;
+ }
+ }
+ }
+ }
+
+ /**
+ * Helper method used by GetLayoutInfo to distribute extra space
+ * based on weight distribution.
+ *
+ * @param sizes Sizes of rows/columns.
+ * @param weights Weights of rows/columns.
+ * @param range Dimension of container.
+ */
+ private void calcCellSizes (int[] sizes, double[] weights, int range)
+ {
+ int totalSize = sumIntArray (sizes);
+ double totalWeight = sumDoubleArray (weights);
+
+ int diff = range - totalSize;
+
+ if (diff == 0)
+ return;
+
+ for (int i = 0; i < sizes.length; i++)
+ {
+ int newsize = (int) (sizes[i] + (((double) diff) * weights [i] / totalWeight ));
+
+ if (newsize > 0)
+ sizes[i] = newsize;
+ }
+ }
+
+ private void dumpLayoutInfo (GridBagLayoutInfo info)
+ {
+ System.out.println ("GridBagLayoutInfo:");
+ System.out.println ("cols: " + info.cols + ", rows: " + info.rows);
+ System.out.print ("colWidths: ");
+ dumpArray(info.colWidths);
+ System.out.print ("rowHeights: ");
+ dumpArray(info.rowHeights);
+ System.out.print ("colWeights: ");
+ dumpArray(info.colWeights);
+ System.out.print ("rowWeights: ");
+ dumpArray(info.rowWeights);
+ }
+
+ private void dumpArray(int[] array)
+ {
+ String sep = "";
+ for(int i = 0; i < array.length; i++)
+ {
+ System.out.print(sep);
+ System.out.print(array[i]);
+ sep = ", ";
+ }
+ System.out.println();
+ }
+
+ private void dumpArray(double[] array)
+ {
+ String sep = "";
+ for(int i = 0; i < array.length; i++)
+ {
+ System.out.print(sep);
+ System.out.print(array[i]);
+ sep = ", ";
+ }
+ System.out.println();
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected void arrangeGrid (Container parent)
+ {
+ ArrangeGrid (parent);
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected GridBagLayoutInfo getLayoutInfo (Container parent, int sizeflag)
+ {
+ return GetLayoutInfo (parent, sizeflag);
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected void adjustForGravity (GridBagConstraints gbc, Rectangle rect)
+ {
+ AdjustForGravity (gbc, rect);
+ }
+}
diff --git a/libjava/classpath/java/awt/GridBagLayoutInfo.java b/libjava/classpath/java/awt/GridBagLayoutInfo.java
new file mode 100644
index 00000000000..43ba09d72c1
--- /dev/null
+++ b/libjava/classpath/java/awt/GridBagLayoutInfo.java
@@ -0,0 +1,70 @@
+/* GridBagLayoutInfo -
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ */
+class GridBagLayoutInfo implements Serializable
+{
+ private static final long serialVersionUID = -4899416460737170217L;
+
+ int pos_x;
+ int pos_y;
+ int cols;
+ int rows;
+ int colWidths[];
+ int rowHeights[];
+ double colWeights[];
+ double rowWeights[];
+
+ GridBagLayoutInfo (int cols, int rows)
+ {
+ this.pos_x = 0;
+ this.pos_y = 0;
+ this.cols = cols;
+ this.rows = rows;
+ this.colWidths = new int [cols];
+ this.rowHeights = new int [rows];
+ this.colWeights = new double [cols];
+ this.rowWeights = new double [rows];
+ }
+}
diff --git a/libjava/classpath/java/awt/GridLayout.java b/libjava/classpath/java/awt/GridLayout.java
new file mode 100644
index 00000000000..80d96414249
--- /dev/null
+++ b/libjava/classpath/java/awt/GridLayout.java
@@ -0,0 +1,360 @@
+/* GridLayout.java -- Grid-based layout engine
+ Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/** This class implements a grid-based layout scheme. Components are
+ * all given the same size and are laid out from left to right and top
+ * to bottom. A GridLayout is configured with a number of rows and a
+ * number of columns. If both are specified, then the number of
+ * columns is ignored and is derived from the number of rows and the
+ * total number of components. If either is zero then that dimension
+ * is computed based on the actual size of the container. An
+ * exception is thrown if an attempt is made to set both the number of
+ * rows and the number of columns to 0. This class also supports
+ * horizontal and vertical gaps; these are used as spacing between
+ * cells.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class GridLayout implements LayoutManager, Serializable
+{
+ static final long serialVersionUID = -7411804673224730901L;
+
+ /** Add a new component to the layout. This particular implementation
+ * does nothing.
+ * @param name The name of the component to add.
+ * @param comp The component to add.
+ */
+ public void addLayoutComponent (String name, Component comp)
+ {
+ // Nothing.
+ }
+
+ /** Return the number of columns in this layout. */
+ public int getColumns ()
+ {
+ return cols;
+ }
+
+ /** Return the horizontal gap. */
+ public int getHgap ()
+ {
+ return hgap;
+ }
+
+ /** Return the number of rows in this layout. */
+ public int getRows ()
+ {
+ return rows;
+ }
+
+ /** Return the vertical gap. */
+ public int getVgap ()
+ {
+ return vgap;
+ }
+
+ /** Create a new <code>GridLayout</code> with one row and any number
+ * of columns. Both gaps are set to 0.
+ */
+ public GridLayout ()
+ {
+ this (1, 0, 0, 0);
+ }
+
+ /** Create a new <code>GridLayout</code> with the specified number
+ * of rows and columns. Both gaps are set to 0. Note that the row
+ * and column settings cannot both be zero. If both the row and
+ * column values are non-zero, the rows value takes precedence.
+ * @param rows Number of rows
+ * @param cols Number of columns
+ * @exception IllegalArgumentException If rows and columns are both
+ * 0, or if either are negative
+ */
+ public GridLayout (int rows, int cols)
+ {
+ this (rows, cols, 0, 0);
+ }
+
+ /** Create a new GridLayout with the specified number of rows and
+ * columns and the specified gaps.
+ * Note that the row and column settings cannot both be
+ * zero. If both the row and column values are non-zero, the rows value
+ * takes precedence.
+ * @param rows Number of rows
+ * @param cols Number of columns
+ * @param hgap The horizontal gap
+ * @param vgap The vertical gap
+ * @exception IllegalArgumentException If rows and columns are both
+ * 0, if either are negative, or if either gap is negative
+ */
+ public GridLayout (int rows, int cols, int hgap, int vgap)
+ {
+ if (rows < 0)
+ throw new IllegalArgumentException ("number of rows cannot be negative");
+ if (cols < 0)
+ throw new IllegalArgumentException ("number of columns cannot be negative");
+ if (rows == 0 && cols == 0)
+ throw new IllegalArgumentException ("both rows and columns cannot be 0");
+ if (hgap < 0)
+ throw new IllegalArgumentException ("horizontal gap must be nonnegative");
+ if (vgap < 0)
+ throw new IllegalArgumentException ("vertical gap must be nonnegative");
+ this.rows = rows;
+ this.cols = cols;
+ this.hgap = hgap;
+ this.vgap = vgap;
+ }
+
+ /** Lay out the container's components based on current settings.
+ * The free space in the container is divided evenly into the specified
+ * number of rows and columns in this object.
+ * @param parent The container to lay out
+ */
+ public void layoutContainer (Container parent)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int num = parent.ncomponents;
+
+ // There's no point, and handling this would mean adding special
+ // cases.
+ if (num == 0)
+ return;
+
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ int real_rows = rows;
+ int real_cols = cols;
+ if (real_rows == 0)
+ real_rows = (num + real_cols - 1) / real_cols;
+ else
+ real_cols = (num + real_rows - 1) / real_rows;
+
+ // We might have less than a single row. In this case we expand
+ // to fill.
+ if (num < real_cols)
+ real_cols = num;
+
+ Dimension d = parent.getSize ();
+ Insets ins = parent.getInsets ();
+
+ // Compute width and height of each cell in the grid.
+ int tw = d.width - ins.left - ins.right;
+ tw = (tw - (real_cols - 1) * hgap) / real_cols;
+ int th = d.height - ins.top - ins.bottom;
+ th = (th - (real_rows - 1) * vgap) / real_rows;
+
+ // If the cells are too small, still try to do something.
+ if (tw < 0)
+ tw = 1;
+ if (th < 0)
+ th = 1;
+
+ int x = ins.left;
+ int y = ins.top;
+ int i = 0;
+ int recount = 0;
+
+ while (i < num)
+ {
+ comps[i].setBounds (x, y, tw, th);
+
+ ++i;
+ ++recount;
+ if (recount == real_cols)
+ {
+ recount = 0;
+ y += vgap + th;
+ x = ins.left;
+ }
+ else
+ x += hgap + tw;
+ }
+ }
+ }
+
+ /** Get the minimum layout size of the container.
+ * @param cont The parent container
+ */
+ public Dimension minimumLayoutSize (Container cont)
+ {
+ return getSize (cont, true);
+ }
+
+ /** Get the preferred layout size of the container.
+ * @param cont The parent container
+ */
+ public Dimension preferredLayoutSize (Container cont)
+ {
+ return getSize (cont, false);
+ }
+
+ /** Remove the indicated component from this layout manager.
+ * This particular implementation does nothing.
+ * @param comp The component to remove
+ */
+ public void removeLayoutComponent (Component comp)
+ {
+ // Nothing.
+ }
+
+ /** Set the number of columns.
+ * @param newCols
+ * @exception IllegalArgumentException If the number of columns is
+ * negative, or if the number of columns is zero and the number
+ * of rows is already 0.
+ */
+ public void setColumns (int newCols)
+ {
+ if (newCols < 0)
+ throw new IllegalArgumentException ("number of columns cannot be negative");
+ if (newCols == 0 && rows == 0)
+ throw new IllegalArgumentException ("number of rows is already 0");
+ this.cols = newCols;
+ }
+
+ /** Set the horizontal gap
+ * @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;
+ }
+
+ /** Set the number of rows
+ * @param newRows
+ * @exception IllegalArgumentException If the number of rows is
+ * negative, or if the number of rows is zero and the number
+ * of columns is already 0.
+ */
+ public void setRows (int newRows)
+ {
+ if (newRows < 0)
+ throw new IllegalArgumentException ("number of rows cannot be negative");
+ if (newRows == 0 && cols == 0)
+ throw new IllegalArgumentException ("number of columns is already 0");
+ this.rows = newRows;
+ }
+
+ /** Set the vertical gap.
+ * @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 ()
+ + ",hgap=" + hgap + ",vgap=" + vgap
+ + ",rows=" + rows + ",cols=" + cols
+ + "]");
+ }
+
+ // This method is used to compute the various sizes.
+ private Dimension getSize (Container parent, boolean is_min)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int w = 0, h = 0, num = parent.ncomponents;
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ for (int i = 0; i < num; ++i)
+ {
+ Dimension d;
+
+ if (is_min)
+ d = comps[i].getMinimumSize ();
+ else
+ d = comps[i].getPreferredSize ();
+
+ w = Math.max (d.width, w);
+ h = Math.max (d.height, h);
+ }
+
+ int real_rows = rows;
+ int real_cols = cols;
+ if (real_rows == 0)
+ real_rows = (num + real_cols - 1) / real_cols;
+ else
+ real_cols = (num + real_rows - 1) / real_rows;
+
+ Insets ins = parent.getInsets ();
+ // We subtract out an extra gap here because the gaps are only
+ // between cells.
+ w = ins.left + ins.right + real_cols * (w + hgap) - hgap;
+ h = ins.top + ins.bottom + real_rows * (h + vgap) - vgap;
+ return new Dimension (w, h);
+ }
+ }
+
+ /**
+ * @serial The number of columns in the grid.
+ */
+ private int cols;
+
+ /**
+ * @serial The number of rows in the grid.
+ */
+ private int rows;
+
+ /**
+ * @serial The horizontal gap between columns
+ */
+ private int hgap;
+
+ /**
+ * @serial The vertical gap between rows
+ */
+ private int vgap;
+}
diff --git a/libjava/classpath/java/awt/HeadlessException.java b/libjava/classpath/java/awt/HeadlessException.java
new file mode 100644
index 00000000000..b180b1d86f7
--- /dev/null
+++ b/libjava/classpath/java/awt/HeadlessException.java
@@ -0,0 +1,72 @@
+/* HeadlessException.java -- operation not possible in headless environment
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This exception is thrown when code dependent on a keyboard, mouse, or
+ * display is executed in a headless environment.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class HeadlessException extends UnsupportedOperationException
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 167183644944358563L;
+
+ /**
+ * Create a new instance with no detailed error message.
+ */
+ public HeadlessException()
+ {
+ }
+
+ /**
+ * Create a new instance with the specified detailed error message.
+ *
+ * @param message the detailed error message
+ */
+ public HeadlessException(String message)
+ {
+ super(message);
+ }
+} // class HeadlessException
diff --git a/libjava/classpath/java/awt/IllegalComponentStateException.java b/libjava/classpath/java/awt/IllegalComponentStateException.java
new file mode 100644
index 00000000000..4a47f1da95d
--- /dev/null
+++ b/libjava/classpath/java/awt/IllegalComponentStateException.java
@@ -0,0 +1,71 @@
+/* IllegalComponentStateException.java -- bad component state
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This exception is thrown when the requested operation failed because
+ * a component was not in the proper state.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class IllegalComponentStateException extends IllegalStateException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -1889339587208144238L;
+
+ /**
+ * Create a new instance with no detailed error message.
+ */
+ public IllegalComponentStateException()
+ {
+ }
+
+ /**
+ * Create a new instance with the specified detailed error message.
+ *
+ * @param message the detailed error message
+ */
+ public IllegalComponentStateException(String message)
+ {
+ super(message);
+ }
+} // class IllegalComponentStateException
diff --git a/libjava/classpath/java/awt/Image.java b/libjava/classpath/java/awt/Image.java
new file mode 100644
index 00000000000..b657ad007d9
--- /dev/null
+++ b/libjava/classpath/java/awt/Image.java
@@ -0,0 +1,203 @@
+/* Image.java -- superclass for images
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.ReplicateScaleFilter;
+
+/**
+ * This is the abstract superclass of all image objects in Java.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class Image
+{
+ /**
+ * This variable is returned whenever a property that is not defined
+ * is requested.
+ */
+ // For debug purposes, this might as well be a unique string.
+ public static final Object UndefinedProperty
+ = new String("undefined property");
+
+ /**
+ * Constant indicating that the default scaling algorithm should be used.
+ *
+ * @since 1.1
+ */
+ public static final int SCALE_DEFAULT = 1;
+
+ /**
+ * Constant indicating that a fast scaling algorithm should be used.
+ *
+ * @since 1.1
+ */
+ public static final int SCALE_FAST = 2;
+
+ /**
+ * Constant indicating that a smooth scaling algorithm should be used.
+ *
+ * @since 1.1
+ */
+ public static final int SCALE_SMOOTH = 4;
+
+ /**
+ * Constant indicating that the <code>ReplicateScaleFilter</code> class
+ * algorithm should be used for scaling.
+ *
+ * @see ReplicateScaleFilter
+ * @since 1.1
+ */
+ public static final int SCALE_REPLICATE = 8;
+
+ /**
+ * Constant indicating that the area averaging scaling algorithm should be
+ * used.
+ *
+ * @see java.awt.image.AreaAveragingScaleFilter
+ * @since 1.1
+ */
+ public static final int SCALE_AREA_AVERAGING = 16;
+
+ /**
+ * A default constructor for subclasses.
+ */
+ public Image()
+ {
+ }
+
+ /**
+ * Returns the width of the image, or -1 if it is unknown. If the
+ * image width is unknown, the observer object will be notified when
+ * the value is known.
+ *
+ * @param observer the image observer for this object
+ * @return the width in pixels
+ * @see #getHeight(ImageObserver)
+ */
+ public abstract int getWidth(ImageObserver observer);
+
+ /**
+ * Returns the height of the image, or -1 if it is unknown. If the
+ * image height is unknown, the observer object will be notified when
+ * the value is known.
+ *
+ * @param observer the image observer for this object
+ * @return the height in pixels
+ * @see #getWidth(ImageObserver)
+ */
+ public abstract int getHeight(ImageObserver observer);
+
+ /**
+ * Returns the image producer object for this object. The producer is the
+ * object which generates pixels for this image.
+ *
+ * @return the image producer for this object
+ */
+ public abstract ImageProducer getSource();
+
+ /**
+ * Returns a graphics context object for drawing an off-screen object.
+ * This method is only valid for off-screen objects.
+ *
+ * @return a graphics context object for an off-screen object
+ * @see Graphics#getcreateImage(int, int)
+ */
+ public abstract Graphics getGraphics();
+
+ /**
+ * This method requests a named property for an object. The value of the
+ * property is returned. The value <code>UndefinedProperty</code> is
+ * returned if there is no property with the specified name. The value
+ * <code>null</code> is returned if the properties for the object are
+ * not yet known. In this case, the specified image observer is notified
+ * when the properties are known.
+ *
+ * @param name the requested property name
+ * @param observer the image observer for this object
+ * @return the named property, if available
+ * @see #UndefinedProperty
+ */
+ public abstract Object getProperty(String name, ImageObserver observer);
+
+ /**
+ * Scales the image to the requested dimension. A new Image with asynchronous
+ * loading will be produced according to the hints of the algorithm
+ * requested. If either the width or height is non-positive, it is adjusted
+ * to preserve the original aspect ratio.
+ *
+ * @param width the width of the scaled image
+ * @param height the height of the scaled image
+ * @param flags a value indicating the algorithm to use
+ * @return the scaled <code>Image</code> object
+ * @see #SCALE_DEFAULT
+ * @see #SCALE_FAST
+ * @see #SCALE_SMOOTH
+ * @see #SCALE_REPLICATE
+ * @see #SCALE_AREA_AVERAGING
+ * @since 1.1
+ */
+ public Image getScaledInstance(int width, int height, int flags)
+ {
+ switch (flags)
+ {
+ case SCALE_DEFAULT:
+ case SCALE_FAST:
+ case SCALE_REPLICATE:
+ ImageProducer producer =
+ new FilteredImageSource(this.getSource(),
+ new ReplicateScaleFilter(width, height));
+ return Toolkit.getDefaultToolkit().createImage(producer);
+ case SCALE_SMOOTH:
+ case SCALE_AREA_AVERAGING:
+ default:
+ throw new Error("not implemented");
+ }
+ }
+
+ /**
+ * Flushes (that is, destroys) any resources used for this image. This
+ * includes the actual image data.
+ */
+ public abstract void flush();
+} // class Image
diff --git a/libjava/classpath/java/awt/ImageCapabilities.java b/libjava/classpath/java/awt/ImageCapabilities.java
new file mode 100644
index 00000000000..2fe71d1e23b
--- /dev/null
+++ b/libjava/classpath/java/awt/ImageCapabilities.java
@@ -0,0 +1,107 @@
+/* ImageCapabilities.java -- the capabilities of an image buffer
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class represents the capabilities of an image buffer. An
+ * image buffer may be backed by accelerated graphics resources.
+ * Those resources may or may not be volatile. This class is used to
+ * describe these image buffer characteristics.
+ */
+public class ImageCapabilities implements Cloneable
+{
+ /**
+ * Whether or not this the image buffer uses accelerated graphics
+ * resources.
+ */
+ private final boolean accelerated;
+
+ /**
+ * Create a new image capability descriptor.
+ *
+ * @param accelerated true if the image buffer uses accelerated
+ * graphics resources
+ */
+ public ImageCapabilities(boolean accelerated)
+ {
+ this.accelerated = accelerated;
+ }
+
+ /**
+ * Returns whether or not the image buffer uses accelerated graphics
+ * resources.
+ *
+ * @return true if the image buffer uses accelerated graphics
+ * resources; false otherwise
+ */
+ public boolean isAccelerated()
+ {
+ return accelerated;
+ }
+
+ /**
+ * Returns whether or not the image buffer's resources are volatile,
+ * meaning that they can be reclaimed by the graphics system at any
+ * time.
+ *
+ * @return true if the image buffer's resources are volatile; false
+ * otherwise
+ */
+ public boolean isTrueVolatile()
+ {
+ return true;
+ }
+
+ /**
+ * Clone this image capability descriptor.
+ *
+ * @return a clone of this image capability descriptor
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/Insets.java b/libjava/classpath/java/awt/Insets.java
new file mode 100644
index 00000000000..7238a34e22a
--- /dev/null
+++ b/libjava/classpath/java/awt/Insets.java
@@ -0,0 +1,158 @@
+/* Insets.java -- information about a container border
+ Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * This class represents the "margin" or space around a container.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status
+ */
+public class Insets implements Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -2272572637695466749L;
+
+ /**
+ * The gap from the top.
+ *
+ * @serial the top inset
+ */
+ public int top;
+
+ /**
+ * The gap from the left.
+ *
+ * @serial the left inset
+ */
+ public int left;
+
+ /**
+ * The gap from the bottom.
+ *
+ * @serial the bottom inset
+ */
+ public int bottom;
+
+ /**
+ * The gap from the right.
+ *
+ * @serial the right inset
+ */
+ public int right;
+
+ /**
+ * Initializes a new instance of <code>Inset</code> with the specified
+ * inset values.
+ *
+ * @param top the top inset
+ * @param left the left inset
+ * @param bottom the bottom inset
+ * @param right the right inset
+ */
+ public Insets(int top, int left, int bottom, int right)
+ {
+ this.top = top;
+ this.left = left;
+ this.bottom = bottom;
+ this.right = right;
+ }
+
+ /**
+ * Tests whether this object is equal to the specified object. The other
+ * object must be an instance of Insets with identical field values.
+ *
+ * @param obj the object to test against
+ * @return true if the specified object is equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Insets))
+ return false;
+ Insets i = (Insets) obj;
+ return top == i.top && bottom == i.bottom
+ && left == i.left && right == i.right;
+ }
+
+ /**
+ * Returns a hashcode for this instance. The formula is unspecified, but
+ * appears to be <code>XXX what is it? </code>.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // This can't be right...
+ return top + bottom + left + right;
+ }
+
+ /**
+ * Returns a string representation of this object, which will be non-null.
+ * The format is unspecified, but appears to be <code>XXX what is it?</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return getClass().getName() + "(top=" + top + ",bottom=" + bottom +
+ ",left=" + left + ",right=" + right + ')';
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return a copy of this object
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+} // class Insets
diff --git a/libjava/classpath/java/awt/ItemSelectable.java b/libjava/classpath/java/awt/ItemSelectable.java
new file mode 100644
index 00000000000..f155f723efe
--- /dev/null
+++ b/libjava/classpath/java/awt/ItemSelectable.java
@@ -0,0 +1,75 @@
+/* ItemSelectable.java -- items that can be selected
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ItemListener;
+
+/**
+ * This interface is for objects that can have one or more items selected.
+ * For example, radio buttons.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface ItemSelectable
+{
+ /**
+ * Returns the list of objects that are selected in this component.
+ *
+ * @return the list of selected objects, or null
+ */
+ Object[] getSelectedObjects();
+
+ /**
+ * Adds an item listener to this object. It will receive selection events
+ * for this object by the user (but not programatically). If listener is
+ * null, it is ignored.
+ *
+ * @param listener the item listener to add
+ */
+ void addItemListener(ItemListener listener);
+
+ /**
+ * Removes an item listener from this object.
+ *
+ * @param listener the item listener to remove
+ */
+ void removeItemListener(ItemListener listener);
+} // interface ItemSelectable
diff --git a/libjava/classpath/java/awt/JobAttributes.java b/libjava/classpath/java/awt/JobAttributes.java
new file mode 100644
index 00000000000..2acb3a01ed3
--- /dev/null
+++ b/libjava/classpath/java/awt/JobAttributes.java
@@ -0,0 +1,500 @@
+/* JobAttributes.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * Needs documentation...
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4, lacks documentation
+ */
+public final class JobAttributes implements Cloneable
+{
+ public static final class DefaultSelectionType extends AttributeValue
+ {
+ private static final String[] NAMES = { "all", "range", "selection" };
+ public static final DefaultSelectionType ALL
+ = new DefaultSelectionType(0);
+ public static final DefaultSelectionType RANGE
+ = new DefaultSelectionType(1);
+ public static final DefaultSelectionType SELECTION
+ = new DefaultSelectionType(2);
+ private DefaultSelectionType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class DefaultSelectionType
+
+ public static final class DestinationType extends AttributeValue
+ {
+ private static final String[] NAMES = { "file", "printer" };
+ public static final DestinationType FILE = new DestinationType(0);
+ public static final DestinationType PRINTER = new DestinationType(1);
+ private DestinationType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class DestinationType
+
+ public static final class DialogType extends AttributeValue
+ {
+ private static final String[] NAMES = { "common", "native", "none" };
+ public static final DialogType COMMON = new DialogType(0);
+ public static final DialogType NATIVE = new DialogType(1);
+ public static final DialogType NONE = new DialogType(2);
+ private DialogType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class DialogType
+
+ public static final class MultipleDocumentHandlingType
+ extends AttributeValue
+ {
+ private static final String[] NAMES = {
+ "separate-documents-collated-copies",
+ "separate-documents-uncollated-copies"
+ };
+ public static final MultipleDocumentHandlingType
+ SEPARATE_DOCUMENTS_COLLATED_COPIES
+ = new MultipleDocumentHandlingType(0);
+ public static final MultipleDocumentHandlingType
+ SEPARATE_DOCUMENTS_UNCOLLATED_COPIES
+ = new MultipleDocumentHandlingType(1);
+ private MultipleDocumentHandlingType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class MultipleDocumentHandlingType
+
+ public static final class SidesType extends AttributeValue
+ {
+ private static final String[] NAMES
+ = { "one-sided", "two-sided-long-edge", "two-sided-short-edge" };
+ public static final SidesType ONE_SIDED = new SidesType(0);
+ public static final SidesType TWO_SIDED_LONG_EDGE = new SidesType(1);
+ public static final SidesType TWO_SIDED_SHORT_EDGE = new SidesType(2);
+ private SidesType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class SidesType
+
+ private int copies;
+ private DefaultSelectionType selection;
+ private DestinationType destination;
+ private DialogType dialog;
+ private String filename;
+ private int maxPage;
+ private int minPage;
+ private MultipleDocumentHandlingType multiple;
+ private int[][] pageRanges; // null for default value
+ private int fromPage; // 0 for default value
+ private int toPage; // 0 for default value
+ private String printer;
+ private SidesType sides;
+
+ public JobAttributes()
+ {
+ copies = 1;
+ selection = DefaultSelectionType.ALL;
+ destination = DestinationType.PRINTER;
+ dialog = DialogType.NATIVE;
+ maxPage = Integer.MAX_VALUE;
+ minPage = 1;
+ multiple
+ = MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES;
+ sides = SidesType.ONE_SIDED;
+ }
+
+ public JobAttributes(JobAttributes attr)
+ {
+ set(attr);
+ }
+
+ public JobAttributes(int copies, DefaultSelectionType selection,
+ DestinationType destination, DialogType dialog,
+ String filename, int max, int min,
+ MultipleDocumentHandlingType multiple,
+ int[][] pageRanges, String printer, SidesType sides)
+ {
+ if (copies <= 0 || selection == null || destination == null
+ || dialog == null || max < min || min <= 0 || multiple == null
+ || sides == null)
+ throw new IllegalArgumentException();
+ this.copies = copies;
+ this.selection = selection;
+ this.destination = destination;
+ this.dialog = dialog;
+ this.filename = filename;
+ maxPage = max;
+ minPage = min;
+ this.multiple = multiple;
+ setPageRanges(pageRanges);
+ this.printer = printer;
+ this.sides = sides;
+ }
+
+ public Object clone()
+ {
+ return new JobAttributes(this);
+ }
+
+ public void set(JobAttributes attr)
+ {
+ copies = attr.copies;
+ selection = attr.selection;
+ destination = attr.destination;
+ dialog = attr.dialog;
+ filename = attr.filename;
+ maxPage = attr.maxPage;
+ minPage = attr.minPage;
+ multiple = attr.multiple;
+ pageRanges = (int[][]) attr.pageRanges.clone();
+ printer = attr.printer;
+ sides = attr.sides;
+ fromPage = attr.fromPage;
+ toPage = attr.toPage;
+ }
+
+ public int getCopies()
+ {
+ return copies;
+ }
+
+ public void setCopies(int copies)
+ {
+ if (copies <= 0)
+ throw new IllegalArgumentException();
+ this.copies = copies;
+ }
+
+ public void setCopiesToDefault()
+ {
+ copies = 1;
+ }
+
+ public DefaultSelectionType getDefaultSelection()
+ {
+ return selection;
+ }
+
+ public void setDefaultSelection(DefaultSelectionType selection)
+ {
+ if (selection == null)
+ throw new IllegalArgumentException();
+ this.selection = selection;
+ }
+
+ public DestinationType getDestination()
+ {
+ return destination;
+ }
+
+ public void setDestination(DestinationType destination)
+ {
+ if (destination == null)
+ throw new IllegalArgumentException();
+ this.destination = destination;
+ }
+
+ public DialogType getDialog()
+ {
+ return dialog;
+ }
+
+ public void setDialog(DialogType dialog)
+ {
+ if (dialog == null)
+ throw new IllegalArgumentException();
+ this.dialog = dialog;
+ }
+
+ public String getFileName()
+ {
+ return filename;
+ }
+
+ public void setFileName(String filename)
+ {
+ this.filename = filename;
+ }
+
+ public int getFromPage()
+ {
+ return fromPage != 0 ? fromPage
+ : pageRanges != null ? pageRanges[0][0]
+ : toPage != 0 ? toPage : minPage;
+ }
+
+ public void setFromPage(int fromPage)
+ {
+ if (fromPage < minPage || (fromPage > toPage && toPage != 0)
+ || fromPage > maxPage)
+ throw new IllegalArgumentException();
+ if (pageRanges == null)
+ this.fromPage = fromPage;
+ }
+
+ public int getMaxPage()
+ {
+ return maxPage;
+ }
+
+ public void setMaxPage(int maxPage)
+ {
+ if (maxPage < minPage)
+ throw new IllegalArgumentException();
+ this.maxPage = maxPage;
+ if (maxPage < fromPage)
+ fromPage = maxPage;
+ if (maxPage < toPage)
+ toPage = maxPage;
+ if (pageRanges != null)
+ {
+ int i = pageRanges.length - 1;
+ while (i >= 0 && maxPage < pageRanges[i][1])
+ i--;
+ if (maxPage >= pageRanges[++i][0])
+ pageRanges[i++][1] = maxPage;
+ if (i == 0)
+ pageRanges = null;
+ else if (i < pageRanges.length)
+ {
+ int[][] tmp = new int[i][];
+ System.arraycopy(pageRanges, 0, tmp, 0, i);
+ pageRanges = tmp;
+ }
+ }
+ }
+
+ public int getMinPage()
+ {
+ return minPage;
+ }
+
+ public void setMinPage(int minPage)
+ {
+ if (minPage <= 0 || minPage > maxPage)
+ throw new IllegalArgumentException();
+ this.minPage = minPage;
+ if (minPage > toPage)
+ toPage = minPage;
+ if (minPage > fromPage)
+ fromPage = minPage;
+ if (pageRanges != null)
+ {
+ int size = pageRanges.length;
+ int i = 0;
+ while (i < size && minPage > pageRanges[i][0])
+ i++;
+ if (minPage <= pageRanges[i - 1][1])
+ pageRanges[--i][0] = minPage;
+ if (i == size)
+ pageRanges = null;
+ else if (i > 0)
+ {
+ int[][] tmp = new int[size - i][];
+ System.arraycopy(pageRanges, i, tmp, 0, size - i);
+ pageRanges = tmp;
+ }
+ }
+ }
+
+ public MultipleDocumentHandlingType getMultipleDocumentHandling()
+ {
+ return multiple;
+ }
+
+ public void setMultipleDocumentHandling
+ (MultipleDocumentHandlingType multiple)
+ {
+ if (multiple == null)
+ throw new IllegalArgumentException();
+ this.multiple = multiple;
+ }
+
+ public void setMultipleDocumentHandlingToDefault()
+ {
+ multiple
+ = MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES;
+ }
+
+ public int[][] getPageRanges()
+ {
+ if (pageRanges == null)
+ return new int[][] { { getFromPage(), getToPage() } };
+ // Perform a deep clone, so user code cannot affect original arrays.
+ int i = pageRanges.length;
+ int[][] result = new int[i][];
+ while (--i >= 0)
+ result[i] = (int[]) pageRanges[i].clone();
+ return result;
+ }
+
+ public void setPageRanges(int[][] pageRanges)
+ {
+ int size = pageRanges == null ? 0 : pageRanges.length;
+ if (size == 0)
+ throw new IllegalArgumentException();
+ while (--size >= 0)
+ {
+ int[] range = pageRanges[size];
+ if (range == null || range.length != 2
+ || range[0] < minPage || range[1] < range[0] || range[1] > maxPage
+ || (size != 0 && range[0] <= pageRanges[size - 1][1]))
+ throw new IllegalArgumentException();
+ }
+ size = pageRanges.length;
+ if (fromPage > 0 && pageRanges[0][0] > fromPage)
+ fromPage = pageRanges[0][0];
+ if (toPage > 0 && pageRanges[size - 1][1] < toPage)
+ toPage = pageRanges[size - 1][1];
+ this.pageRanges = new int[size][];
+ while (--size >= 0)
+ this.pageRanges[size] = (int[]) pageRanges[size].clone();
+ }
+
+ public String getPrinter()
+ {
+ return printer;
+ }
+
+ public void setPrinter(String printer)
+ {
+ this.printer = printer;
+ }
+
+ public SidesType getSides()
+ {
+ return sides;
+ }
+
+ public void setSides(SidesType sides)
+ {
+ if (sides == null)
+ throw new IllegalArgumentException();
+ this.sides = sides;
+ }
+
+ public void setSidesToDefault()
+ {
+ sides = SidesType.ONE_SIDED;
+ }
+
+ public int getToPage()
+ {
+ return toPage != 0 ? toPage
+ : pageRanges != null ? pageRanges[pageRanges.length - 1][1]
+ : fromPage != 0 ? fromPage : maxPage;
+ }
+
+ public void setToPage(int toPage)
+ {
+ if (toPage < minPage || (fromPage > toPage && fromPage != 0)
+ || toPage > maxPage)
+ throw new IllegalArgumentException();
+ if (pageRanges == null)
+ this.toPage = toPage;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (! (o instanceof JobAttributes))
+ return false;
+ JobAttributes ja = (JobAttributes) o;
+ if (copies != ja.copies || selection != ja.selection
+ || destination != ja.destination || dialog != ja.dialog
+ || ! filename.equals(ja.filename) || maxPage != ja.maxPage
+ || minPage != ja.minPage || multiple != ja.multiple
+ || fromPage != ja.fromPage || toPage != ja.toPage
+ || ! printer.equals(ja.printer) || sides != ja.sides
+ || (pageRanges == null) != (ja.pageRanges == null))
+ return false;
+ if (pageRanges != ja.pageRanges)
+ for (int i = pageRanges.length; --i >= 0; )
+ if (pageRanges[i][0] != ja.pageRanges[i][0]
+ || pageRanges[i][1] != ja.pageRanges[i][1])
+ return false;
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int hash = (selection.value << 6) ^ (destination.value << 5)
+ ^ (dialog.value << 3) ^ (multiple.value << 2) ^ sides.value
+ ^ (filename == null ? 0 : filename.hashCode())
+ ^ (printer == null ? 0 : printer.hashCode());
+ // The effect of the above fields on the hashcode match the JDK. However,
+ // I am unable to reverse engineer the effect of the fields listed below,
+ // so I am using my own implementation. Note that this still satisfies
+ // the general contract of hashcode, it just doesn't match the JDK.
+ hash ^= (copies << 27) ^ (maxPage << 22) ^ (minPage << 17);
+ if (pageRanges == null)
+ hash ^= (getFromPage() << 13) ^ (getToPage() << 8);
+ else
+ for (int i = pageRanges.length; --i >= 0; )
+ hash ^= (pageRanges[i][0] << 13) ^ (pageRanges[i][1] << 8);
+ return hash;
+ }
+
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer("copies=").append(copies)
+ .append(",defaultSelection=").append(selection).append(",destination=")
+ .append(destination).append(",dialog=").append(dialog)
+ .append(",fileName=").append(filename).append(",fromPage=")
+ .append(getFromPage()).append(",maxPage=").append(maxPage)
+ .append(",minPage=").append(minPage)
+ .append(",multiple-document-handling=").append(multiple)
+ .append(",page-ranges=[");
+ if (pageRanges == null)
+ s.append(minPage).append(':').append(minPage).append(']');
+ else
+ for (int i = 0; i < pageRanges.length; i++)
+ s.append(pageRanges[i][0]).append(':').append(pageRanges[i][1])
+ .append(',');
+ s.setLength(s.length() - 1);
+ return s.append("],printer=").append(printer).append(",sides=")
+ .append(sides).append(",toPage=").append(getToPage()).toString();
+ }
+} // class JobAttributes
diff --git a/libjava/classpath/java/awt/KeyEventDispatcher.java b/libjava/classpath/java/awt/KeyEventDispatcher.java
new file mode 100644
index 00000000000..30997278e1b
--- /dev/null
+++ b/libjava/classpath/java/awt/KeyEventDispatcher.java
@@ -0,0 +1,82 @@
+/* KeyEventDispatcher.java -- dispatches key events
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.KeyEvent;
+
+/**
+ * An instance of this interface coordinates with a KeyboardFocusManager to
+ * target and dispatch all key events. This allows retargeting, consuming,
+ * changing, or otherwise manipulating the key event before sending it on to
+ * a target.
+ *
+ * <p>By default, the KeyboardFocusManager is the sink for all key events not
+ * dispatched by other dispatchers. Therefore, it is unnecessary for the user
+ * to register the focus manager as a dispatcher.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see KeyboardFocusManager#addKeyEventDispatcher(KeyEventDispatcher)
+ * @see KeyboardFocusManager#removeKeyEventDispatcher(KeyEventDispatcher)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface KeyEventDispatcher
+{
+ /**
+ * Called by the KeyboardFocusManager to request that a key event be
+ * dispatched. The dispatcher is free to retarget the event, consume it,
+ * dispatch it, or make other changes. This is usually done to allow
+ * delivery of key events to objects other than the window in focus, such
+ * as for navigating non-focusable components. If this dispatcher chooses
+ * to dispatch the event itself, it should call <code>redispatchEvent</code>
+ * to avoid infinite recursion.
+ *
+ * <p>If the return value is false, the KeyEvent is passed to the next
+ * dispatcher in the chain, ending with the KeyboardFocusManager. If the
+ * return value is true, the event has been consumed (although it might
+ * have been ignored), and no further action will be taken on the event. Be
+ * sure to check whether the event was consumed before dispatching it
+ * further.
+ *
+ * @param e the key event
+ * @return true if the event has been consumed
+ * @see KeyboardFocusManager#redispatchEvent(Component, AWTEvent)
+ */
+ boolean dispatchKeyEvent(KeyEvent e);
+} // interface KeyEventDispatcher
diff --git a/libjava/classpath/java/awt/KeyEventPostProcessor.java b/libjava/classpath/java/awt/KeyEventPostProcessor.java
new file mode 100644
index 00000000000..0b39dc25075
--- /dev/null
+++ b/libjava/classpath/java/awt/KeyEventPostProcessor.java
@@ -0,0 +1,81 @@
+/* KeyEventPostProcessor.java -- performs actions after a key event dispatch
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.KeyEvent;
+
+/**
+ * An instance of this interface coordinates with a KeyboardFocusManager to
+ * target and dispatch all key events that are otherwise unconsumed. This
+ * allows events which take place when nothing has focus to still operate,
+ * such as menu keyboard shortcuts.
+ *
+ * <p>By default, the KeyboardFocusManager is the sink for all key events not
+ * post-processed elsewhere. Therefore, it is unnecessary for the user
+ * to register the focus manager as a dispatcher.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see KeyboardFocusManager#addKeyEventPostProcessor(KeyEventPostProcessor)
+ * @see KeyboardFocusManager#removeKeyEventPostProcessor(KeyEventPostProcessor)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface KeyEventPostProcessor
+{
+ /**
+ * Called by the KeyboardFocusManager to request that a key event be
+ * post-processed. Typically, the event has already been dispatched and
+ * handled, unless no object has focus. Thus, this allows global event
+ * handling for things like menu shortcuts. If this post-processor chooses
+ * to dispatch the event, it should call <code>redispatchEvent</code>
+ * to avoid infinite recursion.
+ *
+ * <p>If the return value is false, the KeyEvent is passed to the next
+ * dispatcher in the chain, ending with the KeyboardFocusManager. If the
+ * return value is true, the event has been consumed (although it might
+ * have been ignored), and no further action will be taken on the event. Be
+ * sure to check whether the event was consumed before dispatching it
+ * further.
+ *
+ * @param e the key event
+ * @return true if the event has been consumed
+ * @see KeyboardFocusManager#redispatchEvent(Component, AWTEvent)
+ */
+ boolean postProcessKeyEvent(KeyEvent e);
+} // interface KeyEventPostProcessor
diff --git a/libjava/classpath/java/awt/KeyboardFocusManager.java b/libjava/classpath/java/awt/KeyboardFocusManager.java
new file mode 100644
index 00000000000..f64618477bd
--- /dev/null
+++ b/libjava/classpath/java/awt/KeyboardFocusManager.java
@@ -0,0 +1,1478 @@
+/* KeyboardFocusManager.java -- manage component focusing via the keyboard
+ Copyright (C) 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.applet.Applet;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.VetoableChangeSupport;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The <code>KeyboardFocusManager</code> handles the focusing of
+ * windows for receiving keyboard events. The manager handles
+ * the dispatch of all <code>FocusEvent</code>s and
+ * <code>KeyEvent</code>s, along with <code>WindowEvent</code>s
+ * relating to the focused window. Users can use the manager
+ * to ascertain the current focus owner and fire events.
+ * <br />
+ * <br />
+ * The focus owner is the <code>Component</code> that receives
+ * key events. The focus owner is either the currently focused
+ * window or a component within this window.
+ * <br />
+ * <br />
+ * The underlying native windowing system may denote the active
+ * window or its children with special decorations (e.g. a highlighted
+ * title bar). The active window is always either a <code>Frame</code>
+ * or <code>Dialog</code>, and is either the currently focused
+ * window or its owner.
+ * <br />
+ * <br />
+ * Applets may be partitioned into different applet contexts, according
+ * to their code base. In this case, each context has its own
+ * <code>KeyboardFocusManager</code>, as opposed to the global
+ * manager maintained by applets which share the same context.
+ * Each context is insulated from the others, and they don't interact.
+ * The resulting behaviour, as with context division, depends on the browser
+ * supporting the applets. Regardless, there can only ever be
+ * one focused window, one active window and one focus owner
+ * per <code>ClassLoader</code>.
+ * <br />
+ * <br />
+ * To support this separation of focus managers, the manager instances
+ * and the internal state information is grouped by the
+ * <code>ThreadGroup</code> to which it pertains. With respect to
+ * applets, each code base has its own <code>ThreadGroup</code>, so the
+ * isolation of each context is enforced within the manager.
+ * <br />
+ * <br />
+ * By default, the manager defines TAB and Ctrl+TAB as the
+ * forward focus traversal keys and Shift+TAB and Ctrl+Shift+TAB
+ * as the backward focus traversal keys. No up or down cycle
+ * traversal keys are defined by default. Traversal takes effect
+ * on the firing of a relevant <code>KEY_PRESSED</code> event.
+ * However, all other key events related to the use of the
+ * defined focus traversal key sequence are consumed and not
+ * dispatched.
+ * <br />
+ * <br />
+ * These default traversal keys come into effect on all windows
+ * for which no alternative set of keys is defined. This also
+ * applies recursively to any child components of such a window,
+ * which define no traversal keys of their own.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Thomas Fitzsimmons (fitzsim@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.4
+ */
+public abstract class KeyboardFocusManager
+ implements KeyEventDispatcher, KeyEventPostProcessor
+{
+ /** Identifies {@link AWTKeyStroke}s that move the focus forward in
+ the focus cycle. */
+ public static final int FORWARD_TRAVERSAL_KEYS = 0;
+
+ /** Identifies {@link AWTKeyStroke}s that move the focus backward in
+ the focus cycle. */
+ public static final int BACKWARD_TRAVERSAL_KEYS = 1;
+
+ /** Identifies {@link AWTKeyStroke}s that move the focus up to the
+ parent focus cycle root. */
+ public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
+
+ /** Identifies {@link AWTKeyStroke}s that move the focus down to the
+ child focus cycle root. */
+ public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
+
+ /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
+ the next focusable Component in the focus cycle. */
+ private static final Set DEFAULT_FORWARD_KEYS;
+
+ /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
+ the previous focusable Component in the focus cycle. */
+ private static final Set DEFAULT_BACKWARD_KEYS;
+
+ /** Populate the DEFAULT_FORWARD_KEYS and DEFAULT_BACKWARD_KEYS
+ {@link java.util.Set}s. */
+ static
+ {
+ Set s = new HashSet();
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.CTRL_DOWN_MASK));
+ DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
+ s = new HashSet();
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.SHIFT_DOWN_MASK));
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.SHIFT_DOWN_MASK
+ | KeyEvent.CTRL_DOWN_MASK));
+ DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
+ }
+
+ /** The global object {@link java.util.Map}s. */
+
+ /** For security reasons, {@link java.applet.Applet}s in different
+ codebases must be insulated from one another. Since {@link
+ KeyboardFocusManager}s have the ability to return {@link
+ Component}s from a given {@link java.applet.Applet}, each
+ codebase must have an independent {@link KeyboardFocusManager}.
+ Since each codebase has its own {@link ThreadGroup} in which its
+ {@link Applet}s run, it makes sense to partition {@link
+ KeyboardFocusManager}s according to {@link
+ java.lang.ThreadGroup}. Thus, currentKeyboardFocusManagers is a
+ {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}. */
+ private static Map currentKeyboardFocusManagers = new HashMap ();
+
+ /** {@link java.applet.Applet}s in one codebase must not be allowed
+ to access {@link Component}s in {@link java.applet.Applet}s in
+ other codebases. To enforce this restriction, we key the
+ following {@link java.util.Map}s on {@link java.lang.ThreadGroup}s (which
+ are per-codebase). For example, if {@link
+ java.lang.ThreadGroup} A calls {@link #setGlobalFocusOwner},
+ passing {@link Component} C, currentFocusOwners[A] is assigned
+ C, and all other currentFocusOwners values are nullified. Then
+ if {@link java.lang.ThreadGroup} A subsequently calls {@link
+ #getGlobalFocusOwner}, it will return currentFocusOwners[A],
+ that is, {@link Component} C. If another {@link
+ java.lang.ThreadGroup} K calls {@link #getGlobalFocusOwner}, it
+ will return currentFocusOwners[K], that is, null.
+
+ Since this is a static field, we ensure that there is only one
+ focused {@link Component} per class loader. */
+ private static Map currentFocusOwners = new HashMap ();
+
+ /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
+ that stores the {@link Component} that owns the permanent
+ keyboard focus. @see currentFocusOwners */
+ private static Map currentPermanentFocusOwners = new HashMap ();
+
+ /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
+ that stores the focused {@link Window}. @see
+ currentFocusOwners */
+ private static Map currentFocusedWindows = new HashMap ();
+
+ /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
+ that stores the active {@link Window}. @see
+ currentFocusOwners */
+ private static Map currentActiveWindows = new HashMap ();
+
+ /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
+ that stores the focus cycle root {@link Container}. @see
+ currentFocusOwners */
+ private static Map currentFocusCycleRoots = new HashMap ();
+
+ /** The default {@link FocusTraveralPolicy} that focus-managing
+ {@link Container}s will use to define their initial focus
+ traversal policy. */
+ private FocusTraversalPolicy defaultPolicy;
+
+ /** An array that stores the {@link #FORWARD_TRAVERSAL_KEYS}, {@link
+ #BACKWARD_TRAVERSAL_KEYS}, {@link #UP_CYCLE_TRAVERSAL_KEYS} and
+ {@link #DOWN_CYCLE_TRAVERSAL_KEYS} {@link AWTKeyStroke}s {@link
+ java.util.Set}s. */
+ private Set[] defaultFocusKeys = new Set[]
+ {
+ DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS,
+ Collections.EMPTY_SET, Collections.EMPTY_SET
+ };
+
+ /**
+ * A utility class to support the handling of events relating to property changes.
+ */
+ private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this);
+
+ /**
+ * A utility class to support the handling of events relating to vetoable changes.
+ */
+ private final VetoableChangeSupport vetoableChangeSupport = new VetoableChangeSupport (this);
+
+ /** A list of {@link KeyEventDispatcher}s that process {@link
+ KeyEvent}s before they are processed the default keyboard focus
+ manager. */
+ private final ArrayList keyEventDispatchers = new ArrayList();
+
+ /** A list of {@link KeyEventPostProcessor}s that process unconsumed
+ {@link KeyEvent}s. */
+ private final ArrayList keyEventPostProcessors = new ArrayList();
+
+ /**
+ * Construct a KeyboardFocusManager.
+ */
+ public KeyboardFocusManager ()
+ {
+ }
+
+ /**
+ * Retrieve the keyboard focus manager associated with the {@link
+ * java.lang.ThreadGroup} to which the calling thread belongs.
+ *
+ * @return the keyboard focus manager associated with the current
+ * thread group
+ */
+ public static KeyboardFocusManager getCurrentKeyboardFocusManager ()
+ {
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+
+ if (currentKeyboardFocusManagers.get (currentGroup) == null)
+ setCurrentKeyboardFocusManager (null);
+
+ return (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
+ }
+
+ /**
+ * Set the keyboard focus manager associated with the {@link
+ * java.lang.ThreadGroup} to which the calling thread belongs.
+ *
+ * @param m the keyboard focus manager for the current thread group
+ */
+ public static void setCurrentKeyboardFocusManager (KeyboardFocusManager m)
+ {
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission (new AWTPermission ("replaceKeyboardFocusManager"));
+
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ KeyboardFocusManager manager;
+
+ if (m == null)
+ manager = createFocusManager();
+ else
+ manager = m;
+
+ currentKeyboardFocusManagers.put (currentGroup, manager);
+ }
+
+ /**
+ * Creates a KeyboardFocusManager. The exact class is determined by the
+ * system property 'gnu.java.awt.FocusManager'. If this is not set,
+ * we default to DefaultKeyboardFocusManager.
+ */
+ private static KeyboardFocusManager createFocusManager()
+ {
+ String fmClassName = System.getProperty("gnu.java.awt.FocusManager",
+ "java.awt.DefaultKeyboardFocusManager");
+ try
+ {
+ Class fmClass = Class.forName(fmClassName);
+ KeyboardFocusManager fm = (KeyboardFocusManager) fmClass.newInstance();
+ return fm;
+ }
+ catch (ClassNotFoundException ex)
+ {
+ System.err.println("The class " + fmClassName + " cannot be found.");
+ System.err.println("Check the setting of the system property");
+ System.err.println("gnu.java.awt.FocusManager");
+ return null;
+ }
+ catch (InstantiationException ex)
+ {
+ System.err.println("The class " + fmClassName + " cannot be");
+ System.err.println("instantiated.");
+ System.err.println("Check the setting of the system property");
+ System.err.println("gnu.java.awt.FocusManager");
+ return null;
+ }
+ catch (IllegalAccessException ex)
+ {
+ System.err.println("The class " + fmClassName + " cannot be");
+ System.err.println("accessed.");
+ System.err.println("Check the setting of the system property");
+ System.err.println("gnu.java.awt.FocusManager");
+ return null;
+ }
+ }
+
+ /**
+ * Retrieve the {@link Component} that has the keyboard focus, or
+ * null if the focus owner was not set by a thread in the current
+ * {@link java.lang.ThreadGroup}.
+ *
+ * @return the keyboard focus owner or null
+ */
+ public Component getFocusOwner ()
+ {
+ Component owner = (Component) getObject (currentFocusOwners);
+ if (owner == null)
+ owner = (Component) getObject (currentPermanentFocusOwners);
+ return owner;
+ }
+
+ /**
+ * Retrieve the {@link Component} that has the keyboard focus,
+ * regardless of whether or not it was set by a thread in the
+ * current {@link java.lang.ThreadGroup}. If there is no temporary
+ * focus owner in effect then this method will return the same value
+ * as {@link #getGlobalPermanentFocusOwner}.
+ *
+ * @return the keyboard focus owner
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Component getGlobalFocusOwner ()
+ {
+ // Check if there is a temporary focus owner.
+ Component focusOwner = (Component) getGlobalObject (currentFocusOwners);
+
+ return (focusOwner == null) ? getGlobalPermanentFocusOwner () : focusOwner;
+ }
+
+ /**
+ * Set the {@link Component} that will be returned by {@link
+ * #getFocusOwner} (when it is called from the current {@link
+ * java.lang.ThreadGroup}) and {@link #getGlobalFocusOwner}. This
+ * method does not actually transfer the keyboard focus.
+ *
+ * @param owner the Component to return from getFocusOwner and
+ * getGlobalFocusOwner
+ *
+ * @see Component#requestFocus()
+ * @see Component#requestFocusInWindow()
+ */
+ protected void setGlobalFocusOwner (Component owner)
+ {
+ if (owner == null || owner.focusable)
+ setGlobalObject (currentFocusOwners, owner, "focusOwner");
+ }
+
+ /**
+ * Clear the global focus owner and deliver a FOCUS_LOST event to
+ * the previously-focused {@link Component}. Until another {@link
+ * Component} becomes the keyboard focus owner, key events will be
+ * discarded by top-level windows.
+ */
+ public void clearGlobalFocusOwner ()
+ {
+ synchronized (currentFocusOwners)
+ {
+ Component focusOwner = getGlobalFocusOwner ();
+ Component permanentFocusOwner = getGlobalPermanentFocusOwner ();
+
+ setGlobalFocusOwner (null);
+ setGlobalPermanentFocusOwner (null);
+
+ // Inform the old focus owner that it has lost permanent
+ // focus.
+ if (focusOwner != null)
+ {
+ // We can't cache the event queue, because of
+ // bootstrapping issues. We need to set the default
+ // KeyboardFocusManager in EventQueue before the event
+ // queue is started.
+ EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+ if (focusOwner != permanentFocusOwner)
+ q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, true));
+ else
+ q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, false));
+ }
+
+ if (focusOwner != permanentFocusOwner)
+ {
+ EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+ q.postEvent (new FocusEvent (permanentFocusOwner, FocusEvent.FOCUS_LOST, false));
+ }
+ }
+ }
+
+ /**
+ * Retrieve the {@link Component} that has the permanent keyboard
+ * focus, or null if the focus owner was not set by a thread in the
+ * current {@link java.lang.ThreadGroup}.
+ *
+ * @return the keyboard focus owner or null
+ */
+ public Component getPermanentFocusOwner ()
+ {
+ return (Component) getObject (currentPermanentFocusOwners);
+ }
+
+ /**
+ * Retrieve the {@link Component} that has the permanent keyboard
+ * focus, regardless of whether or not it was set by a thread in the
+ * current {@link java.lang.ThreadGroup}.
+ *
+ * @return the keyboard focus owner
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Component getGlobalPermanentFocusOwner ()
+ {
+ return (Component) getGlobalObject (currentPermanentFocusOwners);
+ }
+
+ /**
+ * Set the {@link Component} that will be returned by {@link
+ * #getPermanentFocusOwner} (when it is called from the current
+ * {@link java.lang.ThreadGroup}) and {@link
+ * #getGlobalPermanentFocusOwner}. This method does not actually
+ * transfer the keyboard focus.
+ *
+ * @param focusOwner the Component to return from
+ * getPermanentFocusOwner and getGlobalPermanentFocusOwner
+ *
+ * @see Component#requestFocus()
+ * @see Component#requestFocusInWindow()
+ */
+ protected void setGlobalPermanentFocusOwner (Component focusOwner)
+ {
+ if (focusOwner == null || focusOwner.focusable)
+ setGlobalObject (currentPermanentFocusOwners, focusOwner,
+ "permanentFocusOwner");
+ }
+
+ /**
+ * Retrieve the {@link Window} that is or contains the keyboard
+ * focus owner, or null if the focused window was not set by a
+ * thread in the current {@link java.lang.ThreadGroup}.
+ *
+ * @return the focused window or null
+ */
+ public Window getFocusedWindow ()
+ {
+ return (Window) getObject (currentFocusedWindows);
+ }
+
+ /**
+ * Retrieve the {@link Window} that is or contains the focus owner,
+ * regardless of whether or not the {@link Window} was set focused
+ * by a thread in the current {@link java.lang.ThreadGroup}.
+ *
+ * @return the focused window
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Window getGlobalFocusedWindow ()
+ {
+ return (Window) getGlobalObject (currentFocusedWindows);
+ }
+
+ /**
+ * Set the {@link Window} that will be returned by {@link
+ * #getFocusedWindow} (when it is called from the current {@link
+ * java.lang.ThreadGroup}) and {@link #getGlobalFocusedWindow}.
+ * This method does not actually cause <code>window</code> to become
+ * the focused {@link Window}.
+ *
+ * @param window the Window to return from getFocusedWindow and
+ * getGlobalFocusedWindow
+ */
+ protected void setGlobalFocusedWindow (Window window)
+ {
+ if (window == null || window.focusable)
+ setGlobalObject (currentFocusedWindows, window, "focusedWindow");
+ }
+
+ /**
+ * Retrieve the active {@link Window}, or null if the active window
+ * was not set by a thread in the current {@link
+ * java.lang.ThreadGroup}.
+ *
+ * @return the active window or null
+ */
+ public Window getActiveWindow()
+ {
+ return (Window) getObject (currentActiveWindows);
+ }
+
+ /**
+ * Retrieve the active {@link Window}, regardless of whether or not
+ * the {@link Window} was made active by a thread in the current
+ * {@link java.lang.ThreadGroup}.
+ *
+ * @return the active window
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Window getGlobalActiveWindow()
+ {
+ return (Window) getGlobalObject (currentActiveWindows);
+ }
+
+ /**
+ * Set the {@link Window} that will be returned by {@link
+ * #getActiveWindow} (when it is called from the current {@link
+ * java.lang.ThreadGroup}) and {@link #getGlobalActiveWindow}. This
+ * method does not actually cause <code>window</code> to be made
+ * active.
+ *
+ * @param window the Window to return from getActiveWindow and
+ * getGlobalActiveWindow
+ */
+ protected void setGlobalActiveWindow(Window window)
+ {
+ setGlobalObject (currentActiveWindows, window, "activeWindow");
+ }
+
+ /**
+ * Retrieve the default {@link FocusTraversalPolicy}.
+ * Focus-managing {@link Container}s use the returned object to
+ * define their initial focus traversal policy.
+ *
+ * @return a non-null default FocusTraversalPolicy object
+ */
+ public FocusTraversalPolicy getDefaultFocusTraversalPolicy ()
+ {
+ if (defaultPolicy == null)
+ defaultPolicy = new DefaultFocusTraversalPolicy ();
+ return defaultPolicy;
+ }
+
+ /**
+ * Set the {@link FocusTraversalPolicy} returned by {@link
+ * #getDefaultFocusTraversalPolicy}. Focus-managing {@link
+ * Container}s created after this call will use policy as their
+ * initial focus traversal policy. Existing {@link Container}s'
+ * focus traversal policies will not be affected by calls to this
+ * method.
+ *
+ * @param policy the FocusTraversalPolicy that will be returned by
+ * subsequent calls to getDefaultFocusTraversalPolicy
+ * @throws IllegalArgumentException if policy is null
+ */
+ public void setDefaultFocusTraversalPolicy (FocusTraversalPolicy policy)
+ {
+ if (policy == null)
+ throw new IllegalArgumentException ();
+ firePropertyChange ("defaultFocusTraversalPolicy", defaultPolicy, policy);
+ defaultPolicy = policy;
+ }
+
+ /**
+ * Set the default {@link java.util.Set} of focus traversal keys for
+ * one of the focus traversal directions.
+ *
+ * @param id focus traversal direction identifier
+ * @param keystrokes set of AWTKeyStrokes
+ *
+ * @see #FORWARD_TRAVERSAL_KEYS
+ * @see #BACKWARD_TRAVERSAL_KEYS
+ * @see #UP_CYCLE_TRAVERSAL_KEYS
+ * @see #DOWN_CYCLE_TRAVERSAL_KEYS
+ */
+ public void setDefaultFocusTraversalKeys (int id, Set keystrokes)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ if (keystrokes == null)
+ throw new IllegalArgumentException ();
+
+ Set sa;
+ Set sb;
+ Set sc;
+ String type;
+ switch (id)
+ {
+ case FORWARD_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "forwardDefaultFocusTraversalKeys";
+ break;
+ case BACKWARD_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "backwardDefaultFocusTraversalKeys";
+ break;
+ case UP_CYCLE_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "upCycleDefaultFocusTraversalKeys";
+ break;
+ case DOWN_CYCLE_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ type = "downCycleDefaultFocusTraversalKeys";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+ int i = keystrokes.size ();
+ Iterator iter = keystrokes.iterator ();
+ while (--i >= 0)
+ {
+ Object o = iter.next ();
+ if (!(o instanceof AWTKeyStroke)
+ || sa.contains (o) || sb.contains (o) || sc.contains (o)
+ || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
+ throw new IllegalArgumentException ();
+ }
+ keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
+ firePropertyChange (type, defaultFocusKeys[id], keystrokes);
+ defaultFocusKeys[id] = keystrokes;
+ }
+
+ /**
+ * Retrieve the default {@link java.util.Set} of focus traversal
+ * keys for one of the focus traversal directions.
+ *
+ * @param id focus traversal direction identifier
+ *
+ * @return the default set of AWTKeyStrokes
+ *
+ * @see #FORWARD_TRAVERSAL_KEYS
+ * @see #BACKWARD_TRAVERSAL_KEYS
+ * @see #UP_CYCLE_TRAVERSAL_KEYS
+ * @see #DOWN_CYCLE_TRAVERSAL_KEYS
+ */
+ public Set getDefaultFocusTraversalKeys (int id)
+ {
+ if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+ return defaultFocusKeys[id];
+ }
+
+ /**
+ * Retrieve the current focus cycle root, or null if the focus owner
+ * was not set by a thread in the current {@link
+ * java.lang.ThreadGroup}.
+ *
+ * @return the current focus cycle root or null
+ */
+ public Container getCurrentFocusCycleRoot ()
+ {
+ return (Container) getObject (currentFocusCycleRoots);
+ }
+
+ /**
+ * Retrieve the current focus cycle root, regardless of whether or
+ * not it was made set by a thread in the current {@link
+ * java.lang.ThreadGroup}.
+ *
+ * @return the current focus cycle root
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Container getGlobalCurrentFocusCycleRoot ()
+ {
+ return (Container) getGlobalObject (currentFocusCycleRoots);
+ }
+
+ /**
+ * Set the {@link Container} that will be returned by {@link
+ * #getCurrentFocusCycleRoot} (when it is called from the current
+ * {@link java.lang.ThreadGroup}) and {@link
+ * #getGlobalCurrentFocusCycleRoot}. This method does not actually
+ * make <code>cycleRoot</code> the current focus cycle root.
+ *
+ * @param cycleRoot the focus cycle root to return from
+ * getCurrentFocusCycleRoot and getGlobalCurrentFocusCycleRoot
+ */
+ public void setGlobalCurrentFocusCycleRoot (Container cycleRoot)
+ {
+ setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot");
+ }
+
+ /**
+ * Registers the supplied property change listener for receiving
+ * events caused by the following property changes:
+ *
+ * <ul>
+ * <li>the current focus owner ("focusOwner")</li>
+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
+ * <li>the focused window ("focusedWindow")</li>
+ * <li>the active window ("activeWindow")</li>
+ * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
+ * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
+ * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
+ * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
+ * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
+ * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
+ * </ul>
+ *
+ * If the supplied listener is null, nothing occurs.
+ *
+ * @param l the new listener to register.
+ * @see KeyboardFocusManager#addPropertyChangeListener(String, java.beans.PropertyChangeListener)
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.addPropertyChangeListener(l);
+ }
+
+ /**
+ * Removes the supplied property change listener from the list
+ * of registered listeners. If the supplied listener is null,
+ * nothing occurs.
+ *
+ * @param l the listener to remove.
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.removePropertyChangeListener(l);
+ }
+
+ /**
+ * Returns the currently registered property change listeners
+ * in array form. The returned array is empty if no listeners are
+ * currently registered.
+ *
+ * @return an array of registered property change listeners.
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return propertyChangeSupport.getPropertyChangeListeners();
+ }
+
+ /**
+ * Registers a property change listener for receiving events relating
+ * to a change to a specified property. The supplied property name can be
+ * either user-defined or one from the following list of properties
+ * relevant to this class:
+ *
+ * <ul>
+ * <li>the current focus owner ("focusOwner")</li>
+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
+ * <li>the focused window ("focusedWindow")</li>
+ * <li>the active window ("activeWindow")</li>
+ * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
+ * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
+ * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
+ * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
+ * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
+ * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
+ * </ul>
+ *
+ * Nothing occurs if a null listener is supplied. null is regarded as a valid property name.
+ *
+ * @param name the name of the property to handle change events for.
+ * @param l the listener to register for changes to the specified property.
+ * @see KeyboardFocusManager#addPropertyChangeListener(java.beans.PropertyChangeListener)
+ */
+ public void addPropertyChangeListener(String name, PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.addPropertyChangeListener(name, l);
+ }
+
+ /**
+ * Removes the supplied property change listener registered for the
+ * specified property from the list of registered listeners. If the
+ * supplied listener is null, nothing occurs.
+ *
+ * @param name the name of the property the listener is
+ * monitoring changes to.
+ * @param l the listener to remove.
+ */
+ public void removePropertyChangeListener(String name,
+ PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.removePropertyChangeListener(name, l);
+ }
+
+ /**
+ * Returns the currently registered property change listeners
+ * in array form, which listen for changes to the supplied property.
+ * The returned array is empty, if no listeners are currently registered
+ * for events pertaining to the supplied property.
+ *
+ * @param name The property the returned listeners monitor for changes.
+ * @return an array of registered property change listeners which
+ * listen for changes to the supplied property.
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners(String name)
+ {
+ return propertyChangeSupport.getPropertyChangeListeners(name);
+ }
+
+ /**
+ * Fires a property change event as a response to a change to
+ * to the specified property. The event is only fired if a
+ * change has actually occurred (i.e. o and n are different).
+ *
+ * @param name The name of the property to which a change occurred.
+ * @param o The old value of the property.
+ * @param n The new value of the property.
+ */
+ protected void firePropertyChange(String name, Object o, Object n)
+ {
+ propertyChangeSupport.firePropertyChange(name, o, n);
+ }
+
+ /**
+ * Registers a vetoable property change listener for receiving events
+ * relating to the following properties:
+ *
+ * <ul>
+ * <li>the current focus owner ("focusOwner")</li>
+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
+ * <li>the focused window ("focusedWindow")</li>
+ * <li>the active window ("activeWindow")</li>
+ * </ul>
+ *
+ * Nothing occurs if a null listener is supplied.
+ *
+ * @param l the listener to register.
+ * @see KeyboardFocusManager#addVetoableChangeListener(String, java.beans.VetoableChangeListener)
+ */
+ public void addVetoableChangeListener(VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.addVetoableChangeListener(l);
+ }
+
+ /**
+ * Removes the supplied vetoable property change listener from
+ * the list of registered listeners. If the supplied listener
+ * is null, nothing occurs.
+ *
+ * @param l the listener to remove.
+ */
+ public void removeVetoableChangeListener(VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.removeVetoableChangeListener(l);
+ }
+
+ /**
+ * Returns the currently registered vetoable property change listeners
+ * in array form. The returned array is empty if no listeners are
+ * currently registered.
+ *
+ * @return an array of registered vetoable property change listeners.
+ * @since 1.4
+ */
+ public VetoableChangeListener[] getVetoableChangeListeners()
+ {
+ return vetoableChangeSupport.getVetoableChangeListeners();
+ }
+
+ /**
+ * Registers a vetoable property change listener for receiving events relating
+ * to a vetoable change to a specified property. The supplied property name can be
+ * either user-defined or one from the following list of properties
+ * relevant to this class:
+ *
+ * <ul>
+ * <li>the current focus owner ("focusOwner")</li>
+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
+ * <li>the focused window ("focusedWindow")</li>
+ * <li>the active window ("activeWindow")</li>
+ * </ul>
+ *
+ * Nothing occurs if a null listener is supplied. null is regarded as a valid property name.
+ *
+ * @param name the name of the property to handle change events for.
+ * @param l the listener to register for changes to the specified property.
+ * @see KeyboardFocusManager#addVetoableChangeListener(java.beans.VetoableChangeListener)
+ */
+ public void addVetoableChangeListener(String name, VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.addVetoableChangeListener(name, l);
+ }
+
+ /**
+ * Removes the supplied vetoable property change listener registered
+ * for the specified property from the list of registered listeners.
+ * If the supplied listener is null, nothing occurs.
+ *
+ * @param name the name of the vetoable property the listener is
+ * monitoring changes to.
+ * @param l the listener to remove.
+ */
+ public void removeVetoableChangeListener(String name,
+ VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.removeVetoableChangeListener(name, l);
+ }
+
+ /**
+ * Returns the currently registered vetoable property change listeners
+ * in array form, which listen for changes to the supplied property.
+ * The returned array is empty, if no listeners are currently registered
+ * for events pertaining to the supplied property.
+ *
+ * @param name The property the returned listeners monitor for changes.
+ * @return an array of registered property change listeners which
+ * listen for changes to the supplied property.
+ * @since 1.4
+ */
+ public VetoableChangeListener[] getVetoableChangeListeners(String name)
+ {
+ return vetoableChangeSupport.getVetoableChangeListeners(name);
+ }
+
+ /**
+ * Fires a property change event as a response to a vetoable change to
+ * to the specified property. The event is only fired if a
+ * change has actually occurred (i.e. o and n are different).
+ * In the event that the property change is vetoed, the following
+ * occurs:
+ *
+ * <ol>
+ * <li>
+ * This method throws a <code>PropertyVetoException</code> to
+ * the proposed change.
+ * </li>
+ * <li>
+ * A new event is fired to reverse the previous change.
+ * </li>
+ * <li>
+ * This method again throws a <code>PropertyVetoException</code>
+ * in response to the reversion.
+ * </li>
+ * </ol>
+ *
+ * @param name The name of the property to which a change occurred.
+ * @param o The old value of the property.
+ * @param n The new value of the property.
+ * @throws PropertyVetoException if one of the listeners vetos
+ * the change by throwing this exception.
+ */
+ protected void fireVetoableChange(String name, Object o, Object n)
+ throws PropertyVetoException
+ {
+ vetoableChangeSupport.fireVetoableChange(name, o, n);
+ }
+
+ /**
+ * Adds a key event dispatcher to the list of registered dispatchers.
+ * When a key event is fired, each dispatcher's <code>dispatchKeyEvent</code>
+ * method is called in the order that they were added, prior to the manager
+ * dispatching the event itself. Notifications halt when one of the
+ * dispatchers returns true.
+ * <br />
+ * <br />
+ * The same dispatcher can exist multiple times within the list
+ * of registered dispatchers, and there is no limit on the length
+ * of this list. A null dispatcher is simply ignored.
+ *
+ * @param dispatcher The dispatcher to register.
+ */
+ public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
+ {
+ if (dispatcher != null)
+ keyEventDispatchers.add(dispatcher);
+ }
+
+ /**
+ * Removes the specified key event dispatcher from the list of
+ * registered dispatchers. The manager always dispatches events,
+ * regardless of its existence within the list. The manager
+ * can be added and removed from the list, as with any other
+ * dispatcher, but this does not affect its ability to dispatch
+ * key events. Non-existent and null dispatchers are simply ignored
+ * by this method.
+ *
+ * @param dispatcher The dispatcher to remove.
+ */
+ public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
+ {
+ keyEventDispatchers.remove(dispatcher);
+ }
+
+ /**
+ * Returns the currently registered key event dispatchers in <code>List</code>
+ * form. At present, this only includes dispatchers explicitly registered
+ * via the <code>addKeyEventDispatcher()</code> method, but this behaviour
+ * is subject to change and should not be depended on. The manager itself
+ * may be a member of the list, but only if explicitly registered. If no
+ * dispatchers have been registered, the list will be empty.
+ *
+ * @return A list of explicitly registered key event dispatchers.
+ * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
+ */
+ protected List getKeyEventDispatchers ()
+ {
+ return (List) keyEventDispatchers.clone ();
+ }
+
+ /**
+ * Adds a key event post processor to the list of registered post processors.
+ * Post processors work in the same way as key event dispatchers, except
+ * that they are invoked after the manager has dispatched the key event,
+ * and not prior to this. Each post processor's <code>postProcessKeyEvent</code>
+ * method is called to see if any post processing needs to be performed. THe
+ * processors are called in the order in which they were added to the list,
+ * and notifications continue until one returns true. As with key event
+ * dispatchers, the manager is implicitly called following this process,
+ * regardless of whether or not it is present within the list.
+ * <br />
+ * <br />
+ * The same post processor can exist multiple times within the list
+ * of registered post processors, and there is no limit on the length
+ * of this list. A null post processor is simply ignored.
+ *
+ * @param postProcessor the post processor to register.
+ * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
+ */
+ public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
+ {
+ if (postProcessor != null)
+ keyEventPostProcessors.add (postProcessor);
+ }
+
+ /**
+ * Removes the specified key event post processor from the list of
+ * registered post processors. The manager always post processes events,
+ * regardless of its existence within the list. The manager
+ * can be added and removed from the list, as with any other
+ * post processor, but this does not affect its ability to post process
+ * key events. Non-existent and null post processors are simply ignored
+ * by this method.
+ *
+ * @param postProcessor the post processor to remove.
+ */
+ public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
+ {
+ keyEventPostProcessors.remove (postProcessor);
+ }
+
+ /**
+ * Returns the currently registered key event post processors in <code>List</code>
+ * form. At present, this only includes post processors explicitly registered
+ * via the <code>addKeyEventPostProcessor()</code> method, but this behaviour
+ * is subject to change and should not be depended on. The manager itself
+ * may be a member of the list, but only if explicitly registered. If no
+ * post processors have been registered, the list will be empty.
+ *
+ * @return A list of explicitly registered key event post processors.
+ * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor)
+ */
+ protected List getKeyEventPostProcessors ()
+ {
+ return (List) keyEventPostProcessors.clone ();
+ }
+
+ /**
+ * The AWT event dispatcher uses this method to request that the manager
+ * handle a particular event. If the manager fails or refuses to
+ * dispatch the supplied event (this method returns false), the
+ * AWT event dispatcher will try to dispatch the event itself.
+ * <br />
+ * <br />
+ * The manager is expected to handle all <code>FocusEvent</code>s
+ * and <code>KeyEvent</code>s, and <code>WindowEvent</code>s
+ * relating to the focus. Dispatch is done with regard to the
+ * the focus owner and the currently focused and active windows.
+ * In handling the event, the source of the event may be overridden.
+ * <br />
+ * <br />
+ * The actual dispatching is performed by calling
+ * <code>redispatchEvent()</code>. This avoids the infinite recursion
+ * of dispatch requests which may occur if this method is called on
+ * the target component.
+ *
+ * @param e the event to dispatch.
+ * @return true if the event was dispatched.
+ * @see KeyboardFocusManager#redispatchEvent(java.awt.Component, java.awt.AWTEvent)
+ * @see KeyEvent
+ * @see FocusEvent
+ * @see WindowEvent
+ */
+ public abstract boolean dispatchEvent (AWTEvent e);
+
+ /**
+ * Handles redispatching of an event so that recursion of
+ * dispatch requests does not occur. Event dispatch methods
+ * within this manager (<code>dispatchEvent()</code>) and
+ * the key event dispatchers should use this method to handle
+ * dispatching rather than the dispatch method of the target
+ * component.
+ * <br />
+ * <br />
+ * <strong>
+ * This method is not intended for general consumption, and is
+ * only for the use of the aforementioned classes.
+ * </strong>
+ *
+ * @param target the target component to which the event is
+ * dispatched.
+ * @param e the event to dispatch.
+ */
+ public final void redispatchEvent (Component target, AWTEvent e)
+ {
+ synchronized (e)
+ {
+ e.setSource (target);
+ target.dispatchEvent (e);
+ }
+ }
+
+ /**
+ * Attempts to dispatch key events for which no key event dispatcher
+ * has so far succeeded. This method is usually called by
+ * <code>dispatchEvent()</code> following the sending of the key
+ * event to any registered key event dispatchers. If the key
+ * event reaches this stage, none of the dispatchers returned
+ * true. This is, of course, always the case if there are no
+ * registered dispatchers.
+ * <br />
+ * <br />
+ * If this method also fails to handle the key event, then
+ * false is returned to the caller. In the case of
+ * <code>dispatchEvent()</code>, the calling method may try
+ * to handle the event itself or simply forward on the
+ * false result to its caller. When the event is dispatched
+ * by this method, a true result is propogated through the
+ * calling methods.
+ *
+ * @param e the key event to dispatch.
+ * @return true if the event was dispatched successfully.
+ */
+ public abstract boolean dispatchKeyEvent (KeyEvent e);
+
+ /**
+ * Handles the post processing of key events. By default,
+ * this method will map unhandled key events to appropriate
+ * <code>MenuShortcut</code>s. The event is consumed
+ * in the process and the shortcut is activated. This
+ * method is usually called by <code>dispatchKeyEvent</code>.
+ *
+ * @param e the key event to post process.
+ * @return true by default, as the event was handled.
+ */
+ public abstract boolean postProcessKeyEvent (KeyEvent e);
+
+ /**
+ * Handles focus traversal operations for key events which
+ * represent focus traversal keys in relation to the supplied
+ * component. The supplied component is assumed to have the
+ * focus, whether it does so or not, and the operation is
+ * carried out as appropriate, with this in mind.
+ *
+ * @param focused the component on which to perform focus traversal,
+ * on the assumption that this component has the focus.
+ * @param e the possible focus traversal key event.
+ */
+ public abstract void processKeyEvent (Component focused, KeyEvent e);
+
+ /**
+ * Delays all key events following the specified timestamp until the
+ * supplied component has focus. The AWT calls this method when it is
+ * determined that a focus change may occur within the native windowing
+ * system. Any key events which occur following the time specified by
+ * after are delayed until a <code>FOCUS_GAINED</code> event is received
+ * for the untilFocused component. The manager is responsible for ensuring
+ * this takes place.
+ *
+ * @param after the timestamp beyond which all key events are delayed until
+ * the supplied component gains focus.
+ * @param untilFocused the component to wait on gaining focus.
+ */
+ protected abstract void enqueueKeyEvents (long after, Component untilFocused);
+
+ /**
+ * Removes the key event block specified by the supplied timestamp and component.
+ * All delayed key events are released for normal dispatching following its
+ * removal and subsequent key events that would have been blocked are now
+ * immediately dispatched. If the specified timestamp is below 0, then
+ * the request with the oldest timestamp is removed.
+ *
+ * @param after the timestamp of the key event block to be removed, or a
+ * value smaller than 0 if the oldest is to be removed.
+ * @param untilFocused the component of the key event block to be removed.
+ */
+ protected abstract void dequeueKeyEvents (long after, Component untilFocused);
+
+ /**
+ * Discards all key event blocks relating to focus requirements for
+ * the supplied component, regardless of timestamp.
+ *
+ * @param comp the component of the key event block(s) to be removed.
+ */
+ protected abstract void discardKeyEvents (Component comp);
+
+ /**
+ * Moves the current focus to the next component following
+ * comp, based on the current focus traversal policy. By
+ * default, only visible, displayable, accepted components
+ * can receive focus. <code>Canvas</code>es, <code>Panel</code>s,
+ * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
+ * <code>Window</code>s and lightweight components are judged
+ * to be unacceptable by default. See the
+ * <code>DefaultFocusTraversalPolicy</code> for more details.
+ *
+ * @param comp the component prior to the one which will
+ * become the focus, following execution of this method.
+ * @see DefaultFocusTraversalPolicy
+ */
+ public abstract void focusNextComponent(Component comp);
+
+ /**
+ * Moves the current focus to the previous component, prior to
+ * comp, based on the current focus traversal policy. By
+ * default, only visible, displayable, accepted components
+ * can receive focus. <code>Canvas</code>es, <code>Panel</code>s,
+ * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
+ * <code>Window</code>s and lightweight components are judged
+ * to be unacceptable by default. See the
+ * <code>DefaultFocusTraversalPolicy</code> for more details.
+ *
+ * @param comp the component following the one which will
+ * become the focus, following execution of this method.
+ * @see DefaultFocusTraversalPolicy
+ */
+ public abstract void focusPreviousComponent(Component comp);
+
+ /**
+ * Moves the current focus upwards by one focus cycle.
+ * Both the current focus owner and current focus cycle root
+ * become the focus cycle root of the supplied component.
+ * However, in the case of a <code>Window</code>, the default
+ * focus component becomes the focus owner and the focus cycle
+ * root is not changed.
+ *
+ * @param comp the component used as part of the focus traversal.
+ */
+ public abstract void upFocusCycle(Component comp);
+
+ /**
+ * Moves the current focus downwards by one focus cycle.
+ * If the supplied container is a focus cycle root, then this
+ * becomes the current focus cycle root and the focus goes
+ * to the default component of the specified container.
+ * Nothing happens for non-focus cycle root containers.
+ *
+ * @param cont the container used as part of the focus traversal.
+ */
+ public abstract void downFocusCycle(Container cont);
+
+ /**
+ * Moves the current focus to the next component, based on the
+ * current focus traversal policy. By default, only visible,
+ * displayable, accepted component can receive focus.
+ * <code>Canvas</code>es, <code>Panel</code>s,
+ * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
+ * <code>Window</code>s and lightweight components are judged
+ * to be unacceptable by default. See the
+ * <code>DefaultFocusTraversalPolicy</code> for more details.
+ *
+ * @see DefaultFocusTraversalPolicy
+ */
+ public final void focusNextComponent()
+ {
+ focusNextComponent (null);
+ }
+
+ /**
+ * Moves the current focus to the previous component, based on the
+ * current focus traversal policy. By default, only visible,
+ * displayable, accepted component can receive focus.
+ * <code>Canvas</code>es, <code>Panel</code>s,
+ * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
+ * <code>Window</code>s and lightweight components are judged
+ * to be unacceptable by default. See the
+ * <code>DefaultFocusTraversalPolicy</code> for more details.
+ *
+ * @see DefaultFocusTraversalPolicy
+ */
+ public final void focusPreviousComponent()
+ {
+ focusPreviousComponent (null);
+ }
+
+ /**
+ * Moves the current focus upwards by one focus cycle,
+ * so that the new focus owner is the focus cycle root
+ * of the current owner. The current focus cycle root then
+ * becomes the focus cycle root of the new focus owner.
+ * However, in the case of the focus cycle root of the
+ * current focus owner being a <code>Window</code>, the default
+ * component of this window becomes the focus owner and the
+ * focus cycle root is not changed.
+ */
+ public final void upFocusCycle()
+ {
+ upFocusCycle (null);
+ }
+
+ /**
+ * Moves the current focus downwards by one focus cycle,
+ * iff the current focus cycle root is a <code>Container</code>.
+ * Usually, the new focus owner is set to the default component
+ * of the container and the current focus cycle root is set
+ * to the current focus owner. Nothing occurs if the current
+ * focus cycle root is not a container.
+ */
+ public final void downFocusCycle()
+ {
+ Component focusOwner = getGlobalFocusOwner ();
+ if (focusOwner instanceof Container
+ && ((Container) focusOwner).isFocusCycleRoot ())
+ downFocusCycle ((Container) focusOwner);
+ }
+
+ /**
+ * Retrieve an object from one of the global object {@link
+ * java.util.Map}s, if the object was set by the a thread in the
+ * current {@link java.lang.ThreadGroup}. Otherwise, return null.
+ *
+ * @param globalMap one of the global object Maps
+ *
+ * @return a global object set by the current ThreadGroup, or null
+ *
+ * @see getFocusOwner
+ * @see getPermanentFocusOwner
+ * @see getFocusedWindow
+ * @see getActiveWindow
+ * @see getCurrentFocusCycleRoot
+ */
+ private Object getObject (Map globalMap)
+ {
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ return globalMap.get (currentGroup);
+ }
+
+ /**
+ * Retrieve an object from one of the global object {@link
+ * java.util.Map}s, regardless of whether or not the object was set
+ * by a thread in the current {@link java.lang.ThreadGroup}.
+ *
+ * @param globalMap one of the global object Maps
+ *
+ * @return a global object set by the current ThreadGroup, or null
+ *
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ *
+ * @see getGlobalFocusOwner
+ * @see getGlobalPermanentFocusOwner
+ * @see getGlobalFocusedWindow
+ * @see getGlobalActiveWindow
+ * @see getGlobalCurrentFocusCycleRoot
+ */
+ private Object getGlobalObject (Map globalMap)
+ {
+ 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 ();
+ Iterator i = globalObjects.iterator ();
+ Component globalObject;
+
+ while (i.hasNext ())
+ {
+ globalObject = (Component) i.next ();
+ if (globalObject != null)
+ return globalObject;
+ }
+ }
+
+ // No Object was found.
+ return null;
+ }
+
+ /**
+ * Set an object in one of the global object {@link java.util.Map}s,
+ * that will be returned by subsequent calls to getGlobalObject on
+ * the same {@link java.util.Map}.
+ *
+ * @param globalMap one of the global object Maps
+ * @param newObject the object to set
+ * @param property the property that will change
+ *
+ * @see setGlobalFocusOwner
+ * @see setGlobalPermanentFocusOwner
+ * @see setGlobalFocusedWindow
+ * @see setGlobalActiveWindow
+ * @see setGlobalCurrentFocusCycleRoot
+ */
+ private void setGlobalObject (Map globalMap,
+ Object newObject,
+ String property)
+ {
+ synchronized (globalMap)
+ {
+ // Save old object.
+ Object oldObject = getGlobalObject (globalMap);
+
+ // Nullify old object.
+ Collection threadGroups = globalMap.keySet ();
+ Iterator i = threadGroups.iterator ();
+ while (i.hasNext ())
+ {
+ ThreadGroup oldThreadGroup = (ThreadGroup) i.next ();
+ if (globalMap.get (oldThreadGroup) != null)
+ {
+ globalMap.put (oldThreadGroup, null);
+ // There should only be one object set at a time, so
+ // we can short circuit.
+ break;
+ }
+ }
+
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ firePropertyChange (property, oldObject, newObject);
+ try
+ {
+ fireVetoableChange (property, oldObject, newObject);
+ // Set new object.
+ globalMap.put (currentGroup, newObject);
+ }
+ catch (PropertyVetoException e)
+ {
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/Label.java b/libjava/classpath/java/awt/Label.java
new file mode 100644
index 00000000000..8867fa12e35
--- /dev/null
+++ b/libjava/classpath/java/awt/Label.java
@@ -0,0 +1,314 @@
+/* Label.java -- Java label widget
+ Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.LabelPeer;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This component is used for displaying simple text strings that cannot
+ * be edited by the user.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class Label extends Component implements Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * Alignment constant aligning the text to the left of its window.
+ */
+public static final int LEFT = 0;
+
+/**
+ * Alignment constant aligning the text in the center of its window.
+ */
+public static final int CENTER = 1;
+
+/**
+ * Alignment constant aligning the text to the right of its window.
+ */
+public static final int RIGHT = 2;
+
+// Serialization version constant:
+private static final long serialVersionUID = 3094126758329070636L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial Indicates the alignment of the text within this label's window.
+ * This is one of the constants in this class. The default value is
+ * <code>LEFT</code>.
+ */
+private int alignment;
+
+/**
+ * @serial The text displayed in the label
+ */
+private String text;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>Label</code> with no text.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+Label()
+{
+ this("", LEFT);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Label</code> with the specified
+ * text that is aligned to the left.
+ *
+ * @param text The text of the label.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+Label(String text)
+{
+ this(text, LEFT);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Label</code> with the specified
+ * text and alignment.
+ *
+ * @param text The text of the label.
+ * @param alignment The desired alignment for the text in this label,
+ * which must be one of <code>LEFT</code>, <code>CENTER</code>, or
+ * <code>RIGHT</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+Label(String text, int alignment)
+{
+ setAlignment (alignment);
+ setText (text);
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the constant indicating the alignment of the text in this
+ * label. The value returned will be one of the alignment constants
+ * from this class.
+ *
+ * @return The alignment of the text in the label.
+ */
+public int
+getAlignment()
+{
+ return(alignment);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the text alignment of this label to the specified value.
+ *
+ * @param alignment The desired alignment for the text in this label,
+ * which must be one of <code>LEFT</code>, <code>CENTER</code>, or
+ * <code>RIGHT</code>.
+ */
+public synchronized void
+setAlignment(int alignment)
+{
+ if (alignment != CENTER && alignment != LEFT && alignment != RIGHT)
+ throw new IllegalArgumentException ("invalid alignment: " + alignment);
+ this.alignment = alignment;
+ if (peer != null)
+ {
+ LabelPeer lp = (LabelPeer) peer;
+ lp.setAlignment (alignment);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the text displayed in this label.
+ *
+ * @return The text for this label.
+ */
+public String
+getText()
+{
+ return(text);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the text in this label to the specified value.
+ *
+ * @param text The new text for this label.
+ */
+public synchronized void
+setText(String text)
+{
+ this.text = text;
+
+ if (peer != null)
+ {
+ LabelPeer lp = (LabelPeer) peer;
+ lp.setText (text);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies this label that it has been added to a container, causing
+ * the peer to be created. This method is called internally by the AWT
+ * system.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createLabel (this);
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a parameter string useful for debugging.
+ *
+ * @return A debugging string.
+ */
+protected String
+paramString()
+{
+ return ("text=" + getText() + ",alignment=" +
+ getAlignment() + "," + super.paramString());
+}
+
+/**
+ * This class provides accessibility support for the label.
+ */
+protected class AccessibleAWTLabel
+ extends AccessibleAWTComponent
+{
+ /**
+ * For compatability with Sun's JDK 1.4.2 rev. 5
+ */
+ private static final long serialVersionUID = -3568967560160480438L;
+
+ /**
+ * Constructor for the accessible label.
+ */
+ public AccessibleAWTLabel()
+ {
+ }
+
+ /**
+ * Returns the accessible name for the label. This is
+ * the text used in the label.
+ *
+ * @return a <code>String</code> containing the accessible
+ * name for this label.
+ */
+ public String getAccessibleName()
+ {
+ return getText();
+ }
+
+ /**
+ * Returns the accessible role for the label.
+ *
+ * @return an instance of <code>AccessibleRole</code>, describing
+ * the role of the label.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LABEL;
+ }
+
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>Label</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTLabel();
+ return accessibleContext;
+}
+
+} // class Label
+
diff --git a/libjava/classpath/java/awt/LayoutManager.java b/libjava/classpath/java/awt/LayoutManager.java
new file mode 100644
index 00000000000..62ff8087e76
--- /dev/null
+++ b/libjava/classpath/java/awt/LayoutManager.java
@@ -0,0 +1,92 @@
+/* LayoutManager.java -- lay out elements in a Container
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This interface is for laying out containers in a particular sequence.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Container
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface LayoutManager
+{
+ /**
+ * Adds the specified component to the layout group.
+ *
+ * @param name the name of the component to add
+ * @param component the component to add
+ */
+ void addLayoutComponent(String name, Component component);
+
+ /**
+ * Removes the specified component from the layout group.
+ *
+ * @param component the component to remove
+ */
+ void removeLayoutComponent(Component component);
+
+ /**
+ * Calculates the preferred size for this container, taking into account
+ * the components it contains.
+ *
+ * @param parent the parent container to lay out
+ * @return the preferred dimensions of this container
+ * @see #minimumLayoutSize(Container)
+ */
+ Dimension preferredLayoutSize(Container parent);
+
+ /**
+ * Calculates the minimum size for this container, taking into account
+ * the components it contains.
+ *
+ * @param parent the parent container to lay out
+ * @return the minimum dimensions of this container
+ * @see #preferredLayoutSize(Container)
+ */
+ Dimension minimumLayoutSize(Container parent);
+
+ /**
+ * Lays out the components in the given container.
+ *
+ * @param parent the container to lay out
+ */
+ void layoutContainer(Container parent);
+} // interface LayoutManager
diff --git a/libjava/classpath/java/awt/LayoutManager2.java b/libjava/classpath/java/awt/LayoutManager2.java
new file mode 100644
index 00000000000..45fc5430f29
--- /dev/null
+++ b/libjava/classpath/java/awt/LayoutManager2.java
@@ -0,0 +1,100 @@
+/* LayoutManager2.java -- enhanced layout manager
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * Layout manager for laying out containers based on contraints. The
+ * constraints control how the layout will proceed.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see LayoutManager
+ * @see Container
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface LayoutManager2 extends LayoutManager
+{
+ /**
+ * Adds the specified component to the layout, with the specified
+ * constraints object.
+ *
+ * @param component the component to add
+ * @param constraints the constraints to satisfy
+ */
+ void addLayoutComponent(Component component, Object constraints);
+
+ /**
+ * Determines the maximum size of the specified target container.
+ *
+ * @param target the container to lay out
+ * @return the maximum size of the container
+ * @see Component#getMaximumSize()
+ */
+ Dimension maximumLayoutSize(Container target);
+
+ /**
+ * Returns the preferred X axis alignment for the specified target
+ * container. This value will range from 0 to 1 where 0 is alignment
+ * closest to the origin, 0.5 is centered, and 1 is aligned furthest
+ * from the origin.
+ *
+ * @param target the target container
+ * @return the x-axis alignment preference
+ */
+ float getLayoutAlignmentX(Container target);
+
+ /**
+ * Returns the preferred Y axis alignment for the specified target
+ * container. This value will range from 0 to 1 where 0 is alignment
+ * closest to the origin, 0.5 is centered, and 1 is aligned furthest
+ * from the origin.
+ *
+ * @param target the target container
+ * @return the y-axis alignment preference
+ */
+ float getLayoutAlignmentY(Container target);
+
+ /**
+ * Forces the layout manager to purge any cached information about the
+ * layout of the target container. This will force it to be recalculated.
+ *
+ * @param target the target container
+ */
+ void invalidateLayout(Container target);
+} // interface LayoutManager2
diff --git a/libjava/classpath/java/awt/List.java b/libjava/classpath/java/awt/List.java
new file mode 100644
index 00000000000..5fcc79bfcef
--- /dev/null
+++ b/libjava/classpath/java/awt/List.java
@@ -0,0 +1,1263 @@
+/* List.java -- A listbox widget
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.peer.ListPeer;
+import java.util.EventListener;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * Class that implements a listbox widget
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class List extends Component
+ implements ItemSelectable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization constant
+private static final long serialVersionUID = -3304312411574666869L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+// FIXME: Need read/writeObject
+
+/**
+ * @serial The items in the list.
+ */
+private Vector items = new Vector();
+
+/**
+ * @serial Indicates whether or not multiple items can be selected
+ * simultaneously.
+ */
+private boolean multipleMode;
+
+/**
+ * @serial The number of rows in the list. This is set on creation
+ * only and cannot be modified.
+ */
+private int rows;
+
+/**
+ * @serial An array of the item indices that are selected.
+ */
+private int[] selected;
+
+/**
+ * @serial An index value used by <code>makeVisible()</code> and
+ * <code>getVisibleIndex</code>.
+ */
+private int visibleIndex;
+
+// The list of ItemListeners for this object.
+private ItemListener item_listeners;
+
+// The list of ActionListeners for this object.
+private ActionListener action_listeners;
+
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>List</code> with no visible lines
+ * and multi-select disabled.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+List()
+{
+ this(4, false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>List</code> with the specified
+ * number of visible lines and multi-select disabled.
+ *
+ * @param rows The number of visible rows in the list.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+List(int rows)
+{
+ this(rows, false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>List</code> with the specified
+ * number of lines and the specified multi-select setting.
+ *
+ * @param rows The number of visible rows in the list.
+ * @param multipleMode <code>true</code> if multiple lines can be selected
+ * simultaneously, <code>false</code> otherwise.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+List(int rows, boolean multipleMode)
+{
+ this.rows = rows;
+ this.multipleMode = multipleMode;
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the number of items in this list.
+ *
+ * @return The number of items in this list.
+ */
+public int
+getItemCount()
+{
+ return countItems ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the number of items in this list.
+ *
+ * @return The number of items in this list.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getItemCount()</code>
+ */
+public int
+countItems()
+{
+ return items.size ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the complete list of items.
+ *
+ * @return The complete list of items in the list.
+ */
+public synchronized String[]
+getItems()
+{
+ String[] l_items = new String[getItemCount()];
+
+ items.copyInto(l_items);
+ return(l_items);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the item at the specified index.
+ *
+ * @param index The index of the item to retrieve.
+ *
+ * @exception IndexOutOfBoundsException If the index value is not valid.
+ */
+public String
+getItem(int index)
+{
+ return((String)items.elementAt(index));
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the number of visible rows in the list.
+ *
+ * @return The number of visible rows in the list.
+ */
+public int
+getRows()
+{
+ return(rows);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not multi-select mode is enabled.
+ *
+ * @return <code>true</code> if multi-select mode is enabled,
+ * <code>false</code> otherwise.
+ */
+public boolean
+isMultipleMode()
+{
+ return allowsMultipleSelections ();
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not multi-select mode is enabled.
+ *
+ * @return <code>true</code> if multi-select mode is enabled,
+ * <code>false</code> otherwise.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>isMultipleMode()</code>.
+ */
+public boolean
+allowsMultipleSelections()
+{
+ return multipleMode;
+}
+
+/*************************************************************************/
+
+/**
+ * This method enables or disables multiple selection mode for this
+ * list.
+ *
+ * @param multipleMode <code>true</code> to enable multiple mode,
+ * <code>false</code> otherwise.
+ */
+public void
+setMultipleMode(boolean multipleMode)
+{
+ setMultipleSelections (multipleMode);
+}
+
+/*************************************************************************/
+
+/**
+ * This method enables or disables multiple selection mode for this
+ * list.
+ *
+ * @param multipleMode <code>true</code> to enable multiple mode,
+ * <code>false</code> otherwise.
+ *
+ * @deprecated
+ */
+public void
+setMultipleSelections(boolean multipleMode)
+{
+ this.multipleMode = multipleMode;
+
+ ListPeer peer = (ListPeer) getPeer ();
+ if (peer != null)
+ peer.setMultipleMode (multipleMode);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size of this component.
+ *
+ * @return The minimum size of this component.
+ */
+public Dimension
+getMinimumSize()
+{
+ return getMinimumSize (getRows ());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size of this component.
+ *
+ * @return The minimum size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize</code>.
+ */
+public Dimension
+minimumSize()
+{
+ return minimumSize (getRows ());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The minimum size of this component.
+ */
+public Dimension
+getMinimumSize(int rows)
+{
+ return minimumSize (rows);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The minimum size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize(int)</code>>
+ */
+public Dimension
+minimumSize(int rows)
+{
+ ListPeer peer = (ListPeer) getPeer ();
+ if (peer != null)
+ return peer.minimumSize (rows);
+ else
+ return new Dimension (0, 0);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size of this component.
+ *
+ * @return The preferred size of this component.
+ */
+public Dimension
+getPreferredSize()
+{
+ return getPreferredSize (getRows ());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size of this component.
+ *
+ * @return The preferred size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize</code>.
+ */
+public Dimension
+preferredSize()
+{
+ return preferredSize (getRows ());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The preferred size of this component.
+ */
+public Dimension
+getPreferredSize(int rows)
+{
+ return preferredSize (rows);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The preferred size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize(int)</code>>
+ */
+public Dimension
+preferredSize(int rows)
+{
+ ListPeer peer = (ListPeer) getPeer ();
+ if (peer != null)
+ return peer.preferredSize (rows);
+ else
+ return new Dimension (0, 0);
+}
+
+/*************************************************************************/
+
+/**
+ * This method adds the specified item to the end of the list.
+ *
+ * @param item The item to add to the list.
+ */
+public void
+add(String item)
+{
+ add (item, -1);
+}
+
+/*************************************************************************/
+
+/**
+ * This method adds the specified item to the end of the list.
+ *
+ * @param item The item to add to the list.
+ *
+ * @deprecated Use add() instead.
+ */
+public void
+addItem(String item)
+{
+ addItem (item, -1);
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified item to the specified location in the list.
+ * If the desired index is -1 or greater than the number of rows
+ * in the list, then the item is added to the end.
+ *
+ * @param item The item to add to the list.
+ * @param index The location in the list to add the item, or -1 to add
+ * to the end.
+ */
+public void
+add(String item, int index)
+{
+ addItem (item, index);
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified item to the specified location in the list.
+ * If the desired index is -1 or greater than the number of rows
+ * in the list, then the item is added to the end.
+ *
+ * @param item The item to add to the list.
+ * @param index The location in the list to add the item, or -1 to add
+ * to the end.
+ *
+ * @deprecated Use add() instead.
+ */
+public void
+addItem(String item, int index)
+{
+ if ((index == -1) || (index >= items.size ()))
+ items.addElement (item);
+ else
+ items.insertElementAt (item, index);
+
+ ListPeer peer = (ListPeer) getPeer ();
+ if (peer != null)
+ peer.add (item, index);
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes the item at the specified index.
+ *
+ * @param index The index of the item to delete.
+ *
+ * @exception IllegalArgumentException If the index is not valid
+ *
+ * @deprecated
+ */
+public void
+delItem(int index) throws IllegalArgumentException
+{
+ items.removeElementAt (index);
+
+ ListPeer peer = (ListPeer) getPeer ();
+ if (peer != null)
+ peer.delItems (index, index);
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes the item at the specified index.
+ *
+ * @param index The index of the item to delete.
+ *
+ * @exception IllegalArgumentException If the index is not valid
+ */
+public void
+remove(int index) throws IllegalArgumentException
+{
+ delItem (index);
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes all items in the specified index range.
+ *
+ * @param start The beginning index of the range to delete.
+ * @param end The ending index of the range to delete.
+ *
+ * @exception IllegalArgumentException If the indexes are not valid
+ *
+ * @deprecated This method is deprecated for some unknown reason.
+ */
+public synchronized void
+delItems(int start, int end) throws IllegalArgumentException
+{
+ if ((start < 0) || (start >= items.size()))
+ throw new IllegalArgumentException("Bad list start index value: " + start);
+
+ if ((start < 0) || (start >= items.size()))
+ throw new IllegalArgumentException("Bad list start index value: " + start);
+
+ if (start > end)
+ throw new IllegalArgumentException("Start is greater than end!");
+
+ // We must run the loop in reverse direction.
+ for (int i = end; i >= start; --i)
+ items.removeElementAt (i);
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ l.delItems (start, end);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes the first occurrence of the specified item from the list.
+ *
+ * @param item The item to delete.
+ *
+ * @exception IllegalArgumentException If the specified item does not exist.
+ */
+public synchronized void
+remove(String item) throws IllegalArgumentException
+{
+ int index = items.indexOf(item);
+ if (index == -1)
+ throw new IllegalArgumentException("List element to delete not found");
+
+ remove(index);
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes all of the items from the list.
+ */
+public synchronized void
+removeAll()
+{
+ clear ();
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes all of the items from the list.
+ *
+ * @deprecated This method is deprecated in favor of <code>removeAll()</code>.
+ */
+public void
+clear()
+{
+ items.clear();
+
+ ListPeer peer = (ListPeer) getPeer ();
+ if (peer != null)
+ peer.removeAll ();
+}
+
+/*************************************************************************/
+
+/**
+ * Replaces the item at the specified index with the specified item.
+ *
+ * @param item The new item value.
+ * @param index The index of the item to replace.
+ *
+ * @exception IllegalArgumentException If the index is not valid.
+ */
+public synchronized void
+replaceItem(String item, int index) throws IllegalArgumentException
+{
+ if ((index < 0) || (index >= items.size()))
+ throw new IllegalArgumentException("Bad list index: " + index);
+
+ items.insertElementAt(item, index + 1);
+ items.removeElementAt (index);
+
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+
+ /* We add first and then remove so that the selected
+ item remains the same */
+ l.add (item, index + 1);
+ l.delItems (index, index);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the index of the currently selected item. -1 will be returned
+ * if there are no selected rows or if there are multiple selected rows.
+ *
+ * @return The index of the selected row.
+ */
+public synchronized int
+getSelectedIndex()
+{
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ selected = l.getSelectedIndexes ();
+ }
+
+ if (selected == null || selected.length != 1)
+ return -1;
+ return selected[0];
+}
+
+/*************************************************************************/
+
+/**
+ * Returns an array containing the indexes of the rows that are
+ * currently selected.
+ *
+ * @return A list of indexes of selected rows.
+ */
+public synchronized int[]
+getSelectedIndexes()
+{
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ selected = l.getSelectedIndexes ();
+ }
+ return selected;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the item that is currently selected, or <code>null</code> if there
+ * is no item selected. FIXME: What happens if multiple items selected?
+ *
+ * @return The selected item, or <code>null</code> if there is no
+ * selected item.
+ */
+public synchronized String
+getSelectedItem()
+{
+ int index = getSelectedIndex();
+ if (index == -1)
+ return(null);
+
+ return((String)items.elementAt(index));
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the list of items that are currently selected in this list.
+ *
+ * @return The list of currently selected items.
+ */
+public synchronized String[]
+getSelectedItems()
+{
+ int[] indexes = getSelectedIndexes();
+ if (indexes == null)
+ return(new String[0]);
+
+ String[] retvals = new String[indexes.length];
+ if (retvals.length > 0)
+ for (int i = 0 ; i < retvals.length; i++)
+ retvals[i] = (String)items.elementAt(indexes[i]);
+
+ return(retvals);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the list of items that are currently selected in this list as
+ * an array of type <code>Object[]</code> instead of <code>String[]</code>.
+ *
+ * @return The list of currently selected items.
+ */
+public synchronized Object[]
+getSelectedObjects()
+{
+ int[] indexes = getSelectedIndexes();
+ if (indexes == null)
+ return(new Object[0]);
+
+ Object[] retvals = new Object[indexes.length];
+ if (retvals.length > 0)
+ for (int i = 0 ; i < retvals.length; i++)
+ retvals[i] = items.elementAt(indexes[i]);
+
+ return(retvals);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not the specified index is selected.
+ *
+ * @param index The index to test.
+ *
+ * @return <code>true</code> if the index is selected, <code>false</code>
+ * otherwise.
+ */
+public boolean
+isIndexSelected(int index)
+{
+ return isSelected (index);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not the specified index is selected.
+ *
+ * @param index The index to test.
+ *
+ * @return <code>true</code> if the index is selected, <code>false</code>
+ * otherwise.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>isIndexSelected(int)</code>.
+ */
+public boolean
+isSelected(int index)
+{
+ int[] indexes = getSelectedIndexes ();
+
+ for (int i = 0; i < indexes.length; i++)
+ if (indexes[i] == index)
+ return true;
+
+ return false;
+}
+
+/*************************************************************************/
+
+/**
+ * This method ensures that the item at the specified index is visible.
+ *
+ * @exception IllegalArgumentException If the specified index is out of
+ * range.
+ */
+public synchronized void
+makeVisible(int index) throws IllegalArgumentException
+{
+ if ((index < 0) || (index >= items.size()))
+ throw new IllegalArgumentException("Bad list index: " + index);
+
+ visibleIndex = index;
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ l.makeVisible (index);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the index of the last item that was made visible via the
+ * <code>makeVisible()</code> method.
+ *
+ * @return The index of the last item made visible via the
+ * <code>makeVisible()</code> method.
+ */
+public int
+getVisibleIndex()
+{
+ return(visibleIndex);
+}
+
+/*************************************************************************/
+
+/**
+ * Makes the item at the specified index selected.
+ *
+ * @param index The index of the item to select.
+ */
+public synchronized void
+select(int index)
+{
+ ListPeer lp = (ListPeer)getPeer();
+ if (lp != null)
+ lp.select(index);
+}
+
+/*************************************************************************/
+
+/**
+ * Makes the item at the specified index not selected.
+ *
+ * @param index The index of the item to unselect.
+ */
+public synchronized void
+deselect(int index)
+{
+ ListPeer lp = (ListPeer)getPeer();
+ if (lp != null)
+ lp.deselect(index);
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies this object to create its native peer.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createList (this);
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies this object to destroy its native peer.
+ */
+public void
+removeNotify()
+{
+ super.removeNotify();
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified <code>ActionListener</code> to the list of
+ * registered listeners for this object.
+ *
+ * @param listener The listener to add.
+ */
+public synchronized void
+addActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified <code>ActionListener</code> from the list of
+ * registers listeners for this object.
+ *
+ * @param listener The listener to remove.
+ */
+public synchronized void
+removeActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified <code>ItemListener</code> to the list of
+ * registered listeners for this object.
+ *
+ * @param listener The listener to add.
+ */
+public synchronized void
+addItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.add(item_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified <code>ItemListener</code> from the list of
+ * registers listeners for this object.
+ *
+ * @param listener The listener to remove.
+ */
+public synchronized void
+removeItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event for this object. If the event is an
+ * instance of <code>ActionEvent</code> then the
+ * <code>processActionEvent()</code> method is called. Similarly, if the
+ * even is an instance of <code>ItemEvent</code> then the
+ * <code>processItemEvent()</code> method is called. Otherwise the
+ * superclass method is called to process this event.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+ else if (event instanceof ItemEvent)
+ processItemEvent((ItemEvent)event);
+ else
+ super.processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * This method processes the specified event by dispatching it to any
+ * registered listeners. Note that this method will only get called if
+ * action events are enabled. This will happen automatically if any
+ * listeners are added, or it can be done "manually" by calling
+ * the <code>enableEvents()</code> method.
+ *
+ * @param event The event to process.
+ */
+protected void
+processActionEvent(ActionEvent event)
+{
+ if (action_listeners != null)
+ action_listeners.actionPerformed(event);
+}
+
+/*************************************************************************/
+
+/**
+ * This method processes the specified event by dispatching it to any
+ * registered listeners. Note that this method will only get called if
+ * item events are enabled. This will happen automatically if any
+ * listeners are added, or it can be done "manually" by calling
+ * the <code>enableEvents()</code> method.
+ *
+ * @param event The event to process.
+ */
+protected void
+processItemEvent(ItemEvent event)
+{
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ItemEvent.ITEM_LAST
+ && e.id >= ItemEvent.ITEM_FIRST
+ && (item_listeners != null
+ || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
+ processEvent(e);
+ else if (e.id <= ActionEvent.ACTION_LAST
+ && e.id >= ActionEvent.ACTION_FIRST
+ && (action_listeners != null
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+protected String
+paramString()
+{
+ return "multiple=" + multipleMode + ",rows=" + rows + super.paramString();
+}
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>List</code>. FooListeners are registered using the
+ * addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ */
+ public EventListener[] getListeners (Class listenerType)
+ {
+ if (listenerType == ActionListener.class)
+ return AWTEventMulticaster.getListeners (action_listeners, listenerType);
+
+ if (listenerType == ItemListener.class)
+ return AWTEventMulticaster.getListeners (item_listeners, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Returns all action listeners registered to this object.
+ */
+ public ActionListener[] getActionListeners ()
+ {
+ return (ActionListener[]) getListeners (ActionListener.class);
+ }
+
+ /**
+ * Returns all action listeners registered to this object.
+ */
+ public ItemListener[] getItemListeners ()
+ {
+ return (ItemListener[]) getListeners (ItemListener.class);
+ }
+
+ // Accessibility internal class
+ protected class AccessibleAWTList extends AccessibleAWTComponent
+ implements AccessibleSelection, ItemListener, ActionListener
+ {
+ protected class AccessibleAWTListChild extends AccessibleAWTComponent
+ implements Accessible
+ {
+ private int index;
+ private List parent;
+
+ public AccessibleAWTListChild(List parent, int indexInParent)
+ {
+ this.parent = parent;
+ index = indexInParent;
+ if (parent == null)
+ index = -1;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.Accessible#getAccessibleContext()
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return this;
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LIST_ITEM;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (parent.isIndexSelected(index))
+ states.add(AccessibleState.SELECTED);
+ return states;
+ }
+
+ public int getAccessibleIndexInParent()
+ {
+ return index;
+ }
+
+ }
+
+ public AccessibleAWTList()
+ {
+ addItemListener(this);
+ addActionListener(this);
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LIST;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ states.add(AccessibleState.SELECTABLE);
+ if (isMultipleMode())
+ states.add(AccessibleState.MULTISELECTABLE);
+ return states;
+ }
+
+ public int getAccessibleChildrenCount()
+ {
+ return getItemCount();
+ }
+
+ public Accessible getAccessibleChild(int i)
+ {
+ if (i >= getItemCount())
+ return null;
+ return new AccessibleAWTListChild(List.this, i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#getAccessibleSelectionCount()
+ */
+ public int getAccessibleSelectionCount()
+ {
+ return getSelectedIndexes().length;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#getAccessibleSelection()
+ */
+ public AccessibleSelection getAccessibleSelection()
+ {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#getAccessibleSelection(int)
+ */
+ public Accessible getAccessibleSelection(int i)
+ {
+ int[] items = getSelectedIndexes();
+ if (i >= items.length)
+ return null;
+ return new AccessibleAWTListChild(List.this, items[i]);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#isAccessibleChildSelected(int)
+ */
+ public boolean isAccessibleChildSelected(int i)
+ {
+ return isIndexSelected(i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#addAccessibleSelection(int)
+ */
+ public void addAccessibleSelection(int i)
+ {
+ select(i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#removeAccessibleSelection(int)
+ */
+ public void removeAccessibleSelection(int i)
+ {
+ deselect(i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#clearAccessibleSelection()
+ */
+ public void clearAccessibleSelection()
+ {
+ for (int i = 0; i < getItemCount(); i++)
+ deselect(i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#selectAllAccessibleSelection()
+ */
+ public void selectAllAccessibleSelection()
+ {
+ if (isMultipleMode())
+ for (int i = 0; i < getItemCount(); i++)
+ select(i);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
+ */
+ public void itemStateChanged(ItemEvent event)
+ {
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ }
+
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>List</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTList();
+ return accessibleContext;
+ }
+} // class List
diff --git a/libjava/classpath/java/awt/MediaTracker.java b/libjava/classpath/java/awt/MediaTracker.java
new file mode 100644
index 00000000000..9abfde6efc2
--- /dev/null
+++ b/libjava/classpath/java/awt/MediaTracker.java
@@ -0,0 +1,697 @@
+/* MediaTracker.java -- Class used for keeping track of images
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ImageObserver;
+import java.util.ArrayList;
+
+/**
+ * This class is used for keeping track of the status of various media
+ * objects.
+ *
+ * Media objects are tracked by assigning them an ID. It is possible
+ * to assign the same ID to mutliple objects, effectivly grouping them
+ * together. In this case the status flags ({@link #statusID}) and error flag
+ * (@link #isErrorID} and {@link #getErrorsID}) are ORed together. This
+ * means that you cannot say exactly which media object has which status,
+ * at most you can say that there <em>are</em> certain media objects with
+ * some certain status.
+ *
+ * At the moment only images are supported by this class.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Bryce McKinlay
+ */
+public class MediaTracker implements java.io.Serializable
+{
+ /** Indicates that the media is still loading. */
+ public static final int LOADING = 1 << 0;
+
+ /** Indicates that the loading operation has been aborted. */
+ public static final int ABORTED = 1 << 1;
+
+ /** Indicates that an error has occured during loading of the media. */
+ public static final int ERRORED = 1 << 2;
+
+ /** Indicates that the media has been successfully and completely loaded. */
+ public static final int COMPLETE = 1 << 3;
+
+ /** The component on which the media is eventually been drawn. */
+ Component target;
+
+ /** The head of the linked list of tracked media objects. */
+ MediaEntry head;
+
+ /** Our serialVersionUID for serialization. */
+ static final long serialVersionUID = -483174189758638095L;
+
+ /**
+ * This represents a media object that is tracked by a MediaTracker.
+ * It also implements a simple linked list.
+ */
+ // FIXME: The serialized form documentation says MediaEntry is a
+ // serializable field, but the serialized form of MediaEntry itself
+ // doesn't appear to be documented.
+ class MediaEntry implements ImageObserver
+ {
+ /** The ID of the media object. */
+ int id;
+
+ /** The media object. (only images are supported ATM). */
+ Image image;
+
+ /** The link to the next entry in the list. */
+ MediaEntry next;
+
+ /** The tracking status. */
+ int status;
+
+ /** The width of the image. */
+ int width;
+
+ /** The height of the image. */
+ int height;
+
+ /**
+ * Receives notification from an {@link java.awt.image.ImageProducer}
+ * that more data of the image is available.
+ *
+ * @param img the image that is updated
+ * @param flags flags from the ImageProducer that indicate the status
+ * of the loading process
+ * @param x the X coordinate of the upper left corner of the image
+ * @param y the Y coordinate of the upper left corner of the image
+ * @param width the width of the image
+ * @param height the height of the image
+ *
+ * @return <code>true</code> if more data is needed, <code>false</code>
+ * otherwise
+ *
+ * @see java.awt.image.ImageObserver
+ */
+ public boolean imageUpdate(Image img, int flags, int x, int y,
+ int width, int height)
+ {
+ if ((flags & ABORT) != 0)
+ status = ABORTED;
+ else if ((flags & ERROR) != 0)
+ status = ERRORED;
+ else if ((flags & ALLBITS) != 0)
+ status = COMPLETE;
+ else
+ status = 0;
+
+ synchronized (MediaTracker.this)
+ {
+ MediaTracker.this.notifyAll();
+ }
+
+ // If status is not COMPLETE then we need more updates.
+ return ((status & (COMPLETE | ERRORED | ABORTED)) == 0);
+ }
+ }
+
+ /**
+ * Constructs a new MediaTracker for the component <code>c</code>. The
+ * component should be the component that uses the media (i.e. draws it).
+ *
+ * @param c the Component that wants to use the media
+ */
+ public MediaTracker(Component c)
+ {
+ target = c;
+ }
+
+ /**
+ * Adds an image to the tracker with the specified <code>ID</code>.
+ *
+ * @param image the image to be added
+ * @param id the ID of the tracker list to which the image is added
+ */
+ public void addImage(Image image, int id)
+ {
+ MediaEntry e = new MediaEntry();
+ e.id = id;
+ e.image = image;
+ synchronized(this)
+ {
+ e.next = head;
+ head = e;
+ }
+ }
+
+ /**
+ * Adds an image to the tracker with the specified <code>ID</code>.
+ * The image is expected to be rendered with the specified width and
+ * height.
+ *
+ * @param image the image to be added
+ * @param id the ID of the tracker list to which the image is added
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void addImage(Image image, int id, int width, int height)
+ {
+ MediaEntry e = new MediaEntry();
+ e.id = id;
+ e.image = image;
+ e.width = width;
+ e.height = height;
+ synchronized(this)
+ {
+ e.next = head;
+ head = e;
+ }
+ }
+
+ /**
+ * Checks if all media objects have finished loading, i.e. are
+ * {@link #COMPLETE}, {@link #ABORTED} or {@link #ERRORED}.
+ *
+ * If the media objects are not already loading, a call to this
+ * method does <em>not</em> start loading. This is equivalent to
+ * a call to <code>checkAll(false)</code>.
+ *
+ * @return if all media objects have finished loading either by beeing
+ * complete, have been aborted or errored.
+ */
+ public boolean checkAll()
+ {
+ return checkAll(false);
+ }
+
+ /**
+ * Checks if all media objects have finished loading, i.e. are
+ * {@link #COMPLETE}, {@link #ABORTED} or {@link #ERRORED}.
+ *
+ * If the media objects are not already loading, and <code>load</code>
+ * is <code>true</code> then a call to this
+ * method starts loading the media objects.
+ *
+ * @param load if <code>true</code> this method starts loading objects
+ * that are not already loading
+ *
+ * @return if all media objects have finished loading either by beeing
+ * complete, have been aborted or errored.
+ */
+ public boolean checkAll(boolean load)
+ {
+ MediaEntry e = head;
+ boolean result = true;
+
+ while (e != null)
+ {
+ if ((e.status & (COMPLETE | ERRORED | ABORTED)) == 0)
+ {
+ if (load && ((e.status & LOADING) == 0))
+ {
+ if (target.prepareImage(e.image, e))
+ e.status = COMPLETE;
+ else
+ {
+ e.status = LOADING;
+ int flags = target.checkImage(e.image, e);
+ if ((flags & ImageObserver.ABORT) != 0)
+ e.status = ABORTED;
+ else if ((flags & ImageObserver.ERROR) != 0)
+ e.status = ERRORED;
+ else if ((flags & ImageObserver.ALLBITS) != 0)
+ e.status = COMPLETE;
+ }
+ boolean complete = (e.status
+ & (COMPLETE | ABORTED | ERRORED)) != 0;
+ if (!complete)
+ result = false;
+ }
+ else
+ result = false;
+ }
+ e = e.next;
+ }
+ return result;
+ }
+
+ /**
+ * Checks if any of the registered media objects has encountered an error
+ * during loading.
+ *
+ * @return <code>true</code> if at least one media object has encountered
+ * an error during loading, <code>false</code> otherwise
+ *
+ */
+ public boolean isErrorAny()
+ {
+ MediaEntry e = head;
+ while (e != null)
+ {
+ if ((e.status & ERRORED) != 0)
+ return true;
+ e = e.next;
+ }
+ return false;
+ }
+
+ /**
+ * Returns all media objects that have encountered errors during loading.
+ *
+ * @return an array of all media objects that have encountered errors
+ * or <code>null</code> if there were no errors at all
+ */
+ public Object[] getErrorsAny()
+ {
+ MediaEntry e = head;
+ ArrayList result = null;
+ while (e != null)
+ {
+ if ((e.status & ERRORED) != 0)
+ {
+ if (result == null)
+ result = new ArrayList();
+ result.add(e.image);
+ }
+ e = e.next;
+ }
+ if (result == null)
+ return null;
+ else
+ return result.toArray();
+ }
+
+ /**
+ * Waits for all media objects to finish loading, either by completing
+ * successfully or by aborting or encountering an error.
+ *
+ * @throws InterruptedException if another thread interrupted the
+ * current thread while waiting
+ */
+ public void waitForAll() throws InterruptedException
+ {
+ synchronized (this)
+ {
+ while (checkAll(true) == false)
+ wait();
+ }
+ }
+
+ /**
+ * Waits for all media objects to finish loading, either by completing
+ * successfully or by aborting or encountering an error.
+ *
+ * This method waits at most <code>ms</code> milliseconds. If the
+ * media objects have not completed loading within this timeframe, this
+ * method returns <code>false</code>, otherwise <code>true</code>.
+ *
+ * @param ms timeframe in milliseconds to wait for the media objects to
+ * finish
+ *
+ * @return <code>true</code> if all media objects have successfully loaded
+ * within the timeframe, <code>false</code> otherwise
+ *
+ * @throws InterruptedException if another thread interrupted the
+ * current thread while waiting
+ */
+ public boolean waitForAll(long ms) throws InterruptedException
+ {
+ long start = System.currentTimeMillis();
+ boolean result = checkAll(true);
+ synchronized (this)
+ {
+ while (result == false)
+ {
+ wait(ms);
+ result = checkAll(true);
+ if ((System.currentTimeMillis() - start) > ms)
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the status flags of all registered media objects ORed together.
+ * If <code>load</code> is <code>true</code> then media objects that
+ * are not already loading will be started to load.
+ *
+ * @param load if set to <code>true</code> then media objects that are
+ * not already loading are started
+ *
+ * @return the status flags of all tracked media objects ORed together
+ */
+ public int statusAll(boolean load)
+ {
+ int result = 0;
+ MediaEntry e = head;
+ while (e != null)
+ {
+ if (load && e.status == 0)
+ {
+ if (target.prepareImage(e.image, e))
+ e.status = COMPLETE;
+ else
+ {
+ e.status = LOADING;
+ int flags = target.checkImage(e.image, e);
+ if ((flags & ImageObserver.ABORT) != 0)
+ e.status = ABORTED;
+ else if ((flags & ImageObserver.ERROR) != 0)
+ e.status = ERRORED;
+ else if ((flags & ImageObserver.ALLBITS) != 0)
+ e.status = COMPLETE;
+ }
+ }
+ result |= e.status;
+ e = e.next;
+ }
+ return result;
+ }
+
+ /**
+ * Checks if the media objects with <code>ID</code> have completed loading.
+ *
+ * @param id the ID of the media objects to check
+ *
+ * @return <code>true</code> if all media objects with <code>ID</code>
+ * have successfully finished
+ */
+ public boolean checkID(int id)
+ {
+ return checkID(id, false);
+ }
+
+ /**
+ * Checks if the media objects with <code>ID</code> have completed loading.
+ * If <code>load</code> is <code>true</code> then media objects that
+ * are not already loading will be started to load.
+ *
+ * @param id the ID of the media objects to check
+ * @param load if set to <code>true</code> then media objects that are
+ * not already loading are started
+ *
+ * @return <code>true</code> if all media objects with <code>ID</code>
+ * have successfully finished
+ */
+ public boolean checkID(int id, boolean load)
+ {
+ MediaEntry e = head;
+ boolean result = true;
+
+ while (e != null)
+ {
+ if (e.id == id && ((e.status & (COMPLETE | ABORTED | ERRORED)) == 0))
+ {
+ if (load && ((e.status & LOADING) == 0))
+ {
+ e.status = LOADING;
+ if (target.prepareImage(e.image, e))
+ e.status = COMPLETE;
+ else
+ {
+ int flags = target.checkImage(e.image, e);
+ if ((flags & ImageObserver.ABORT) != 0)
+ e.status = ABORTED;
+ else if ((flags & ImageObserver.ERROR) != 0)
+ e.status = ERRORED;
+ else if ((flags & ImageObserver.ALLBITS) != 0)
+ e.status = COMPLETE;
+ }
+ boolean complete = (e.status
+ & (COMPLETE | ABORTED | ERRORED)) != 0;
+ if (!complete)
+ result = false;
+ }
+ else
+ result = false;
+ }
+ e = e.next;
+ }
+ return result;
+ }
+
+ /**
+ * Returns <code>true</code> if any of the media objects with <code>ID</code>
+ * have encountered errors during loading, false otherwise.
+ *
+ * @param id the ID of the media objects to check
+ *
+ * @return <code>true</code> if any of the media objects with <code>ID</code>
+ * have encountered errors during loading, false otherwise
+ */
+ public boolean isErrorID(int id)
+ {
+ MediaEntry e = head;
+ while (e != null)
+ {
+ if (e.id == id && ((e.status & ERRORED) != 0))
+ return true;
+ e = e.next;
+ }
+ return false;
+ }
+
+ /**
+ * Returns all media objects with the specified ID that have encountered
+ * an error.
+ *
+ * @param id the ID of the media objects to check
+ *
+ * @return an array of all media objects with the specified ID that
+ * have encountered an error
+ */
+ public Object[] getErrorsID(int id)
+ {
+ MediaEntry e = head;
+ ArrayList result = null;
+ while (e != null)
+ {
+ if (e.id == id && ((e.status & ERRORED) != 0))
+ {
+ if (result == null)
+ result = new ArrayList();
+ result.add(e.image);
+ }
+ e = e.next;
+ }
+ if (result == null)
+ return null;
+ else
+ return result.toArray();
+ }
+
+ /**
+ * Waits for all media objects with the specified ID to finish loading,
+ * either by completing successfully or by aborting or encountering an error.
+ *
+ * @param id the ID of the media objects to wait for
+ *
+ * @throws InterruptedException if another thread interrupted the
+ * current thread while waiting
+ */
+ public void waitForID(int id) throws InterruptedException
+ {
+ MediaEntry e = head;
+ synchronized (this)
+ {
+ while (checkID (id, true) == false)
+ wait();
+ }
+ }
+
+ /**
+ * Waits for all media objects with the specified ID to finish loading,
+ * either by completing successfully or by aborting or encountering an error.
+ *
+ * This method waits at most <code>ms</code> milliseconds. If the
+ * media objects have not completed loading within this timeframe, this
+ * method returns <code>false</code>, otherwise <code>true</code>.
+ *
+ * @param id the ID of the media objects to wait for
+ * @param ms timeframe in milliseconds to wait for the media objects to
+ * finish
+ *
+ * @return <code>true</code> if all media objects have successfully loaded
+ * within the timeframe, <code>false</code> otherwise
+ *
+ * @throws InterruptedException if another thread interrupted the
+ * current thread while waiting
+ */
+ public boolean waitForID(int id, long ms) throws InterruptedException
+ {
+ MediaEntry e = head;
+ long start = System.currentTimeMillis();
+ boolean result = checkID(id, true);
+
+ synchronized (this)
+ {
+ while (result == false)
+ {
+ wait(ms);
+ result = checkID(id, true);
+ if ((System.currentTimeMillis() - start) > ms)
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the status flags of the media objects with the specified ID
+ * ORed together.
+ *
+ * If <code>load</code> is <code>true</code> then media objects that
+ * are not already loading will be started to load.
+ *
+ * @param load if set to <code>true</code> then media objects that are
+ * not already loading are started
+ *
+ * @return the status flags of all tracked media objects ORed together
+ */
+ public int statusID(int id, boolean load)
+ {
+ int result = 0;
+ MediaEntry e = head;
+ while (e != null)
+ {
+ if (e.id == id)
+ {
+ if (load && e.status == 0)
+ {
+ if (target.prepareImage(e.image, e))
+ e.status = COMPLETE;
+ else
+ {
+ e.status = LOADING;
+ int flags = target.checkImage(e.image, e);
+ if ((flags & ImageObserver.ABORT) != 0)
+ e.status = ABORTED;
+ else if ((flags & ImageObserver.ERROR) != 0)
+ e.status = ERRORED;
+ else if ((flags & ImageObserver.ALLBITS) != 0)
+ e.status = COMPLETE;
+ }
+ }
+ result |= e.status;
+ }
+ e = e.next;
+ }
+ return result;
+ }
+
+ /**
+ * Removes an image from this MediaTracker.
+ *
+ * @param image the image to be removed
+ */
+ public void removeImage(Image image)
+ {
+ synchronized (this)
+ {
+ MediaEntry e = head;
+ MediaEntry prev = null;
+ while (e != null)
+ {
+ if (e.image == image)
+ {
+ if (prev == null)
+ head = e.next;
+ else
+ prev.next = e.next;
+ }
+ prev = e;
+ e = e.next;
+ }
+ }
+ }
+
+ /**
+ * Removes an image with the specified ID from this MediaTracker.
+ *
+ * @param image the image to be removed
+ */
+ public void removeImage(Image image, int id)
+ {
+ synchronized (this)
+ {
+ MediaEntry e = head;
+ MediaEntry prev = null;
+ while (e != null)
+ {
+ if (e.id == id && e.image == image)
+ {
+ if (prev == null)
+ head = e.next;
+ else
+ prev.next = e.next;
+ }
+ else
+ prev = e;
+ e = e.next;
+ }
+ }
+ }
+
+ /**
+ * Removes an image with the specified ID and scale from this MediaTracker.
+ *
+ * @param image the image to be removed
+ */
+ public void removeImage(Image image, int id, int width, int height)
+ {
+ synchronized (this)
+ {
+ MediaEntry e = head;
+ MediaEntry prev = null;
+ while (e != null)
+ {
+ if (e.id == id && e.image == image
+ && e.width == width && e.height == height)
+ {
+ if (prev == null)
+ head = e.next;
+ else
+ prev.next = e.next;
+ }
+ else
+ prev = e;
+ e = e.next;
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/Menu.java b/libjava/classpath/java/awt/Menu.java
new file mode 100644
index 00000000000..56ceccfc542
--- /dev/null
+++ b/libjava/classpath/java/awt/Menu.java
@@ -0,0 +1,468 @@
+/* Menu.java -- A Java AWT Menu
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.MenuPeer;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This class represents a pull down or tear off menu in Java's AWT.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Menu extends MenuItem implements MenuContainer, Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = -8809584163345499784L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The actual items in the menu
+ */
+private Vector items = new Vector();
+
+/**
+ * @serial Flag indicating whether or not this menu is a tear off
+ */
+private boolean tearOff;
+
+/**
+ * @serial Indicates whether or not this is a help menu.
+ */
+private boolean isHelpMenu;
+
+ /*
+ * @serial Unused in this implementation, but present in Sun's
+ * serialization spec. Value obtained via reflection.
+ */
+ private int menuSerializedDataVersion = 1;
+
+static final transient String separatorLabel = "-";
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>Menu</code> with no label and that
+ * is not a tearoff;
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+Menu()
+{
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Menu</code> that is not a tearoff and
+ * that has the specified label.
+ *
+ * @param label The menu label.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+Menu(String label)
+{
+ this(label, false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Menu</code> with the specified
+ * label and tearoff status.
+ *
+ * @param label The label for this menu
+ * @param isTearOff <code>true</code> if this menu is a tear off menu,
+ * <code>false</code> otherwise.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+Menu(String label, boolean isTearOff)
+{
+ super(label);
+
+ tearOff = isTearOff;
+
+ if (label.equals("Help"))
+ isHelpMenu = true;
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Tests whether or not this menu is a tearoff.
+ *
+ * @return <code>true</code> if this menu is a tearoff, <code>false</code>
+ * otherwise.
+ */
+public boolean
+isTearOff()
+{
+ return(tearOff);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the number of items in this menu.
+ *
+ * @return The number of items in this menu.
+ */
+public int
+getItemCount()
+{
+ return countItems ();
+}
+
+/**
+ * Returns the number of items in this menu.
+ *
+ * @return The number of items in this menu.
+ *
+ * @deprecated As of JDK 1.1, replaced by getItemCount().
+ */
+public int countItems ()
+{
+ return items.size ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the item at the specified index.
+ *
+ * @return The item at the specified index.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index value is not valid.
+ */
+public MenuItem
+getItem(int index)
+{
+ return((MenuItem)items.elementAt(index));
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified item to this menu. If it was previously part of
+ * another menu, it is first removed from that menu.
+ *
+ * @param item The new item to add.
+ *
+ * @return The item that was added.
+ */
+public MenuItem
+add(MenuItem item)
+{
+ items.addElement(item);
+ if (item.parent != null)
+ {
+ item.parent.remove(item);
+ }
+ item.parent = this;
+
+ if (peer != null)
+ {
+ MenuPeer mp = (MenuPeer) peer;
+ mp.addItem(item);
+ }
+
+ return item;
+}
+
+/*************************************************************************/
+
+/**
+ * Add an item with the specified label to this menu.
+ *
+ * @param label The label of the menu item to add.
+ */
+public void
+add(String label)
+{
+ add(new MenuItem(label));
+}
+
+/*************************************************************************/
+
+/**
+ * Inserts the specified menu item into this menu at the specified index.
+ *
+ * @param item The menu item to add.
+ * @param index The index of the menu item.
+ *
+ * @exception IllegalArgumentException If the index is less than zero.
+ * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
+ */
+public void
+insert(MenuItem item, int index)
+{
+ if (index < 0)
+ throw new IllegalArgumentException("Index is less than zero");
+
+ MenuPeer peer = (MenuPeer) getPeer();
+ if (peer == null)
+ return;
+
+ int count = getItemCount ();
+
+ if (index >= count)
+ peer.addItem (item);
+ else
+ {
+ for (int i = count - 1; i >= index; i--)
+ peer.delItem (i);
+
+ peer.addItem (item);
+
+ for (int i = index; i < count; i++)
+ peer.addItem ((MenuItem) items.elementAt (i));
+ }
+
+ items.insertElementAt(item, index);
+}
+
+/*************************************************************************/
+
+/**
+ * Inserts an item with the specified label into this menu at the specified index.
+ *
+ * @param label The label of the item to add.
+ * @param index The index of the menu item.
+ *
+ * @exception IllegalArgumentException If the index is less than zero.
+ * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
+ */
+public void
+insert(String label, int index)
+{
+ insert(new MenuItem(label), index);
+}
+
+/*************************************************************************/
+
+/**
+ * Adds a separator bar at the current menu location.
+ */
+public void
+addSeparator()
+{
+ add(new MenuItem(separatorLabel));
+}
+
+/*************************************************************************/
+
+/**
+ * Inserts a separator bar at the specified index value.
+ *
+ * @param index The index at which to insert a separator bar.
+ *
+ * @exception IllegalArgumentException If the index is less than zero.
+ * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
+ */
+public void
+insertSeparator(int index)
+{
+ insert(new MenuItem(separatorLabel), index);
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes the item at the specified index from this menu.
+ *
+ * @param index The index of the item to remove.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
+ */
+public synchronized void
+remove(int index)
+{
+ items.removeElementAt(index);
+
+ MenuPeer mp = (MenuPeer)getPeer();
+ if (mp != null)
+ mp.delItem(index);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specifed item from the menu. If the specified component
+ * does not exist, this method does nothing.
+ *
+ * @param item The component to remove.
+ */
+public void
+remove(MenuComponent item)
+{
+ int index = items.indexOf(item);
+ if (index == -1)
+ return;
+
+ remove(index);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes all the elements from this menu.
+ */
+public synchronized void
+removeAll()
+{
+ int count = getItemCount();
+ for(int i = 0; i < count; i++)
+ {
+ // We must always remove item 0.
+ remove(0);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Creates the native peer for this object.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit().createMenu(this);
+ Enumeration e = items.elements();
+ while (e.hasMoreElements())
+ {
+ MenuItem mi = (MenuItem)e.nextElement();
+ mi.addNotify();
+ }
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Destroys the native peer for this object.
+ */
+public void
+removeNotify()
+{
+ Enumeration e = items.elements();
+ while (e.hasMoreElements())
+ {
+ MenuItem mi = (MenuItem) e.nextElement();
+ mi.removeNotify();
+ }
+ super.removeNotify();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this menu.
+ *
+ * @return A debugging string for this menu.
+ */
+public String
+paramString()
+{
+ return (",tearOff=" + tearOff + ",isHelpMenu=" + isHelpMenu
+ + super.paramString());
+}
+
+ /**
+ * Basic Accessibility class for Menu. Details get provided in derived
+ * classes.
+ */
+ protected class AccessibleAWTMenu extends AccessibleAWTMenuItem
+ {
+ protected AccessibleAWTMenu()
+ {
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.MENU;
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Menu</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTMenu();
+ return accessibleContext;
+ }
+
+} // class Menu
diff --git a/libjava/classpath/java/awt/MenuBar.java b/libjava/classpath/java/awt/MenuBar.java
new file mode 100644
index 00000000000..4089fe189e0
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuBar.java
@@ -0,0 +1,423 @@
+/* MenuBar.java -- An AWT menu bar class
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuComponentPeer;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This class implements a menu bar in the AWT system.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class MenuBar extends MenuComponent
+ implements MenuContainer, Serializable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = -4930327919388951260L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The menu used for providing help information
+ */
+private Menu helpMenu;
+
+/**
+ * @serial The menus contained in this menu bar.
+ */
+private Vector menus = new Vector();
+
+ /**
+ * The accessible context for this component.
+ *
+ * @see #getAccessibleContext()
+ * @serial ignored.
+ */
+ private transient AccessibleContext accessibleContext;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>MenuBar</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+MenuBar()
+{
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the help menu for this menu bar. This may be <code>null</code>.
+ *
+ * @return The help menu for this menu bar.
+ */
+public Menu
+getHelpMenu()
+{
+ return(helpMenu);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the help menu for this menu bar.
+ *
+ * @param menu The new help menu for this menu bar.
+ */
+public synchronized void
+setHelpMenu(Menu menu)
+{
+ if (helpMenu != null)
+ {
+ helpMenu.removeNotify ();
+ helpMenu.parent = null;
+ }
+ helpMenu = menu;
+
+ if (menu.parent != null)
+ menu.parent.remove (menu);
+ menu.parent = this;
+
+ MenuBarPeer peer = (MenuBarPeer) getPeer ();
+ if (peer != null)
+ {
+ menu.addNotify();
+ peer.addHelpMenu (menu);
+ }
+}
+
+/*************************************************************************/
+
+/** Add a menu to this MenuBar. If the menu has already has a
+ * parent, it is first removed from its old parent before being
+ * added.
+ *
+ * @param menu The menu to add.
+ *
+ * @return The menu that was added.
+ */
+public synchronized Menu
+add(Menu menu)
+{
+ if (menu.parent != null)
+ menu.parent.remove (menu);
+
+ menu.parent = this;
+ menus.addElement(menu);
+
+ if (peer != null)
+ {
+ menu.addNotify();
+ }
+
+ return(menu);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the menu at the specified index.
+ *
+ * @param index The index of the menu to remove from the menu bar.
+ */
+public synchronized void
+remove(int index)
+{
+ Menu m = (Menu) menus.get (index);
+ menus.remove (index);
+ m.removeNotify ();
+ m.parent = null;
+
+ if (peer != null)
+ {
+ MenuBarPeer mp = (MenuBarPeer) peer;
+ mp.delMenu (index);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified menu from the menu bar.
+ *
+ * @param menu The menu to remove from the menu bar.
+ */
+public void
+remove(MenuComponent menu)
+{
+ int index = menus.indexOf(menu);
+ if (index == -1)
+ return;
+
+ remove(index);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the number of elements in this menu bar.
+ *
+ * @return The number of elements in the menu bar.
+ */
+public int
+getMenuCount()
+{
+ return countMenus ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the number of elements in this menu bar.
+ *
+ * @return The number of elements in the menu bar.
+ *
+ * @deprecated This method is deprecated in favor of <code>getMenuCount()</code>.
+ */
+public int
+countMenus()
+{
+ return menus.size () + (getHelpMenu () == null ? 0 : 1);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the menu at the specified index.
+ *
+ * @param index the index of the menu
+ *
+ * @return The requested menu.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index is not valid.
+ */
+public Menu
+getMenu(int index)
+{
+ return((Menu)menus.elementAt(index));
+}
+
+/*************************************************************************/
+
+/**
+ * Creates this object's native peer.
+ */
+public void
+addNotify()
+{
+ if (getPeer() == null)
+ setPeer((MenuComponentPeer)getToolkit().createMenuBar(this));
+ Enumeration e = menus.elements();
+ while (e.hasMoreElements())
+ {
+ Menu mi = (Menu)e.nextElement();
+ mi.addNotify();
+ }
+ if (helpMenu != null)
+ {
+ helpMenu.addNotify();
+ ((MenuBarPeer) peer).addHelpMenu(helpMenu);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Destroys this object's native peer.
+ */
+public void
+removeNotify()
+{
+ Enumeration e = menus.elements();
+ while (e.hasMoreElements())
+ {
+ Menu mi = (Menu) e.nextElement();
+ mi.removeNotify();
+ }
+ super.removeNotify();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a list of all shortcuts for the menus in this menu bar.
+ *
+ * @return A list of all shortcuts for the menus in this menu bar.
+ */
+public synchronized Enumeration
+shortcuts()
+{
+ Vector shortcuts = new Vector();
+ Enumeration e = menus.elements();
+
+ while (e.hasMoreElements())
+ {
+ Menu menu = (Menu)e.nextElement();
+ if (menu.getShortcut() != null)
+ shortcuts.addElement(menu.getShortcut());
+ }
+
+ return(shortcuts.elements());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the menu item for the specified shortcut, or <code>null</code>
+ * if no such item exists.
+ *
+ * @param shortcut The shortcut to return the menu item for.
+ *
+ * @return The menu item for the specified shortcut.
+ */
+public MenuItem
+getShortcutMenuItem(MenuShortcut shortcut)
+{
+ Enumeration e = menus.elements();
+
+ while (e.hasMoreElements())
+ {
+ Menu menu = (Menu)e.nextElement();
+ MenuShortcut s = menu.getShortcut();
+ if ((s != null) && (s.equals(shortcut)))
+ return(menu);
+ }
+
+ return(null);
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes the specified menu shortcut.
+ *
+ * @param shortcut The shortcut to delete.
+ */
+public void
+deleteShortcut(MenuShortcut shortcut)
+{
+ MenuItem it;
+ // This is a slow implementation, but it probably doesn't matter.
+ while ((it = getShortcutMenuItem (shortcut)) != null)
+ it.deleteShortcut ();
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>MenuBar</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTMenuBar();
+ return accessibleContext;
+}
+
+/**
+ * This class provides accessibility support for AWT menu bars.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+protected class AccessibleAWTMenuBar
+ extends AccessibleAWTMenuComponent
+{
+
+ /**
+ * Compatible with JDK 1.4.2 revision 5
+ */
+ private static final long serialVersionUID = -8577604491830083815L;
+
+ /**
+ * This is the default constructor, which simply calls the default
+ * constructor of the superclass.
+ */
+ protected AccessibleAWTMenuBar()
+ {
+ super();
+ }
+
+ /**
+ * Returns the accessible role relating to the menu bar.
+ *
+ * @return <code>AccessibleRole.MENU_BAR</code>.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.MENU_BAR;
+ }
+
+} // class AccessibleAWTMenuBar
+
+} // class MenuBar
diff --git a/libjava/classpath/java/awt/MenuComponent.java b/libjava/classpath/java/awt/MenuComponent.java
new file mode 100644
index 00000000000..ec6980e10ca
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuComponent.java
@@ -0,0 +1,1324 @@
+/* MenuComponent.java -- Superclass of all AWT menu components
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.peer.MenuComponentPeer;
+import java.io.Serializable;
+import java.util.Locale;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This is the superclass of all menu AWT widgets.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public abstract class MenuComponent implements Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = -4536902356223894379L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * The font for this component.
+ *
+ * @see #getFont()
+ * @see #setFont(java.awt.Font)
+ * @serial the component's font.
+ */
+ private Font font;
+
+ /**
+ * The name of the component.
+ *
+ * @see #getName()
+ * @see #setName(String)
+ * @serial the component's name.
+ */
+ private String name;
+
+ /**
+ * The parent of this component.
+ *
+ * @see #getParent()
+ * @see #setParent(java.awt.MenuContainer)
+ * @serial ignored.
+ */
+ transient MenuContainer parent;
+
+ /**
+ * The native peer for this component.
+ *
+ * @see #getPeer()
+ * @see #setPeer(java.awt.peer.MenuComponentPeer)
+ * @serial ignored.
+ */
+ transient MenuComponentPeer peer;
+
+ /**
+ * The synchronization locking object for this component.
+ *
+ * @serial ignored.
+ */
+ private transient Object tree_lock = this;
+
+ /**
+ * The toolkit for this object.
+ *
+ * @see #getToolkit()
+ * @serial ignored.
+ */
+ private static transient Toolkit toolkit = Toolkit.getDefaultToolkit();
+
+ /**
+ * The accessible context for this component.
+ *
+ * @see #getAccessibleContext()
+ * @serial the accessibility information for this component.
+ */
+ AccessibleContext accessibleContext;
+
+ /**
+ * Was the name of the component set? This value defaults
+ * to false and becomes true after a call to <code>setName()</code>.
+ * Please note that this does not guarantee that name will then
+ * be non-null, as this may be the value passed to <code>setName()</code>.
+ *
+ * @see #setName(String)
+ * @serial true if the name value has been explicitly set by calling
+ * <code>setName()</code>.
+ */
+ private boolean nameExplicitlySet;
+
+ /**
+ * Does this component handle new events? Events will be handled
+ * by this component if this is true. Otherwise, they will be forwarded
+ * up the component hierarchy. This implementation does not use this
+ * variable; it is merely provided for serialization compatability.
+ *
+ * @see #dispatchEvent(AWTEvent)
+ * @serial true if events are to be processed locally. Unused.
+ */
+ private boolean newEventsOnly;
+
+ /**
+ * The focus listener chain handler which deals with focus events for
+ * the accessible context of this component.
+ *
+ * @see AccessibleAWTMenuComponent#addFocusListener(java.awt.event.FocusListener)
+ * @serial ignored.
+ * This is package-private to avoid an accessor method.
+ */
+ transient FocusListener focusListener;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Default constructor for subclasses.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+MenuComponent()
+{
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the font in use for this component.
+ *
+ * @return The font for this component.
+ */
+public Font
+getFont()
+{
+ if (font != null)
+ return font;
+
+ if (parent != null)
+ return parent.getFont ();
+
+ return null;
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the font for this component to the specified font.
+ *
+ * @param font The new font for this component.
+ */
+public void
+setFont(Font font)
+{
+ this.font = font;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the name of this component.
+ *
+ * @return The name of this component.
+ */
+public String
+getName()
+{
+ return(name);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the name of this component to the specified name.
+ *
+ * @param name The new name of this component.
+ */
+public void
+setName(String name)
+{
+ this.name = name;
+ nameExplicitlySet = true;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the parent of this component.
+ *
+ * @return The parent of this component.
+ */
+public MenuContainer
+getParent()
+{
+ return(parent);
+}
+
+/*************************************************************************/
+
+// Sets the parent of this component.
+final void
+setParent(MenuContainer parent)
+{
+ this.parent = parent;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the native windowing system peer for this component.
+ *
+ * @return The peer for this component.
+ *
+ * @deprecated
+ */
+public MenuComponentPeer
+getPeer()
+{
+ return(peer);
+}
+
+/*************************************************************************/
+
+// Sets the peer for this component.
+final void
+setPeer(MenuComponentPeer peer)
+{
+ this.peer = peer;
+}
+
+/*************************************************************************/
+
+/**
+ * Destroys this component's native peer
+ */
+public void
+removeNotify()
+{
+ if (peer != null)
+ peer.dispose();
+ peer = null;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the toolkit in use for this component.
+ *
+ * @return The toolkit for this component.
+ */
+final Toolkit
+getToolkit()
+{
+ return(toolkit);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the object used for synchronization locks on this component
+ * when performing tree and layout functions.
+ *
+ * @return The synchronization lock for this component.
+ */
+protected final Object
+getTreeLock()
+{
+ return(tree_lock);
+}
+
+/*************************************************************************/
+
+// The sync lock object for this component.
+final void
+setTreeLock(Object tree_lock)
+{
+ this.tree_lock = tree_lock;
+}
+
+/*************************************************************************/
+
+/**
+ * AWT 1.0 event dispatcher.
+ *
+ * @deprecated Deprecated in favor of <code>dispatchEvent()</code>.
+ * @return true if the event was dispatched, false otherwise.
+ */
+public boolean
+postEvent(Event event)
+{
+ // This is overridden by subclasses that support events.
+ return false;
+}
+/*************************************************************************/
+
+/**
+ * Sends this event to this component or a subcomponent for processing.
+ *
+ * @param event The event to dispatch
+ */
+public final void dispatchEvent(AWTEvent event)
+{
+ // See comment in Component.dispatchEvent().
+ dispatchEventImpl(event);
+}
+
+
+/**
+ * Implementation of dispatchEvent. Allows trusted package classes
+ * to dispatch additional events first. This implementation first
+ * translates <code>event</code> to an AWT 1.0 event and sends the
+ * result to {@link #postEvent}. The event is then
+ * passed on to {@link #processEvent} for local processing.
+ *
+ * @param event the event to dispatch.
+ */
+void dispatchEventImpl(AWTEvent event)
+{
+ Event oldStyleEvent;
+
+ // This is overridden by subclasses that support events.
+ /* Convert AWT 1.1 event to AWT 1.0 event */
+ oldStyleEvent = Component.translateEvent(event);
+ if (oldStyleEvent != null)
+ {
+ postEvent(oldStyleEvent);
+ }
+ /* Do local processing */
+ processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event. In this class, this method simply
+ * calls one of the more specific event handlers.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ /*
+ Pass a focus event to the focus listener for
+ the accessibility context.
+ */
+ if (event instanceof FocusEvent)
+ {
+ if (focusListener != null)
+ {
+ switch (event.id)
+ {
+ case FocusEvent.FOCUS_GAINED:
+ focusListener.focusGained((FocusEvent) event);
+ break;
+ case FocusEvent.FOCUS_LOST:
+ focusListener.focusLost((FocusEvent) event);
+ break;
+ }
+ }
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this component.
+ *
+ * @return A string representation of this component
+ */
+public String
+toString()
+{
+ return this.getClass().getName() + "[" + paramString() + "]";
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this component
+ */
+protected String
+paramString()
+{
+ return "name=" + getName();
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>MenuComponent</code>.
+ * As an abstract class, we return null. Concrete subclasses should return
+ * their implementation of the accessibility context.
+ *
+ * @return null.
+ */
+
+public AccessibleContext getAccessibleContext()
+{
+ return null;
+}
+
+/**
+ * This class provides a base for the accessibility support of menu
+ * components.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+protected abstract class AccessibleAWTMenuComponent
+ extends AccessibleContext
+ implements Serializable, AccessibleComponent, AccessibleSelection
+{
+
+ /**
+ * Compatible with JDK 1.4.2 revision 5
+ */
+ private static final long serialVersionUID = -4269533416223798698L;
+
+ /**
+ * This is the default constructor. It should be called by
+ * concrete subclasses to ensure necessary groundwork is completed.
+ */
+ protected AccessibleAWTMenuComponent()
+ {
+ }
+
+ /**
+ * Replaces or supplements the component's selection with the
+ * <code>Accessible</code> child at the supplied index. If
+ * the component supports multiple selection, the child is
+ * added to the current selection. Otherwise, the current
+ * selection becomes the specified child. If the child is
+ * already selected, nothing happens.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the specified child within a
+ * zero-based list of the component's children.
+ */
+ public void addAccessibleSelection(int index)
+ {
+ /* Subclasses with children should implement this */
+ }
+
+ /**
+ * Registers the specified focus listener to receive
+ * focus events from this component.
+ *
+ * @param listener the new focus listener.
+ */
+ public void addFocusListener(FocusListener listener)
+ {
+ /*
+ * Chain the new focus listener to the existing chain
+ * of focus listeners. Each new focus listener is
+ * coupled via multicasting to the existing chain.
+ */
+ focusListener = AWTEventMulticaster.add(focusListener, listener);
+ }
+
+ /**
+ * Clears the component's current selection. Following
+ * the calling of this method, no children of the component
+ * will be selected.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ */
+ public void clearAccessibleSelection()
+ {
+ }
+
+ /**
+ * Returns true if the specified point lies within the
+ * component. The supplied co-ordinates are assumed to
+ * be relative to the co-ordinate system of the component
+ * itself. Thus, the point (0,0) is the upper left corner
+ * of this component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @param point the point to check against this component.
+ * @return true if the point is within this component.
+ * @see #getBounds()
+ */
+ public boolean contains(Point point)
+ {
+ /*
+ We can simply return the result of a
+ test for containment in the bounding rectangle
+ */
+ return getBounds().contains(point);
+ }
+
+ /**
+ * Returns the <code>Accessible</code> child of this component present
+ * at the specified point. The supplied co-ordinates are
+ * assumed to be relative to the co-ordinate system of this
+ * component (the parent of any returned accessible). Thus,
+ * the point (0,0) is the upper left corner of this menu
+ * component.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param point the point at which the returned accessible
+ * is located.
+ * @return null.
+ */
+ public Accessible getAccessibleAt(Point point)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the <code>Accessible</code> child at the supplied
+ * index within the list of children of this component.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the <code>Accessible</code> child
+ * to retrieve.
+ * @return null.
+ */
+ public Accessible getAccessibleChild(int index)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the number of children of this component which
+ * implement the <code>Accessible</code> interface. If
+ * all children of this component are accessible, then
+ * the returned value will be the same as the number of
+ * children.
+ * <br />
+ * <br />
+ *
+ * @return 0.
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Retrieves the <code>AccessibleComponent</code> associated
+ * with this accessible context and its component. As the
+ * context itself implements <code>AccessibleComponent</code>,
+ * this is the return value.
+ *
+ * @return the context itself.
+ */
+ public AccessibleComponent getAccessibleComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the accessible name for this menu component. This
+ * is the name given to the component, which may be null if
+ * not set using <code>setName()</code>.
+ * <br />
+ * <br />
+ * The name is not the most appropriate description of this
+ * object. Subclasses should preferably provide a more
+ * accurate description. For example, a File menu could
+ * have the description `Lists commands related to the
+ * file system'.
+ *
+ * @return a description of the component. Currently,
+ * this is just the contents of the name property.
+ * @see MenuComponent#setName(String)
+ */
+ public String getAccessibleDescription()
+ {
+ return MenuComponent.this.getName();
+ }
+
+ /**
+ * Retrieves the index of this component within its parent.
+ * If no parent exists, -1 is returned.
+ *
+ * @return -1 as the parent, a <code>MenuContainer</code>
+ * is not <code>Accessible</code>.
+ */
+ public int getAccessibleIndexInParent()
+ {
+ return -1;
+ }
+
+ /**
+ * Returns the accessible name of this component. This
+ * is the name given to the component, which may be null if
+ * not set using <code>setName()</code>.
+ * <br />
+ * <br />
+ * The name property is not the most suitable string to return
+ * for this method. The string should be localized, and
+ * relevant to the operation of the component. For example,
+ * it could be the text of a menu item. However, this can
+ * not be used at this level of abstraction, so it is the
+ * responsibility of subclasses to provide a more appropriate
+ * name.
+ *
+ * @return a localized name for this component. Currently, this
+ * is just the contents of the name property.
+ * @see MenuComponent#setName(String)
+ */
+ public String getAccessibleName()
+ {
+ return MenuComponent.this.getName();
+ }
+
+ /**
+ * Returns the <code>Accessible</code> parent of this component.
+ * As the parent of a <code>MenuComponent</code> is a
+ * <code>MenuContainer</code>, which doesn't implement
+ * <code>Accessible</code>, this method returns null.
+ *
+ * @return null.
+ */
+ public Accessible getAccessibleParent()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the accessible role of this component.
+ * <br />
+ * <br />
+ * The abstract implementation of this method returns
+ * <code>AccessibleRole.AWT_COMPONENT</code>,
+ * as the abstract component has no specific role. This
+ * method should be overridden by concrete subclasses, so
+ * as to return an appropriate role for the component.
+ *
+ * @return <code>AccessibleRole.AWT_COMPONENT</code>.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.AWT_COMPONENT;
+ }
+
+ /**
+ * Retrieves the <code>AccessibleSelection</code> associated
+ * with this accessible context and its component. As the
+ * context itself implements <code>AccessibleSelection</code>,
+ * this is the return value.
+ *
+ * @return the context itself.
+ */
+ public AccessibleSelection getAccessibleSelection()
+ {
+ return this;
+ }
+
+ /**
+ * Retrieves the <code>Accessible</code> selected child
+ * at the specified index. If there are no selected children
+ * or the index is outside the range of selected children,
+ * null is returned. Please note that the index refers
+ * to the index of the child in the list of <strong>selected
+ * children</strong>, and not the index of the child in
+ * the list of all <code>Accessible</code> children.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the selected <code>Accessible</code>
+ * child.
+ */
+ public Accessible getAccessibleSelection(int index)
+ {
+ return null;
+ }
+
+ /**
+ * Returns a count of the number of <code>Accessible</code>
+ * children of this component which are currently selected.
+ * If there are no children currently selected, 0 is returned.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @return 0.
+ */
+ public int getAccessibleSelectionCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Retrieves the current state of this component
+ * in an accessible form. For example, a given component
+ * may be visible, selected, disabled, etc.
+ * <br />
+ * <br />
+ * As this class tells us virtually nothing about the component,
+ * except for its name and font, no state information can be
+ * provided. This implementation thus returns an empty
+ * state set, and it is left to concrete subclasses to provide
+ * a more acceptable and relevant state set. Changes to these
+ * properties also need to be handled using
+ * <code>PropertyChangeListener</code>s.
+ *
+ * @return an empty <code>AccessibleStateSet</code>.
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ return new AccessibleStateSet();
+ }
+
+ /**
+ * Returns the background color of the component, or null
+ * if this property is unsupported.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns the
+ * default system background color used for rendering menus.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @return the default system background color for menus.
+ * @see #setBackground(java.awt.Color)
+ */
+ public Color getBackground()
+ {
+ return SystemColor.menu;
+ }
+
+ /**
+ * Returns a <code>Rectangle</code> which represents the
+ * bounds of this component. The returned rectangle has the
+ * height and width of the component's bounds, and is positioned
+ * at a location relative to this component's parent, the
+ * <code>MenuContainer</code>. null is returned if bounds
+ * are not supported by the component.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns null.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @return null.
+ * @see #setBounds(java.awt.Rectangle)
+ */
+ public Rectangle getBounds()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the <code>Cursor</code> displayed when the pointer
+ * is positioned over this component. Alternatively, null
+ * is returned if the component doesn't support the cursor
+ * property.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns the default
+ * system cursor. Concrete subclasses which handle the drawing
+ * of an onscreen menu component may override this method and provide
+ * the appropriate information.
+ *
+ * @return the default system cursor.
+ * @see #setCursor(java.awt.Cursor)
+ */
+ public Cursor getCursor()
+ {
+ return Cursor.getDefaultCursor();
+ }
+
+ /**
+ * Returns the <code>Font</code> used for text created by this component.
+ *
+ * @return the current font.
+ * @see #setFont(java.awt.Font)
+ */
+ public Font getFont()
+ {
+ return MenuComponent.this.getFont();
+ }
+
+ /**
+ * Retrieves information on the rendering and metrics of the supplied
+ * font. If font metrics are not supported by this component, null
+ * is returned.
+ * <br />
+ * <br />
+ * The abstract implementation of this method simply uses the toolkit
+ * to obtain the <code>FontMetrics</code>. Concrete subclasses may
+ * find it more efficient to invoke their peer class directly, if one
+ * is available.
+ *
+ * @param font the font about which to retrieve rendering and metric
+ * information.
+ * @return the metrics of the given font, as provided by the system
+ * toolkit.
+ * @throws NullPointerException if the supplied font was null.
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return MenuComponent.this.getToolkit().getFontMetrics(font);
+ }
+
+ /**
+ * Returns the foreground color of the component, or null
+ * if this property is unsupported.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns the
+ * default system text color used for rendering menus.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @return the default system text color for menus.
+ * @see #setForeground(java.awt.Color)
+ */
+ public Color getForeground()
+ {
+ return SystemColor.menuText;
+ }
+
+ /**
+ * Returns the locale currently in use by this component.
+ * <br />
+ * <br />
+ * This abstract class has no property relating to the
+ * locale used by the component, so this method simply
+ * returns the default locale for the current instance
+ * of the Java Virtual Machine (JVM). Concrete subclasses
+ * which maintain such a property should override this method
+ * and provide the locale information more accurately.
+ *
+ * @return the default locale for this JVM instance.
+ */
+ public Locale getLocale()
+ {
+ return Locale.getDefault();
+ }
+
+ /**
+ * Returns the location of the component, with co-ordinates
+ * relative to the parent component and using the co-ordinate
+ * space of the screen. Thus, the point (0,0) is the upper
+ * left corner of the parent component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @return the location of the component, relative to its parent.
+ * @see #setLocation(java.awt.Point)
+ */
+ public Point getLocation()
+ {
+ /* Simply return the location of the bounding rectangle */
+ return getBounds().getLocation();
+ }
+
+ /**
+ * Returns the location of the component, with co-ordinates
+ * relative to the screen. Thus, the point (0,0) is the upper
+ * left corner of the screen. null is returned if the component
+ * is either not on screen or if this property is unsupported.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns null.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @return the location of the component, relative to the screen.
+ */
+ public Point getLocationOnScreen()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the size of the component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @return the size of the component.
+ * @see #setSize(java.awt.Dimension)
+ */
+ public Dimension getSize()
+ {
+ /* Simply return the size of the bounding rectangle */
+ return getBounds().getSize();
+ }
+
+ /**
+ * Returns true if the accessible child specified by the supplied index
+ * is currently selected.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the accessible child to check for selection.
+ * @return false.
+ */
+ public boolean isAccessibleChildSelected(int index)
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if this component is currently enabled.
+ * <br />
+ * <br />
+ * As this abstract component has no properties related to
+ * its enabled or disabled state, the implementation of this
+ * method is left to subclasses.
+ *
+ * @return false.
+ * @see #setEnabled(boolean)
+ */
+ public boolean isEnabled()
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if this component is included in the traversal
+ * of the current focus from one component to the other.
+ * <br />
+ * <br />
+ * As this abstract component has no properties related to
+ * its ability to accept the focus, the implementation of this
+ * method is left to subclasses.
+ *
+ * @return false.
+ */
+ public boolean isFocusTraversable()
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if the component is being shown on screen.
+ * A component is determined to be shown if it is visible,
+ * and each parent component is also visible. Please note
+ * that, even when a component is showing, it may still be
+ * obscured by other components in front. This method only
+ * determines if the component is being drawn on the screen.
+ * <br />
+ * <br />
+ * As this abstract component and its parent have no properties
+ * relating to visibility, the implementation of this method is
+ * left to subclasses.
+ *
+ * @return false.
+ * @see #isVisible()
+ */
+ public boolean isShowing()
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if the component is visible. A component may
+ * be visible but not drawn on the screen if one of its parent
+ * components is not visible. To determine if the component is
+ * actually drawn on screen, <code>isShowing()</code> should be
+ * used.
+ * <br />
+ * <br />
+ * As this abstract component has no properties relating to its
+ * visibility, the implementation of this method is left to subclasses.
+ *
+ * @return false.
+ * @see #isShowing()
+ * @see #setVisible(boolean)
+ */
+ public boolean isVisible()
+ {
+ return false;
+ }
+
+ /**
+ * Removes the accessible child specified by the supplied index from
+ * the list of currently selected children. If the child specified
+ * is not selected, nothing happens.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the <code>Accessible</code> child.
+ */
+ public void removeAccessibleSelection(int index)
+ {
+ /* Subclasses with children should implement this */
+ }
+
+ /**
+ * Removes the specified focus listener from the list of registered
+ * focus listeners for this component.
+ *
+ * @param listener the listener to remove.
+ */
+ public void removeFocusListener(FocusListener listener)
+ {
+ /* Remove the focus listener from the chain */
+ focusListener = AWTEventMulticaster.remove(focusListener, listener);
+ }
+
+ /**
+ * Requests that this component gains focus. This depends on the
+ * component being focus traversable.
+ * <br />
+ * <br />
+ * As this abstract component has no properties relating to its
+ * focus traversability, or access to a peer with request focusing
+ * abilities, the implementation of this method is left to subclasses.
+ */
+ public void requestFocus()
+ {
+ /* Ignored */
+ }
+
+ /**
+ * Selects all <code>Accessible</code> children of this component which
+ * it is possible to select. The component needs to support multiple
+ * selections.
+ * <br />
+ * <br />
+ * This abstract component provides a simplistic implementation of this
+ * method, which ignores the ability of the component to support multiple
+ * selections and simply uses <code>addAccessibleSelection</code> to
+ * add each <code>Accessible</code> child to the selection. The last
+ * <code>Accessible</code> component is thus selected for components
+ * which don't support multiple selections. Concrete implementations should
+ * override this with a more appopriate and efficient implementation, which
+ * properly takes into account the ability of the component to support multiple
+ * selections.
+ */
+ public void selectAllAccessibleSelection()
+ {
+ /* Simply call addAccessibleSelection() on all accessible children */
+ for (int a = 0; a < getAccessibleChildrenCount(); ++a)
+ {
+ addAccessibleSelection(a);
+ }
+ }
+
+ /**
+ * Sets the background color of the component to that specified.
+ * Unspecified behaviour occurs when null is given as the new
+ * background color.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply ignores the supplied
+ * color and continues to use the default system color.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @param color the new color to use for the background.
+ * @see getBackground()
+ */
+ public void setBackground(Color color)
+ {
+ /* Ignored */
+ }
+
+ /**
+ * Sets the height and width of the component, and its position
+ * relative to this component's parent, to the values specified
+ * by the supplied rectangle. Unspecified behaviour occurs when
+ * null is given as the new bounds.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply ignores the new
+ * rectangle and continues to return null from <code>getBounds()</code>.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @param rectangle a rectangle which specifies the new bounds of
+ * the component.
+ * @see #getBounds()
+ */
+ public void setBounds(Rectangle rectangle)
+ {
+ /* Ignored */
+ }
+
+ /**
+ * Sets the <code>Cursor</code> used when the pointer is positioned over the
+ * component. Unspecified behaviour occurs when null is given as the new
+ * cursor.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply ignores the new cursor
+ * and continues to return the default system cursor. Concrete
+ * subclasses which handle the drawing of an onscreen menu component
+ * may override this method and provide the appropriate information.
+ *
+ * @param cursor the new cursor to use.
+ * @see #getCursor()
+ */
+ public void setCursor(Cursor cursor)
+ {
+ /* Ignored */
+ }
+
+ /**
+ * Sets the enabled/disabled state of this component.
+ * <br />
+ * <br />
+ * As this abstract component has no properties related to
+ * its enabled or disabled state, the implementation of this
+ * method is left to subclasses.
+ *
+ * @param enabled true if the component should be enabled,
+ * false otherwise.
+ * @see #getEnabled()
+ */
+ public void setEnabled(boolean enabled)
+ {
+ /* Ignored */
+ }
+
+ /**
+ * Sets the <code>Font</code> used for text created by this component.
+ * Unspecified behaviour occurs when null is given as the new
+ * font.
+ *
+ * @param font the new font to use for text.
+ * @see #getFont()
+ */
+ public void setFont(Font font)
+ {
+ /* Call the method of the enclosing component */
+ MenuComponent.this.setFont(font);
+ }
+
+ /**
+ * Sets the foreground color of the component to that specified.
+ * Unspecified behaviour occurs when null is given as the new
+ * background color.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply ignores the supplied
+ * color and continues to return the default system text color used
+ * for rendering menus.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @param color the new foreground color.
+ * @see #getForeground()
+ */
+ public void setForeground(Color color)
+ {
+ /* Ignored */
+ }
+
+ /**
+ * Sets the location of the component, with co-ordinates
+ * relative to the parent component and using the co-ordinate
+ * space of the screen. Thus, the point (0,0) is the upper
+ * left corner of the parent component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @param point the location of the component, relative to its parent.
+ * @see #getLocation()
+ */
+ public void setLocation(Point point)
+ {
+ getBounds().setLocation(point);
+ }
+
+ /**
+ * Sets the size of the component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @param size the new size of the component.
+ * @see #getSize()
+ */
+ public void setSize(Dimension size)
+ {
+ getBounds().setSize(size);
+ }
+
+ /**
+ * Sets the visibility state of the component. A component may
+ * be visible but not drawn on the screen if one of its parent
+ * components is not visible. To determine if the component is
+ * actually drawn on screen, <code>isShowing()</code> should be
+ * used.
+ * <br />
+ * <br />
+ * As this abstract component has no properties relating to its
+ * visibility, the implementation of this method is left to subclasses.
+ *
+ * @param visibility the new visibility of the component -- true if
+ * the component is visible, false if not.
+ * @see #isShowing()
+ * @see #isVisible()
+ */
+ public void setVisible(boolean visibility)
+ {
+ /* Ignored */
+ }
+
+} /* class AccessibleAWTMenuComponent */
+
+
+} // class MenuComponent
diff --git a/libjava/classpath/java/awt/MenuContainer.java b/libjava/classpath/java/awt/MenuContainer.java
new file mode 100644
index 00000000000..c76ec96c20b
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuContainer.java
@@ -0,0 +1,71 @@
+/* MenuContainer.java -- container for menu items
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This interface is a container for menu components.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface MenuContainer
+{
+ /**
+ * Returns the font in use by this container.
+ *
+ * @return the menu font
+ */
+ Font getFont();
+
+ /**
+ * Removes the specified menu component from the menu.
+ *
+ * @param component the menu component to remove
+ */
+ void remove(MenuComponent component);
+
+ /**
+ * Posts an event to the listeners.
+ *
+ * @param event the event to dispatch
+ * @deprecated use {@link MenuComponent#dispatchEvent(AWTEvent)} instead
+ */
+ boolean postEvent(Event event);
+} // interface MenuContainer
diff --git a/libjava/classpath/java/awt/MenuItem.java b/libjava/classpath/java/awt/MenuItem.java
new file mode 100644
index 00000000000..66798c8800c
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuItem.java
@@ -0,0 +1,603 @@
+/* MenuItem.java -- An item in a menu
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.MenuItemPeer;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class represents an item in a menu.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class MenuItem extends MenuComponent
+ implements Serializable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = -21757335363267194L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The name of the action command generated by this item.
+ * This is package-private to avoid an accessor method.
+ */
+String actionCommand;
+
+/**
+ * @serial Indicates whether or not this menu item is enabled.
+ * This is package-private to avoid an accessor method.
+ */
+boolean enabled = true;
+
+/**
+ * @serial The mask of events that are enabled for this menu item.
+ */
+long eventMask;
+
+/**
+ * @serial This menu item's label
+ * This is package-private to avoid an accessor method.
+ */
+String label = "";
+
+/**
+ * @serial The shortcut for this menu item, if any
+ */
+private MenuShortcut shortcut;
+
+// The list of action listeners for this menu item.
+private transient ActionListener action_listeners;
+
+ protected class AccessibleAWTMenuItem
+ extends MenuComponent.AccessibleAWTMenuComponent
+ implements AccessibleAction, AccessibleValue
+ {
+ /** Constructor */
+ public AccessibleAWTMenuItem()
+ {
+ super();
+ }
+
+
+
+ public String getAccessibleName()
+ {
+ return label;
+ }
+
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.MENU_ITEM;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
+ */
+ public int getAccessibleActionCount()
+ {
+ return 1;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ if (i == 0)
+ return label;
+ else
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ if (i != 0)
+ return false;
+ processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand));
+ return true;
+ }
+
+ public AccessibleValue getAccessibleValue()
+ {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
+ */
+ public Number getCurrentAccessibleValue()
+ {
+ return (enabled) ? new Integer(1) : new Integer(0);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
+ */
+ public boolean setCurrentAccessibleValue(Number number)
+ {
+ if (number.intValue() == 0)
+ {
+ setEnabled(false);
+ return false;
+ }
+
+ setEnabled(true);
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
+ */
+ public Number getMinimumAccessibleValue()
+ {
+ return new Integer(0);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
+ */
+ public Number getMaximumAccessibleValue()
+ {
+ return new Integer(0);
+ }
+
+ }
+
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>MenuItem</code> with no label
+ * and no shortcut.
+ */
+public
+MenuItem()
+{
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>MenuItem</code> with the specified
+ * label and no shortcut.
+ *
+ * @param label The label for this menu item.
+ */
+public
+MenuItem(String label)
+{
+ this.label = label;
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>MenuItem</code> with the specified
+ * label and shortcut.
+ *
+ * @param label The label for this menu item.
+ * @param shortcut The shortcut for this menu item.
+ */
+public
+MenuItem(String label, MenuShortcut shortcut)
+{
+ this.label = label;
+ this.shortcut = shortcut;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the label for this menu item, which may be <code>null</code>.
+ *
+ * @return The label for this menu item.
+ */
+public String
+getLabel()
+{
+ return(label);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the label for this menu to the specified value.
+ *
+ * @param label The new label for this menu item.
+ */
+public synchronized void
+setLabel(String label)
+{
+ this.label = label;
+ if (peer != null)
+ {
+ MenuItemPeer mp = (MenuItemPeer) peer;
+ mp.setLabel (label);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this menu item is enabled.
+ *
+ * @return <code>true</code> if this menu item is enabled, <code>false</code>
+ * otherwise.
+ */
+public boolean
+isEnabled()
+{
+ return(enabled);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the enabled status of this menu item.
+ *
+ * @param enabled <code>true</code> to enable this menu item,
+ * <code>false</code> otherwise.
+ */
+public synchronized void
+setEnabled(boolean enabled)
+{
+ enable (enabled);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the enabled status of this menu item.
+ *
+ * @param enabled <code>true</code> to enable this menu item,
+ * <code>false</code> otherwise.
+ *
+ * @deprecated This method is deprecated in favor of <code>setEnabled()</code>.
+ */
+public void
+enable(boolean enabled)
+{
+ if (enabled)
+ enable ();
+ else
+ disable ();
+}
+
+/*************************************************************************/
+
+/**
+ * Enables this menu item.
+ *
+ * @deprecated This method is deprecated in favor of <code>setEnabled()</code>.
+ */
+public void
+enable()
+{
+ if (enabled)
+ return;
+
+ this.enabled = true;
+ if (peer != null)
+ ((MenuItemPeer) peer).setEnabled (true);
+}
+
+/*************************************************************************/
+
+/**
+ * Disables this menu item.
+ *
+ * @deprecated This method is deprecated in favor of <code>setEnabled()</code>.
+ */
+public void
+disable()
+{
+ if (!enabled)
+ return;
+
+ this.enabled = false;
+ if (peer != null)
+ ((MenuItemPeer) peer).setEnabled (false);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the shortcut for this menu item, which may be <code>null</code>.
+ *
+ * @return The shortcut for this menu item.
+ */
+public MenuShortcut
+getShortcut()
+{
+ return(shortcut);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the shortcut for this menu item to the specified value. This
+ * must be done before the native peer is created.
+ *
+ * @param shortcut The new shortcut for this menu item.
+ */
+public void
+setShortcut(MenuShortcut shortcut)
+{
+ this.shortcut = shortcut;
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes the shortcut for this menu item if one exists. This must be
+ * done before the native peer is created.
+ */
+public void
+deleteShortcut()
+{
+ shortcut = null;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the name of the action command in the action events
+ * generated by this menu item.
+ *
+ * @return The action command name
+ */
+public String
+getActionCommand()
+{
+ if (actionCommand == null)
+ return label;
+ else
+ return actionCommand;
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the name of the action command in the action events generated by
+ * this menu item.
+ *
+ * @param actionCommand The new action command name.
+ */
+public void
+setActionCommand(String actionCommand)
+{
+ this.actionCommand = actionCommand;
+}
+
+/*************************************************************************/
+
+/**
+ * Enables the specified events. This is done automatically when a
+ * listener is added and does not normally need to be done by
+ * application code.
+ *
+ * @param events The events to enable, which should be the bit masks
+ * from <code>AWTEvent</code>.
+ */
+protected final void
+enableEvents(long events)
+{
+ eventMask |= events;
+ // TODO: see comment in Component.enableEvents().
+}
+
+/*************************************************************************/
+
+/**
+ * Disables the specified events.
+ *
+ * @param events The events to enable, which should be the bit masks
+ * from <code>AWTEvent</code>.
+ */
+protected final void
+disableEvents(long events)
+{
+ eventMask &= ~events;
+}
+
+/*************************************************************************/
+
+/**
+ * Creates the native peer for this object.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createMenuItem (this);
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified listener to the list of registered action listeners
+ * for this component.
+ *
+ * @param listener The listener to add.
+ */
+public synchronized void
+addActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+
+ enableEvents(AWTEvent.ACTION_EVENT_MASK);
+}
+
+public synchronized void
+removeActionListener(ActionListener l)
+{
+ action_listeners = AWTEventMulticaster.remove(action_listeners, l);
+}
+
+ public synchronized ActionListener[] getActionListeners()
+ {
+ return (ActionListener[])
+ AWTEventMulticaster.getListeners(action_listeners,
+ ActionListener.class);
+ }
+
+/** Returns all registered EventListers of the given listenerType.
+ * listenerType must be a subclass of EventListener, or a
+ * ClassClassException is thrown.
+ * @since 1.3
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ if (listenerType == ActionListener.class)
+ return getActionListeners();
+ return (EventListener[]) Array.newInstance(listenerType, 0);
+ }
+
+/*************************************************************************/
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ActionEvent.ACTION_LAST
+ && e.id >= ActionEvent.ACTION_FIRST
+ && (action_listeners != null
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+
+ // Send the event to the parent menu if it has not yet been
+ // consumed.
+ if (!e.isConsumed ())
+ ((Menu) getParent ()).processEvent (e);
+}
+
+/**
+ * Processes the specified event by calling <code>processActionEvent()</code>
+ * if it is an instance of <code>ActionEvent</code>.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event by dispatching it to any registered listeners.
+ *
+ * @param event The event to process.
+ */
+protected void
+processActionEvent(ActionEvent event)
+{
+ if (action_listeners != null)
+ {
+ event.setSource(this);
+ action_listeners.actionPerformed(event);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+public String
+paramString()
+{
+ return ("label=" + label + ",enabled=" + enabled +
+ ",actionCommand=" + actionCommand + "," + super.paramString());
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>MenuItem</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTMenuItem();
+ return accessibleContext;
+}
+
+} // class MenuItem
diff --git a/libjava/classpath/java/awt/MenuShortcut.java b/libjava/classpath/java/awt/MenuShortcut.java
new file mode 100644
index 00000000000..adfd1d3187a
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuShortcut.java
@@ -0,0 +1,207 @@
+/* MenuShortcut.java -- A class for menu accelerators
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class implements a keyboard accelerator for a menu item.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class MenuShortcut implements java.io.Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = 143448358473180225L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The virtual keycode for the shortcut.
+ */
+private int key;
+
+/**
+ * @serial <code>true</code> if the shift key was used with this shortcut,
+ * or <code>false</code> otherwise.
+ */
+private boolean usesShift;
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>MenuShortcut</code> with the
+ * specified virtual key value.
+ *
+ * @param key The virtual keycode for the shortcut.
+ */
+public
+MenuShortcut(int key)
+{
+ this(key, false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>MenuShortcut</code> with the
+ * specified virtual key value and shift setting.
+ *
+ * @param key The virtual keycode for the shortcut.
+ * @param usesShift <code>true</code> if the shift key was pressed,
+ * <code>false</code> otherwise.
+ */
+public
+MenuShortcut(int key, boolean usesShift)
+{
+ this.key = key;
+ this.usesShift = usesShift;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the virtual keycode for this shortcut.
+ *
+ * @return The virtual keycode for this shortcut.
+ */
+public int
+getKey()
+{
+ return(key);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the shift setting for this shortcut.
+ *
+ * @return <code>true</code> if the shift key was pressed, <code>false</code>
+ * otherwise.
+ */
+public boolean
+usesShiftModifier()
+{
+ return(usesShift);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests this object for equality against the specified object. The two
+ * objects will be considered equal if and only if the specified object
+ * is an instance of <code>MenuShortcut</code> and has the same key value
+ * and shift setting as this object.
+ *
+ * @param obj The object to test for equality against.
+ *
+ * @return <code>true</code> if the two objects are equal, <code>false</code>
+ * otherwise.
+ */
+public boolean
+equals(MenuShortcut obj)
+{
+ if (obj == null)
+ return(false);
+
+ if (obj.key != this.key)
+ return(false);
+
+ if (obj.usesShift != this.usesShift)
+ return(false);
+
+ return(true);
+}
+
+public boolean
+equals(Object obj)
+{
+ if (obj instanceof MenuShortcut)
+ {
+ MenuShortcut ms = (MenuShortcut) obj;
+ return (ms.key == key && ms.usesShift == usesShift);
+ }
+ return false;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this shortcut.
+ *
+ * @return A string representation of this shortcut.
+ */
+public String
+toString()
+{
+ return(getClass().getName() + "[" + paramString () + "]");
+}
+
+public int
+hashCode()
+{
+ // Arbitrary.
+ return key + (usesShift ? 23 : 57);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+protected String
+paramString()
+{
+ return "key=" + key + ",usesShift=" + usesShift;
+}
+
+} // class MenuShortcut
diff --git a/libjava/classpath/java/awt/PageAttributes.java b/libjava/classpath/java/awt/PageAttributes.java
new file mode 100644
index 00000000000..38fb696e339
--- /dev/null
+++ b/libjava/classpath/java/awt/PageAttributes.java
@@ -0,0 +1,482 @@
+/* PageAttributes.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.util.Locale;
+
+/**
+ * Missing Documentation
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4, but missing documentation
+ */
+public final class PageAttributes implements Cloneable
+{
+ public static final class ColorType extends AttributeValue
+ {
+ private static final String[] NAMES = { "color", "monochrome" };
+ public static final ColorType COLOR = new ColorType(0);
+ public static final ColorType MONOCHROME = new ColorType(1);
+ private ColorType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class ColorType
+ public static final class MediaType extends AttributeValue
+ {
+ private static final String[] NAMES
+ = { "iso-4a0", "iso-2a0", "iso-a0", "iso-a1", "iso-a2", "iso-a3",
+ "iso-a4", "iso-a5", "iso-a6", "iso-a7", "iso-a8", "iso-a9",
+ "iso-a10", "iso-b0", "iso-b1", "iso-b2", "iso-b3", "iso-b4",
+ "iso-b5", "iso-b6", "iso-b7", "iso-b8", "iso-b9", "iso-b10",
+ "jis-b0", "jis-b1", "jis-b2", "jis-b3", "jis-b4", "jis-b5",
+ "jis-b6", "jis-b7", "jis-b8", "jis-b9", "jis-b10", "iso-c0",
+ "iso-c1", "iso-c2", "iso-c3", "iso-c4", "iso-c5", "iso-c6",
+ "iso-c7", "iso-c8", "iso-c9", "iso-c10", "iso-designated-long",
+ "executive", "folio", "invoice", "ledger", "na-letter", "na-legal",
+ "quarto", "a", "b", "c", "d", "e", "na-10x15-envelope",
+ "na-10x14-envelope", "na-10x13-envelope", "na-9x12-envelope",
+ "na-9x11-envelope", "na-7x9-envelope", "na-6x9-envelope",
+ "na-number-9-envelope", "na-number-10-envelope",
+ "na-number-11-envelope", "na-number-12-envelope",
+ "na-number-14-envelope", "invite-envelope", "italy-envelope",
+ "monarch-envelope", "personal-envelope" };
+ public static final MediaType ISO_4A0 = new MediaType(0);
+ public static final MediaType ISO_2A0 = new MediaType(1);
+ public static final MediaType ISO_A0 = new MediaType(2);
+ public static final MediaType ISO_A1 = new MediaType(3);
+ public static final MediaType ISO_A2 = new MediaType(4);
+ public static final MediaType ISO_A3 = new MediaType(5);
+ public static final MediaType ISO_A4 = new MediaType(6);
+ public static final MediaType ISO_A5 = new MediaType(7);
+ public static final MediaType ISO_A6 = new MediaType(8);
+ public static final MediaType ISO_A7 = new MediaType(9);
+ public static final MediaType ISO_A8 = new MediaType(10);
+ public static final MediaType ISO_A9 = new MediaType(11);
+ public static final MediaType ISO_A10 = new MediaType(12);
+ public static final MediaType ISO_B0 = new MediaType(13);
+ public static final MediaType ISO_B1 = new MediaType(14);
+ public static final MediaType ISO_B2 = new MediaType(15);
+ public static final MediaType ISO_B3 = new MediaType(16);
+ public static final MediaType ISO_B4 = new MediaType(17);
+ public static final MediaType ISO_B5 = new MediaType(18);
+ public static final MediaType ISO_B6 = new MediaType(19);
+ public static final MediaType ISO_B7 = new MediaType(20);
+ public static final MediaType ISO_B8 = new MediaType(21);
+ public static final MediaType ISO_B9 = new MediaType(22);
+ public static final MediaType ISO_B10 = new MediaType(23);
+ public static final MediaType JIS_B0 = new MediaType(24);
+ public static final MediaType JIS_B1 = new MediaType(25);
+ public static final MediaType JIS_B2 = new MediaType(26);
+ public static final MediaType JIS_B3 = new MediaType(27);
+ public static final MediaType JIS_B4 = new MediaType(28);
+ public static final MediaType JIS_B5 = new MediaType(29);
+ public static final MediaType JIS_B6 = new MediaType(30);
+ public static final MediaType JIS_B7 = new MediaType(31);
+ public static final MediaType JIS_B8 = new MediaType(32);
+ public static final MediaType JIS_B9 = new MediaType(33);
+ public static final MediaType JIS_B10 = new MediaType(34);
+ public static final MediaType ISO_C0 = new MediaType(35);
+ public static final MediaType ISO_C1 = new MediaType(36);
+ public static final MediaType ISO_C2 = new MediaType(37);
+ public static final MediaType ISO_C3 = new MediaType(38);
+ public static final MediaType ISO_C4 = new MediaType(39);
+ public static final MediaType ISO_C5 = new MediaType(40);
+ public static final MediaType ISO_C6 = new MediaType(41);
+ public static final MediaType ISO_C7 = new MediaType(42);
+ public static final MediaType ISO_C8 = new MediaType(43);
+ public static final MediaType ISO_C9 = new MediaType(44);
+ public static final MediaType ISO_C10 = new MediaType(45);
+ public static final MediaType ISO_DESIGNATED_LONG = new MediaType(46);
+ public static final MediaType EXECUTIVE = new MediaType(47);
+ public static final MediaType FOLIO = new MediaType(48);
+ public static final MediaType INVOICE = new MediaType(49);
+ public static final MediaType LEDGER = new MediaType(50);
+ public static final MediaType NA_LETTER = new MediaType(51);
+ public static final MediaType NA_LEGAL = new MediaType(52);
+ public static final MediaType QUARTO = new MediaType(53);
+ public static final MediaType A = new MediaType(54);
+ public static final MediaType B = new MediaType(55);
+ public static final MediaType C = new MediaType(56);
+ public static final MediaType D = new MediaType(57);
+ public static final MediaType E = new MediaType(58);
+ public static final MediaType NA_10X15_ENVELOPE = new MediaType(59);
+ public static final MediaType NA_10X14_ENVELOPE = new MediaType(60);
+ public static final MediaType NA_10X13_ENVELOPE = new MediaType(61);
+ public static final MediaType NA_9X12_ENVELOPE = new MediaType(62);
+ public static final MediaType NA_9X11_ENVELOPE = new MediaType(63);
+ public static final MediaType NA_7X9_ENVELOPE = new MediaType(64);
+ public static final MediaType NA_6X9_ENVELOPE = new MediaType(65);
+ public static final MediaType NA_NUMBER_9_ENVELOPE = new MediaType(66);
+ public static final MediaType NA_NUMBER_10_ENVELOPE = new MediaType(67);
+ public static final MediaType NA_NUMBER_11_ENVELOPE = new MediaType(68);
+ public static final MediaType NA_NUMBER_12_ENVELOPE = new MediaType(69);
+ public static final MediaType NA_NUMBER_14_ENVELOPE = new MediaType(70);
+ public static final MediaType INVITE_ENVELOPE = new MediaType(71);
+ public static final MediaType ITALY_ENVELOPE = new MediaType(72);
+ public static final MediaType MONARCH_ENVELOPE = new MediaType(73);
+ public static final MediaType PERSONAL_ENVELOPE = new MediaType(74);
+ public static final MediaType A0 = ISO_A0;
+ public static final MediaType A1 = ISO_A1;
+ public static final MediaType A2 = ISO_A2;
+ public static final MediaType A3 = ISO_A3;
+ public static final MediaType A4 = ISO_A4;
+ public static final MediaType A5 = ISO_A5;
+ public static final MediaType A6 = ISO_A6;
+ public static final MediaType A7 = ISO_A7;
+ public static final MediaType A8 = ISO_A8;
+ public static final MediaType A9 = ISO_A9;
+ public static final MediaType A10 = ISO_A10;
+ public static final MediaType B0 = ISO_B0;
+ public static final MediaType B1 = ISO_B1;
+ public static final MediaType B2 = ISO_B2;
+ public static final MediaType B3 = ISO_B3;
+ public static final MediaType B4 = ISO_B4;
+ public static final MediaType ISO_B4_ENVELOPE = ISO_B4;
+ public static final MediaType B5 = ISO_B5;
+ public static final MediaType ISO_B5_ENVELOPE = ISO_B4;
+ public static final MediaType B6 = ISO_B6;
+ public static final MediaType B7 = ISO_B7;
+ public static final MediaType B8 = ISO_B8;
+ public static final MediaType B9 = ISO_B9;
+ public static final MediaType B10 = ISO_B10;
+ public static final MediaType C0 = ISO_B0;
+ public static final MediaType ISO_C0_ENVELOPE = ISO_C0;
+ public static final MediaType C1 = ISO_C1;
+ public static final MediaType ISO_C1_ENVELOPE = ISO_C1;
+ public static final MediaType C2 = ISO_C2;
+ public static final MediaType ISO_C2_ENVELOPE = ISO_C2;
+ public static final MediaType C3 = ISO_C3;
+ public static final MediaType ISO_C3_ENVELOPE = ISO_C3;
+ public static final MediaType C4 = ISO_C4;
+ public static final MediaType ISO_C4_ENVELOPE = ISO_C4;
+ public static final MediaType C5 = ISO_C5;
+ public static final MediaType ISO_C5_ENVELOPE = ISO_C5;
+ public static final MediaType C6 = ISO_C6;
+ public static final MediaType ISO_C6_ENVELOPE = ISO_C6;
+ public static final MediaType C7 = ISO_C7;
+ public static final MediaType ISO_C7_ENVELOPE = ISO_C7;
+ public static final MediaType C8 = ISO_C8;
+ public static final MediaType ISO_C8_ENVELOPE = ISO_C8;
+ public static final MediaType C9 = ISO_C9;
+ public static final MediaType ISO_C9_ENVELOPE = ISO_C9;
+ public static final MediaType C10 = ISO_C10;
+ public static final MediaType ISO_C10_ENVELOPE = ISO_C10;
+ public static final MediaType ISO_DESIGNATED_LONG_ENVELOPE
+ = ISO_DESIGNATED_LONG;
+ public static final MediaType STATEMENT = INVOICE;
+ public static final MediaType TABLOID = LEDGER;
+ public static final MediaType LETTER = NA_LETTER;
+ public static final MediaType NOTE = NA_LETTER;
+ public static final MediaType LEGAL = NA_LEGAL;
+ public static final MediaType ENV_10X15 = NA_10X15_ENVELOPE;
+ public static final MediaType ENV_10X14 = NA_10X14_ENVELOPE;
+ public static final MediaType ENV_10X13 = NA_10X13_ENVELOPE;
+ public static final MediaType ENV_9X12 = NA_9X12_ENVELOPE;
+ public static final MediaType ENV_9X11 = NA_9X11_ENVELOPE;
+ public static final MediaType ENV_7X9 = NA_7X9_ENVELOPE;
+ public static final MediaType ENV_6X9 = NA_6X9_ENVELOPE;
+ public static final MediaType ENV_9 = NA_NUMBER_9_ENVELOPE;
+ public static final MediaType ENV_10 = NA_NUMBER_10_ENVELOPE;
+ public static final MediaType ENV_11 = NA_NUMBER_11_ENVELOPE;
+ public static final MediaType ENV_12 = NA_NUMBER_12_ENVELOPE;
+ public static final MediaType ENV_14 = NA_NUMBER_14_ENVELOPE;
+ public static final MediaType ENV_INVITE = INVITE_ENVELOPE;
+ public static final MediaType ENV_ITALY = ITALY_ENVELOPE;
+ public static final MediaType ENV_MONARCH = MONARCH_ENVELOPE;
+ public static final MediaType ENV_PERSONAL = PERSONAL_ENVELOPE;
+ public static final MediaType INVITE = INVITE_ENVELOPE;
+ public static final MediaType ITALY = ITALY_ENVELOPE;
+ public static final MediaType MONARCH = MONARCH_ENVELOPE;
+ public static final MediaType PERSONAL = PERSONAL_ENVELOPE;
+ private MediaType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class MediaType
+ public static final class OrientationRequestedType extends AttributeValue
+ {
+ private static final String[] NAMES = { "portrait", "landscape" };
+ public static final OrientationRequestedType PORTRAIT
+ = new OrientationRequestedType(0);
+ public static final OrientationRequestedType LANDSCAPE
+ = new OrientationRequestedType(1);
+ private OrientationRequestedType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class OrientationRequestedType
+ public static final class OriginType extends AttributeValue
+ {
+ private static final String[] NAMES = { "physical", "printable" };
+ public static final OriginType PHYSICAL = new OriginType(0);
+ public static final OriginType PRINTABLE = new OriginType(1);
+ private OriginType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class OriginType
+ public static final class PrintQualityType extends AttributeValue
+ {
+ private static final String[] NAMES = { "high", "normal", "draft" };
+ public static final PrintQualityType HIGH = new PrintQualityType(0);
+ public static final PrintQualityType NORMAL = new PrintQualityType(1);
+ public static final PrintQualityType DRAFT = new PrintQualityType(2);
+ private PrintQualityType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class PrintQualityType
+
+
+ private ColorType color;
+ private MediaType media;
+ private OrientationRequestedType orientation;
+ private OriginType origin;
+ private PrintQualityType quality;
+ private int resolutionX;
+ private int resolutionY;
+ private int resolutionScale;
+ public PageAttributes()
+ {
+ color = ColorType.MONOCHROME;
+ setMediaToDefault();
+ orientation = OrientationRequestedType.PORTRAIT;
+ origin = OriginType.PHYSICAL;
+ quality = PrintQualityType.NORMAL;
+ setPrinterResolutionToDefault();
+ }
+
+ public PageAttributes(PageAttributes attr)
+ {
+ set(attr);
+ }
+
+ public PageAttributes(ColorType color, MediaType media,
+ OrientationRequestedType orientation,
+ OriginType origin, PrintQualityType quality,
+ int[] resolution)
+ {
+ if (color == null || media == null || orientation == null
+ || origin == null || quality == null)
+ throw new IllegalArgumentException();
+ setPrinterResolution(resolution);
+ this.color = color;
+ this.media = media;
+ this.orientation = orientation;
+ this.origin = origin;
+ this.quality = quality;
+ }
+
+ public Object clone()
+ {
+ return new PageAttributes(this);
+ }
+
+ public void set(PageAttributes attr)
+ {
+ color = attr.color;
+ media = attr.media;
+ orientation = attr.orientation;
+ origin = attr.origin;
+ quality = attr.quality;
+ resolutionX = attr.resolutionX;
+ resolutionY = attr.resolutionY;
+ resolutionScale = attr.resolutionScale;
+ }
+
+ public ColorType getColor()
+ {
+ return color;
+ }
+
+ public void setColor(ColorType color)
+ {
+ if (color == null)
+ throw new IllegalArgumentException();
+ this.color = color;
+ }
+
+ public MediaType getMedia()
+ {
+ return media;
+ }
+
+ public void setMedia(MediaType media)
+ {
+ if (media == null)
+ throw new IllegalArgumentException();
+ this.media = media;
+ }
+
+ public void setMediaToDefault()
+ {
+ String country = Locale.getDefault().getCountry();
+ media = ("US".equals(country) || "CA".equals(country)) ? MediaType.LETTER
+ : MediaType.A4;
+ }
+
+ public OrientationRequestedType getOrientationRequested()
+ {
+ return orientation;
+ }
+
+ public void setOrientationRequested(OrientationRequestedType orientation)
+ {
+ if (orientation == null)
+ throw new IllegalArgumentException();
+ this.orientation = orientation;
+ }
+
+ public void setOrientationRequested(int orientation)
+ {
+ if (orientation == 3)
+ this.orientation = OrientationRequestedType.PORTRAIT;
+ else if (orientation == 4)
+ this.orientation = OrientationRequestedType.LANDSCAPE;
+ else
+ throw new IllegalArgumentException();
+ }
+
+ public void setOrientationRequestedToDefault()
+ {
+ orientation = OrientationRequestedType.PORTRAIT;
+ }
+
+ public OriginType getOrigin()
+ {
+ return origin;
+ }
+
+ public void setOrigin(OriginType origin)
+ {
+ if (origin == null)
+ throw new IllegalArgumentException();
+ this.origin = origin;
+ }
+
+ public PrintQualityType getPrintQuality()
+ {
+ return quality;
+ }
+
+ public void setPrintQuality(PrintQualityType quality)
+ {
+ if (quality == null)
+ throw new IllegalArgumentException();
+ this.quality = quality;
+ }
+
+ public void setPrintQuality(int quality)
+ {
+ if (quality == 3)
+ this.quality = PrintQualityType.DRAFT;
+ else if (quality == 4)
+ this.quality = PrintQualityType.NORMAL;
+ else if (quality == 5)
+ this.quality = PrintQualityType.HIGH;
+ else
+ throw new IllegalArgumentException();
+ }
+
+ public void setPrintQualityToDefault()
+ {
+ quality = PrintQualityType.NORMAL;
+ }
+
+ public int[] getPrinterResolution()
+ {
+ return new int[] { resolutionX, resolutionY, resolutionScale };
+ }
+
+ public void setPrinterResolution(int[] resolution)
+ {
+ if (resolution == null || resolution.length != 3 || resolution[0] <= 0
+ || resolution[1] <= 0 || resolution[2] < 3 || resolution[2] > 4)
+ throw new IllegalArgumentException();
+ resolutionX = resolution[0];
+ resolutionY = resolution[1];
+ resolutionScale = resolution[2];
+ }
+
+ public void setPrinterResolution(int resolution)
+ {
+ if (resolution <= 0)
+ throw new IllegalArgumentException();
+ resolutionX = resolution;
+ resolutionY = resolution;
+ resolutionScale = 3;
+ }
+
+ public void setPrinterResolutionToDefault()
+ {
+ resolutionX = 72;
+ resolutionY = 72;
+ resolutionScale = 3;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (! (o instanceof PageAttributes))
+ return false;
+ PageAttributes pa = (PageAttributes) o;
+ return color == pa.color && media == pa.media
+ && orientation == pa.orientation && origin == pa.origin
+ && quality == pa.quality && resolutionX == pa.resolutionX
+ && resolutionY == pa.resolutionY
+ && resolutionScale == pa.resolutionScale;
+ }
+ public int hashCode()
+ {
+ return (color.value << 31) ^ (media.value << 24)
+ ^ (orientation.value << 23) ^ (origin.value << 22)
+ ^ (quality.value << 20) ^ (resolutionScale << 19)
+ ^ (resolutionY << 10) ^ resolutionX;
+ }
+ public String toString()
+ {
+ return "color=" + color + ",media=" + media + ",orientation-requested="
+ + orientation + ",origin=" + origin + ",print-quality=" + quality
+ + ",printer-resolution=[" + resolutionX + ',' + resolutionY + ','
+ + resolutionScale + ']';
+ }
+} // class PageAttributes
diff --git a/libjava/classpath/java/awt/Paint.java b/libjava/classpath/java/awt/Paint.java
new file mode 100644
index 00000000000..0f099cc0b80
--- /dev/null
+++ b/libjava/classpath/java/awt/Paint.java
@@ -0,0 +1,79 @@
+/* Paint.java -- generate colors for Graphics2D operations
+ Copyright (C) 2000, 2002 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 java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+
+/**
+ * Defines how color patterns are generated for Graphics2D operations. This
+ * is used to perform the <code>draw</code> and <code>fill</code> methods
+ * of the graphics object. Instances must be immutable, because the graphics
+ * object does not clone them.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see PaintContext
+ * @see Color
+ * @see GradientPaint
+ * @see TexturePaint
+ * @see Graphics2D#setPaint(Paint)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Paint extends Transparency
+{
+ /**
+ * Create the context necessary for performing the color pattern generation.
+ * The color model is a hint, and may be null for Classpath implementations;
+ * however some legacy code may throw a NullPointerException when passed a
+ * null. Leaving the color model null provides the most efficiency and leeway
+ * in the generation of the color pattern.
+ *
+ * @param cm the color model, used as a hint
+ * @param deviceBounds the device space bounding box of the painted area
+ * @param userBounds the user space bounding box of the painted area
+ * @param xform the transformation from user space to device space
+ * @param hints any hints for choosing between rendering alternatives
+ * @return the context for performing the paint
+ */
+ PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds, AffineTransform xform,
+ RenderingHints hints);
+} // interface Paint
diff --git a/libjava/classpath/java/awt/PaintContext.java b/libjava/classpath/java/awt/PaintContext.java
new file mode 100644
index 00000000000..3d5fdcdf0e4
--- /dev/null
+++ b/libjava/classpath/java/awt/PaintContext.java
@@ -0,0 +1,76 @@
+/* PaintContext.java -- the environment for performing a paint operation
+ Copyright (C) 2000, 2002 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 java.awt.image.ColorModel;
+import java.awt.image.Raster;
+
+/**
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see Paint
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface PaintContext
+{
+ /**
+ * Release the resources allocated for the paint.
+ */
+ void dispose();
+
+ /**
+ * Return the color model of this context. It may be different from the
+ * hint specified during createContext, as not all contexts can generate
+ * color patterns in an arbitrary model.
+ *
+ * @return the context color model
+ */
+ ColorModel getColorModel();
+
+ /**
+ * Return a raster containing the colors for the graphics operation.
+ *
+ * @param x the x-coordinate, in device space
+ * @param y the y-coordinate, in device space
+ * @param w the width, in device space
+ * @param h the height, in device space
+ * @return a raster for the given area and color
+ */
+ Raster getRaster(int x, int y, int w, int h);
+} // interface PaintContext
diff --git a/libjava/classpath/java/awt/Panel.java b/libjava/classpath/java/awt/Panel.java
new file mode 100644
index 00000000000..cc17eef2285
--- /dev/null
+++ b/libjava/classpath/java/awt/Panel.java
@@ -0,0 +1,173 @@
+/* Panel.java -- Simple container object
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * A panel is a simple container class. It's default layout is the
+ * <code>FlowLayout</code> manager.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see FlowLayout
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Panel extends Container implements Accessible
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -2728009084054400034L;
+
+ /** The cached accessible context. */
+ private transient AccessibleContext context;
+
+ /** Flag set when the first system-requested paint event is
+ dispatched. */
+ private transient boolean initialSystemUpdateDone;
+
+ /** Flag set when the first application-requested paint event is
+ consumed. */
+ private transient boolean initialUpdateConsumed;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_panel_number;
+
+ /**
+ * Initializes a new instance of <code>Panel</code> that has a default
+ * layout manager of <code>FlowLayout</code>.
+ */
+ public Panel()
+ {
+ this(new FlowLayout());
+ }
+
+ /**
+ * Initializes a new instance of <code>Panel</code> with the specified
+ * layout manager.
+ *
+ * @param layoutManager the layout manager for this object
+ * @since 1.1
+ */
+ public Panel(LayoutManager layoutManager)
+ {
+ setLayout(layoutManager);
+ }
+
+ /**
+ * Notifies this object to create its native peer.
+ *
+ * @see #isDisplayable()
+ * @see #removeNotify()
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createPanel(this);
+ super.addNotify();
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this panel, creating one if
+ * necessary. This always returns an instance of {@link AccessibleAWTPanel}.
+ *
+ * @return the accessibility context of this panel
+ * @since 1.3
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (context == null)
+ context = new AccessibleAWTPanel();
+ return context;
+ }
+
+ /**
+ * This class provides accessibility support for Panels, and is the
+ * runtime type returned by {@link #getAccessibleContext()}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ */
+ protected class AccessibleAWTPanel extends AccessibleAWTContainer
+ {
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -6409552226660031050L;
+
+ /**
+ * The default constructor.
+ */
+ protected AccessibleAWTPanel()
+ {
+ }
+
+ /**
+ * Get the role of this accessible object, a panel.
+ *
+ * @return the role of the object
+ * @see AccessibleRole#PANEL
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.PANEL;
+ }
+ }
+
+ /**
+ * Generate a unique name for this panel.
+ *
+ * @return A unique name for this panel.
+ */
+ String generateName ()
+ {
+ return "panel" + getUniqueLong ();
+ }
+
+ private static synchronized long getUniqueLong ()
+ {
+ return next_panel_number++;
+ }
+}
diff --git a/libjava/classpath/java/awt/Point.java b/libjava/classpath/java/awt/Point.java
new file mode 100644
index 00000000000..492749b8dc3
--- /dev/null
+++ b/libjava/classpath/java/awt/Point.java
@@ -0,0 +1,245 @@
+/* Point.java -- represents a point in 2-D space
+ Copyright (C) 1999, 2002 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 java.awt.geom.Point2D;
+import java.io.Serializable;
+
+/**
+ * This class represents a point on the screen using cartesian coordinates.
+ * Remember that in screen coordinates, increasing x values go from left to
+ * right, and increasing y values go from top to bottom.
+ *
+ * <p>There are some public fields; if you mess with them in an inconsistent
+ * manner, it is your own fault when you get invalid results. Also, this
+ * class is not threadsafe.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Point extends Point2D implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -5276940640259749850L;
+
+ /**
+ * The x coordinate.
+ *
+ * @see #getLocation()
+ * @see #move(int, int)
+ * @serial the X coordinate of the point
+ */
+ public int x;
+
+ /**
+ * The y coordinate.
+ *
+ * @see #getLocation()
+ * @see #move(int, int)
+ * @serial The Y coordinate of the point
+ */
+ public int y;
+
+ /**
+ * Initializes a new instance of <code>Point</code> representing the
+ * coordiates (0,0).
+ *
+ * @since 1.1
+ */
+ public Point()
+ {
+ }
+
+ /**
+ * Initializes a new instance of <code>Point</code> with coordinates
+ * identical to the coordinates of the specified points.
+ *
+ * @param p the point to copy the coordinates from
+ * @throws NullPointerException if p is null
+ */
+ public Point(Point p)
+ {
+ x = p.x;
+ y = p.y;
+ }
+
+ /**
+ * Initializes a new instance of <code>Point</code> with the specified
+ * coordinates.
+ *
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ */
+ public Point(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Get the x coordinate.
+ *
+ * @return the value of x, as a double
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Get the y coordinate.
+ *
+ * @return the value of y, as a double
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Returns the location of this point. A pretty useless method, as this
+ * is already a point.
+ *
+ * @return a copy of this point
+ * @see #setLocation(Point)
+ * @since 1.1
+ */
+ public Point getLocation()
+ {
+ return new Point(x, y);
+ }
+
+ /**
+ * Sets this object's coordinates to match those of the specified point.
+ *
+ * @param p the point to copy the coordinates from
+ * @throws NullPointerException if p is null
+ * @since 1.1
+ */
+ public void setLocation(Point p)
+ {
+ x = p.x;
+ y = p.y;
+ }
+
+ /**
+ * Sets this object's coordinates to the specified values. This method
+ * is identical to the <code>move()</code> method.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ */
+ public void setLocation(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Sets this object's coordinates to the specified values. This method
+ * performs normal casting from double to int, so you may lose precision.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ */
+ public void setLocation(double x, double y)
+ {
+ this.x = (int) x;
+ this.y = (int) y;
+ }
+
+ /**
+ * Sets this object's coordinates to the specified values. This method
+ * is identical to the <code>setLocation(int, int)</code> method.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ */
+ public void move(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Changes the coordinates of this point such that the specified
+ * <code>dx</code> parameter is added to the existing X coordinate and
+ * <code>dy</code> is added to the existing Y coordinate.
+ *
+ * @param dx the amount to add to the X coordinate
+ * @param dy the amount to add to the Y coordinate
+ */
+ public void translate(int dx, int dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ /**
+ * Tests whether or not this object is equal to the specified object.
+ * This will be true if and only if the specified object is an instance
+ * of Point2D and has the same X and Y coordinates.
+ *
+ * @param obj the object to test against for equality
+ * @return true if the specified object is equal
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Point2D))
+ return false;
+ Point2D p = (Point2D) obj;
+ return x == p.getX() && y == p.getY();
+ }
+
+ /**
+ * Returns a string representation of this object. The format is:
+ * <code>getClass().getName() + "[x=" + x + ",y=" + y + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ']';
+ }
+} // class Point
diff --git a/libjava/classpath/java/awt/Polygon.java b/libjava/classpath/java/awt/Polygon.java
new file mode 100644
index 00000000000..a72522cb089
--- /dev/null
+++ b/libjava/classpath/java/awt/Polygon.java
@@ -0,0 +1,613 @@
+/* Polygon.java -- class representing a polygon
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Line2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+
+/**
+ * This class represents a polygon, a closed, two-dimensional region in a
+ * coordinate space. The region is bounded by an arbitrary number of line
+ * segments, between (x,y) coordinate vertices. The polygon has even-odd
+ * winding, meaning that a point is inside the shape if it crosses the
+ * boundary an odd number of times on the way to infinity.
+ *
+ * <p>There are some public fields; if you mess with them in an inconsistent
+ * manner, it is your own fault when you get NullPointerException,
+ * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is
+ * not threadsafe.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Polygon implements Shape, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -6460061437900069969L;
+
+ /**
+ * This total number of endpoints.
+ *
+ * @serial the number of endpoints, possibly less than the array sizes
+ */
+ public int npoints;
+
+ /**
+ * The array of X coordinates of endpoints. This should not be null.
+ *
+ * @see #addPoint(int, int)
+ * @serial the x coordinates
+ */
+ public int[] xpoints;
+
+ /**
+ * The array of Y coordinates of endpoints. This should not be null.
+ *
+ * @see #addPoint(int, int)
+ * @serial the y coordinates
+ */
+ public int[] ypoints;
+
+ /**
+ * The bounding box of this polygon. This is lazily created and cached, so
+ * it must be invalidated after changing points.
+ *
+ * @see #getBounds()
+ * @serial the bounding box, or null
+ */
+ protected Rectangle bounds;
+
+ /** A big number, but not so big it can't survive a few float operations */
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+
+ /**
+ * Initializes an empty polygon.
+ */
+ public Polygon()
+ {
+ // Leave room for growth.
+ xpoints = new int[4];
+ ypoints = new int[4];
+ }
+
+ /**
+ * Create a new polygon with the specified endpoints. The arrays are copied,
+ * so that future modifications to the parameters do not affect the polygon.
+ *
+ * @param xpoints the array of X coordinates for this polygon
+ * @param ypoints the array of Y coordinates for this polygon
+ * @param npoints the total number of endpoints in this polygon
+ * @throws NegativeArraySizeException if npoints is negative
+ * @throws IndexOutOfBoundsException if npoints exceeds either array
+ * @throws NullPointerException if xpoints or ypoints is null
+ */
+ public Polygon(int[] xpoints, int[] ypoints, int npoints)
+ {
+ this.xpoints = new int[npoints];
+ this.ypoints = new int[npoints];
+ System.arraycopy(xpoints, 0, this.xpoints, 0, npoints);
+ System.arraycopy(ypoints, 0, this.ypoints, 0, npoints);
+ this.npoints = npoints;
+ }
+
+ /**
+ * Reset the polygon to be empty. The arrays are left alone, to avoid object
+ * allocation, but the number of points is set to 0, and all cached data
+ * is discarded. If you are discarding a huge number of points, it may be
+ * more efficient to just create a new Polygon.
+ *
+ * @see #invalidate()
+ * @since 1.4
+ */
+ public void reset()
+ {
+ npoints = 0;
+ invalidate();
+ }
+
+ /**
+ * Invalidate or flush all cached data. After direct manipulation of the
+ * public member fields, this is necessary to avoid inconsistent results
+ * in methods like <code>contains</code>.
+ *
+ * @see #getBounds()
+ * @since 1.4
+ */
+ public void invalidate()
+ {
+ bounds = null;
+ }
+
+ /**
+ * Translates the polygon by adding the specified values to all X and Y
+ * coordinates. This updates the bounding box, if it has been calculated.
+ *
+ * @param dx the amount to add to all X coordinates
+ * @param dy the amount to add to all Y coordinates
+ * @since 1.1
+ */
+ public void translate(int dx, int dy)
+ {
+ int i = npoints;
+ while (--i >= 0)
+ {
+ xpoints[i] += dx;
+ ypoints[i] += dy;
+ }
+ if (bounds != null)
+ {
+ bounds.x += dx;
+ bounds.y += dy;
+ }
+ }
+
+ /**
+ * Adds the specified endpoint to the polygon. This updates the bounding
+ * box, if it has been created.
+ *
+ * @param x the X coordinate of the point to add
+ * @param y the Y coordiante of the point to add
+ */
+ public void addPoint(int x, int y)
+ {
+ if (npoints + 1 > xpoints.length)
+ {
+ int[] newx = new int[npoints + 1];
+ System.arraycopy(xpoints, 0, newx, 0, npoints);
+ xpoints = newx;
+ }
+ if (npoints + 1 > ypoints.length)
+ {
+ int[] newy = new int[npoints + 1];
+ System.arraycopy(ypoints, 0, newy, 0, npoints);
+ ypoints = newy;
+ }
+ xpoints[npoints] = x;
+ ypoints[npoints] = y;
+ npoints++;
+ if (bounds != null)
+ {
+ if (npoints == 1)
+ {
+ bounds.x = x;
+ bounds.y = y;
+ }
+ else
+ {
+ if (x < bounds.x)
+ {
+ bounds.width += bounds.x - x;
+ bounds.x = x;
+ }
+ else if (x > bounds.x + bounds.width)
+ bounds.width = x - bounds.x;
+ if (y < bounds.y)
+ {
+ bounds.height += bounds.y - y;
+ bounds.y = y;
+ }
+ else if (y > bounds.y + bounds.height)
+ bounds.height = y - bounds.y;
+ }
+ }
+ }
+
+ /**
+ * Returns the bounding box of this polygon. This is the smallest
+ * rectangle with sides parallel to the X axis that will contain this
+ * polygon.
+ *
+ * @return the bounding box for this polygon
+ * @see #getBounds2D()
+ * @since 1.1
+ */
+ public Rectangle getBounds()
+ {
+ return getBoundingBox();
+ }
+
+ /**
+ * Returns the bounding box of this polygon. This is the smallest
+ * rectangle with sides parallel to the X axis that will contain this
+ * polygon.
+ *
+ * @return the bounding box for this polygon
+ * @see #getBounds2D()
+ * @deprecated use {@link #getBounds()} instead
+ */
+ public Rectangle getBoundingBox()
+ {
+ if (bounds == null)
+ {
+ if (npoints == 0)
+ return bounds = new Rectangle();
+ int i = npoints - 1;
+ int minx = xpoints[i];
+ int maxx = minx;
+ int miny = ypoints[i];
+ int maxy = miny;
+ while (--i >= 0)
+ {
+ int x = xpoints[i];
+ int y = ypoints[i];
+ if (x < minx)
+ minx = x;
+ else if (x > maxx)
+ maxx = x;
+ if (y < miny)
+ miny = y;
+ else if (y > maxy)
+ maxy = y;
+ }
+ bounds = new Rectangle(minx, miny, maxx - minx, maxy - miny);
+ }
+ return bounds;
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param p the point to test
+ * @return true if the point is inside this polygon
+ * @throws NullPointerException if p is null
+ * @see #contains(double, double)
+ */
+ public boolean contains(Point p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside this polygon
+ * @see #contains(double, double)
+ * @since 1.1
+ */
+ public boolean contains(int x, int y)
+ {
+ return contains((double) x, (double) y);
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside this polygon
+ * @see #contains(double, double)
+ * @deprecated use {@link #contains(int, int)} instead
+ */
+ public boolean inside(int x, int y)
+ {
+ return contains((double) x, (double) y);
+ }
+
+ /**
+ * Returns a high-precision bounding box of this polygon. This is the
+ * smallest rectangle with sides parallel to the X axis that will contain
+ * this polygon.
+ *
+ * @return the bounding box for this polygon
+ * @see #getBounds()
+ * @since 1.2
+ */
+ public Rectangle2D getBounds2D()
+ {
+ // For polygons, the integer version is exact!
+ return getBounds();
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside this polygon
+ * @since 1.2
+ */
+ public boolean contains(double x, double y)
+ {
+ return ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0);
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param p the point to test
+ * @return true if the point is inside this polygon
+ * @throws NullPointerException if p is null
+ * @see #contains(double, double)
+ * @since 1.2
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Test if a high-precision rectangle intersects the shape. This is true
+ * if any point in the rectangle is in the shape. This implementation is
+ * precise.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle, treated as point if negative
+ * @param h the height of the rectangle, treated as point if negative
+ * @return true if the rectangle intersects this shape
+ * @since 1.2
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ /* Does any edge intersect? */
+ if (evaluateCrossings(x, y, false, w) != 0 /* top */
+ || evaluateCrossings(x, y + h, false, w) != 0 /* bottom */
+ || evaluateCrossings(x + w, y, true, h) != 0 /* right */
+ || evaluateCrossings(x, y, true, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Test if a high-precision rectangle intersects the shape. This is true
+ * if any point in the rectangle is in the shape. This implementation is
+ * precise.
+ *
+ * @param r the rectangle
+ * @return true if the rectangle intersects this shape
+ * @throws NullPointerException if r is null
+ * @see #intersects(double, double, double, double)
+ * @since 1.2
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Test if a high-precision rectangle lies completely in the shape. This is
+ * true if all points in the rectangle are in the shape. This implementation
+ * is precise.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle, treated as point if negative
+ * @param h the height of the rectangle, treated as point if negative
+ * @return true if the rectangle is contained in this shape
+ * @since 1.2
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (evaluateCrossings(x, y, false, w) != 0 /* top */
+ || evaluateCrossings(x, y + h, false, w) != 0 /* bottom */
+ || evaluateCrossings(x + w, y, true, h) != 0 /* right */
+ || evaluateCrossings(x, y, true, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Test if a high-precision rectangle lies completely in the shape. This is
+ * true if all points in the rectangle are in the shape. This implementation
+ * is precise.
+ *
+ * @param r the rectangle
+ * @return true if the rectangle is contained in this shape
+ * @throws NullPointerException if r is null
+ * @see #contains(double, double, double, double)
+ * @since 1.2
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. Each call returns
+ * a new object, independent from others in use. This class is not
+ * threadsafe to begin with, so the path iterator is not either.
+ *
+ * @param transform an optional transform to apply to the iterator
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(final AffineTransform transform)
+ {
+ return new PathIterator()
+ {
+ /** The current vertex of iteration. */
+ private int vertex;
+
+ public int getWindingRule()
+ {
+ return WIND_EVEN_ODD;
+ }
+
+ public boolean isDone()
+ {
+ return vertex > npoints;
+ }
+
+ public void next()
+ {
+ vertex++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ if (vertex >= npoints)
+ return SEG_CLOSE;
+ coords[0] = xpoints[vertex];
+ coords[1] = ypoints[vertex];
+ if (transform != null)
+ transform.transform(coords, 0, coords, 0, 1);
+ return vertex == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ if (vertex >= npoints)
+ return SEG_CLOSE;
+ coords[0] = xpoints[vertex];
+ coords[1] = ypoints[vertex];
+ if (transform != null)
+ transform.transform(coords, 0, coords, 0, 1);
+ return vertex == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+ };
+ }
+
+ /**
+ * Return an iterator along the flattened version of the shape boundary.
+ * Since polygons are already flat, the flatness parameter is ignored, and
+ * the resulting iterator only has SEG_MOVETO, SEG_LINETO and SEG_CLOSE
+ * points. If the optional transform is provided, the iterator is
+ * transformed accordingly. Each call returns a new object, independent
+ * from others in use. This class is not threadsafe to begin with, so the
+ * path iterator is not either.
+ *
+ * @param transform an optional transform to apply to the iterator
+ * @param flatness the maximum distance for deviation from the real boundary
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(AffineTransform transform,
+ double flatness)
+ {
+ return getPathIterator(transform);
+ }
+
+ /**
+ * Helper for contains, intersects, calculates the number of intersections
+ * between the polygon and a line extending from the point (x, y) along
+ * the positive X, or Y axis, within a given interval.
+ *
+ * @return the winding number.
+ * @see #condensed
+ * @see #contains(double, double)
+ */
+ private int evaluateCrossings(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ double x0;
+ double x1;
+ double y0;
+ double y1;
+ double epsilon = 0.0;
+ int crossings = 0;
+ int[] xp;
+ int[] yp;
+
+ if (useYaxis)
+ {
+ xp = ypoints;
+ yp = xpoints;
+ double swap;
+ swap = y;
+ y = x;
+ x = swap;
+ }
+ else
+ {
+ xp = xpoints;
+ yp = ypoints;
+ }
+
+ /* Get a value which is small but not insignificant relative the path. */
+ epsilon = 1E-7;
+
+ x0 = xp[0] - x;
+ y0 = yp[0] - y;
+ for (int i = 1; i < npoints; i++)
+ {
+ x1 = xp[i] - x;
+ y1 = yp[i] - y;
+
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (y0 * y1 < 0)
+ if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0))
+ ++crossings;
+
+ x0 = xp[i] - x;
+ y0 = yp[i] - y;
+ }
+
+ // end segment
+ x1 = xp[0] - x;
+ y1 = yp[0] - y;
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (y0 * y1 < 0)
+ if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0))
+ ++crossings;
+
+ return crossings;
+ }
+} // class Polygon
+
diff --git a/libjava/classpath/java/awt/PopupMenu.java b/libjava/classpath/java/awt/PopupMenu.java
new file mode 100644
index 00000000000..90d48d903b9
--- /dev/null
+++ b/libjava/classpath/java/awt/PopupMenu.java
@@ -0,0 +1,169 @@
+/* PopupMenu.java -- An AWT popup menu
+ Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.PopupMenuPeer;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This class implement an AWT popup menu widget
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class PopupMenu extends Menu
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = -4620452533522760060L;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>PopupMenu</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+PopupMenu()
+{
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>PopupMenu</code> with the specified
+ * label.
+ *
+ * @param label The label for this popup menu.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+PopupMenu(String label)
+{
+ super(label);
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Creates this object's native peer.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createPopupMenu (this);
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Displays this popup menu at the specified coordinates relative to
+ * the specified component.
+ *
+ * @param component The component to which the display coordinates are relative.
+ * @param x The X coordinate of the menu.
+ * @param y The Y coordinate of the menu.
+ */
+public void
+show(Component component, int x, int y)
+{
+ if (getPeer() == null)
+ this.addNotify();
+ PopupMenuPeer pmp = (PopupMenuPeer)getPeer();
+ if (pmp != null)
+ {
+ /* XXX
+ Event e = new Event (component, Event.ACTION_EVENT, component);
+ e.x = x;
+ e.y = y;*/
+ pmp.show (component, x, y);
+ }
+}
+
+ protected class AccessibleAWTPopupMenu extends AccessibleAWTMenu
+ {
+ protected AccessibleAWTPopupMenu()
+ {
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.POPUP_MENU;
+ }
+
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>PopupMenu</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTPopupMenu();
+ return accessibleContext;
+ }
+
+} // class PopupMenu
+
diff --git a/libjava/classpath/java/awt/PrintGraphics.java b/libjava/classpath/java/awt/PrintGraphics.java
new file mode 100644
index 00000000000..e7f857797d3
--- /dev/null
+++ b/libjava/classpath/java/awt/PrintGraphics.java
@@ -0,0 +1,57 @@
+/* PrintGraphics.java -- a print graphics context
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This interface allows the originating print job to be obtained.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface PrintGraphics
+{
+ /**
+ * Returns the <code>PrintJob</code> that this object is being
+ * managed by.
+ *
+ * @return the print job for this object
+ */
+ PrintJob getPrintJob();
+} // interface PrintGraphics
diff --git a/libjava/classpath/java/awt/PrintJob.java b/libjava/classpath/java/awt/PrintJob.java
new file mode 100644
index 00000000000..62aa8b1956e
--- /dev/null
+++ b/libjava/classpath/java/awt/PrintJob.java
@@ -0,0 +1,104 @@
+/* PrintJob.java -- A print job class
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.util.Properties;
+
+/**
+ * This abstract class represents a print job.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Toolkit#getPrintJob(Frame, String, Properties)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class PrintJob
+{
+ /**
+ * Create a new PrintJob.
+ */
+ public PrintJob()
+ {
+ }
+
+ /**
+ * Returns a graphics context suitable for rendering the next page. The
+ * return must also implement {@link PrintGraphics}.
+ *
+ * @return a graphics context for printing the next page
+ */
+ public abstract Graphics getGraphics();
+
+ /**
+ * Returns the dimension of the page in pixels. The resolution will be
+ * chosen to be similar to the on screen image.
+ *
+ * @return the page dimensions
+ */
+ public abstract Dimension getPageDimension();
+
+ /**
+ * Returns the resolution of the page in pixels per inch. Note that this is
+ * not necessarily the printer's resolution.
+ *
+ * @return the resolution of the page in pixels per inch
+ */
+ public abstract int getPageResolution();
+
+ /**
+ * Tests whether or not the last page will be printed first.
+ *
+ * @return true if the last page prints first
+ */
+ public abstract boolean lastPageFirst();
+
+ /**
+ * Informs the print job that printing is complete or should be aborted.
+ */
+ public abstract void end();
+
+ /**
+ * This method explicitly ends the print job in the event the job
+ * becomes un-referenced without the application having done so.
+ */
+ public void finalize()
+ {
+ end();
+ }
+} // class PrintJob
diff --git a/libjava/classpath/java/awt/Rectangle.java b/libjava/classpath/java/awt/Rectangle.java
new file mode 100644
index 00000000000..0f21d495cd8
--- /dev/null
+++ b/libjava/classpath/java/awt/Rectangle.java
@@ -0,0 +1,749 @@
+/* Rectangle.java -- represents a graphics rectangle
+ Copyright (C) 1999, 2000, 2001, 2002 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 java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+
+/**
+ * This class represents a rectangle and all the interesting things you
+ * might want to do with it. Note that the coordinate system uses
+ * the origin (0,0) as the top left of the screen, with the x and y
+ * values increasing as they move to the right and down respectively.
+ *
+ * <p>It is valid for a rectangle to have negative width or height; but it
+ * is considered to have no area or internal points. Therefore, the behavior
+ * in methods like <code>contains</code> or <code>intersects</code> is
+ * undefined unless the rectangle has positive width and height.
+ *
+ * <p>There are some public fields; if you mess with them in an inconsistent
+ * manner, it is your own fault when you get NullPointerException,
+ * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is
+ * not threadsafe.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Rectangle extends Rectangle2D implements Shape, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4345857070255674764L;
+
+ /**
+ * The X coordinate of the top-left corner of the rectangle.
+ *
+ * @see #setLocation(int, int)
+ * @see #getLocation()
+ * @serial the x coordinate
+ */
+ public int x;
+
+ /**
+ * The Y coordinate of the top-left corner of the rectangle.
+ *
+ * @see #setLocation(int, int)
+ * @see #getLocation()
+ * @serial the y coordinate
+ */
+ public int y;
+
+ /**
+ * The width of the rectangle.
+ *
+ * @see #setSize(int, int)
+ * @see #getSize()
+ * @serial
+ */
+ public int width;
+
+ /**
+ * The height of the rectangle.
+ *
+ * @see #setSize(int, int)
+ * @see #getSize()
+ * @serial
+ */
+ public int height;
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with a top
+ * left corner at (0,0) and a width and height of 0.
+ */
+ public Rectangle()
+ {
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> from the
+ * coordinates of the specified rectangle.
+ *
+ * @param r the rectangle to copy from
+ * @throws NullPointerException if r is null
+ * @since 1.1
+ */
+ public Rectangle(Rectangle r)
+ {
+ x = r.x;
+ y = r.y;
+ width = r.width;
+ height = r.height;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> from the specified
+ * inputs.
+ *
+ * @param x the X coordinate of the top left corner
+ * @param y the Y coordinate of the top left corner
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+ public Rectangle(int x, int y, int width, int height)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with the specified
+ * width and height. The upper left corner of the rectangle will be at
+ * the origin (0,0).
+ *
+ * @param width the width of the rectangle
+ * @param height the height of the rectange
+ */
+ public Rectangle(int width, int height)
+ {
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with a top-left
+ * corner represented by the specified point and the width and height
+ * represented by the specified dimension.
+ *
+ * @param p the upper left corner of the rectangle
+ * @param d the width and height of the rectangle
+ * @throws NullPointerException if p or d is null
+ */
+ public Rectangle(Point p, Dimension d)
+ {
+ x = p.x;
+ y = p.y;
+ width = d.width;
+ height = d.height;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with a top left
+ * corner at the specified point and a width and height of zero.
+ *
+ * @param p the upper left corner of the rectangle
+ */
+ public Rectangle(Point p)
+ {
+ x = p.x;
+ y = p.y;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with an
+ * upper left corner at the origin (0,0) and a width and height represented
+ * by the specified dimension.
+ *
+ * @param d the width and height of the rectangle
+ */
+ public Rectangle(Dimension d)
+ {
+ width = d.width;
+ height = d.height;
+ }
+
+ /**
+ * Get the X coordinate of the upper-left corner.
+ *
+ * @return the value of x, as a double
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Get the Y coordinate of the upper-left corner.
+ *
+ * @return the value of y, as a double
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Get the width of the rectangle.
+ *
+ * @return the value of width, as a double
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Get the height of the rectangle.
+ *
+ * @return the value of height, as a double
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the bounds of this rectangle. A pretty useless method, as this
+ * is already a rectangle; it is included to mimic the
+ * <code>getBounds</code> method in Component.
+ *
+ * @return a copy of this rectangle
+ * @see #setBounds(Rectangle)
+ * @since 1.1
+ */
+ public Rectangle getBounds()
+ {
+ return new Rectangle(this);
+ }
+
+ /**
+ * Returns the high-precision bounds of this rectangle. A pretty useless
+ * method, as this is already a rectangle.
+ *
+ * @return a copy of this rectangle
+ * @see #setBounds(Rectangle)
+ * @since 1.2
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle(x, y, width, height);
+ }
+
+ /**
+ * Updates this rectangle to match the dimensions of the specified
+ * rectangle.
+ *
+ * @param r the rectangle to update from
+ * @throws NullPointerException if r is null
+ * @see #setBounds(int, int, int, int)
+ * @since 1.1
+ */
+ public void setBounds(Rectangle r)
+ {
+ setBounds (r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Updates this rectangle to have the specified dimensions.
+ *
+ * @param x the new X coordinate of the upper left hand corner
+ * @param y the new Y coordinate of the upper left hand corner
+ * @param width the new width of this rectangle
+ * @param height the new height of this rectangle
+ * @since 1.1
+ */
+ public void setBounds(int x, int y, int width, int height)
+ {
+ reshape (x, y, width, height);
+ }
+
+ /**
+ * Updates this rectangle to have the specified dimensions, as rounded to
+ * integers.
+ *
+ * @param x the new X coordinate of the upper left hand corner
+ * @param y the new Y coordinate of the upper left hand corner
+ * @param width the new width of this rectangle
+ * @param height the new height of this rectangle
+ * @since 1.2
+ */
+ public void setRect(double x, double y, double width, double height)
+ {
+ this.x = (int) x;
+ this.y = (int) y;
+ this.width = (int) width;
+ this.height = (int) height;
+ }
+
+ /**
+ * Updates this rectangle to have the specified dimensions.
+ *
+ * @param x the new X coordinate of the upper left hand corner
+ * @param y the new Y coordinate of the upper left hand corner
+ * @param width the new width of this rectangle
+ * @param height the new height of this rectangle
+ * @deprecated use {@link #setBounds(int, int, int, int)} instead
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Returns the location of this rectangle, which is the coordinates of
+ * its upper left corner.
+ *
+ * @return the point where this rectangle is located
+ * @see #setLocation(Point)
+ * @since 1.1
+ */
+ public Point getLocation()
+ {
+ return new Point(x,y);
+ }
+
+ /**
+ * Moves the location of this rectangle by setting its upper left
+ * corner to the specified point.
+ *
+ * @param p the point to move the rectangle to
+ * @throws NullPointerException if p is null
+ * @see #getLocation()
+ * @since 1.1
+ */
+ public void setLocation(Point p)
+ {
+ setLocation (p.x, p.y);
+ }
+
+ /**
+ * Moves the location of this rectangle by setting its upper left
+ * corner to the specified coordinates.
+ *
+ * @param x the new X coordinate for this rectangle
+ * @param y the new Y coordinate for this rectangle
+ * @since 1.1
+ */
+ public void setLocation(int x, int y)
+ {
+ move (x, y);
+ }
+
+ /**
+ * Moves the location of this rectangle by setting its upper left
+ * corner to the specified coordinates.
+ *
+ * @param x the new X coordinate for this rectangle
+ * @param y the new Y coordinate for this rectangle
+ * @deprecated use {@link #setLocation(int, int)} instead
+ */
+ public void move(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Translate the location of this rectangle by the given amounts.
+ *
+ * @param dx the x distance to move by
+ * @param dy the y distance to move by
+ * @see #setLocation(int, int)
+ */
+ public void translate(int dx, int dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ /**
+ * Returns the size of this rectangle.
+ *
+ * @return the size of this rectangle
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public Dimension getSize()
+ {
+ return new Dimension(width, height);
+ }
+
+ /**
+ * Sets the size of this rectangle based on the specified dimensions.
+ *
+ * @param d the new dimensions of the rectangle
+ * @throws NullPointerException if d is null
+ * @see #getSize()
+ * @since 1.1
+ */
+ public void setSize(Dimension d)
+ {
+ setSize (d.width, d.height);
+ }
+
+ /**
+ * Sets the size of this rectangle based on the specified dimensions.
+ *
+ * @param width the new width of the rectangle
+ * @param height the new height of the rectangle
+ * @since 1.1
+ */
+ public void setSize(int width, int height)
+ {
+ resize (width, height);
+ }
+
+ /**
+ * Sets the size of this rectangle based on the specified dimensions.
+ *
+ * @param width the new width of the rectangle
+ * @param height the new height of the rectangle
+ * @deprecated use {@link #setSize(int, int)} instead
+ */
+ public void resize(int width, int height)
+ {
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this rectangle.
+ * According to the contract of Shape, a point on the border is in only if
+ * it has an adjacent point inside the rectangle in either the increasing
+ * x or y direction.
+ *
+ * @param p the point to test
+ * @return true if the point is inside the rectangle
+ * @throws NullPointerException if p is null
+ * @see #contains(int, int)
+ * @since 1.1
+ */
+ public boolean contains(Point p)
+ {
+ return contains (p.x, p.y);
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this rectangle.
+ * According to the contract of Shape, a point on the border is in only if
+ * it has an adjacent point inside the rectangle in either the increasing
+ * x or y direction.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside the rectangle
+ * @since 1.1
+ */
+ public boolean contains(int x, int y)
+ {
+ return inside (x, y);
+ }
+
+ /**
+ * Checks whether all points in the given rectangle are contained in this
+ * rectangle.
+ *
+ * @param r the rectangle to check
+ * @return true if r is contained in this rectangle
+ * @throws NullPointerException if r is null
+ * @see #contains(int, int, int, int)
+ * @since 1.1
+ */
+ public boolean contains(Rectangle r)
+ {
+ return contains (r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Checks whether all points in the given rectangle are contained in this
+ * rectangle.
+ *
+ * @param x the x coordinate of the rectangle to check
+ * @param y the y coordinate of the rectangle to check
+ * @param w the width of the rectangle to check
+ * @param h the height of the rectangle to check
+ * @return true if the parameters are contained in this rectangle
+ * @since 1.1
+ */
+ public boolean contains(int x, int y, int w, int h)
+ {
+ return width > 0 && height > 0 && w > 0 && h > 0
+ && x >= this.x && x + w <= this.x + this.width
+ && y >= this.y && y + h <= this.y + this.height;
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this rectangle.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside the rectangle
+ * @deprecated use {@link #contains(int, int)} instead
+ */
+ public boolean inside(int x, int y)
+ {
+ return width > 0 && height > 0
+ && x >= this.x && x < this.x + width
+ && y >= this.y && y < this.y + height;
+ }
+
+ /**
+ * Tests whether or not the specified rectangle intersects this rectangle.
+ * This means the two rectangles share at least one internal point.
+ *
+ * @param r the rectangle to test against
+ * @return true if the specified rectangle intersects this one
+ * @throws NullPointerException if r is null
+ * @since 1.2
+ */
+ public boolean intersects(Rectangle r)
+ {
+ return r.width > 0 && r.height > 0 && width > 0 && height > 0
+ && r.x < x + width && r.x + r.width > x
+ && r.y < y + height && r.y + r.height > y;
+ }
+
+ /**
+ * Determines the rectangle which is formed by the intersection of this
+ * rectangle with the specified rectangle. If the two do not intersect,
+ * an empty rectangle will be returned (meaning the width and/or height
+ * will be non-positive).
+ *
+ * @param r the rectange to calculate the intersection with
+ * @return a new rectangle bounding the intersection
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle intersection(Rectangle r)
+ {
+ Rectangle res = new Rectangle();
+ intersect(this, r, res);
+ return res;
+ }
+
+ /**
+ * Returns the smallest rectangle that contains both this rectangle
+ * and the specified rectangle.
+ *
+ * @param r the rectangle to compute the union with
+ * @return the smallest rectangle containing both rectangles
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle union(Rectangle r)
+ {
+ Rectangle res = new Rectangle();
+ union(this, r, res);
+ return res;
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified point.
+ * However, if the point falls on one of the two borders which are not
+ * inside the rectangle, a subsequent call to <code>contains</code> may
+ * return false.
+ *
+ * @param x the X coordinate of the point to add to this rectangle
+ * @param y the Y coordinate of the point to add to this rectangle
+ */
+ public void add(int x, int y)
+ {
+ add((double) x, (double) y);
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified point.
+ * However, if the point falls on one of the two borders which are not
+ * inside the rectangle, a subsequent call to <code>contains</code> may
+ * return false.
+ *
+ * @param p the point to add to this rectangle
+ * @throws NullPointerException if p is null
+ */
+ public void add(Point p)
+ {
+ add((double) p.x, (double) p.y);
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified rectangle.
+ *
+ * @param r the rectangle to add to this rectangle
+ * @throws NullPointerException if r is null
+ * @see #union(Rectangle)
+ */
+ public void add(Rectangle r)
+ {
+ union(this, r, this);
+ }
+
+ /**
+ * Expands the rectangle by the specified amount. The horizontal
+ * and vertical expansion values are applied both to the X,Y coordinate
+ * of this rectangle, and its width and height. Thus the width and
+ * height will increase by 2h and 2v accordingly.
+ *
+ * @param h the horizontal expansion value
+ * @param v the vertical expansion value
+ */
+ public void grow(int h, int v)
+ {
+ x -= h;
+ y -= v;
+ width += h + h;
+ height += v + v;
+ }
+
+ /**
+ * Tests whether or not this rectangle is empty. An empty rectangle
+ * has a non-positive width or height.
+ *
+ * @return true if the rectangle is empty
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param x the x coordinate to check
+ * @param y the y coordinate to check
+ * @return the binary OR of the result
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ * @since 1.2
+ */
+ public int outcode(double x, double y)
+ {
+ int result = 0;
+ if (width <= 0)
+ result |= OUT_LEFT | OUT_RIGHT;
+ else if (x < this.x)
+ result |= OUT_LEFT;
+ else if (x > this.x + width)
+ result |= OUT_RIGHT;
+ if (height <= 0)
+ result |= OUT_BOTTOM | OUT_TOP;
+ else if (y < this.y) // Remember that +y heads top-to-bottom.
+ result |= OUT_TOP;
+ else if (y > this.y + height)
+ result |= OUT_BOTTOM;
+ return result;
+ }
+
+ /**
+ * Determines the rectangle which is formed by the intersection of this
+ * rectangle with the specified rectangle. If the two do not intersect,
+ * an empty rectangle will be returned (meaning the width and/or height
+ * will be non-positive).
+ *
+ * @param r the rectange to calculate the intersection with
+ * @return a new rectangle bounding the intersection
+ * @throws NullPointerException if r is null
+ * @since 1.2
+ */
+ public Rectangle2D createIntersection(Rectangle2D r)
+ {
+ // Favor runtime type of other rectangle.
+ Rectangle2D res = r.getBounds2D();
+ intersect(this, r, res);
+ return res;
+ }
+
+ /**
+ * Returns the smallest rectangle that contains both this rectangle
+ * and the specified rectangle.
+ *
+ * @param r the rectangle to compute the union with
+ * @return the smallest rectangle containing both rectangles
+ * @throws NullPointerException if r is null
+ * @since 1.2
+ */
+ public Rectangle2D createUnion(Rectangle2D r)
+ {
+ // Favor runtime type of other rectangle.
+ Rectangle2D res = r.getBounds2D();
+ union(this, r, res);
+ return res;
+ }
+
+ /**
+ * Tests this rectangle for equality against the specified object. This
+ * will be true if an only if the specified object is an instance of
+ * Rectangle2D with the same coordinates and dimensions.
+ *
+ * @param obj the object to test against for equality
+ * @return true if the specified object is equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Rectangle2D))
+ return false;
+ Rectangle2D r = (Rectangle2D) obj;
+ return r.getX() == x && r.getY() == y
+ && r.getWidth() == width && r.getHeight() == height;
+ }
+
+ /**
+ * Returns a string representation of this rectangle. This is in the form
+ * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width
+ * + ",height=" + height + ']'</code>.
+ *
+ * @return a string representation of this rectangle
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width
+ + ",height=" + height + ']';
+ }
+} // class Rectangle
diff --git a/libjava/classpath/java/awt/RenderingHints.java b/libjava/classpath/java/awt/RenderingHints.java
new file mode 100644
index 00000000000..0e1db72b75f
--- /dev/null
+++ b/libjava/classpath/java/awt/RenderingHints.java
@@ -0,0 +1,803 @@
+/* RenderingHints.java --
+ Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A collection of (key, value) items that provide 'hints' for the
+ * {@link java.awt.Graphics2D} rendering pipeline. Because these
+ * items are hints only, they may be ignored by a particular
+ * {@link java.awt.Graphics2D} implementation.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+public class RenderingHints implements Map, Cloneable
+{
+ /**
+ * The base class used to represent keys.
+ */
+ public abstract static class Key
+ {
+ private final int key;
+
+ /**
+ * Creates a new key.
+ *
+ * @param privateKey the private key.
+ */
+ protected Key(int privateKey)
+ {
+ key = privateKey;
+ }
+
+ /**
+ * Returns <code>true</code> if the specified value is compatible with
+ * this key, and <code>false</code> otherwise.
+ *
+ * @param value the value (<code>null</code> permitted).
+ *
+ * @return A boolean.
+ */
+ public abstract boolean isCompatibleValue(Object value);
+
+ /**
+ * Returns the private key for this instance.
+ *
+ * @return The private key.
+ */
+ protected final int intKey()
+ {
+ return key;
+ }
+
+ /**
+ * Returns a hash code for the key.
+ *
+ * @return A hash code.
+ */
+ public final int hashCode()
+ {
+ return System.identityHashCode(this);
+ }
+
+ /**
+ * Checks this key for equality with an arbitrary object.
+ *
+ * @param other the object (<code>null</code> permitted)
+ *
+ * @return A boolean.
+ */
+ public final boolean equals(Object other)
+ {
+ return this == other;
+ }
+ } // class Key
+
+ private static final class KeyImpl extends Key
+ {
+ final String description;
+ final Object v1;
+ final Object v2;
+ final Object v3;
+
+ KeyImpl(int privateKey, String description,
+ Object v1, Object v2, Object v3)
+ {
+ super(privateKey);
+ this.description = description;
+ this.v1 = v1;
+ this.v2 = v2;
+ this.v3 = v3;
+ }
+
+ /**
+ * Returns <code>true</code> if the specified value is compatible with
+ * this key, and <code>false</code> otherwise.
+ *
+ * @param value the value (<code>null</code> permitted).
+ *
+ * @return A boolean.
+ */
+ public boolean isCompatibleValue(Object value)
+ {
+ return value == v1 || value == v2 || value == v3;
+ }
+
+ /**
+ * Returns a string representation of the key.
+ *
+ * @return A string.
+ */
+ public String toString()
+ {
+ return description;
+ }
+ } // class KeyImpl
+
+ private HashMap hintMap = new HashMap();
+
+ /**
+ * A key for the 'antialiasing' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_ANTIALIAS_OFF}</td>
+ * <td>Render without antialiasing (better speed).</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_ANTIALIAS_ON}</td>
+ * <td>Render with antialiasing (better quality).</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_ANTIALIAS_DEFAULT}</td>
+ * <td>Use the default value for antialiasing.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_ANTIALIASING;
+
+ /**
+ * This value is for use with the {@link #KEY_ANTIALIASING} key.
+ */
+ public static final Object VALUE_ANTIALIAS_ON
+ = "Antialiased rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_ANTIALIASING} key.
+ */
+ public static final Object VALUE_ANTIALIAS_OFF
+ = "Nonantialiased rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_ANTIALIASING} key.
+ */
+ public static final Object VALUE_ANTIALIAS_DEFAULT
+ = "Default antialiasing rendering mode";
+
+ /**
+ * A key for the 'rendering' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_RENDER_SPEED}</td>
+ * <td>Prefer speed over quality when rendering.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_RENDER_QUALITY}</td>
+ * <td>Prefer quality over speed when rendering.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_RENDER_DEFAULT}</td>
+ * <td>Use the default value for quality vs. speed when rendering.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_RENDERING;
+
+ /**
+ * This value is for use with the {@link #KEY_RENDERING} key.
+ */
+ public static final Object VALUE_RENDER_SPEED
+ = "Fastest rendering methods";
+
+ /**
+ * This value is for use with the {@link #KEY_RENDERING} key.
+ */
+ public static final Object VALUE_RENDER_QUALITY
+ = "Highest quality rendering methods";
+
+ /**
+ * This value is for use with the {@link #KEY_RENDERING} key.
+ */
+ public static final Object VALUE_RENDER_DEFAULT
+ = "Default rendering methods";
+
+ /**
+ * A key for the 'dithering' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_DITHER_DISABLE}</td>
+ * <td>Disable dithering.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_DITHER_ENABLE}</td>
+ * <td>Enable dithering.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_DITHER_DEFAULT}</td>
+ * <td>Use the default value for dithering.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_DITHERING;
+
+ /**
+ * This value is for use with the {@link #KEY_DITHERING} key.
+ */
+ public static final Object VALUE_DITHER_DISABLE
+ = "Nondithered rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_DITHERING} key.
+ */
+ public static final Object VALUE_DITHER_ENABLE
+ = "Dithered rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_DITHERING} key.
+ */
+ public static final Object VALUE_DITHER_DEFAULT
+ = "Default dithering mode";
+
+ /**
+ * A key for the 'text antialiasing' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_TEXT_ANTIALIAS_ON}</td>
+ * <td>Render text with antialiasing (better quality usually).</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_TEXT_ANTIALIAS_OFF}</td>
+ * <td>Render test without antialiasing (better speed).</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_TEXT_ANTIALIAS_DEFAULT}</td>
+ * <td>Use the default value for text antialiasing.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_TEXT_ANTIALIASING;
+
+ /**
+ * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key.
+ */
+ public static final Object VALUE_TEXT_ANTIALIAS_ON
+ = "Antialiased text mode";
+
+ /**
+ * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key.
+ */
+ public static final Object VALUE_TEXT_ANTIALIAS_OFF
+ = "Nonantialiased text mode";
+
+ /**
+ * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key.
+ */
+ public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT
+ = "Default antialiasing text mode";
+
+ /**
+ * A key for the 'fractional metrics' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_FRACTIONALMETRICS_OFF}</td>
+ * <td>Render text with fractional metrics off.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_FRACTIONALMETRICS_ON}</td>
+ * <td>Render text with fractional metrics on.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_FRACTIONALMETRICS_DEFAULT}</td>
+ * <td>Use the default value for fractional metrics.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_FRACTIONALMETRICS;
+
+ /**
+ * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key.
+ */
+ public static final Object VALUE_FRACTIONALMETRICS_OFF
+ = "Integer text metrics mode";
+
+ /**
+ * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key.
+ */
+ public static final Object VALUE_FRACTIONALMETRICS_ON
+ = "Fractional text metrics mode";
+
+ /**
+ * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key.
+ */
+ public static final Object VALUE_FRACTIONALMETRICS_DEFAULT
+ = "Default fractional text metrics mode";
+
+ /**
+ * A key for the 'interpolation' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR}</td>
+ * <td>Use nearest neighbour interpolation.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_INTERPOLATION_BILINEAR}</td>
+ * <td>Use bilinear interpolation.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_INTERPOLATION_BICUBIC}</td>
+ * <td>Use bicubic interpolation.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_INTERPOLATION;
+
+ /**
+ * This value is for use with the {@link #KEY_INTERPOLATION} key.
+ */
+ public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR
+ = "Nearest Neighbor image interpolation mode";
+
+ /**
+ * This value is for use with the {@link #KEY_INTERPOLATION} key.
+ */
+ public static final Object VALUE_INTERPOLATION_BILINEAR
+ = "Bilinear image interpolation mode";
+
+ /**
+ * This value is for use with the {@link #KEY_INTERPOLATION} key.
+ */
+ public static final Object VALUE_INTERPOLATION_BICUBIC
+ = "Bicubic image interpolation mode";
+
+ /**
+ * A key for the 'alpha interpolation' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_ALPHA_INTERPOLATION_SPEED}</td>
+ * <td>Prefer speed over quality.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_ALPHA_INTERPOLATION_QUALITY}</td>
+ * <td>Prefer quality over speed.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_ALPHA_INTERPOLATION_DEFAULT}</td>
+ * <td>Use the default setting.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_ALPHA_INTERPOLATION;
+
+ /**
+ * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key.
+ */
+ public static final Object VALUE_ALPHA_INTERPOLATION_SPEED
+ = "Fastest alpha blending methods";
+
+ /**
+ * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key.
+ */
+ public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY
+ = "Highest quality alpha blending methods";
+
+ /**
+ * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key.
+ */
+ public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT
+ = "Default alpha blending methods";
+
+ /**
+ * A key for the 'color rendering' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_COLOR_RENDER_SPEED}</td>
+ * <td>Prefer speed over quality.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_COLOR_RENDER_QUALITY}</td>
+ * <td>Prefer quality over speed.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_COLOR_RENDER_DEFAULT}</td>
+ * <td>Use the default setting.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_COLOR_RENDERING;
+
+ /**
+ * This value is for use with the {@link #KEY_COLOR_RENDERING} key.
+ */
+ public static final Object VALUE_COLOR_RENDER_SPEED
+ = "Fastest color rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_COLOR_RENDERING} key.
+ */
+ public static final Object VALUE_COLOR_RENDER_QUALITY
+ = "Highest quality color rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_COLOR_RENDERING} key.
+ */
+ public static final Object VALUE_COLOR_RENDER_DEFAULT
+ = "Default color rendering mode";
+
+ /**
+ * A key for the 'stroke control' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_STROKE_DEFAULT}</td>
+ * <td>Use the default setting.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_STROKE_NORMALIZE}</td>
+ * <td>XXX</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_STROKE_PURE}</td>
+ * <td>XXX</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_STROKE_CONTROL;
+
+ /**
+ * This value is for use with the {@link #KEY_STROKE_CONTROL} key.
+ */
+ public static final Object VALUE_STROKE_DEFAULT
+ = "Default stroke normalization";
+
+ /**
+ * This value is for use with the {@link #KEY_STROKE_CONTROL} key.
+ */
+ public static final Object VALUE_STROKE_NORMALIZE
+ = "Normalize strokes for consistent rendering";
+
+ /**
+ * This value is for use with the {@link #KEY_STROKE_CONTROL} key.
+ */
+ public static final Object VALUE_STROKE_PURE
+ = "Pure stroke conversion for accurate paths";
+
+ static
+ {
+ KEY_ANTIALIASING = new KeyImpl(1, "Global antialiasing enable key",
+ VALUE_ANTIALIAS_ON,
+ VALUE_ANTIALIAS_OFF,
+ VALUE_ANTIALIAS_DEFAULT);
+ KEY_RENDERING = new KeyImpl(2, "Global rendering quality key",
+ VALUE_RENDER_SPEED,
+ VALUE_RENDER_QUALITY,
+ VALUE_RENDER_DEFAULT);
+ KEY_DITHERING = new KeyImpl(3, "Dithering quality key",
+ VALUE_DITHER_DISABLE,
+ VALUE_DITHER_ENABLE,
+ VALUE_DITHER_DEFAULT);
+ KEY_TEXT_ANTIALIASING
+ = new KeyImpl(4, "Text-specific antialiasing enable key",
+ VALUE_TEXT_ANTIALIAS_ON,
+ VALUE_TEXT_ANTIALIAS_OFF,
+ VALUE_TEXT_ANTIALIAS_DEFAULT);
+ KEY_FRACTIONALMETRICS = new KeyImpl(5, "Fractional metrics enable key",
+ VALUE_FRACTIONALMETRICS_OFF,
+ VALUE_FRACTIONALMETRICS_ON,
+ VALUE_FRACTIONALMETRICS_DEFAULT);
+ KEY_INTERPOLATION = new KeyImpl(6, "Image interpolation method key",
+ VALUE_INTERPOLATION_NEAREST_NEIGHBOR,
+ VALUE_INTERPOLATION_BILINEAR,
+ VALUE_INTERPOLATION_BICUBIC);
+ KEY_ALPHA_INTERPOLATION
+ = new KeyImpl(7, "Alpha blending interpolation method key",
+ VALUE_ALPHA_INTERPOLATION_SPEED,
+ VALUE_ALPHA_INTERPOLATION_QUALITY,
+ VALUE_ALPHA_INTERPOLATION_DEFAULT);
+ KEY_COLOR_RENDERING = new KeyImpl(8, "Color rendering quality key",
+ VALUE_COLOR_RENDER_SPEED,
+ VALUE_COLOR_RENDER_QUALITY,
+ VALUE_COLOR_RENDER_DEFAULT);
+ KEY_STROKE_CONTROL = new KeyImpl(9, "Stroke normalization control key",
+ VALUE_STROKE_DEFAULT,
+ VALUE_STROKE_NORMALIZE,
+ VALUE_STROKE_PURE);
+ }
+
+ /**
+ * Creates a new collection of hints containing all the (key, value) pairs
+ * in the specified map.
+ *
+ * @param init a map containing a collection of hints (<code>null</code>
+ * permitted).
+ */
+ public RenderingHints(Map init)
+ {
+ if (init != null)
+ putAll(init);
+ }
+
+ /**
+ * Creates a new collection containing a single (key, value) pair.
+ *
+ * @param key the key.
+ * @param value the value.
+ */
+ public RenderingHints(Key key, Object value)
+ {
+ put(key, value);
+ }
+
+ /**
+ * Returns the number of hints in the collection.
+ *
+ * @return The number of hints.
+ */
+ public int size()
+ {
+ return hintMap.size();
+ }
+
+ /**
+ * Returns <code>true</code> if there are no hints in the collection,
+ * and <code>false</code> otherwise.
+ *
+ * @return A boolean.
+ */
+ public boolean isEmpty()
+ {
+ return hintMap.isEmpty();
+ }
+
+ /**
+ * Returns <code>true</code> if the collection of hints contains the
+ * specified key, and <code>false</code> otherwise.
+ *
+ * @param key the key (<code>null</code> not permitted).
+ *
+ * @return A boolean.
+ *
+ * @throws NullPointerException if <code>key</code> is <code>null</code>.
+ * @throws ClassCastException if <code>key</code> is not a {@link Key}.
+ */
+ public boolean containsKey(Object key)
+ {
+ if (key == null)
+ throw new NullPointerException();
+ // don't remove the cast, it is necessary to throw the required exception
+ return hintMap.containsKey((Key) key);
+ }
+
+ /**
+ * Returns <code>true</code> if the collection of hints contains the
+ * specified value, and <code>false</code> otherwise.
+ *
+ * @param value the value.
+ *
+ * @return A boolean.
+ */
+ public boolean containsValue(Object value)
+ {
+ return hintMap.containsValue(value);
+ }
+
+ /**
+ * Returns the value associated with the specified key, or <code>null</code>
+ * if there is no value defined for the key.
+ *
+ * @param key the key (<code>null</code> permitted).
+ *
+ * @return The value (possibly <code>null</code>).
+ *
+ * @throws ClassCastException if <code>key</code> is not a {@link Key}.
+ *
+ * @see #containsKey(Object)
+ */
+ public Object get(Object key)
+ {
+ // don't remove the cast, it is necessary to throw the required exception
+ return hintMap.get((Key) key);
+ }
+
+ /**
+ * Adds a (key, value) pair to the collection of hints (if the
+ * collection already contains the specified key, then the
+ * value is updated).
+ *
+ * @param key the key.
+ * @param value the value.
+ *
+ * @return the previous value of the key or <code>null</code> if the key
+ * didn't have a value yet.
+ */
+ public Object put(Object key, Object value)
+ {
+ if (key == null || value == null)
+ throw new NullPointerException();
+ if (! ((Key) key).isCompatibleValue(value))
+ throw new IllegalArgumentException();
+ return hintMap.put(key, value);
+ }
+
+ /**
+ * Adds all the hints from a collection to this collection.
+ *
+ * @param hints the hint collection.
+ */
+ public void add(RenderingHints hints)
+ {
+ hintMap.putAll(hints);
+ }
+
+ /**
+ * Clears all the hints from this collection.
+ */
+ public void clear()
+ {
+ hintMap.clear();
+ }
+
+ /**
+ * Removes a hint from the collection.
+ *
+ * @param key the key.
+ *
+ * @return The value that was associated with the key, or <code>null</code> if
+ * the key was not part of the collection
+ *
+ * @throws ClassCastException if the key is not a subclass of
+ * {@link RenderingHints.Key}.
+ */
+ public Object remove(Object key)
+ {
+ // don't remove the (Key) cast, it is necessary to throw the exception
+ // required by the spec
+ return hintMap.remove((Key) key);
+ }
+
+ /**
+ * Adds a collection of (key, value) pairs to the collection.
+ *
+ * @param m a map containing (key, value) items.
+ *
+ * @throws ClassCastException if the map contains a key that is not
+ * a subclass of {@link RenderingHints.Key}.
+ * @throws IllegalArgumentException if the map contains a value that is
+ * not compatible with its key.
+ */
+ public void putAll(Map m)
+ {
+ // preprocess map to generate appropriate exceptions
+ Iterator iterator = m.keySet().iterator();
+ while (iterator.hasNext())
+ {
+ Key key = (Key) iterator.next();
+ if (!key.isCompatibleValue(m.get(key)))
+ throw new IllegalArgumentException();
+ }
+ // map is OK, update
+ hintMap.putAll(m);
+ }
+
+ /**
+ * Returns a set containing the keys from this collection.
+ *
+ * @return A set of keys.
+ */
+ public Set keySet()
+ {
+ return hintMap.keySet();
+ }
+
+ /**
+ * Returns a collection of the values from this hint collection. The
+ * collection is backed by the <code>RenderingHints</code> instance,
+ * so updates to one will affect the other.
+ *
+ * @return A collection of values.
+ */
+ public Collection values()
+ {
+ return hintMap.values();
+ }
+
+ /**
+ * Returns a set of entries from the collection.
+ *
+ * @return A set of entries.
+ */
+ public Set entrySet()
+ {
+ return Collections.unmodifiableSet(hintMap.entrySet());
+ }
+
+ /**
+ * Checks this collection for equality with an arbitrary object.
+ *
+ * @param o the object (<code>null</code> permitted)
+ *
+ * @return A boolean.
+ */
+ public boolean equals(Object o)
+ {
+ return hintMap.equals(o);
+ }
+
+ /**
+ * Returns a hash code for the collection of hints.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ return hintMap.hashCode();
+ }
+
+ /**
+ * Creates a clone of this instance.
+ *
+ * @return A clone.
+ */
+ public Object clone()
+ {
+ try
+ {
+ RenderingHints copy = (RenderingHints) super.clone();
+ copy.hintMap = (HashMap) hintMap.clone();
+ return copy;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Returns a string representation of this instance.
+ *
+ * @return A string.
+ */
+ public String toString()
+ {
+ return hintMap.toString();
+ }
+} // class RenderingHints
diff --git a/libjava/classpath/java/awt/Robot.java b/libjava/classpath/java/awt/Robot.java
new file mode 100644
index 00000000000..485a14e1e0f
--- /dev/null
+++ b/libjava/classpath/java/awt/Robot.java
@@ -0,0 +1,423 @@
+/* Robot.java -- a native input event generator
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+
+import java.lang.reflect.InvocationTargetException;
+import java.awt.event.InputEvent;
+import java.awt.image.BufferedImage;
+import java.awt.peer.RobotPeer;
+
+/**
+ * The Robot class is used to simulate user interaction with graphical
+ * programs. It can generate native windowing system input events and
+ * retrieve image data from the current screen. Robot is used to test
+ * the AWT and Swing library implementations; it can also be used to
+ * create self-running demo programs.
+ *
+ * Since Robot generates native windowing system events, rather than
+ * simply inserting {@link AWTEvent}s on the AWT event queue, its use
+ * is not restricted to Java programs. It can be used to
+ * programatically drive any graphical application.
+ *
+ * This implementation requires an X server that supports the XTest
+ * extension.
+ *
+ * @author Thomas Fitzsimmons (fitzsim@redhat.com)
+ *
+ * @since 1.3
+ */
+public class Robot
+{
+ private boolean waitForIdle;
+ private int autoDelay;
+ private RobotPeer peer;
+
+ /**
+ * Construct a Robot object that operates on the default screen.
+ *
+ * @exception AWTException if GraphicsEnvironment.isHeadless()
+ * returns true or if the X server does not support the XTest
+ * extension
+ * @exception SecurityException if createRobot permission is not
+ * granted
+ */
+ public Robot () throws AWTException
+ {
+ if (GraphicsEnvironment.isHeadless ())
+ throw new AWTException ("Robot: headless graphics environment");
+
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission (new AWTPermission ("createRobot"));
+
+ ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit ();
+
+ // createRobot will throw AWTException if XTest is not supported.
+ peer = tk.createRobot (GraphicsEnvironment.getLocalGraphicsEnvironment ()
+ .getDefaultScreenDevice ());
+ }
+
+ /**
+ * Construct a Robot object that operates on the specified screen.
+ *
+ * @exception AWTException if GraphicsEnvironment.isHeadless()
+ * returns true or if the X server does not support the XTest
+ * extension
+ * @exception IllegalArgumentException if screen is not a screen
+ * GraphicsDevice
+ * @exception SecurityException if createRobot permission is not
+ * granted
+ */
+ public Robot (GraphicsDevice screen) throws AWTException
+ {
+ if (GraphicsEnvironment.isHeadless ())
+ throw new AWTException ("Robot: headless graphics environment");
+
+ if (screen.getType () != GraphicsDevice.TYPE_RASTER_SCREEN)
+ throw new IllegalArgumentException ("Robot: graphics"
+ + " device is not a screen");
+
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission (new AWTPermission ("createRobot"));
+
+ ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit ();
+
+ // createRobot will throw AWTException if XTest is not supported.
+ peer = tk.createRobot (screen);
+ }
+
+ /**
+ * Move the mouse pointer to absolute coordinates (x, y).
+ *
+ * @param x the destination x coordinate
+ * @param y the destination y coordinate
+ */
+ public void mouseMove(int x, int y)
+ {
+ peer.mouseMove (x, y);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Press one or more mouse buttons.
+ *
+ * @param buttons the buttons to press; a bitmask of one or more of
+ * these {@link InputEvent} fields:
+ *
+ * <ul>
+ * <li>BUTTON1_MASK</li>
+ * <li>BUTTON2_MASK</li>
+ * <li>BUTTON3_MASK</li>
+ * </ul>
+ *
+ * @exception IllegalArgumentException if the button mask is invalid
+ */
+ public void mousePress (int buttons)
+ {
+ if ((buttons & InputEvent.BUTTON1_MASK) == 0
+ && (buttons & InputEvent.BUTTON2_MASK) == 0
+ && (buttons & InputEvent.BUTTON3_MASK) == 0)
+ throw new IllegalArgumentException ("Robot: mousePress:"
+ + " invalid button mask");
+
+ peer.mousePress (buttons);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Release one or more mouse buttons.
+ *
+ * @param buttons the buttons to release; a bitmask of one or more
+ * of these {@link InputEvent} fields:
+ *
+ * <ul>
+ * <li>BUTTON1_MASK</li>
+ * <li>BUTTON2_MASK</li>
+ * <li>BUTTON3_MASK</li>
+ * </ul>
+ *
+ * @exception IllegalArgumentException if the button mask is invalid
+ */
+ public void mouseRelease(int buttons)
+ {
+ if ((buttons & InputEvent.BUTTON1_MASK) == 0
+ && (buttons & InputEvent.BUTTON2_MASK) == 0
+ && (buttons & InputEvent.BUTTON3_MASK) == 0)
+ throw new IllegalArgumentException ("Robot: mouseRelease:"
+ + " invalid button mask");
+
+ peer.mouseRelease (buttons);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Rotate the mouse scroll wheel.
+ *
+ * @param wheelAmt number of steps to rotate mouse wheel. negative
+ * to rotate wheel up (away from the user), positive to rotate wheel
+ * down (toward the user).
+ *
+ * @since 1.4
+ */
+ public void mouseWheel (int wheelAmt)
+ {
+ peer.mouseWheel (wheelAmt);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Press a key.
+ *
+ * @param keycode key to press, a {@link java.awt.event.KeyEvent} VK_ constant
+ *
+ * @exception IllegalArgumentException if keycode is not a valid key
+ */
+ public void keyPress (int keycode)
+ {
+ peer.keyPress (keycode);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Release a key.
+ *
+ * @param keycode key to release, a {@link java.awt.event.KeyEvent} VK_
+ * constant
+ *
+ * @exception IllegalArgumentException if keycode is not a valid key
+ */
+ public void keyRelease (int keycode)
+ {
+ peer.keyRelease (keycode);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Return the color of the pixel at the given screen coordinates.
+ *
+ * @param x the x coordinate of the pixel
+ * @param y the y coordinate of the pixel
+ *
+ * @return the Color of the pixel at screen coodinates <code>(x, y)</code>
+ */
+ public Color getPixelColor (int x, int y)
+ {
+ return new Color (peer.getRGBPixel (x, y));
+ }
+
+ /**
+ * Create an image containing pixels read from the screen. The
+ * image does not include the mouse pointer.
+ *
+ * @param screenRect the rectangle of pixels to capture, in screen
+ * coordinates
+ *
+ * @return a BufferedImage containing the requested pixels
+ *
+ * @exception IllegalArgumentException if requested width and height
+ * are not both greater than zero
+ * @exception SecurityException if readDisplayPixels permission is
+ * not granted
+ */
+ public BufferedImage createScreenCapture (Rectangle screenRect)
+ {
+ if (screenRect.width <= 0)
+ throw new IllegalArgumentException ("Robot: capture width is <= 0");
+
+ if (screenRect.height <= 0)
+ throw new IllegalArgumentException ("Robot: capture height is <= 0");
+
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission (new AWTPermission ("readDisplayPixels"));
+
+ int[] pixels = peer.getRGBPixels (screenRect);
+
+ BufferedImage bufferedImage =
+ new BufferedImage (screenRect.width, screenRect.height,
+ BufferedImage.TYPE_INT_ARGB);
+
+ bufferedImage.setRGB (0, 0, screenRect.width, screenRect.height,
+ pixels, 0, screenRect.width);
+
+ return bufferedImage;
+ }
+
+ /**
+ * Check if this Robot automatically calls {@link #waitForIdle()} after
+ * generating an event.
+ *
+ * @return true if waitForIdle is automatically called
+ */
+ public boolean isAutoWaitForIdle ()
+ {
+ return waitForIdle;
+ }
+
+ /**
+ * Set whether or not this Robot automatically calls {@link
+ * #waitForIdle()} after generating an event.
+ *
+ * @param isOn true if waitForIdle should be called automatically
+ */
+ public void setAutoWaitForIdle (boolean isOn)
+ {
+ waitForIdle = isOn;
+ }
+
+ /**
+ * Retrieve the length of time this Robot sleeps after generating an
+ * event.
+ *
+ * @return the length of time in milliseconds
+ */
+ public int getAutoDelay ()
+ {
+ return autoDelay;
+ }
+
+ /**
+ * Set the length of time this Robot sleeps after generating an
+ * event.
+ *
+ * @param ms the length of time in milliseconds
+ *
+ * @exception IllegalArgumentException if ms is not between 0 and
+ * 60,000 milliseconds inclusive
+ */
+ public void setAutoDelay (int ms)
+ {
+ if (ms <= 0 || ms >= 60000)
+ throw new IllegalArgumentException ("Robot: delay length out-of-bounds");
+
+ autoDelay = ms;
+ }
+
+ /**
+ * Sleep for a specified length of time.
+ *
+ * @param ms the length of time in milliseconds
+ *
+ * @exception IllegalArgumentException if ms is not between 0 and
+ * 60,000 milliseconds inclusive
+ */
+ public void delay (int ms)
+ {
+ if (ms < 0 || ms > 60000)
+ throw new IllegalArgumentException ("Robot: delay length out-of-bounds");
+
+ try
+ {
+ Thread.sleep (ms);
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println ("Robot: delay interrupted");
+ }
+ }
+
+ /**
+ * Wait until all events currently on the event queue have been
+ * dispatched.
+ */
+ public void waitForIdle ()
+ {
+ if (EventQueue.isDispatchThread ())
+ throw new IllegalThreadStateException ("Robot: waitForIdle called from "
+ + "the event dispatch thread");
+
+ try
+ {
+ EventQueue.invokeAndWait (new Runnable () { public void run () { } });
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println ("Robot: waitForIdle interrupted");
+ }
+ catch (InvocationTargetException e)
+ {
+ System.err.println ("Robot: waitForIdle cannot invoke target");
+ }
+ }
+
+ /**
+ * Return a string representation of this Robot.
+ *
+ * @return a string representation
+ */
+ public String toString ()
+ {
+ return getClass ().getName ()
+ + "[ autoDelay = " + autoDelay + ", autoWaitForIdle = "
+ + waitForIdle + " ]";
+ }
+}
diff --git a/libjava/classpath/java/awt/ScrollPane.java b/libjava/classpath/java/awt/ScrollPane.java
new file mode 100644
index 00000000000..b3ecc59fcd5
--- /dev/null
+++ b/libjava/classpath/java/awt/ScrollPane.java
@@ -0,0 +1,615 @@
+/* ScrollPane.java -- Scrolling window
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.MouseEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.ScrollPanePeer;
+
+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.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class ScrollPane extends Container implements Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * Constant indicating that scrollbars are created as needed in this
+ * windows.
+ */
+public static final int SCROLLBARS_AS_NEEDED = 0;
+
+/**
+ * Constant indicating that scrollbars are always displayed in this
+ * window.
+ */
+public static final int SCROLLBARS_ALWAYS = 1;
+
+/**
+ * Constant indicating that scrollbars are never displayed in this window.
+ */
+public static final int SCROLLBARS_NEVER = 2;
+
+// Serialization constant
+private static final long serialVersionUID = 7956609840827222915L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The horizontal scrollbar for this window. The methods
+ * <code>setMinimum()</code>, <code>setMaximum</code>, and
+ * <code>setVisibleAmount</code> must not be called on this scrollbar.
+ */
+private ScrollPaneAdjustable hAdjustable;
+
+/**
+ * @serial The vertical scrollbar for this window. The methods
+ * <code>setMinimum()</code>, <code>setMaximum</code>, and
+ * <code>setVisibleAmount</code> must not be called on this scrollbar.
+ */
+private ScrollPaneAdjustable vAdjustable;
+
+/**
+ * @serial Indicates when scrollbars are displayed in this window, will
+ * be one of the constants from this class.
+ */
+private int scrollbarDisplayPolicy;
+
+// Current scroll position
+private Point scrollPosition = new Point(0, 0);
+
+private boolean wheelScrollingEnabled;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>ScrollPane</code> with a default
+ * scrollbar policy of <code>SCROLLBARS_AS_NEEDED</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+ScrollPane()
+{
+ this(SCROLLBARS_AS_NEEDED);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>ScrollPane</code> with the
+ * specified scrollbar policy.
+ *
+ * @param scrollbarDisplayPolicy When to display scrollbars, which must
+ * be one of the constants defined in this class.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+ScrollPane(int scrollbarDisplayPolicy)
+{
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+
+ this.scrollbarDisplayPolicy = scrollbarDisplayPolicy;
+
+ if (scrollbarDisplayPolicy != SCROLLBARS_ALWAYS
+ && scrollbarDisplayPolicy != SCROLLBARS_AS_NEEDED
+ && scrollbarDisplayPolicy != SCROLLBARS_NEVER)
+ throw new IllegalArgumentException("Bad scrollbarDisplayPolicy: " +
+ scrollbarDisplayPolicy);
+
+ if (scrollbarDisplayPolicy != SCROLLBARS_NEVER)
+ {
+ hAdjustable = new ScrollPaneAdjustable (this, Scrollbar.HORIZONTAL);
+ vAdjustable = new ScrollPaneAdjustable (this, Scrollbar.VERTICAL);
+ }
+
+ wheelScrollingEnabled = true;
+
+ // Default size.
+ setSize(100,100);
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the current scrollbar display policy.
+ *
+ * @return The current scrollbar display policy.
+ */
+public int
+getScrollbarDisplayPolicy()
+{
+ return(scrollbarDisplayPolicy);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the horizontal scrollbar for this object. If the scrollbar
+ * display policy is set to <code>SCROLLBARS_NEVER</code> then this
+ * will be <code>null</code>.
+ *
+ * @return The horizontal scrollbar for this window.
+ */
+public Adjustable
+getHAdjustable()
+{
+ return(hAdjustable);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the vertical scrollbar for this object. If the scrollbar
+ * display policy is set to <code>SCROLLBARS_NEVER</code> then this
+ * will be <code>null</code>.
+ *
+ * @return The horizontal scrollbar for this window.
+ */
+public Adjustable
+getVAdjustable()
+{
+ return(vAdjustable);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the current viewport size. The viewport is the region of
+ * this object's window where the child is actually displayed.
+ *
+ * @return The viewport size.
+ */
+public Dimension getViewportSize ()
+{
+ Dimension viewsize = getSize ();
+ Insets insets = getInsets ();
+
+ viewsize.width -= (insets.left + insets.right);
+ viewsize.height -= (insets.top + insets.bottom);
+
+ 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;
+
+ int vScrollbarWidth = getVScrollbarWidth ();
+ int hScrollbarHeight = getHScrollbarHeight ();
+
+ if (scrollbarDisplayPolicy == SCROLLBARS_ALWAYS)
+ {
+ viewsize.width -= vScrollbarWidth;
+ viewsize.height -= hScrollbarHeight;
+ return viewsize;
+ }
+
+ if (scrollbarDisplayPolicy == SCROLLBARS_NEVER)
+ return viewsize;
+
+ // The scroll policy is SCROLLBARS_AS_NEEDED, so we need to see if
+ // either scrollbar is needed.
+
+ // Assume we don't need either scrollbar.
+ boolean mayNeedVertical = false;
+ boolean mayNeedHorizontal = false;
+
+ boolean needVertical = false;
+ boolean needHorizontal = false;
+
+ // Check if we need vertical scrollbars. If we do, then we need to
+ // subtract the width of the vertical scrollbar from the viewport's
+ // width.
+ if (dim.height > viewsize.height)
+ needVertical = true;
+ else if (dim.height > (viewsize.height - hScrollbarHeight))
+ // This is tricky. In this case the child is tall enough that its
+ // bottom edge would be covered by a horizontal scrollbar, if one
+ // were present. This means that if there's a horizontal
+ // scrollbar then we need a vertical scrollbar.
+ mayNeedVertical = true;
+
+ if (dim.width > viewsize.width)
+ needHorizontal = true;
+ else if (dim.width > (viewsize.width - vScrollbarWidth))
+ mayNeedHorizontal = true;
+
+ if (needVertical && mayNeedHorizontal)
+ needHorizontal = true;
+
+ if (needHorizontal && mayNeedVertical)
+ needVertical = true;
+
+ if (needHorizontal)
+ viewsize.height -= hScrollbarHeight;
+
+ if (needVertical)
+ viewsize.width -= vScrollbarWidth;
+
+ return viewsize;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the height of a horizontal scrollbar.
+ *
+ * @return The height of a horizontal scrollbar.
+ */
+public int
+getHScrollbarHeight()
+{
+ ScrollPanePeer spp = (ScrollPanePeer)getPeer();
+ if (spp != null)
+ return(spp.getHScrollbarHeight());
+ else
+ return(0); // FIXME: What to do here?
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the width of a vertical scrollbar.
+ *
+ * @return The width of a vertical scrollbar.
+ */
+public int
+getVScrollbarWidth()
+{
+ ScrollPanePeer spp = (ScrollPanePeer)getPeer();
+ if (spp != null)
+ return(spp.getVScrollbarWidth());
+ else
+ return(0); // FIXME: What to do here?
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the current scroll position of the viewport.
+ *
+ * @return The current scroll position of the viewport.
+ */
+public Point
+getScrollPosition()
+{
+ int x = 0;
+ int y = 0;
+
+ Adjustable v = getVAdjustable();
+ Adjustable h = getHAdjustable();
+
+ if (v != null)
+ y = v.getValue();
+ if (h != null)
+ x = h.getValue();
+
+ return(new Point(x, y));
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the scroll position to the specified value.
+ *
+ * @param scrollPosition The new scrollPosition.
+ *
+ * @exception IllegalArgumentException If the specified value is outside
+ * the legal scrolling range.
+ */
+public void
+setScrollPosition(Point scrollPosition) throws IllegalArgumentException
+{
+ setScrollPosition(scrollPosition.x, scrollPosition.y);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the scroll position to the specified value.
+ *
+ * @param x The new X coordinate of the scroll position.
+ * @param y The new Y coordinate of the scroll position.
+ *
+ * @exception IllegalArgumentException If the specified value is outside
+ * the legal scrolling range.
+ */
+public void
+setScrollPosition(int x, int y)
+{
+ Adjustable h = getHAdjustable();
+ Adjustable v = getVAdjustable();
+
+ if (h != null)
+ h.setValue(x);
+ if (v != null)
+ v.setValue(y);
+
+ ScrollPanePeer spp = (ScrollPanePeer)getPeer();
+ if (spp != null)
+ spp.setScrollPosition(x, y);
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies this object that it should create its native peer.
+ */
+public void
+addNotify()
+{
+ if (!isDisplayable ())
+ return;
+
+ setPeer((ComponentPeer)getToolkit().createScrollPane(this));
+ super.addNotify();
+
+ Component[] list = getComponents();
+ if (list != null && list.length > 0 && ! (list[0] instanceof Panel))
+ {
+ Panel panel = new Panel();
+ panel.setLayout(new BorderLayout());
+ panel.add(list[0], BorderLayout.CENTER);
+ add(panel);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies this object that it should destroy its native peers.
+ */
+public void
+removeNotify()
+{
+ super.removeNotify();
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified child component to this container. A
+ * <code>ScrollPane</code> can have at most one child, so if a second
+ * one is added, then first one is removed.
+ *
+ * @param component The component to add to this container.
+ * @param constraints A list of layout constraints for this object.
+ * @param index The index at which to add the child, which is ignored
+ * in this implementation.
+ */
+ protected final void addImpl (Component component, Object constraints,
+ int index)
+{
+ Component[] list = getComponents();
+ if ((list != null) && (list.length > 0))
+ remove(list[0]);
+
+ super.addImpl(component, constraints, -1);
+
+ doLayout();
+}
+
+/*************************************************************************/
+
+/**
+ * Lays out this component. This consists of resizing the sole child
+ * component to its perferred size.
+ */
+public void
+doLayout()
+{
+ layout ();
+}
+
+/*************************************************************************/
+
+/**
+ * Lays out this component. This consists of resizing the sole child
+ * component to its perferred size.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>doLayout()</code>.
+ */
+public void
+layout()
+{
+ Component[] list = getComponents ();
+ if ((list != null) && (list.length > 0))
+ {
+ Dimension dim = list[0].getPreferredSize ();
+ Dimension vp = getViewportSize ();
+
+ if (dim.width < vp.width)
+ dim.width = vp.width;
+
+ if (dim.height < vp.height)
+ dim.height = vp.height;
+
+ ScrollPanePeer peer = (ScrollPanePeer) getPeer ();
+ if (peer != null)
+ peer.childResized (dim.width, dim.height);
+
+ list[0].setSize (dim);
+
+ Point p = getScrollPosition ();
+ if (p.x > dim.width)
+ p.x = dim.width;
+ if (p.y > dim.height)
+ p.y = dim.height;
+
+ setScrollPosition (p);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * This method overrides its superclass method to ensure no layout
+ * manager is set for this container. <code>ScrollPane</code>'s do
+ * not have layout managers.
+ *
+ * @param layoutManager Ignored
+ */
+public final void
+setLayout(LayoutManager layoutManager)
+{
+ return;
+}
+
+/*************************************************************************/
+
+/**
+ * Prints all of the components in this container.
+ *
+ * @param graphics The desired graphics context for printing.
+ */
+public void
+printComponents(Graphics graphics)
+{
+ super.printComponents(graphics);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debug string for this object.
+ *
+ * @return A debug string for this object.
+ */
+public String
+paramString()
+{
+ Insets insets = getInsets();
+ return getName() + ","
+ + getX() + ","
+ + getY() + ","
+ + getWidth() + "x" + getHeight() + ","
+ + "ScrollPosition=(" + scrollPosition.getX() + ","
+ + scrollPosition.getY() + "),"
+ + "Insets=(" + insets.top + ","
+ + insets.left + ","
+ + insets.bottom + ","
+ + insets.right + "),"
+ + "ScrollbarDisplayPolicy=" + getScrollbarDisplayPolicy() + ","
+ + "wheelScrollingEnabled=" + isWheelScrollingEnabled();
+}
+
+ /**
+ * Tells whether or not an event is enabled.
+ *
+ * @since 1.4
+ */
+ protected boolean eventTypeEnabled (int type)
+ {
+ if (type == MouseEvent.MOUSE_WHEEL)
+ return wheelScrollingEnabled;
+
+ return super.eventTypeEnabled (type);
+ }
+
+ /**
+ * Tells whether or not wheel scrolling is enabled.
+ *
+ * @since 1.4
+ */
+ public boolean isWheelScrollingEnabled ()
+ {
+ return wheelScrollingEnabled;
+ }
+
+ /**
+ * Enables/disables wheel scrolling.
+ *
+ * @since 1.4
+ */
+ public void setWheelScrollingEnabled (boolean enable)
+ {
+ wheelScrollingEnabled = enable;
+ }
+
+ protected class AccessibleAWTScrollPane extends AccessibleAWTContainer
+ {
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.SCROLL_PANE;
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>ScrollPane</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTScrollPane();
+ return accessibleContext;
+ }
+} // class ScrollPane
+
diff --git a/libjava/classpath/java/awt/ScrollPaneAdjustable.java b/libjava/classpath/java/awt/ScrollPaneAdjustable.java
new file mode 100644
index 00000000000..cfca19b4423
--- /dev/null
+++ b/libjava/classpath/java/awt/ScrollPaneAdjustable.java
@@ -0,0 +1,200 @@
+/* ScrollPaneAdjustable.java -- Scrollbars for a ScrollPane
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.AdjustmentListener;
+import java.io.Serializable;
+
+/**
+ * Need this class since the serialization spec for ScrollPane
+ * uses it.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.4
+ */
+public class ScrollPaneAdjustable
+ implements Adjustable, Serializable
+{
+ private static final long serialVersionUID = -3359745691033257079L;
+
+ ScrollPane sp;
+ int orientation;
+ int value;
+ int minimum;
+ int maximum;
+ int visibleAmount;
+ int unitIncrement = 1;
+ int blockIncrement = 1;
+ AdjustmentListener adjustmentListener;
+
+ private transient boolean valueIsAdjusting = false;
+
+ ScrollPaneAdjustable (ScrollPane sp, int orientation)
+ {
+ this.sp = sp;
+ this.orientation = orientation;
+ }
+
+ ScrollPaneAdjustable (ScrollPane sp, int orientation, int value, int minimum,
+ int maximum, int visibleAmount, int unitIncrement,
+ int blockIncrement)
+ {
+ this.sp = sp;
+ this.orientation = orientation;
+ this.value = value;
+ this.minimum = minimum;
+ this.maximum = maximum;
+ this.visibleAmount = visibleAmount;
+ this.unitIncrement = unitIncrement;
+ this.blockIncrement = blockIncrement;
+ }
+
+ public void addAdjustmentListener (AdjustmentListener listener)
+ {
+ AWTEventMulticaster.add (adjustmentListener, listener);
+ }
+
+ public void removeAdjustmentListener (AdjustmentListener listener)
+ {
+ AWTEventMulticaster.remove (adjustmentListener, listener);
+ }
+
+ public AdjustmentListener[] getAdjustmentListeners ()
+ {
+ return (AdjustmentListener[]) AWTEventMulticaster.getListeners
+ (adjustmentListener, AdjustmentListener.class);
+ }
+
+ public int getBlockIncrement ()
+ {
+ return blockIncrement;
+ }
+
+ public int getMaximum ()
+ {
+ return maximum;
+ }
+
+ public int getMinimum ()
+ {
+ return minimum;
+ }
+
+ public int getOrientation ()
+ {
+ return orientation;
+ }
+
+ public int getUnitIncrement ()
+ {
+ return unitIncrement;
+ }
+
+ public int getValue ()
+ {
+ return value;
+ }
+
+ public int getVisibleAmount ()
+ {
+ return visibleAmount;
+ }
+
+ public void setBlockIncrement (int blockIncrement)
+ {
+ this.blockIncrement = blockIncrement;
+ }
+
+ public void setMaximum (int maximum)
+ {
+ this.maximum = maximum;
+ }
+
+ public void setMinimum (int minimum)
+ {
+ this.minimum = minimum;
+ }
+
+ public void setUnitIncrement (int unitIncrement)
+ {
+ this.unitIncrement = unitIncrement;
+ }
+
+ public void setValue (int value)
+ {
+ this.value = value;
+
+ if (value < minimum)
+ minimum = value;
+
+ if (value > maximum)
+ maximum = value;
+ }
+
+ public void setVisibleAmount (int visibleAmount)
+ {
+ this.visibleAmount = visibleAmount;
+ }
+
+ public String paramString ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ /**
+ * Returns true if the value is in the process of changing.
+ *
+ * @since 1.4
+ */
+ public boolean getValueIsAdjusting ()
+ {
+ return valueIsAdjusting;
+ }
+
+ /**
+ * Sets the value of valueIsAdjusting.
+ *
+ * @since 1.4
+ */
+ public void setValueIsAdjusting (boolean valueIsAdjusting)
+ {
+ this.valueIsAdjusting = valueIsAdjusting;
+ }
+} // class ScrollPaneAdjustable
+
diff --git a/libjava/classpath/java/awt/Scrollbar.java b/libjava/classpath/java/awt/Scrollbar.java
new file mode 100644
index 00000000000..6e506c78584
--- /dev/null
+++ b/libjava/classpath/java/awt/Scrollbar.java
@@ -0,0 +1,825 @@
+/* Scrollbar.java -- AWT Scrollbar widget
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.peer.ScrollbarPeer;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class implements a scrollbar widget.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class Scrollbar extends Component implements Accessible, Adjustable
+{
+ // FIXME: Serialization readObject/writeObject
+
+ /**
+ * Constant indicating that a scrollbar is horizontal.
+ */
+ public static final int HORIZONTAL = 0;
+
+ /**
+ * Constant indicating that a scrollbar is vertical.
+ */
+ public static final int VERTICAL = 1;
+
+ /**
+ * Serialization Constant.
+ */
+ private static final long serialVersionUID = 8451667562882310543L;
+
+ /**
+ * @serial The amount by which the value of the scrollbar is changed
+ * when incrementing in line mode.
+ */
+ private int lineIncrement;
+
+ /**
+ * @serial The amount by which the value of the scrollbar is changed
+ * when incrementing in page mode.
+ */
+ private int pageIncrement;
+
+ /**
+ * @serial The maximum value for this scrollbar
+ */
+ private int maximum;
+
+ /**
+ * @serial The minimum value for this scrollbar
+ */
+ private int minimum;
+
+ /**
+ * @serial The orientation of this scrollbar, which will be either
+ * the <code>HORIZONTAL</code> or <code>VERTICAL</code> constant
+ * from this class.
+ */
+ private int orientation;
+
+ /**
+ * @serial The current value of this scrollbar.
+ */
+ private int value;
+
+ /**
+ * @serial The width of the scrollbar's thumb, which is relative
+ * to the minimum and maximum value of the scrollbar.
+ */
+ private int visibleAmount;
+
+ /**
+ * List of AdjustmentListener's.
+ */
+ private AdjustmentListener adjustment_listeners;
+
+ /**
+ * true if the scrollbar is adjusting, false otherwise.
+ */
+ private transient boolean valueIsAdjusting = false;
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_scrollbar_number;
+
+ /**
+ * Initializes a new instance of <code>Scrollbar</code> with a
+ * vertical orientation and default values for all other parameters.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+ public Scrollbar()
+ {
+ this(VERTICAL);
+ }
+
+ /**
+ * Initializes a new instance of <code>Scrollbar</code> with the
+ * specified orientation and default values for all other parameters.
+ * The orientation must be either the constant <code>HORIZONTAL</code> or
+ * <code>VERTICAL</code> from this class. An incorrect value will throw
+ * an exception.
+ *
+ * @param orientation The orientation of this scrollbar.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ * @exception IllegalArgumentException If the orientation value is not valid.
+ */
+ public Scrollbar(int orientation) throws IllegalArgumentException
+ {
+ this(orientation, 0, 10, 0, 100);
+ }
+
+ /**
+ * Initializes a new instance of <code>Scrollbar</code> with the
+ * specified parameters. The orientation must be either the constant
+ * <code>HORIZONTAL</code> or <code>VERTICAL</code>. An incorrect value
+ * will throw an exception. Inconsistent values for other parameters
+ * are silently corrected to valid values.
+ *
+ * @param orientation The orientation of this scrollbar.
+ * @param value The initial value of the scrollbar.
+ * @param visibleAmount The width of the scrollbar thumb.
+ * @param minimum The minimum value of the scrollbar.
+ * @param maximum The maximum value of the scrollbar.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ * @exception IllegalArgumentException If the orientation value is not valid.
+ */
+ public Scrollbar(int orientation, int value, int visibleAmount, int minimum,
+ int maximum) throws IllegalArgumentException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+
+ if ((orientation != HORIZONTAL) && (orientation != VERTICAL))
+ throw new IllegalArgumentException("Bad orientation value: "
+ + orientation);
+
+ this.orientation = orientation;
+
+ setValues(value, visibleAmount, minimum, maximum);
+
+ // Default is 1 according to online docs.
+ lineIncrement = 1;
+
+ // Default is 10 according to javadocs.
+ pageIncrement = 10;
+ }
+
+ /**
+ * Returns the orientation constant for this object.
+ *
+ * @return The orientation constant for this object.
+ */
+ public int getOrientation()
+ {
+ return orientation;
+ }
+
+ /**
+ * Sets the orientation of this scrollbar to the specified value. This
+ * value must be either the constant <code>HORIZONTAL</code> or
+ * <code>VERTICAL</code> from this class or an exception will be thrown.
+ *
+ * @param orientation The new orientation value.
+ *
+ * @exception IllegalArgumentException If the orientation value is not valid.
+ */
+ public void setOrientation(int orientation)
+ {
+ if ((orientation != HORIZONTAL) && (orientation != VERTICAL))
+ throw new IllegalArgumentException("Bad orientation value: "
+ + orientation);
+
+ // FIXME: Communicate to peer? Or must this be called before peer creation?
+ this.orientation = orientation;
+ }
+
+ /**
+ * Returns the current value for this scrollbar.
+ *
+ * @return The current value for this scrollbar.
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Sets the current value for this scrollbar to the specified value.
+ * If this is inconsistent with the minimum and maximum values for this
+ * scrollbar, the value is silently adjusted.
+ *
+ * @param value The new value for this scrollbar.
+ */
+ public void setValue(int value)
+ {
+ setValues(value, visibleAmount, minimum, maximum);
+ }
+
+ /**
+ * Returns the maximum value for this scrollbar.
+ *
+ * @return The maximum value for this scrollbar.
+ */
+ public int getMaximum()
+ {
+ return maximum;
+ }
+
+ /**
+ * Sets the maximum value for this scrollbar to the specified value.
+ * If the value is less than the current minimum value, it is silent
+ * set to equal the minimum value.
+ *
+ * @param maximum The new maximum value for this scrollbar.
+ */
+ public void setMaximum(int maximum)
+ {
+ setValues(value, visibleAmount, minimum, maximum);
+ }
+
+ /**
+ * Returns the minimum value for this scrollbar.
+ *
+ * @return The minimum value for this scrollbar.
+ */
+ public int getMinimum()
+ {
+ return minimum;
+ }
+
+ /**
+ * Sets the minimum value for this scrollbar to the specified value. If
+ * this is not consistent with the current value and maximum, it is
+ * silently adjusted to be consistent.
+ *
+ * @param minimum The new minimum value for this scrollbar.
+ */
+ public void setMinimum(int minimum)
+ {
+ setValues(value, visibleAmount, minimum, maximum);
+ }
+
+ /**
+ * Returns the width of the scrollbar's thumb, in units relative to the
+ * maximum and minimum value of the scrollbar.
+ *
+ * @return The width of the scrollbar's thumb.
+ */
+ public int getVisibleAmount()
+ {
+ return getVisible();
+ }
+
+ /**
+ * Returns the width of the scrollbar's thumb, in units relative to the
+ * maximum and minimum value of the scrollbar.
+ *
+ * @return The width of the scrollbar's thumb.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getVisibleAmount()</code>.
+ */
+ public int getVisible()
+ {
+ return visibleAmount;
+ }
+
+ /**
+ * Sets the width of the scrollbar's thumb, in units relative to the
+ * maximum and minimum value of the scrollbar.
+ *
+ * @param visibleAmount The new visible amount value of the scrollbar.
+ */
+ public void setVisibleAmount(int visibleAmount)
+ {
+ setValues(value, visibleAmount, minimum, maximum);
+ }
+
+ /**
+ * Sets the current value, visible amount, minimum, and maximum for this
+ * scrollbar. These values are adjusted to be internally consistent
+ * if necessary.
+ *
+ * @param value The new value for this scrollbar.
+ * @param visibleAmount The new visible amount for this scrollbar.
+ * @param minimum The new minimum value for this scrollbar.
+ * @param maximum The new maximum value for this scrollbar.
+ */
+ public synchronized void setValues(int value, int visibleAmount,
+ int minimum, int maximum)
+ {
+ if (maximum < minimum)
+ maximum = minimum;
+
+ if (value < minimum)
+ value = minimum;
+
+ if (value > maximum)
+ value = maximum;
+
+ if (visibleAmount > maximum - minimum)
+ visibleAmount = maximum - minimum;
+
+ ScrollbarPeer peer = (ScrollbarPeer) getPeer();
+ if (peer != null
+ && (this.value != value || this.visibleAmount != visibleAmount
+ || this.minimum != minimum || this.maximum != maximum))
+ peer.setValues(value, visibleAmount, minimum, maximum);
+
+ this.value = value;
+ this.visibleAmount = visibleAmount;
+ this.minimum = minimum;
+ this.maximum = maximum;
+
+ int range = maximum - minimum;
+ if (lineIncrement > range)
+ {
+ if (range == 0)
+ lineIncrement = 1;
+ else
+ lineIncrement = range;
+
+ if (peer != null)
+ peer.setLineIncrement(lineIncrement);
+ }
+
+ if (pageIncrement > range)
+ {
+ if (range == 0)
+ pageIncrement = 1;
+ else
+ pageIncrement = range;
+
+ if (peer != null)
+ peer.setPageIncrement(pageIncrement);
+ }
+ }
+
+ /**
+ * Returns the value added or subtracted when the user activates the scrollbar
+ * scroll by a "unit" amount.
+ *
+ * @return The unit increment value.
+ */
+ public int getUnitIncrement()
+ {
+ return getLineIncrement();
+ }
+
+ /**
+ * Returns the value added or subtracted when the user selects the scrollbar
+ * scroll by a "unit" amount control.
+ *
+ * @return The unit increment value.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getUnitIncrement()</code>.
+ */
+ public int getLineIncrement()
+ {
+ return lineIncrement;
+ }
+
+ /**
+ * Sets the value added or subtracted to the scrollbar value when the
+ * user selects the scroll by a "unit" amount control.
+ *
+ * @param unitIncrement The new unit increment amount.
+ */
+ public synchronized void setUnitIncrement(int unitIncrement)
+ {
+ setLineIncrement(unitIncrement);
+ }
+
+ /**
+ * Sets the value added or subtracted to the scrollbar value when the
+ * user selects the scroll by a "unit" amount control.
+ *
+ * @param lineIncrement The new unit increment amount.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>setUnitIncrement()</code>.
+ */
+ public void setLineIncrement(int lineIncrement)
+ {
+ if (lineIncrement < 0)
+ throw new IllegalArgumentException("Unit increment less than zero.");
+
+ int range = maximum - minimum;
+ if (lineIncrement > range)
+ {
+ if (range == 0)
+ lineIncrement = 1;
+ else
+ lineIncrement = range;
+ }
+
+ if (lineIncrement == this.lineIncrement)
+ return;
+
+ this.lineIncrement = lineIncrement;
+
+ ScrollbarPeer peer = (ScrollbarPeer) getPeer();
+ if (peer != null)
+ peer.setLineIncrement(this.lineIncrement);
+ }
+
+ /**
+ * Returns the value added or subtracted when the user activates the scrollbar
+ * scroll by a "block" amount.
+ *
+ * @return The block increment value.
+ */
+ public int getBlockIncrement()
+ {
+ return getPageIncrement();
+ }
+
+ /**
+ * Returns the value added or subtracted when the user selects the scrollbar
+ * scroll by a "block" amount control.
+ *
+ * @return The block increment value.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getBlockIncrement()</code>.
+ */
+ public int getPageIncrement()
+ {
+ return pageIncrement;
+ }
+
+ /**
+ * Sets the value added or subtracted to the scrollbar value when the
+ * user selects the scroll by a "block" amount control.
+ *
+ * @param blockIncrement The new block increment amount.
+ */
+ public synchronized void setBlockIncrement(int blockIncrement)
+ {
+ setPageIncrement(blockIncrement);
+ }
+
+ /**
+ * Sets the value added or subtracted to the scrollbar value when the
+ * user selects the scroll by a "block" amount control.
+ *
+ * @param pageIncrement The new block increment amount.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>setBlockIncrement()</code>.
+ */
+ public void setPageIncrement(int pageIncrement)
+ {
+ if (pageIncrement < 0)
+ throw new IllegalArgumentException("Block increment less than zero.");
+
+ int range = maximum - minimum;
+ if (pageIncrement > range)
+ {
+ if (range == 0)
+ pageIncrement = 1;
+ else
+ pageIncrement = range;
+ }
+
+ if (pageIncrement == this.pageIncrement)
+ return;
+
+ this.pageIncrement = pageIncrement;
+
+ ScrollbarPeer peer = (ScrollbarPeer) getPeer();
+ if (peer != null)
+ peer.setPageIncrement(this.pageIncrement);
+ }
+
+ /**
+ * Notifies this object to create its native peer.
+ */
+ public synchronized void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createScrollbar(this);
+ super.addNotify();
+ }
+
+ /**
+ * Adds a new adjustment listener to the list of registered listeners
+ * for this object.
+ *
+ * @param listener The listener to add.
+ */
+ public synchronized void addAdjustmentListener(AdjustmentListener listener)
+ {
+ adjustment_listeners = AWTEventMulticaster.add(adjustment_listeners,
+ listener);
+ enableEvents(AWTEvent.ADJUSTMENT_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the list of registered listeners
+ * for this object.
+ *
+ * @param listener The listener to remove.
+ */
+ public synchronized void removeAdjustmentListener(AdjustmentListener listener)
+ {
+ adjustment_listeners = AWTEventMulticaster.remove(adjustment_listeners,
+ listener);
+ }
+
+ /**
+ * Processes events for this scrollbar. It does this by calling
+ * <code>processAdjustmentEvent()</code> if the event is an instance of
+ * <code>AdjustmentEvent</code>, otherwise it calls the superclass to
+ * process the event.
+ *
+ * @param event The event to process.
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ if (event instanceof AdjustmentEvent)
+ processAdjustmentEvent((AdjustmentEvent) event);
+ else
+ super.processEvent(event);
+ }
+
+ /**
+ * Processes adjustment events for this object by dispatching them to
+ * any registered listeners. Note that this method will only be called
+ * if adjustment events are enabled. This will happen automatically if
+ * any listeners are registered. Otherwise, it can be enabled by a
+ * call to <code>enableEvents()</code>.
+ *
+ * @param event The event to process.
+ */
+ protected void processAdjustmentEvent(AdjustmentEvent event)
+ {
+ value = event.getValue();
+ if (adjustment_listeners != null)
+ adjustment_listeners.adjustmentValueChanged(event);
+ }
+
+ void dispatchEventImpl(AWTEvent e)
+ {
+ if (e.id <= AdjustmentEvent.ADJUSTMENT_LAST
+ && e.id >= AdjustmentEvent.ADJUSTMENT_FIRST
+ && (adjustment_listeners != null
+ || (eventMask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+ }
+
+ /**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+ protected String paramString()
+ {
+ return ("value=" + getValue() + ",visibleAmount=" + getVisibleAmount()
+ + ",minimum=" + getMinimum() + ",maximum=" + getMaximum()
+ + ",pageIncrement=" + pageIncrement + ",lineIncrement="
+ + lineIncrement + ",orientation="
+ + (orientation == HORIZONTAL ? "HORIZONTAL" : "VERTICAL")
+ + super.paramString());
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>Scrollbar</code>. FooListeners are registered using the
+ * addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ if (listenerType == AdjustmentListener.class)
+ return AWTEventMulticaster.getListeners(adjustment_listeners,
+ listenerType);
+
+ return super.getListeners(listenerType);
+ }
+
+ /**
+ * Returns an array of all registered adjustment listeners.
+ */
+ public AdjustmentListener[] getAdjustmentListeners()
+ {
+ return (AdjustmentListener[]) getListeners(AdjustmentListener.class);
+ }
+
+ /**
+ * Returns true if the value is in the process of changing.
+ *
+ * @since 1.4
+ */
+ public boolean getValueIsAdjusting()
+ {
+ return valueIsAdjusting;
+ }
+
+ /**
+ * Sets the value of valueIsAdjusting.
+ *
+ * @since 1.4
+ */
+ public void setValueIsAdjusting(boolean valueIsAdjusting)
+ {
+ this.valueIsAdjusting = valueIsAdjusting;
+ }
+
+ /**
+ * Generate a unique name for this scroll bar.
+ *
+ * @return A unique name for this scroll bar.
+ */
+ String generateName()
+ {
+ return "scrollbar" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_scrollbar_number++;
+ }
+
+ /**
+ * This class provides accessibility support for the
+ * scrollbar.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ protected class AccessibleAWTScrollBar extends AccessibleAWTComponent
+ implements AccessibleValue
+ {
+ /**
+ * Serialization constant to match JDK 1.5
+ */
+ private static final long serialVersionUID = -344337268523697807L;
+
+ /**
+ * Returns the role of this accessible object.
+ *
+ * @return the instance of <code>AccessibleRole</code>,
+ * which describes this object.
+ *
+ * @see javax.accessibility.AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.SCROLL_BAR;
+ }
+
+ /**
+ * Returns the state set of this accessible object.
+ *
+ * @return a set of <code>AccessibleState</code>s which
+ * represent the current state of the accessible object.
+ *
+ * @see javax.accessibility.AccessibleState
+ * @see javax.accessibility.AccessibleStateSet
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (getOrientation() == HORIZONTAL)
+ states.add(AccessibleState.HORIZONTAL);
+ else
+ states.add(AccessibleState.VERTICAL);
+ if (getValueIsAdjusting())
+ states.add(AccessibleState.BUSY);
+ return states;
+ }
+
+ /**
+ * Returns an implementation of the <code>AccessibleValue</code>
+ * interface for this accessible object. In this case, the
+ * current instance is simply returned (with a more appropriate
+ * type), as it also implements the accessible value as well as
+ * the context.
+ *
+ * @return the accessible value associated with this context.
+ *
+ * @see javax.accessibility.AccessibleValue
+ */
+ public AccessibleValue getAccessibleValue()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the current value of this accessible object.
+ * In this case, this is the same as the value for
+ * the scrollbar, wrapped in an <code>Integer</code>
+ * object.
+ *
+ * @return the numeric value of this scrollbar.
+ *
+ * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
+ */
+ public Number getCurrentAccessibleValue()
+ {
+ return new Integer(getValue());
+ }
+
+ /**
+ * Sets the current value of this accessible object
+ * to that supplied. In this case, the value of the
+ * scrollbar is set, and this method always returns
+ * true.
+ *
+ * @param number the new accessible value.
+ *
+ * @return true if the value was set.
+ *
+ * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
+ */
+ public boolean setCurrentAccessibleValue(Number number)
+ {
+ setValue(number.intValue());
+ return true;
+ }
+
+ /**
+ * Returns the minimum acceptable accessible value used
+ * by this object. In this case, this is the same as
+ * the minimum value of the scrollbar, wrapped in an
+ * object.
+ *
+ * @return the minimum value of this scrollbar.
+ *
+ * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
+ */
+ public Number getMinimumAccessibleValue()
+ {
+ return new Integer(getMinimum());
+ }
+
+ /**
+ * Returns the maximum acceptable accessible value used
+ * by this object. In this case, this is the same as
+ * the maximum value of the scrollbar, wrapped in an
+ * object.
+ *
+ * @return the maximum value of this scrollbar.
+ *
+ * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
+ */
+ public Number getMaximumAccessibleValue()
+ {
+ return new Integer(getMaximum());
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Scrollbar</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTScrollBar();
+
+ return accessibleContext;
+ }
+}
diff --git a/libjava/classpath/java/awt/Shape.java b/libjava/classpath/java/awt/Shape.java
new file mode 100644
index 00000000000..bd8a4343528
--- /dev/null
+++ b/libjava/classpath/java/awt/Shape.java
@@ -0,0 +1,203 @@
+/* Shape.java -- the classic Object-Oriented shape interface
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * This interface represents an abstract shape. The shape is described by
+ * a {@link PathIterator}, and has callbacks for determining bounding box,
+ * where points and rectangles lie in relation to the shape, and tracing
+ * the trajectory.
+ *
+ * <p>A point is inside if it is completely inside, or on the boundary and
+ * adjacent points in the increasing x or y direction are completely inside.
+ * Unclosed shapes are considered as implicitly closed when performing
+ * <code>contains</code> or <code>intersects</code>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see PathIterator
+ * @see AffineTransform
+ * @see java.awt.geom.FlatteningPathIterator
+ * @see java.awt.geom.GeneralPath
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface Shape
+{
+ /**
+ * Returns a <code>Rectange</code> that bounds the shape. There is no
+ * guarantee that this is the minimum bounding box, particularly if
+ * the shape overflows the finite integer range of a bound. Generally,
+ * <code>getBounds2D</code> returns a tighter bound.
+ *
+ * @return the shape's bounding box
+ * @see #getBounds2D()
+ */
+ Rectangle getBounds();
+
+ /**
+ * Returns a high precision bounding box of the shape. There is no guarantee
+ * that this is the minimum bounding box, but at least it never overflows.
+ *
+ * @return the shape's bounding box
+ * @see #getBounds()
+ * @since 1.2
+ */
+ Rectangle2D getBounds2D();
+
+ /**
+ * Test if the coordinates lie in the shape.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @return true if (x,y) lies inside the shape
+ * @since 1.2
+ */
+ boolean contains(double x, double y);
+
+ /**
+ * Test if the point lie in the shape.
+ *
+ * @param p the high-precision point
+ * @return true if p lies inside the shape
+ * @throws NullPointerException if p is null
+ * @since 1.2
+ */
+ boolean contains(Point2D p);
+
+ /**
+ * Test if a high-precision rectangle intersects the shape. This is true
+ * if any point in the rectangle is in the shape, with the caveat that the
+ * operation may include high probability estimates when the actual
+ * calculation is prohibitively expensive. The {@link java.awt.geom.Area}
+ * class can be used for more precise answers.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle, undefined results if negative
+ * @param h the height of the rectangle, undefined results if negative
+ * @return true if the rectangle intersects this shape
+ * @see java.awt.geom.Area
+ * @since 1.2
+ */
+ boolean intersects(double x, double y, double w, double h);
+
+ /**
+ * Test if a high-precision rectangle intersects the shape. This is true
+ * if any point in the rectangle is in the shape, with the caveat that the
+ * operation may include high probability estimates when the actual
+ * calculation is prohibitively expensive. The {@link java.awt.geom.Area}
+ * class can be used for more precise answers.
+ *
+ * @param r the rectangle
+ * @return true if the rectangle intersects this shape
+ * @throws NullPointerException if r is null
+ * @see #intersects(double, double, double, double)
+ * @since 1.2
+ */
+ boolean intersects(Rectangle2D r);
+
+ /**
+ * Test if a high-precision rectangle lies completely in the shape. This is
+ * true if all points in the rectangle are in the shape, with the caveat
+ * that the operation may include high probability estimates when the actual
+ * calculation is prohibitively expensive. The {@link java.awt.geom.Area}
+ * class can be used for more precise answers.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle, undefined results if negative
+ * @param h the height of the rectangle, undefined results if negative
+ * @return true if the rectangle is contained in this shape
+ * @see java.awt.geom.Area
+ * @since 1.2
+ */
+ boolean contains(double x, double y, double w, double h);
+
+ /**
+ * Test if a high-precision rectangle lies completely in the shape. This is
+ * true if all points in the rectangle are in the shape, with the caveat
+ * that the operation may include high probability estimates when the actual
+ * calculation is prohibitively expensive. The {@link java.awt.geom.Area}
+ * class can be used for more precise answers.
+ *
+ * @param r the rectangle
+ * @return true if the rectangle is contained in this shape
+ * @throws NullPointerException if r is null
+ * @see #contains(double, double, double, double)
+ * @since 1.2
+ */
+ boolean contains(Rectangle2D r);
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. Each call returns
+ * a new object, independent from others in use. It is recommended, but
+ * not required, that the Shape isolate iterations from future changes to
+ * the boundary, and document this fact.
+ *
+ * @param transform an optional transform to apply to the iterator
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ PathIterator getPathIterator(AffineTransform transform);
+
+ /**
+ * Return an iterator along the flattened version of the shape boundary.
+ * Only SEG_MOVETO, SEG_LINETO, and SEG_CLOSE points are returned in the
+ * iterator. The flatness paramter controls how far points are allowed to
+ * differ from the real curve; although a limit on accuracy may cause this
+ * parameter to be enlarged if needed.
+ *
+ * <p>If the optional transform is provided, the iterator is transformed
+ * accordingly. Each call returns a new object, independent from others in
+ * use. It is recommended, but not required, that the Shape isolate
+ * iterations from future changes to the boundary, and document this fact.
+ *
+ * @param transform an optional transform to apply to the iterator
+ * @param flatness the maximum distance for deviation from the real boundary
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ PathIterator getPathIterator(AffineTransform transform, double flatness);
+} // interface Shape
diff --git a/libjava/classpath/java/awt/Stroke.java b/libjava/classpath/java/awt/Stroke.java
new file mode 100644
index 00000000000..1a4c61cfb1f
--- /dev/null
+++ b/libjava/classpath/java/awt/Stroke.java
@@ -0,0 +1,65 @@
+/* Stroke.java -- a stroked outline of a shape
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This interface allows a Graphics2D to grab the outline of a shape, as if
+ * stroked by a marking pen of appropriate size and shape. The area inked
+ * by the pen is the area of this stroke. Anything in the graphic which
+ * traces an outline will use this stroke, such as <code>drawLine</code>.
+ * Strokes must be immutable, because the graphics object does not clone
+ * them.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see BasicStroke
+ * @see Graphics2D#setStroke(Stroke)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Stroke
+{
+ /**
+ * Returns a shape which outlines the boundary of the given shape, in
+ * effect converting the infinitely thin line into a new shape.
+ *
+ * @param s the shape to stroke
+ * @return the stroked outline shape
+ */
+ Shape createStrokedShape(Shape s);
+} // interface Stroke
diff --git a/libjava/classpath/java/awt/SystemColor.java b/libjava/classpath/java/awt/SystemColor.java
new file mode 100644
index 00000000000..2ead74a0dbd
--- /dev/null
+++ b/libjava/classpath/java/awt/SystemColor.java
@@ -0,0 +1,462 @@
+/* SystemColor.java -- access dynamic system color values
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+import java.io.Serializable;
+
+/**
+ * This class contains the various "system colors" in use by the native
+ * windowing system. The <code>getRGB()</code> method is dynamic on systems
+ * which support dynamic system color changes, and most methods in the
+ * superclass are written to use this dynamic value when reporting colors.
+ * However, the <code>equals()</code> method is not dynamic, and does not
+ * track the actual color of instances in this class. This means that equals
+ * may give surprising results; you are better off relying on getRGB.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class SystemColor extends Color implements Serializable
+{
+ // Implementation note: To be serial compatible with JDK, this class must
+ // violate the semantic meaning of super.value to be one of the
+ // NUM_COLORS constants instead of the actual RGB value. Hence there are
+ // a lot of ugly workarounds in Color and in this class. I would have
+ // designed it MUCH differently, making a separate id field in this class.
+
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4503142729533789064L;
+
+ /**
+ * Array index of the desktop color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #desktop
+ */
+ public static final int DESKTOP = 0;
+
+ /**
+ * Array index of the active caption color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #activeCaption
+ */
+ public static final int ACTIVE_CAPTION = 1;
+
+ /**
+ * Array index of the active caption text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #activeCaptionText
+ */
+ public static final int ACTIVE_CAPTION_TEXT = 2;
+
+ /**
+ * Array index of the active caption border color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #activeCaptionBorder
+ */
+ public static final int ACTIVE_CAPTION_BORDER = 3;
+
+ /**
+ * Array index of the inactive caption color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #inactiveCaption
+ */
+ public static final int INACTIVE_CAPTION = 4;
+
+ /**
+ * Array index of the inactive caption text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #inactiveCaptionText
+ */
+ public static final int INACTIVE_CAPTION_TEXT = 5;
+
+ /**
+ * Array index of the inactive caption border color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #inactiveCaptionBorder
+ */
+ public static final int INACTIVE_CAPTION_BORDER = 6;
+
+ /**
+ * Array index of the window background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #window
+ */
+ public static final int WINDOW = 7;
+
+ /**
+ * Array index of the window border color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #windowBorder
+ */
+ public static final int WINDOW_BORDER = 8;
+
+ /**
+ * Array index of the window text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #windowText
+ */
+ public static final int WINDOW_TEXT = 9;
+
+ /**
+ * Array index of the menu background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #menu
+ */
+ public static final int MENU = 10;
+
+ /**
+ * Array index of the menu text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #menuText
+ */
+ public static final int MENU_TEXT = 11;
+
+ /**
+ * Array index of the text background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #text
+ */
+ public static final int TEXT = 12;
+
+ /**
+ * Array index of the text foreground color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #textText
+ */
+ public static final int TEXT_TEXT = 13;
+
+ /**
+ * Array index of the highlighted text background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #textHighlight
+ */
+ public static final int TEXT_HIGHLIGHT = 14;
+
+ /**
+ * Array index of the highlighted text foreground color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #textHighlightText
+ */
+ public static final int TEXT_HIGHLIGHT_TEXT = 15;
+
+ /**
+ * Array index of the inactive text foreground color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #textInactiveText
+ */
+ public static final int TEXT_INACTIVE_TEXT = 16;
+
+ /**
+ * Array index of the control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #control
+ */
+ public static final int CONTROL = 17;
+
+ /**
+ * Array index of the control text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlText
+ */
+ public static final int CONTROL_TEXT = 18;
+
+ /**
+ * Array index of the highlighted control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlHighlight
+ */
+ public static final int CONTROL_HIGHLIGHT = 19;
+
+ /**
+ * Array index of the lightly highlighted control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlLtHighlight
+ */
+ public static final int CONTROL_LT_HIGHLIGHT = 20;
+
+ /**
+ * Array index of the shadowed control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlShadow
+ */
+ public static final int CONTROL_SHADOW = 21;
+
+ /**
+ * Array index of the darkly shadowed control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlDkShadow
+ */
+ public static final int CONTROL_DK_SHADOW = 22;
+
+ /**
+ * Array index of the scrollbar background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #scrollbar
+ */
+ public static final int SCROLLBAR = 23;
+
+ /**
+ * Array index of the info background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #info
+ */
+ public static final int INFO = 24;
+
+ /**
+ * Array index of the info text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #infoText
+ */
+ public static final int INFO_TEXT = 25;
+
+ /**
+ * The number of system colors. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ */
+ public static final int NUM_COLORS = 26;
+
+ /**
+ * The internal array used to dynamically update <code>getRGB()</code>.
+ */
+ private static final int[] colors = new int[NUM_COLORS];
+
+ /** The desktop color. */
+ public static final SystemColor desktop
+ = new SystemColor(DESKTOP);
+
+ /** The active caption background color. */
+ public static final SystemColor activeCaption
+ = new SystemColor(ACTIVE_CAPTION);
+
+ /** The active caption text color. */
+ public static final SystemColor activeCaptionText
+ = new SystemColor(ACTIVE_CAPTION_TEXT);
+
+ /** The active caption border color. */
+ public static final SystemColor activeCaptionBorder
+ = new SystemColor(ACTIVE_CAPTION_BORDER);
+
+ /** The inactive caption background color. */
+ public static final SystemColor inactiveCaption
+ = new SystemColor(INACTIVE_CAPTION);
+
+ /** The inactive caption text color. */
+ public static final SystemColor inactiveCaptionText
+ = new SystemColor(INACTIVE_CAPTION_TEXT);
+
+ /** The inactive caption border color. */
+ public static final SystemColor inactiveCaptionBorder
+ = new SystemColor(INACTIVE_CAPTION_BORDER);
+
+ /** The window background color. */
+ public static final SystemColor window
+ = new SystemColor(WINDOW);
+
+ /** The window border color. */
+ public static final SystemColor windowBorder
+ = new SystemColor(WINDOW_BORDER);
+
+ /** The window text color. */
+ public static final SystemColor windowText
+ = new SystemColor(WINDOW_TEXT);
+
+ /** The menu background color. */
+ public static final SystemColor menu
+ = new SystemColor(MENU);
+
+ /** The menu text color. */
+ public static final SystemColor menuText
+ = new SystemColor(MENU_TEXT);
+
+ /** The text background color. */
+ public static final SystemColor text
+ = new SystemColor(TEXT);
+
+ /** The text foreground color. */
+ public static final SystemColor textText
+ = new SystemColor(TEXT_TEXT);
+
+ /** The highlighted text background color. */
+ public static final SystemColor textHighlight
+ = new SystemColor(TEXT_HIGHLIGHT);
+
+ /** The highlighted text foreground color. */
+ public static final SystemColor textHighlightText
+ = new SystemColor(TEXT_HIGHLIGHT_TEXT);
+
+ /** The inactive text color. */
+ public static final SystemColor textInactiveText
+ = new SystemColor(TEXT_INACTIVE_TEXT);
+
+ /** The control background color. */
+ public static final SystemColor control
+ = new SystemColor(CONTROL);
+
+ /** The control text color. */
+ public static final SystemColor controlText
+ = new SystemColor(CONTROL_TEXT);
+
+ /** The control highlight color. */
+ public static final SystemColor controlHighlight
+ = new SystemColor(CONTROL_HIGHLIGHT);
+
+ /** The control light highlight color. */
+ public static final SystemColor controlLtHighlight
+ = new SystemColor(CONTROL_LT_HIGHLIGHT);
+
+ /** The control shadow color. */
+ public static final SystemColor controlShadow
+ = new SystemColor(CONTROL_SHADOW);
+
+ /** The control dark shadow color. */
+ public static final SystemColor controlDkShadow
+ = new SystemColor(CONTROL_DK_SHADOW);
+
+ /** The scrollbar color. */
+ public static final SystemColor scrollbar
+ = new SystemColor(SCROLLBAR);
+
+ /** The info text background color. */
+ public static final SystemColor info
+ = new SystemColor(INFO);
+
+ /** The info text foreground color. */
+ public static final SystemColor infoText
+ = new SystemColor(INFO_TEXT);
+
+ /**
+ * Construct a system color which is dynamically updated.
+ *
+ * @param id the color id
+ */
+ private SystemColor(int id)
+ {
+ // Note: See Color#Color(int, boolean) to explain why we use this
+ // particular constructor.
+ super(id, true);
+ }
+
+ /**
+ * Returns the RGB value for this color, in the sRGB color space. The blue
+ * value will be in bits 0-7, green in 8-15, red in 6-23, and the alpha
+ * value (bits 24-31) is 0xff. This is dynamically updated, so it may not
+ * match the results of <code>getRed()</code>, <code>getGreen()</code>, or
+ * <code>getBlue()</code>.
+ *
+ * @return the current RGB value
+ */
+ public int getRGB()
+ {
+ Toolkit.getDefaultToolkit().loadSystemColors(colors);
+ return colors[value] | ALPHA_MASK;
+ }
+
+ /**
+ * Returns a paint context, used for filling areas of a raster scan with
+ * the current value of this system color. Since the system colors may be
+ * dynamically updated, the returned value may not always be the same; but
+ * as the system color is solid, the context does not need any of the
+ * passed parameters to do its job.
+ *
+ * @param cm the requested color model
+ * @param deviceBounds the bounding box in device coordinates, ignored
+ * @param userBounds the bounding box in user coordinates, ignored
+ * @param xform the bounds transformation, ignored
+ * @param hints any rendering hints, ignored
+ * @return a context for painting this solid color
+ */
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds,
+ AffineTransform xform,
+ RenderingHints hints)
+ {
+ Toolkit.getDefaultToolkit().loadSystemColors(colors);
+ int color = colors[value] | ALPHA_MASK;
+ if (context == null || color != context.color || !context.getColorModel().equals(cm))
+ context = new ColorPaintContext(cm,color);
+ return context;
+ }
+
+ /**
+ * Returns a string describing this color. This is in the format
+ * "java.awt.SystemColor[i=" + index + ']', where index is one of the
+ * integer constants of this class. Unfortunately, this description
+ * does not describe the current value of the color; for that you should
+ * use <code>new Color(syscolor.getRGB()).toString()</code>.
+ *
+ * @return a string describing this color
+ */
+ public String toString()
+ {
+ return "java.awt.SystemColor[i=" + value + ']';
+ }
+} // class SystemColor
diff --git a/libjava/classpath/java/awt/TextArea.java b/libjava/classpath/java/awt/TextArea.java
new file mode 100644
index 00000000000..d422d3306d2
--- /dev/null
+++ b/libjava/classpath/java/awt/TextArea.java
@@ -0,0 +1,629 @@
+/* TextArea.java -- A multi-line text entry component
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.KeyEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.TextAreaPeer;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleStateSet;
+
+
+/**
+ * A TextArea is a text component capable of displaying multiple lines
+ * of user-editable text. A TextArea handles its own scrolling and
+ * can display vertical and horizontal scrollbars as navigation aids.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class TextArea extends TextComponent implements java.io.Serializable
+{
+ /**
+ * Display both horiztonal and vertical scroll bars.
+ */
+ public static final int SCROLLBARS_BOTH = 0;
+
+ /**
+ * Display vertical scroll bar only.
+ */
+ public static final int SCROLLBARS_VERTICAL_ONLY = 1;
+
+ /**
+ * Display horizatonal scroll bar only.
+ */
+ public static final int SCROLLBARS_HORIZONTAL_ONLY = 2;
+
+ /**
+ * Do not display scrollbars.
+ */
+ public static final int SCROLLBARS_NONE = 3;
+
+ /**
+ * Serialization constant.
+ */
+ private static final long serialVersionUID = 3692302836626095722L;
+
+ /**
+ * @serial The number of columns used in this text area's preferred
+ * and minimum size calculations.
+ */
+ private int columns;
+
+ /**
+ * @serial The number of rows used in this text area's preferred and
+ * minimum size calculations.
+ */
+ private int rows;
+
+ /**
+ * @serial The scrollbar display policy. One of SCROLLBARS_BOTH,
+ * SCROLLBARS_VERTICAL_ONLY, SCROLLBARS_HORIZONTAL_ONLY,
+ * SCROLLBARS_NONE.
+ */
+ private int scrollbarVisibility;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_text_number;
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that is empty.
+ * Conceptually the <code>TextArea</code> has 0 rows and 0 columns
+ * but its initial bounds are defined by its peer or by the
+ * container in which it is packed. Both horizontal and vertical
+ * scrollbars will be displayed.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea ()
+ {
+ this ("", 0, 0, SCROLLBARS_BOTH);
+ }
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that contains
+ * the specified text. Conceptually the <code>TextArea</code> has 0
+ * rows and 0 columns but its initial bounds are defined by its peer
+ * or by the container in which it is packed. Both horizontal and
+ * veritcal scrollbars will be displayed.
+ *
+ * @param text The text to display in this text area.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea (String text)
+ {
+ this (text, 0, 0, SCROLLBARS_BOTH);
+ }
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that is empty
+ * and can display the specified number of rows and columns of text,
+ * without the need to scroll. Both horizontal and vertical
+ * scrollbars will be displayed.
+ *
+ * @param rows The number of rows in this text area.
+ * @param columns The number of columns in this text area.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea (int rows, int columns)
+ {
+ this ("", rows, columns, SCROLLBARS_BOTH);
+ }
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that can
+ * display the specified number of rows and columns of text, without
+ * the need to scroll. The TextArea initially contains the
+ * specified text.
+ *
+ * @param text The text to display in this text area.
+ * @param rows The number of rows in this text area.
+ * @param columns The number of columns in this text area.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea (String text, int rows, int columns)
+ {
+ this (text, rows, columns, SCROLLBARS_BOTH);
+ }
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that initially
+ * contains the specified text. The TextArea can display the
+ * specified number of rows and columns of text, without the need to
+ * scroll. This constructor allows specification of the scroll bar
+ * display policy.
+ *
+ * @param text The text to display in this text area.
+ * @param rows The number of rows in this text area.
+ * @param columns The number of columns in this text area.
+ * @param scrollbarVisibility The scroll bar display policy. One of
+ * SCROLLBARS_BOTH, SCROLLBARS_VERTICAL_ONLY,
+ * SCROLLBARS_HORIZONTAL_ONLY, SCROLLBARS_NONE.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea (String text, int rows, int columns, int scrollbarVisibility)
+ {
+ super (text);
+
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+
+ if (rows < 0 || columns < 0)
+ throw new IllegalArgumentException ("Bad row or column value");
+
+ if (scrollbarVisibility != SCROLLBARS_BOTH
+ && scrollbarVisibility != SCROLLBARS_VERTICAL_ONLY
+ && scrollbarVisibility != SCROLLBARS_HORIZONTAL_ONLY
+ && scrollbarVisibility != SCROLLBARS_NONE)
+ throw new IllegalArgumentException ("Bad scrollbar visibility value");
+
+ this.rows = rows;
+ this.columns = columns;
+ this.scrollbarVisibility = scrollbarVisibility;
+
+ // TextAreas need to receive tab key events so we override the
+ // default forward and backward traversal key sets.
+ Set s = new HashSet ();
+ s.add (AWTKeyStroke.getAWTKeyStroke (KeyEvent.VK_TAB,
+ KeyEvent.CTRL_DOWN_MASK));
+ setFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, s);
+ s = new HashSet ();
+ s.add (AWTKeyStroke.getAWTKeyStroke (KeyEvent.VK_TAB,
+ KeyEvent.SHIFT_DOWN_MASK
+ | KeyEvent.CTRL_DOWN_MASK));
+ setFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, s);
+ }
+
+ /**
+ * Retrieve the number of columns that this text area would prefer
+ * to display. This value may or may not correspond to the number
+ * of columns that are actually displayed.
+ *
+ * @return The preferred number of columns.
+ */
+ public int getColumns ()
+ {
+ return columns;
+ }
+
+ /**
+ * Set the preferred number of columns for this text area. This
+ * method does not cause the number of columns displayed by the text
+ * area to be updated, if the text area is currently visible.
+ *
+ * @param columns The preferred number of columns.
+ *
+ * @exception IllegalArgumentException If columns is less than zero.
+ */
+ public synchronized void setColumns (int columns)
+ {
+ if (columns < 0)
+ throw new IllegalArgumentException ("Value is less than zero: "
+ + columns);
+
+ this.columns = columns;
+ }
+
+ /**
+ * Retrieve the number of rows that this text area would prefer to
+ * display. This value may or may not correspond to the number of
+ * rows that are actually displayed.
+ *
+ * @return The preferred number of rows.
+ */
+ public int getRows ()
+ {
+ return rows;
+ }
+
+ /**
+ * Set the preferred number of rows for this text area. This method
+ * does not cause the number of columns displayed by the text area
+ * to be updated, if the text area is currently visible.
+ *
+ * @param rows The preferred number of rows.
+ *
+ * @exception IllegalArgumentException If rows is less than zero.
+ */
+ public synchronized void setRows (int rows)
+ {
+ if (rows < 1)
+ throw new IllegalArgumentException ("Value is less than one: " + rows);
+
+ this.rows = rows;
+ }
+
+ /**
+ * Retrieve the minimum size for this text area, considering the
+ * text area's current row and column values. A text area's minimum
+ * size depends on the number of rows and columns of text it would
+ * prefer to display, and on the size of the font in which the text
+ * would be displayed.
+ *
+ * @return The minimum size for this text field.
+ */
+ public Dimension getMinimumSize ()
+ {
+ return getMinimumSize (getRows (), getColumns ());
+ }
+
+ /**
+ * Retrieve the minimum size that this text area would have if its
+ * row and column values were equal to those specified. A text
+ * area's minimum size depends on the number of rows and columns of
+ * text it would prefer to display, and on the size of the font in
+ * which the text would be displayed.
+ *
+ * @param rows The number of rows to use in the minimum size
+ * calculation.
+ * @param columns The number of columns to use in the minimum size
+ * calculation.
+ *
+ * @return The minimum size for this text area.
+ */
+ public Dimension getMinimumSize (int rows, int columns)
+ {
+ return minimumSize (rows, columns);
+ }
+
+ /**
+ * Retrieve the minimum size for this text area, considering the
+ * text area's current row and column values. A text area's minimum
+ * size depends on the number of rows and columns of text it would
+ * prefer to display, and on the size of the font in which the text
+ * would be displayed.
+ *
+ * @return The minimum size for this text area.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize ()</code>.
+ */
+ public Dimension minimumSize ()
+ {
+ return minimumSize (getRows (), getColumns ());
+ }
+
+ /**
+ * Retrieve the minimum size that this text area would have if its
+ * row and column values were equal to those specified. A text
+ * area's minimum size depends on the number of rows and columns of
+ * text it would prefer to display, and on the size of the font in
+ * which the text would be displayed.
+ *
+ * @param rows The number of rows to use in the minimum size
+ * calculation.
+ * @param columns The number of columns to use in the minimum size
+ * calculation.
+ *
+ * @return The minimum size for this text area.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize (int, int)</code>.
+ */
+ public Dimension minimumSize (int rows, int columns)
+ {
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+
+ // Sun returns Dimension (0,0) in this case.
+ if (peer == null)
+ return new Dimension (0, 0);
+
+ return peer.getMinimumSize (rows, columns);
+ }
+
+ /**
+ * Retrieve the preferred size for this text area, considering the
+ * text area's current row and column values. A text area's preferred
+ * size depends on the number of rows and columns of text it would
+ * prefer to display, and on the size of the font in which the text
+ * would be displayed.
+ *
+ * @return The preferred size for this text field.
+ */
+ public Dimension getPreferredSize ()
+ {
+ return getPreferredSize (getRows (), getColumns ());
+ }
+
+ /**
+ * Retrieve the preferred size that this text area would have if its
+ * row and column values were equal to those specified. A text
+ * area's preferred size depends on the number of rows and columns
+ * of text it would prefer to display, and on the size of the font
+ * in which the text would be displayed.
+ *
+ * @param rows The number of rows to use in the preferred size
+ * calculation.
+ * @param columns The number of columns to use in the preferred size
+ * calculation.
+ *
+ * @return The preferred size for this text area.
+ */
+ public Dimension getPreferredSize (int rows, int columns)
+ {
+ return preferredSize (rows, columns);
+ }
+
+ /**
+ * Retrieve the preferred size for this text area, considering the
+ * text area's current row and column values. A text area's preferred
+ * size depends on the number of rows and columns of text it would
+ * prefer to display, and on the size of the font in which the text
+ * would be displayed.
+ *
+ * @return The preferred size for this text field.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize ()</code>.
+ */
+ public Dimension preferredSize ()
+ {
+ return preferredSize (getRows (), getColumns ());
+ }
+
+ /**
+ * Retrieve the preferred size that this text area would have if its
+ * row and column values were equal to those specified. A text
+ * area's preferred size depends on the number of rows and columns
+ * of text it would prefer to display, and on the size of the font
+ * in which the text would be displayed.
+ *
+ * @param rows The number of rows to use in the preferred size
+ * calculation.
+ * @param columns The number of columns to use in the preferred size
+ * calculation.
+ *
+ * @return The preferred size for this text area.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize (int, int)</code>.
+ */
+ public Dimension preferredSize (int rows, int columns)
+ {
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+
+ // Sun returns Dimension (0,0) in this case.
+ if (peer == null)
+ return new Dimension (0, 0);
+
+ return peer.getPreferredSize (rows, columns);
+ }
+
+ /**
+ * Retrieve the scroll bar display policy -- one of SCROLLBARS_BOTH,
+ * SCROLLBARS_VERTICAL_ONLY, SCROLLBARS_HORIZONTAL_ONLY,
+ * SCROLLBARS_NONE.
+ *
+ * @return The current scroll bar display policy.
+ */
+ public int getScrollbarVisibility ()
+ {
+ return scrollbarVisibility;
+ }
+
+ /**
+ * Notify this object that it should create its native peer.
+ */
+ public void addNotify ()
+ {
+ if (getPeer () == null)
+ setPeer ((ComponentPeer) getToolkit().createTextArea (this));
+ }
+
+ /**
+ * Append the specified text to the end of the current text.
+ *
+ * @param str The text to append.
+ */
+ public void append (String str)
+ {
+ appendText (str);
+ }
+
+ /**
+ * Append the specified text to the end of the current text.
+ *
+ * @param str The text to append.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>append ()</code>.
+ */
+ public void appendText (String str)
+ {
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+
+ if (peer != null)
+ peer.insert (str, peer.getText().length ());
+ }
+
+ /**
+ * Insert the specified text at the specified position. The first
+ * character in the text area is at position zero.
+ *
+ * @param str The text to insert.
+ * @param pos The position at which to insert text.
+ */
+ public void insert (String str, int pos)
+ {
+ insertText (str, pos);
+ }
+
+ /**
+ * Insert the specified text at the specified position. The first
+ * character in the text area is at position zero.
+ *
+ * @param str The text to insert.
+ * @param pos The position at which to insert text.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>insert ()</code>.
+ */
+ public void insertText (String str, int pos)
+ {
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+
+ if (peer != null)
+ peer.insert (str, pos);
+ }
+
+ /**
+ * Replace a range of characters with the specified text. The
+ * character at the start position will be replaced, unless start ==
+ * end. The character at the end posistion will not be replaced.
+ * The first character in the text area is at position zero. The
+ * length of the replacement text may differ from the length of the
+ * text that is replaced.
+ *
+ * @param str The new text for the range.
+ * @param start The start position of the replacement range.
+ * @param end The end position of the replacement range.
+ */
+ public void replaceRange (String str, int start, int end)
+ {
+ replaceText (str, start, end);
+ }
+
+ /**
+ * Replace a range of characters with the specified text. The
+ * character at the start position will be replaced, unless start ==
+ * end. The character at the end posistion will not be replaced.
+ * The first character in the text area is at position zero. The
+ * length of the replacement text may differ from the length of the
+ * text that is replaced.
+ *
+ * @param str The new text for the range.
+ * @param start The start position of the replacement range.
+ * @param end The end position of the replacement range.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>replaceRange ()</code>.
+ */
+ public void replaceText (String str, int start, int end)
+ {
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+
+ if (peer != null)
+ peer.replaceRange (str, start, end);
+ }
+
+ /**
+ * Retrieve a debugging string for this text area.
+ *
+ * @return A debugging string for this text area.
+ */
+ protected String paramString ()
+ {
+ String sbVisibility = "";
+
+ switch (scrollbarVisibility)
+ {
+ case SCROLLBARS_BOTH:
+ sbVisibility = "both";
+ break;
+ case SCROLLBARS_VERTICAL_ONLY:
+ sbVisibility = "vertical-only";
+ break;
+ case SCROLLBARS_HORIZONTAL_ONLY:
+ sbVisibility = "horizontal-only";
+ break;
+ case SCROLLBARS_NONE:
+ sbVisibility = "none";
+ break;
+ }
+
+ String editable = "";
+ if (isEditable ())
+ editable = "editable,";
+
+ return getName () + "," + getX () + "," + getY () + "," + getWidth ()
+ + "x" + getHeight () + "," + "text=" + getText () + "," + editable
+ + "selection=" + getSelectionStart () + "-" + getSelectionEnd ()
+ + ",rows=" + rows + ",columns=" + columns + ",scrollbarVisibility="
+ + sbVisibility;
+ }
+
+ /**
+ * Generate a unique name for this text area.
+ *
+ * @return A unique name for this text area.
+ */
+ String generateName ()
+ {
+ return "text" + getUniqueLong ();
+ }
+
+ private static synchronized long getUniqueLong ()
+ {
+ return next_text_number++;
+ }
+
+ protected class AccessibleAWTTextArea extends AccessibleAWTTextComponent
+ {
+ protected AccessibleAWTTextArea()
+ {
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ return super.getAccessibleStateSet();
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>TextArea</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTTextArea();
+ return accessibleContext;
+ }
+}
diff --git a/libjava/classpath/java/awt/TextComponent.java b/libjava/classpath/java/awt/TextComponent.java
new file mode 100644
index 00000000000..9edbd88fe33
--- /dev/null
+++ b/libjava/classpath/java/awt/TextComponent.java
@@ -0,0 +1,739 @@
+/* TextComponent.java -- Widgets for entering text
+ Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
+import java.awt.peer.TextComponentPeer;
+import java.io.Serializable;
+import java.text.BreakIterator;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleText;
+import javax.swing.text.AttributeSet;
+
+/**
+ * This class provides common functionality for widgets than
+ * contain text.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class TextComponent extends Component
+ implements Serializable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+// Constant for serialization
+private static final long serialVersionUID = -2214773872412987419L;
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial Indicates whether or not this component is editable.
+ * This is package-private to avoid an accessor method.
+ */
+boolean editable;
+
+/**
+ * @serial The starting position of the selected text region.
+ * This is package-private to avoid an accessor method.
+ */
+int selectionStart;
+
+/**
+ * @serial The ending position of the selected text region.
+ * This is package-private to avoid an accessor method.
+ */
+int selectionEnd;
+
+/**
+ * @serial The text in the component
+ * This is package-private to avoid an accessor method.
+ */
+String text;
+
+/**
+ * A list of listeners that will receive events from this object.
+ */
+protected transient TextListener textListener;
+
+ protected class AccessibleAWTTextComponent
+ extends AccessibleAWTComponent
+ implements AccessibleText, TextListener
+ {
+ // Constructor
+ // Adds a listener for tracking caret changes
+ public AccessibleAWTTextComponent()
+ {
+ TextComponent.this.addTextListener(this);
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.TEXT;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ // TODO: Docs say PropertyChangeEvent will fire if this state changes.
+ // That means that the event has to fire when editable changes.
+ AccessibleStateSet ss = super.getAccessibleStateSet();
+ if (editable)
+ ss.add(AccessibleState.EDITABLE);
+ return ss;
+ }
+
+ public AccessibleText getAccessibleText()
+ {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getIndexAtPoint(java.awt.Point)
+ */
+ public int getIndexAtPoint(Point point)
+ {
+ return TextComponent.this.getIndexAtPoint(point);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getCharacterBounds(int)
+ */
+ public Rectangle getCharacterBounds(int index)
+ {
+ return TextComponent.this.getCharacterBounds(index);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getCharCount()
+ */
+ public int getCharCount()
+ {
+ return text.length();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getCaretPosition()
+ */
+ public int getCaretPosition()
+ {
+ return TextComponent.this.getCaretPosition();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getAtIndex(int, int)
+ */
+ public String getAtIndex(int part, int index)
+ {
+ if (index < 0 || index >= text.length())
+ return null;
+ BreakIterator it = null;
+ switch (part)
+ {
+ case CHARACTER:
+ return text.substring(index, index + 1);
+ case WORD:
+ it = BreakIterator.getWordInstance();
+ break;
+ case SENTENCE:
+ it = BreakIterator.getSentenceInstance();
+ break;
+ default:
+ return null;
+ }
+ it.setText(text);
+ int start = index;
+ if (!it.isBoundary(index))
+ start = it.preceding(index);
+ int end = it.following(index);
+ if (end == -1)
+ return text.substring(index);
+ else
+ return text.substring(index, end);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getAfterIndex(int, int)
+ */
+ public String getAfterIndex(int part, int index) {
+ if (index < 0 || index >= text.length())
+ return null;
+ BreakIterator it = null;
+ switch (part)
+ {
+ case CHARACTER:
+ return text.substring(index, index + 1);
+ case WORD:
+ it = BreakIterator.getWordInstance();
+ break;
+ case SENTENCE:
+ it = BreakIterator.getSentenceInstance();
+ break;
+ default:
+ return null;
+ }
+ it.setText(text);
+ int start = index;
+ if (!it.isBoundary(index))
+ start = it.following(index);
+ // Make sure there was a complete unit. I.e. if index is in the middle
+ // of a word, return null if there is no word after the that one.
+ if (start == -1)
+ return null;
+ int end = it.following(start);
+ if (end == -1)
+ return text.substring(index);
+ else
+ return text.substring(index, end);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getBeforeIndex(int, int)
+ */
+ public String getBeforeIndex(int part, int index)
+ {
+ if (index < 1 || index >= text.length())
+ return null;
+ BreakIterator it = null;
+ switch (part)
+ {
+ case CHARACTER:
+ return text.substring(index - 1, index);
+ case WORD:
+ it = BreakIterator.getWordInstance();
+ break;
+ case SENTENCE:
+ it = BreakIterator.getSentenceInstance();
+ break;
+ default:
+ return null;
+ }
+ it.setText(text);
+ int end = index;
+ if (!it.isBoundary(index))
+ end = it.preceding(index);
+ // Make sure there was a complete unit. I.e. if index is in the middle
+ // of a word, return null if there is no word before that one.
+ if (end == -1)
+ return null;
+ int start = it.preceding(end);
+ if (start == -1)
+ return text.substring(0, end);
+ else
+ return text.substring(start, end);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getCharacterAttribute(int)
+ */
+ public AttributeSet getCharacterAttribute(int index)
+ {
+ // FIXME: I suspect this really gets filled in by subclasses.
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getSelectionStart()
+ */
+ public int getSelectionStart() {
+ // TODO Auto-generated method stub
+ return selectionStart;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getSelectionEnd()
+ */
+ public int getSelectionEnd()
+ {
+ return selectionEnd;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getSelectedText()
+ */
+ public String getSelectedText()
+ {
+ if (selectionEnd - selectionStart > 0)
+ return text.substring(selectionStart, selectionEnd);
+ else
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.TextListener#textValueChanged(java.awt.event.TextEvent)
+ */
+ public void textValueChanged(TextEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+TextComponent(String text)
+{
+ this.text = text;
+ this.editable = true;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the text in this component
+ *
+ * @return The text in this component.
+ */
+public synchronized String
+getText()
+{
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ text = tcp.getText();
+
+ return(text);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the text in this component to the specified string.
+ *
+ * @param text The new text for this component.
+ */
+public synchronized void
+setText(String text)
+{
+ if (text == null)
+ text = "";
+
+ this.text = text;
+
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ tcp.setText(text);
+ setCaretPosition(0);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string that contains the text that is currently selected.
+ *
+ * @return The currently selected text region.
+ */
+public synchronized String
+getSelectedText()
+{
+ String alltext = getText();
+ int start = getSelectionStart();
+ int end = getSelectionEnd();
+
+ return(alltext.substring(start, end));
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the starting position of the selected text region.
+ * If the text is not selected then caret position is returned.
+ *
+ * @return The starting position of the selected text region.
+ */
+public synchronized int
+getSelectionStart()
+{
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ selectionStart = tcp.getSelectionStart();
+
+ return(selectionStart);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the starting position of the selected region to the
+ * specified value. If the specified value is out of range, then it
+ * will be silently changed to the nearest legal value.
+ *
+ * @param selectionStart The new start position for selected text.
+ */
+public synchronized void
+setSelectionStart(int selectionStart)
+{
+ select(selectionStart, getSelectionEnd());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the ending position of the selected text region.
+ * If the text is not selected, then caret position is returned
+ *
+ * @return The ending position of the selected text region.
+ */
+public synchronized int
+getSelectionEnd()
+{
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ selectionEnd = tcp.getSelectionEnd();
+
+ return(selectionEnd);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the ending position of the selected region to the
+ * specified value. If the specified value is out of range, then it
+ * will be silently changed to the nearest legal value.
+ *
+ * @param selectionEnd The new start position for selected text.
+ */
+public synchronized void
+setSelectionEnd(int selectionEnd)
+{
+ select(getSelectionStart(), selectionEnd);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the selected text range to the text between the
+ * specified start and end positions. Illegal values for these
+ * positions are silently fixed.
+ *
+ * @param selectionStart The new start position for the selected text.
+ * @param selectionEnd The new end position for the selected text.
+ */
+public synchronized void
+select(int selectionStart, int selectionEnd)
+{
+ if (selectionStart < 0)
+ selectionStart = 0;
+
+ if (selectionStart > getText().length())
+ selectionStart = text.length();
+
+ if (selectionEnd > text.length())
+ selectionEnd = text.length();
+
+ if (selectionStart > getSelectionEnd())
+ selectionStart = selectionEnd;
+
+ this.selectionStart = selectionStart;
+ this.selectionEnd = selectionEnd;
+
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ tcp.select(selectionStart, selectionEnd);
+}
+
+/*************************************************************************/
+
+/**
+ * Selects all of the text in the component.
+ */
+public synchronized void
+selectAll()
+{
+ select(0, getText().length());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the current caret position in the text.
+ *
+ * @return The caret position in the text.
+ */
+public synchronized int
+getCaretPosition()
+{
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ return(tcp.getCaretPosition());
+ else
+ return(0);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the caret position to the specified value.
+ *
+ * @param caretPosition The new caret position.
+ *
+ * @exception IllegalArgumentException If the value supplied for position
+ * is less than zero.
+ *
+ * @since 1.1
+ */
+public synchronized void
+setCaretPosition(int caretPosition)
+{
+ if (caretPosition < 0)
+ throw new IllegalArgumentException ();
+
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ tcp.setCaretPosition(caretPosition);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this component's text can be edited.
+ *
+ * @return <code>true</code> if the text can be edited, <code>false</code>
+ * otherwise.
+ */
+public boolean
+isEditable()
+{
+ return(editable);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets whether or not this component's text can be edited.
+ *
+ * @param editable <code>true</code> to enable editing of the text,
+ * <code>false</code> to disable it.
+ */
+public synchronized void
+setEditable(boolean editable)
+{
+ this.editable = editable;
+
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ tcp.setEditable(editable);
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies the component that it should destroy its native peer.
+ */
+public void
+removeNotify()
+{
+ super.removeNotify();
+}
+
+/*************************************************************************/
+
+/**
+ * Adds a new listener to the list of text listeners for this
+ * component.
+ *
+ * @param listener The listener to be added.
+ */
+public synchronized void
+addTextListener(TextListener listener)
+{
+ textListener = AWTEventMulticaster.add(textListener, listener);
+
+ enableEvents(AWTEvent.TEXT_EVENT_MASK);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified listener from the list of listeners
+ * for this component.
+ *
+ * @param listener The listener to remove.
+ */
+public synchronized void
+removeTextListener(TextListener listener)
+{
+ textListener = AWTEventMulticaster.remove(textListener, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event for this component. Text events are
+ * processed by calling the <code>processTextEvent()</code> method.
+ * All other events are passed to the superclass method.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof TextEvent)
+ processTextEvent((TextEvent)event);
+ else
+ super.processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified text event by dispatching it to any listeners
+ * that are registered. Note that this method will only be called
+ * if text event's are enabled. This will be true if there are any
+ * registered listeners, or if the event has been specifically
+ * enabled using <code>enableEvents()</code>.
+ *
+ * @param event The text event to process.
+ */
+protected void
+processTextEvent(TextEvent event)
+{
+ if (textListener != null)
+ textListener.textValueChanged(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= TextEvent.TEXT_LAST
+ && e.id >= TextEvent.TEXT_FIRST
+ && (textListener != null
+ || (eventMask & AWTEvent.TEXT_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string.
+ *
+ * @return A debugging string.
+ */
+protected String
+paramString()
+{
+ return(getClass().getName() + "(text=" + getText() + ")");
+}
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>TextComponent</code>. FooListeners are registered using
+ * the addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ */
+ public EventListener[] getListeners (Class listenerType)
+ {
+ if (listenerType == TextListener.class)
+ return AWTEventMulticaster.getListeners (textListener, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Returns all text listeners registered to this object.
+ */
+ public TextListener[] getTextListeners ()
+ {
+ return (TextListener[]) getListeners (TextListener.class);
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>TextComponent</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTTextComponent();
+ return accessibleContext;
+ }
+
+
+ /*******************************/
+ // Provide AccessibleAWTTextComponent access to several peer functions that
+ // aren't publicly exposed. This is package-private to avoid an accessor
+ // method.
+ synchronized int
+ getIndexAtPoint(Point p)
+ {
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ return tcp.getIndexAtPoint(p.x, p.y);
+ return -1;
+ }
+
+ synchronized Rectangle
+ getCharacterBounds(int i)
+ {
+ TextComponentPeer tcp = (TextComponentPeer)getPeer();
+ if (tcp != null)
+ return tcp.getCharacterBounds(i);
+ return null;
+ }
+
+
+
+
+} // class TextComponent
+
diff --git a/libjava/classpath/java/awt/TextField.java b/libjava/classpath/java/awt/TextField.java
new file mode 100644
index 00000000000..4d62d024aad
--- /dev/null
+++ b/libjava/classpath/java/awt/TextField.java
@@ -0,0 +1,541 @@
+/* TextField.java -- A one line text entry field
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.TextFieldPeer;
+import java.util.EventListener;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This class implements a single line text entry field widget
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class TextField extends TextComponent
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization constant
+private static final long serialVersionUID = -2966288784432217853L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The number of columns in the text entry field.
+ */
+private int columns;
+
+/**
+ * @serial The character that is echoed when doing protected input
+ */
+private char echoChar;
+
+// List of registered ActionListener's for this object.
+private ActionListener action_listeners;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>TextField</code> that is empty
+ * and has one column.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+public
+TextField()
+{
+ this("", 1);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>TextField</code> containing
+ * the specified text. The number of columns will be equal to the
+ * length of the text string.
+ *
+ * @param text The text to display in the field.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+public
+TextField(String text)
+{
+ this(text, text.length());
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>TextField</code> that is empty
+ * and has the specified number of columns.
+ *
+ * @param columns The number of columns in the text field.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+public
+TextField(int columns)
+{
+ this("", columns);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>TextField</code> with the
+ * specified text and number of columns.
+ *
+ * @param text The text to display in the field.
+ * @param columns The number of columns in the field.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+public
+TextField(String text, int columns)
+{
+ super(text);
+ this.columns = columns;
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the number of columns in the field.
+ *
+ * @return The number of columns in the field.
+ */
+public int
+getColumns()
+{
+ return(columns);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the number of columns in this field to the specified value.
+ *
+ * @param columns The new number of columns in the field.
+ *
+ * @exception IllegalArgumentException If columns is less than zero.
+ */
+public synchronized void
+setColumns(int columns)
+{
+ if (columns < 0)
+ throw new IllegalArgumentException("Value is less than zero: " +
+ columns);
+
+ this.columns = columns;
+ // FIXME: How to we communicate this to our peer?
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the character that is echoed to the screen when a text
+ * field is protected (such as when a password is being entered).
+ *
+ * @return The echo character for this text field.
+ */
+public char
+getEchoChar()
+{
+ return(echoChar);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the character that is echoed when protected input such as
+ * a password is displayed.
+ *
+ * @param echoChar The new echo character.
+ */
+public void
+setEchoChar(char echoChar)
+{
+ setEchoCharacter (echoChar);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the character that is echoed when protected input such as
+ * a password is displayed.
+ *
+ * @param echoChar The new echo character.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>setEchoChar()</code>
+ */
+public void
+setEchoCharacter(char echoChar)
+{
+ this.echoChar = echoChar;
+
+ TextFieldPeer peer = (TextFieldPeer) getPeer ();
+ if (peer != null)
+ peer.setEchoChar (echoChar);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this text field has an echo character set
+ * so that characters the user type are not echoed to the screen.
+ *
+ * @return <code>true</code> if an echo character is set,
+ * <code>false</code> otherwise.
+ */
+public boolean
+echoCharIsSet()
+{
+ if (echoChar == '\u0000')
+ return(false);
+ else
+ return(true);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size for this text field.
+ *
+ * @return The minimum size for this text field.
+ */
+public Dimension
+getMinimumSize()
+{
+ return getMinimumSize (getColumns ());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size of a text field with the specified number
+ * of columns.
+ *
+ * @param columns The number of columns to get the minimum size for.
+ */
+public Dimension
+getMinimumSize(int columns)
+{
+ return minimumSize (columns);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size for this text field.
+ *
+ * @return The minimum size for this text field.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize()</code>.
+ */
+public Dimension
+minimumSize()
+{
+ return minimumSize (getColumns ());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the minimum size of a text field with the specified number
+ * of columns.
+ *
+ * @param columns The number of columns to get the minimum size for.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize(int)</code>.
+ */
+public Dimension
+minimumSize(int columns)
+{
+ TextFieldPeer peer = (TextFieldPeer) getPeer ();
+ if (peer == null)
+ return null; // FIXME: What do we do if there is no peer?
+
+ return peer.getMinimumSize (columns);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size for this text field.
+ *
+ * @return The preferred size for this text field.
+ */
+public Dimension
+getPreferredSize()
+{
+ return getPreferredSize (getColumns ());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size of a text field with the specified number
+ * of columns.
+ *
+ * @param columns The number of columns to get the preferred size for.
+ */
+public Dimension
+getPreferredSize(int columns)
+{
+ return preferredSize (columns);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size for this text field.
+ *
+ * @return The preferred size for this text field.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize()</code>.
+ */
+public Dimension
+preferredSize()
+{
+ return preferredSize (getColumns ());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the preferred size of a text field with the specified number
+ * of columns.
+ *
+ * @param columns The number of columns to get the preferred size for.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize(int)</code>.
+ */
+public Dimension
+preferredSize(int columns)
+{
+ TextFieldPeer peer = (TextFieldPeer) getPeer ();
+ if (peer == null)
+ return new Dimension (0, 0);
+
+ return peer.getPreferredSize (columns);
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies this object that it should create its native peer.
+ */
+public void
+addNotify()
+{
+ if (getPeer() != null)
+ return;
+
+ setPeer((ComponentPeer)getToolkit().createTextField(this));
+}
+
+/*************************************************************************/
+
+/**
+ * Addes a new listener to the list of action listeners for this
+ * object.
+ *
+ * @param listener The listener to add to the list.
+ */
+public synchronized void
+addActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+
+ enableEvents(AWTEvent.ACTION_EVENT_MASK);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified listener from the list of action listeners
+ * for this object.
+ *
+ * @param listener The listener to remove from the list.
+ */
+public synchronized void
+removeActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event. If the event is an instance of
+ * <code>ActionEvent</code> then <code>processActionEvent()</code> is
+ * called to process it, otherwise the event is sent to the
+ * superclass.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+ else
+ super.processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes an action event by calling any registered listeners.
+ * Note to subclasses: This method is not called unless action events
+ * are enabled on this object. This will be true if any listeners
+ * are registered, or if action events were specifically enabled
+ * using <code>enableEvents()</code>.
+ *
+ * @param event The event to process.
+ */
+protected void
+processActionEvent(ActionEvent event)
+{
+ if (action_listeners != null)
+ action_listeners.actionPerformed(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ActionEvent.ACTION_LAST
+ && e.id >= ActionEvent.ACTION_FIRST
+ && (action_listeners != null
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debug string for this object.
+ *
+ * @return A debug string for this object.
+ */
+protected String
+paramString()
+{
+ return(getClass().getName() + "(columns=" + getColumns() + ",echoChar=" +
+ getEchoChar());
+}
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>TextField</code>. FooListeners are registered using the
+ * addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public EventListener[] getListeners (Class listenerType)
+ {
+ if (listenerType == ActionListener.class)
+ return AWTEventMulticaster.getListeners (action_listeners, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Return all ActionListeners register to this <code>TextField</code> object
+ * as an array.
+ *
+ * @since 1.4
+ */
+ public ActionListener[] getActionListeners ()
+ {
+ return (ActionListener[]) getListeners (ActionListener.class);
+ }
+
+ protected class AccessibleAWTTextField extends AccessibleAWTTextComponent
+ {
+ protected AccessibleAWTTextField()
+ {
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ return super.getAccessibleStateSet();
+ }
+ }
+
+ public AccessibleContext getAccessibleContext()
+ {
+ return new AccessibleAWTTextField();
+ }
+
+} // class TextField
diff --git a/libjava/classpath/java/awt/TexturePaint.java b/libjava/classpath/java/awt/TexturePaint.java
new file mode 100644
index 00000000000..a12e38463f1
--- /dev/null
+++ b/libjava/classpath/java/awt/TexturePaint.java
@@ -0,0 +1,75 @@
+/* TexturePaint.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+
+/** STUB CLASS ONLY */
+public class TexturePaint implements Paint
+{
+ private final BufferedImage texture;
+ private final Rectangle2D anchor;
+ public TexturePaint(BufferedImage texture, Rectangle2D anchor)
+ {
+ this.texture = texture;
+ this.anchor = anchor;
+ }
+ public BufferedImage getImage()
+ {
+ return texture;
+ }
+ public Rectangle2D getAnchorRect()
+ {
+ return anchor;
+ }
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds,
+ AffineTransform xform,
+ RenderingHints hints)
+ {
+ throw new Error("not implemented");
+ }
+ public int getTransparency()
+ {
+ throw new Error("not implemented");
+ }
+} // class TexturePaint
diff --git a/libjava/classpath/java/awt/Toolkit.java b/libjava/classpath/java/awt/Toolkit.java
new file mode 100644
index 00000000000..c7c6f9f0ecb
--- /dev/null
+++ b/libjava/classpath/java/awt/Toolkit.java
@@ -0,0 +1,995 @@
+/* Toolkit.java -- AWT Toolkit superclass
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+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.event.KeyEvent;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.LightweightPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * The AWT system uses a set of native peer objects to implement its
+ * widgets. These peers are provided by a peer toolkit, that is accessed
+ * via a subclass of this superclass. The system toolkit is retrieved
+ * by the static methods <code>getDefaultToolkit</code>. This method
+ * determines the system toolkit by examining the system property
+ * <code>awt.toolkit</code>. That property is set to the name of the
+ * <code>Toolkit</code> subclass for the specified peer set. If the
+ * <code>awt.toolkit</code> property is not set, then the default
+ * toolkit <code>gnu.java.awt.peer.gtk.GtkToolkit</code> is used. This
+ * toolkit creates its peers using the GTK+ toolkit.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class Toolkit
+{
+ /** The default toolkit name. */
+ private static String default_toolkit_name
+ = gnu.classpath.Configuration.default_awt_peer_toolkit;
+
+ /**
+ * The toolkit in use. Once we load it, we don't ever change it
+ * if the awt.toolkit property is set.
+ */
+ private static Toolkit toolkit;
+
+ /** The toolkit properties. */
+ private static Properties props = new Properties();
+
+ protected final Map desktopProperties = new Properties();
+
+ protected final PropertyChangeSupport desktopPropsSupport
+ = new PropertyChangeSupport(this);
+
+ /**
+ * Default constructor for subclasses.
+ */
+ public Toolkit()
+ {
+ }
+
+ /**
+ * Creates a peer object for the specified <code>Button</code>.
+ *
+ * @param target The <code>Button</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Button</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ButtonPeer createButton(Button target);
+
+ /**
+ * Creates a peer object for the specified <code>TextField</code>.
+ *
+ * @param target The <code>TextField</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>TextField</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract TextFieldPeer createTextField(TextField target);
+
+ /**
+ * Creates a peer object for the specified <code>Label</code>.
+ *
+ * @param target The <code>Label</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Label</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract LabelPeer createLabel(Label target);
+
+ /**
+ * Creates a peer object for the specified <code>List</code>.
+ *
+ * @param target The <code>List</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>List</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ListPeer createList(List target);
+
+ /**
+ * Creates a peer object for the specified <code>Checkbox</code>.
+ *
+ * @param target The <code>Checkbox</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Checkbox</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract CheckboxPeer createCheckbox(Checkbox target);
+
+ /**
+ * Creates a peer object for the specified <code>Scrollbar</code>.
+ *
+ * @param target The <code>Scrollbar</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Scrollbar</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ScrollbarPeer createScrollbar(Scrollbar target);
+
+ /**
+ * Creates a peer object for the specified <code>ScrollPane</code>.
+ *
+ * @param target The <code>ScrollPane</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>ScrollPane</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ScrollPanePeer createScrollPane(ScrollPane target);
+
+ /**
+ * Creates a peer object for the specified <code>TextArea</code>.
+ *
+ * @param target The <code>TextArea</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>TextArea</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract TextAreaPeer createTextArea(TextArea target);
+
+ /**
+ * Creates a peer object for the specified <code>Choice</code>.
+ *
+ * @param target The <code>Choice</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Choice</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ChoicePeer createChoice(Choice target);
+
+ /**
+ * Creates a peer object for the specified <code>Frame</code>.
+ *
+ * @param target The <code>Frame</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Frame</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract FramePeer createFrame(Frame target);
+
+ /**
+ * Creates a peer object for the specified <code>Canvas</code>.
+ *
+ * @param target The <code>Canvas</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Canvas</code> object.
+ */
+ protected abstract CanvasPeer createCanvas(Canvas target);
+
+ /**
+ * Creates a peer object for the specified <code>Panel</code>.
+ *
+ * @param target The <code>Panel</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Panel</code> object.
+ */
+ protected abstract PanelPeer createPanel(Panel target);
+
+ /**
+ * Creates a peer object for the specified <code>Window</code>.
+ *
+ * @param target The <code>Window</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Window</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract WindowPeer createWindow(Window target);
+
+ /**
+ * Creates a peer object for the specified <code>Dialog</code>.
+ *
+ * @param target The dialog to create the peer for
+ *
+ * @return The peer for the specified font name.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract DialogPeer createDialog(Dialog target);
+
+ /**
+ * Creates a peer object for the specified <code>MenuBar</code>.
+ *
+ * @param target The <code>MenuBar</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>MenuBar</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract MenuBarPeer createMenuBar(MenuBar target);
+
+ /**
+ * Creates a peer object for the specified <code>Menu</code>.
+ *
+ * @param target The <code>Menu</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Menu</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract MenuPeer createMenu(Menu target);
+
+ /**
+ * Creates a peer object for the specified <code>PopupMenu</code>.
+ *
+ * @param target The <code>PopupMenu</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>PopupMenu</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract PopupMenuPeer createPopupMenu(PopupMenu target);
+
+ /**
+ * Creates a peer object for the specified <code>MenuItem</code>.
+ *
+ * @param target The <code>MenuItem</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>MenuItem</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract MenuItemPeer createMenuItem(MenuItem target);
+
+ /**
+ * Creates a peer object for the specified <code>FileDialog</code>.
+ *
+ * @param target The <code>FileDialog</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>FileDialog</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract FileDialogPeer createFileDialog(FileDialog target);
+
+ /**
+ * Creates a peer object for the specified <code>CheckboxMenuItem</code>.
+ *
+ * @param target The <code>CheckboxMenuItem</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>CheckboxMenuItem</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract CheckboxMenuItemPeer
+ createCheckboxMenuItem(CheckboxMenuItem target);
+
+ /**
+ * Creates a peer object for the specified <code>Component</code>. The
+ * peer returned by this method is not a native windowing system peer
+ * with its own native window. Instead, this method allows the component
+ * to draw on its parent window as a "lightweight" widget.
+ *
+ * @param target The <code>Component</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Component</code> object.
+ */
+ protected LightweightPeer createComponent(Component target)
+ {
+ return new gnu.java.awt.peer.GLightweightPeer (target);
+ }
+
+ /**
+ * Creates a peer object for the specified font name.
+ *
+ * @param name The font to create the peer for.
+ * @param style The font style to create the peer for.
+ *
+ * @return The peer for the specified font name.
+ *
+ * @deprecated
+ */
+ protected abstract FontPeer getFontPeer(String name, int style);
+
+ /**
+ * Copies the current system colors into the specified array. This is
+ * the interface used by the <code>SystemColor</code> class. Although
+ * this method fills in the array with some default colors a real Toolkit
+ * should override this method and provide real system colors for the
+ * native GUI platform.
+ *
+ * @param systemColors The array to copy the system colors into.
+ * It must be at least 26 elements.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ *
+ * @see java.awt.SystemColor
+ */
+ protected void loadSystemColors(int systemColors[])
+ {
+ systemColors[SystemColor.DESKTOP] = 0xFF005C5C;
+ systemColors[SystemColor.ACTIVE_CAPTION] = 0xFF000080;
+ systemColors[SystemColor.ACTIVE_CAPTION_TEXT] = 0xFFFFFFFF;
+ systemColors[SystemColor.ACTIVE_CAPTION_BORDER] = 0xFFC0C0C0;
+ systemColors[SystemColor.INACTIVE_CAPTION] = 0xFF808080;
+ systemColors[SystemColor.INACTIVE_CAPTION_TEXT] = 0xFFC0C0C0;
+ systemColors[SystemColor.INACTIVE_CAPTION_BORDER] = 0xFFC0C0C0;
+ systemColors[SystemColor.WINDOW] = 0xFFFFFFFF;
+ systemColors[SystemColor.WINDOW_BORDER] = 0xFF000000;
+ systemColors[SystemColor.WINDOW_TEXT] = 0xFF000000;
+ systemColors[SystemColor.MENU] = 0xFFC0C0C0;
+ systemColors[SystemColor.MENU_TEXT] = 0xFF000000;
+ systemColors[SystemColor.TEXT] = 0xFFC0C0C0;
+ systemColors[SystemColor.TEXT_TEXT] = 0xFF000000;
+ systemColors[SystemColor.TEXT_HIGHLIGHT] = 0xFF000090;
+ systemColors[SystemColor.TEXT_HIGHLIGHT_TEXT] = 0xFFFFFFFF;
+ systemColors[SystemColor.TEXT_INACTIVE_TEXT] = 0xFF808080;
+ systemColors[SystemColor.CONTROL] = 0xFFC0C0C0;
+ systemColors[SystemColor.CONTROL_TEXT] = 0xFF000000;
+ systemColors[SystemColor.CONTROL_HIGHLIGHT] = 0xFFFFFFFF;
+ systemColors[SystemColor.CONTROL_LT_HIGHLIGHT] = 0xFFE0E0E0;
+ systemColors[SystemColor.CONTROL_SHADOW] = 0xFF808080;
+ systemColors[SystemColor.CONTROL_DK_SHADOW] = 0xFF000000;
+ systemColors[SystemColor.SCROLLBAR] = 0xFFE0E0E0;
+ systemColors[SystemColor.INFO] = 0xFFE0E000;
+ systemColors[SystemColor.INFO_TEXT] = 0xFF000000;
+ }
+
+ /**
+ * @since 1.4
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public void setDynamicLayout(boolean dynamic)
+ {
+ }
+
+ /**
+ * @since 1.4
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected boolean isDynamicLayoutSet()
+ {
+ return false;
+ }
+
+ /**
+ * @since 1.4
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public boolean isDynamicLayoutActive()
+ {
+ return false;
+ }
+
+ /**
+ * Returns the dimensions of the screen in pixels.
+ *
+ * @return The dimensions of the screen in pixels.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public abstract Dimension getScreenSize();
+
+ /**
+ * Returns the screen resolution in dots per square inch.
+ *
+ * @return The screen resolution in dots per square inch.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public abstract int getScreenResolution();
+
+ /**
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ *
+ * @since 1.4
+ */
+ public Insets getScreenInsets(GraphicsConfiguration gc)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the color model of the screen.
+ *
+ * @return The color model of the screen.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public abstract ColorModel getColorModel();
+
+ /**
+ * Returns the names of the available fonts.
+ *
+ * @return The names of the available fonts.
+ *
+ * @deprecated
+ */
+ public abstract String[] getFontList();
+
+ /**
+ * Return the font metrics for the specified font
+ *
+ * @param name The name of the font to return metrics for.
+ *
+ * @return The requested font metrics.
+ *
+ * @deprecated
+ */
+ public abstract FontMetrics getFontMetrics(Font name);
+
+ /**
+ * Flushes any buffered data to the screen so that it is in sync with
+ * what the AWT system has drawn to it.
+ */
+ public abstract void sync();
+
+ /**
+ * Returns an instance of the default toolkit. The default toolkit is
+ * the subclass of <code>Toolkit</code> specified in the system property
+ * <code>awt.toolkit</code>, or <code>gnu.java.awt.peer.gtk.GtkToolkit</code>
+ * if the property is not set.
+ *
+ * @return An instance of the system default toolkit.
+ *
+ * @throws AWTError If the toolkit cannot be loaded.
+ */
+ public static Toolkit getDefaultToolkit()
+ {
+ if (toolkit != null)
+ return toolkit;
+ String toolkit_name = System.getProperty("awt.toolkit",
+ default_toolkit_name);
+ try
+ {
+ Class cls = Class.forName(toolkit_name);
+ Object obj = cls.newInstance();
+ if (!(obj instanceof Toolkit))
+ throw new AWTError(toolkit_name + " is not a subclass of " +
+ "java.awt.Toolkit");
+ toolkit = (Toolkit) obj;
+ return toolkit;
+ }
+ catch (ThreadDeath death)
+ {
+ throw death;
+ }
+ catch (Throwable t)
+ {
+ AWTError e = new AWTError("Cannot load AWT toolkit: " + toolkit_name);
+ throw (AWTError) e.initCause(t);
+ }
+ }
+
+ /**
+ * Returns an image from the specified file, which must be in a
+ * recognized format. Supported formats vary from toolkit to toolkit.
+ *
+ * @return name The name of the file to read the image from.
+ */
+ public abstract Image getImage(String name);
+
+ /**
+ * Returns an image from the specified URL, which must be in a
+ * recognized format. Supported formats vary from toolkit to toolkit.
+ *
+ * @return url The URl to read the image from.
+ */
+ public abstract Image getImage(URL url);
+
+ public abstract Image createImage(String filename);
+
+ public abstract Image createImage(URL url);
+
+ /**
+ * Readies an image to be rendered on the screen. The width and height
+ * values can be set to the default sizes for the image by passing -1
+ * in those parameters.
+ *
+ * @param image The image to prepare for rendering.
+ * @param width The width of the image.
+ * @param height The height of the image.
+ * @param observer The observer to receive events about the preparation
+ * process.
+ *
+ * @return <code>true</code> if the image is already prepared for rendering,
+ * <code>false</code> otherwise.
+ */
+ public abstract boolean prepareImage(Image image, int width, int height,
+ ImageObserver observer);
+
+ /**
+ * Checks the status of specified image as it is being readied for
+ * rendering.
+ *
+ * @param image The image to prepare for rendering.
+ * @param width The width of the image.
+ * @param height The height of the image.
+ * @param observer The observer to receive events about the preparation
+ * process.
+ *
+ * @return A union of the bitmasks from
+ * <code>java.awt.image.ImageObserver</code> that indicates the current
+ * state of the imaging readying process.
+ */
+ public abstract int checkImage(Image image, int width, int height,
+ ImageObserver observer);
+
+ /**
+ * Creates an image using the specified <code>ImageProducer</code>
+ *
+ * @param producer The <code>ImageProducer</code> to create the image from.
+ *
+ * @return The created image.
+ */
+ public abstract Image createImage(ImageProducer producer);
+
+ /**
+ * Creates an image from the specified byte array. The array must be in
+ * a recognized format. Supported formats vary from toolkit to toolkit.
+ *
+ * @param data The raw image data.
+ *
+ * @return The created image.
+ */
+ public Image createImage(byte[] data)
+ {
+ return createImage(data, 0, data.length);
+ }
+
+ /**
+ * Creates an image from the specified portion of the byte array passed.
+ * The array must be in a recognized format. Supported formats vary from
+ * toolkit to toolkit.
+ *
+ * @param data The raw image data.
+ * @param offset The offset into the data where the image data starts.
+ * @param len The length of the image data.
+ *
+ * @return The created image.
+ */
+ public abstract Image createImage(byte[] data, int offset, int len);
+
+ /**
+ * Returns a instance of <code>PrintJob</code> for the specified
+ * arguments.
+ *
+ * @param frame The window initiating the print job.
+ * @param title The print job title.
+ * @param props The print job properties.
+ *
+ * @return The requested print job, or <code>null</code> if the job
+ * was cancelled.
+ *
+ * @exception NullPointerException If frame is null,
+ * or GraphicsEnvironment.isHeadless() returns true.
+ * @exception SecurityException If this thread is not allowed to initiate
+ * a print job request.
+ */
+ public abstract PrintJob getPrintJob(Frame frame, String title,
+ Properties props);
+
+ /**
+ * Returns a instance of <code>PrintJob</code> for the specified
+ * arguments.
+ *
+ * @param frame The window initiating the print job.
+ * @param title The print job title.
+ * @param jobAttr A set of job attributes which will control the print job.
+ * @param pageAttr A set of page attributes which will control the print job.
+ *
+ * @exception NullPointerException If frame is null, and either jobAttr is null
+ * or jobAttr.getDialog() returns JobAttributes.DialogType.NATIVE.
+ * @exception IllegalArgumentException If pageAttrspecifies differing cross
+ * feed and feed resolutions, or when GraphicsEnvironment.isHeadless() returns
+ * true.
+ * @exception SecurityException If this thread is not allowed to initiate
+ * a print job request.
+ *
+ * @since 1.3
+ */
+ public PrintJob getPrintJob(Frame frame, String title,
+ JobAttributes jobAttr, PageAttributes pageAttr)
+ {
+ return null;
+ }
+
+ /**
+ * Causes a "beep" tone to be generated.
+ */
+ public abstract void beep();
+
+ /**
+ * Returns the system clipboard.
+ *
+ * @return THe system clipboard.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public abstract Clipboard getSystemClipboard();
+
+ /**
+ * Gets the singleton instance of the system selection as a Clipboard object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ *
+ * @since 1.4
+ */
+ public Clipboard getSystemSelection()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the accelerator key mask for menu shortcuts. The default is
+ * <code>Event.CTRL_MASK</code>. A toolkit must override this method
+ * to change the default.
+ *
+ * @return The key mask for the menu accelerator key.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public int getMenuShortcutKeyMask()
+ {
+ return Event.CTRL_MASK;
+ }
+
+ /**
+ * Returns whether the given locking key on the keyboard is currently in its
+ * "on" state.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ * @exception IllegalArgumentException If keyCode is not one of the valid keys.
+ * @exception UnsupportedOperationException If the host system doesn't allow
+ * getting the state of this key programmatically, or if the keyboard doesn't
+ * have this key.
+ */
+ public boolean getLockingKeyState(int keyCode)
+ {
+ if (keyCode != KeyEvent.VK_CAPS_LOCK
+ && keyCode != KeyEvent.VK_NUM_LOCK
+ && keyCode != KeyEvent.VK_SCROLL_LOCK)
+ throw new IllegalArgumentException();
+
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Sets the state of the given locking key on the keyboard.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ * @exception IllegalArgumentException If keyCode is not one of the valid keys.
+ * @exception UnsupportedOperationException If the host system doesn't allow
+ * getting the state of this key programmatically, or if the keyboard doesn't
+ * have this key.
+ */
+ public void setLockingKeyState(int keyCode, boolean on)
+ {
+ if (keyCode != KeyEvent.VK_CAPS_LOCK
+ && keyCode != KeyEvent.VK_NUM_LOCK
+ && keyCode != KeyEvent.VK_SCROLL_LOCK)
+ throw new IllegalArgumentException();
+
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the native container object of the specified component. This
+ * method is necessary because the parent component might be a lightweight
+ * component.
+ *
+ * @param component The component to fetch the native container for.
+ *
+ * @return The native container object for this component.
+ */
+ protected static Container getNativeContainer(Component component)
+ {
+ component = component.getParent();
+ while (true)
+ {
+ if (component == null)
+ return null;
+ if (! (component instanceof Container))
+ {
+ component = component.getParent();
+ continue;
+ }
+ if (component.getPeer() instanceof LightweightPeer)
+ {
+ component = component.getParent();
+ continue;
+ }
+ return (Container) component;
+ }
+ }
+
+ /**
+ * Creates a new custom cursor object.
+ *
+ * @exception IndexOutOfBoundsException If the hotSpot values are outside
+ * the bounds of the cursor.
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
+ {
+ // Presumably the only reason this isn't abstract is for backwards
+ // compatibility? FIXME?
+ return null;
+ }
+
+ /**
+ * Returns the supported cursor dimension which is closest to the
+ * desired sizes.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Dimension getBestCursorSize(int preferredWidth, int preferredHeight)
+ {
+ return new Dimension (0,0);
+ }
+
+ /**
+ * Returns the maximum number of colors the Toolkit supports in a custom
+ * cursor palette.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public int getMaximumCursorColors()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns whether Toolkit supports this state for Frames.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ *
+ * @since 1.4
+ */
+ public boolean isFrameStateSupported(int state)
+ {
+ return false;
+ }
+
+ /**
+ * Returns the value of the property with the specified name, or the
+ * default value if the property does not exist.
+ *
+ * @param key The name of the property to retrieve.
+ * @param def The default value of the property.
+ */
+ public static String getProperty(String key, String def)
+ {
+ return props.getProperty(key, def);
+ }
+
+
+ /**
+ * Returns the event queue that is suitable for the calling context.
+ *
+ * <p>Despite the word &#x201c;System&#x201d; in the name of this
+ * method, a toolkit may provide different event queues for each
+ * applet. There is no guarantee that the same queue is shared
+ * system-wide.
+ *
+ * <p>The implementation first checks whether a
+ * SecurityManager has been installed. If so, its {@link
+ * java.lang.SecurityManager#checkAwtEventQueueAccess()} method gets
+ * called. The security manager will throw a SecurityException if it
+ * does not grant the permission to access the event queue.
+ *
+ * <p>Next, the call is delegated to {@link
+ * #getSystemEventQueueImpl()}.
+ *
+ * @return The event queue for this applet (or application).
+ *
+ * @throws SecurityException if a security manager has been
+ * installed, and it does not grant the permission to access the
+ * event queue.
+ */
+ public final EventQueue getSystemEventQueue()
+ {
+ SecurityManager sm;
+
+ sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkAwtEventQueueAccess();
+
+ return getSystemEventQueueImpl();
+ }
+
+
+ /**
+ * Returns the event queue that is suitable for the calling context.
+ *
+ * <p>Despite the word &#x201c;System&#x201d; in the name of this
+ * method, a toolkit may provide different event queues for each
+ * applet. There is no guarantee that the same queue is shared
+ * system-wide.
+ *
+ * <p>No security checks are performed, which is why this method
+ * may only be called by Toolkits.
+ *
+ * @see #getSystemEventQueue()
+ */
+ protected abstract EventQueue getSystemEventQueueImpl();
+
+
+ /**
+ * @since 1.3
+ */
+ public abstract DragSourceContextPeer
+ createDragSourceContextPeer(DragGestureEvent e);
+
+ /**
+ * @since 1.3
+ */
+ public DragGestureRecognizer
+ createDragGestureRecognizer(Class recognizer, DragSource ds,
+ Component comp, int actions,
+ DragGestureListener l)
+ {
+ return null;
+ }
+
+ public final Object getDesktopProperty(String propertyName)
+ {
+ return desktopProperties.get(propertyName);
+ }
+
+ protected final void setDesktopProperty(String name, Object newValue)
+ {
+ Object oldValue = getDesktopProperty(name);
+ desktopProperties.put(name, newValue);
+ desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
+ }
+
+ protected Object lazilyLoadDesktopProperty(String name)
+ {
+ // FIXME - what is this??
+ return null;
+ }
+
+ protected void initializeDesktopProperties()
+ {
+ // Overridden by toolkit implementation?
+ }
+
+ public void addPropertyChangeListener(String name,
+ PropertyChangeListener pcl)
+ {
+ desktopPropsSupport.addPropertyChangeListener(name, pcl);
+ }
+
+ public void removePropertyChangeListener(String name,
+ PropertyChangeListener pcl)
+ {
+ desktopPropsSupport.removePropertyChangeListener(name, pcl);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return desktopPropsSupport.getPropertyChangeListeners();
+ }
+
+ /**
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners(String name)
+ {
+ return desktopPropsSupport.getPropertyChangeListeners(name);
+ }
+
+ public void addAWTEventListener(AWTEventListener listener, long eventMask)
+ {
+ // SecurityManager s = System.getSecurityManager();
+ // if (s != null)
+ // s.checkPermission(AWTPermission("listenToAllAWTEvents"));
+ // FIXME
+ }
+
+ public void removeAWTEventListener(AWTEventListener listener)
+ {
+ // FIXME
+ }
+
+ /**
+ * @since 1.4
+ */
+ public AWTEventListener[] getAWTEventListeners()
+ {
+ return null;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public AWTEventListener[] getAWTEventListeners(long mask)
+ {
+ return null;
+ }
+
+ /**
+ * @since 1.3
+ */
+ public abstract Map mapInputMethodHighlight(InputMethodHighlight highlight);
+} // class Toolkit
diff --git a/libjava/classpath/java/awt/Transparency.java b/libjava/classpath/java/awt/Transparency.java
new file mode 100644
index 00000000000..88858717693
--- /dev/null
+++ b/libjava/classpath/java/awt/Transparency.java
@@ -0,0 +1,67 @@
+/* Transparency.java -- common transparency modes in graphics
+ Copyright (C) 2000, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt;
+
+/**
+ * A common transparency mode for layering graphics.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Transparency
+{
+ /** Image data which is completely opaque, for an alpha value of 1.0. */
+ int OPAQUE = 1;
+
+ /**
+ * Image data which is either completely opaque or transparent, for an
+ * exact integer alpha value.
+ */
+ int BITMASK = 2;
+
+ /** Image data which is translucent, for a non-integer alpha value. */
+ int TRANSLUCENT = 3;
+
+ /**
+ * Return the transparency type.
+ *
+ * @return One of {@link #OPAQUE}, {@link #BITMASK}, or {@link #TRANSLUCENT}.
+ */
+ int getTransparency();
+} // interface Transparency
diff --git a/libjava/classpath/java/awt/Window.java b/libjava/classpath/java/awt/Window.java
new file mode 100644
index 00000000000..e26c4e32fe7
--- /dev/null
+++ b/libjava/classpath/java/awt/Window.java
@@ -0,0 +1,1125 @@
+/* Window.java --
+ Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.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;
+import java.awt.event.WindowStateListener;
+import java.awt.image.BufferStrategy;
+import java.awt.peer.WindowPeer;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.EventListener;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This class represents a top-level window with no decorations.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class Window extends Container implements Accessible
+{
+ private static final long serialVersionUID = 4497834738069338734L;
+
+ // Serialized fields, from Sun's serialization spec.
+ private String warningString = null;
+ private int windowSerializedDataVersion = 0; // FIXME
+ /** @since 1.2 */
+ // private FocusManager focusMgr; // FIXME: what is this?
+ /** @since 1.2 */
+ private int state = 0;
+ /** @since 1.4 */
+ private boolean focusableWindowState = true;
+
+ // A list of other top-level windows owned by this window.
+ private transient Vector ownedWindows = new Vector();
+
+ private transient WindowListener windowListener;
+ private transient WindowFocusListener windowFocusListener;
+ private transient WindowStateListener windowStateListener;
+ private transient GraphicsConfiguration graphicsConfiguration;
+
+ private transient boolean shown;
+
+ // This is package-private to avoid an accessor method.
+ transient Component windowFocusOwner;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_window_number;
+
+ protected class AccessibleAWTWindow extends AccessibleAWTContainer
+ {
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.WINDOW;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (isActive())
+ states.add(AccessibleState.ACTIVE);
+ return states;
+ }
+ }
+
+ /**
+ * This (package access) constructor is used by subclasses that want
+ * to build windows that do not have parents. Eg. toplevel
+ * application frames. Subclasses cannot call super(null), since
+ * null is an illegal argument.
+ */
+ Window()
+ {
+ visible = false;
+ // Windows are the only Containers that default to being focus
+ // cycle roots.
+ focusCycleRoot = true;
+ setLayout(new BorderLayout());
+
+ addWindowFocusListener (new WindowAdapter ()
+ {
+ public void windowGainedFocus (WindowEvent event)
+ {
+ if (windowFocusOwner != null)
+ {
+ // FIXME: move this section and the other similar
+ // sections in Component into a separate method.
+ 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, windowFocusOwner));
+ eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED,
+ false, currentFocusOwner));
+ }
+ else
+ eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED, false));
+ }
+ }
+ }
+ });
+ }
+
+ Window(GraphicsConfiguration gc)
+ {
+ this();
+ graphicsConfiguration = gc;
+ }
+
+ /**
+ * Initializes a new instance of <code>Window</code> with the specified
+ * parent. The window will initially be invisible.
+ *
+ * @param owner The owning <code>Frame</code> of this window.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null; this exception is always
+ * thrown when GraphicsEnvironment.isHeadless returns true.
+ */
+ public Window(Frame owner)
+ {
+ this (owner, owner.getGraphicsConfiguration ());
+ }
+
+ /**
+ * Initializes a new instance of <code>Window</code> with the specified
+ * parent. The window will initially be invisible.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null; this exception is always
+ * thrown when GraphicsEnvironment.isHeadless returns true.
+ *
+ * @since 1.2
+ */
+ public Window(Window owner)
+ {
+ this (owner, owner.getGraphicsConfiguration ());
+ }
+
+ /**
+ * Initializes a new instance of <code>Window</code> with the specified
+ * parent. The window will initially be invisible.
+ *
+ * @exception IllegalArgumentException If owner is null or if gc is not from a
+ * screen device; this exception is always thrown when
+ * GraphicsEnvironment.isHeadless returns true.
+ *
+ * @since 1.3
+ */
+ public Window(Window owner, GraphicsConfiguration gc)
+ {
+ this ();
+
+ synchronized (getTreeLock())
+ {
+ if (owner == null)
+ throw new IllegalArgumentException ("owner must not be null");
+
+ parent = owner;
+ owner.ownedWindows.add(new WeakReference(this));
+ }
+
+ // FIXME: make this text visible in the window.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null && ! s.checkTopLevelWindow(this))
+ warningString = System.getProperty("awt.appletWarning");
+
+ if (gc != null
+ && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
+ throw new IllegalArgumentException ("gc must be from a screen device");
+
+ if (gc == null)
+ graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice()
+ .getDefaultConfiguration();
+ else
+ graphicsConfiguration = gc;
+ }
+
+ GraphicsConfiguration getGraphicsConfigurationImpl()
+ {
+ if (graphicsConfiguration != null)
+ return graphicsConfiguration;
+
+ return super.getGraphicsConfigurationImpl();
+ }
+
+ /**
+ * Creates the native peer for this window.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createWindow(this);
+ super.addNotify();
+ }
+
+ /**
+ * Relays out this window's child components at their preferred size.
+ *
+ * @specnote pack() doesn't appear to be called internally by show(), so
+ * we duplicate some of the functionality.
+ */
+ public void pack()
+ {
+ if (parent != null && !parent.isDisplayable())
+ parent.addNotify();
+ if (peer == null)
+ addNotify();
+
+ setSize(getPreferredSize());
+
+ validate();
+ }
+
+ /**
+ * Shows on-screen this window and any of its owned windows for whom
+ * isVisible returns true.
+ */
+ public void show()
+ {
+ if (parent != null && !parent.isDisplayable())
+ parent.addNotify();
+ if (peer == null)
+ addNotify();
+
+ // Show visible owned windows.
+ synchronized (getTreeLock())
+ {
+ Iterator e = ownedWindows.iterator();
+ while(e.hasNext())
+ {
+ Window w = (Window)(((Reference) e.next()).get());
+ if (w != null)
+ {
+ if (w.isVisible())
+ w.getPeer().setVisible(true);
+ }
+ else
+ // Remove null weak reference from ownedWindows.
+ // Unfortunately this can't be done in the Window's
+ // finalize method because there is no way to guarantee
+ // synchronous access to ownedWindows there.
+ e.remove();
+ }
+ }
+ validate();
+ super.show();
+ toFront();
+
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+ manager.setGlobalFocusedWindow (this);
+
+ if (!shown)
+ {
+ FocusTraversalPolicy policy = getFocusTraversalPolicy ();
+ Component initialFocusOwner = null;
+
+ if (policy != null)
+ initialFocusOwner = policy.getInitialComponent (this);
+
+ if (initialFocusOwner != null)
+ initialFocusOwner.requestFocusInWindow ();
+
+ shown = true;
+ }
+ }
+
+ public void hide()
+ {
+ // Hide visible owned windows.
+ synchronized (getTreeLock ())
+ {
+ Iterator e = ownedWindows.iterator();
+ while(e.hasNext())
+ {
+ Window w = (Window)(((Reference) e.next()).get());
+ if (w != null)
+ {
+ if (w.isVisible() && w.getPeer() != null)
+ w.getPeer().setVisible(false);
+ }
+ else
+ e.remove();
+ }
+ }
+ super.hide();
+ }
+
+ public boolean isDisplayable()
+ {
+ if (super.isDisplayable())
+ return true;
+ return peer != null;
+ }
+
+ /**
+ * Destroys any resources associated with this window. This includes
+ * all components in the window and all owned top-level windows.
+ */
+ public void dispose()
+ {
+ hide();
+
+ synchronized (getTreeLock ())
+ {
+ Iterator e = ownedWindows.iterator();
+ while(e.hasNext())
+ {
+ Window w = (Window)(((Reference) e.next()).get());
+ if (w != null)
+ w.dispose();
+ else
+ // Remove null weak reference from ownedWindows.
+ e.remove();
+ }
+
+ for (int i = 0; i < ncomponents; ++i)
+ component[i].removeNotify();
+ this.removeNotify();
+
+ // Post a WINDOW_CLOSED event.
+ WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
+ getToolkit().getSystemEventQueue().postEvent(we);
+ }
+ }
+
+ /**
+ * Sends this window to the back so that all other windows display in
+ * front of it.
+ */
+ public void toBack()
+ {
+ if (peer != null)
+ {
+ WindowPeer wp = (WindowPeer) peer;
+ wp.toBack();
+ }
+ }
+
+ /**
+ * Brings this window to the front so that it displays in front of
+ * any other windows.
+ */
+ public void toFront()
+ {
+ if (peer != null)
+ {
+ WindowPeer wp = (WindowPeer) peer;
+ wp.toFront();
+ }
+ }
+
+ /**
+ * Returns the toolkit used to create this window.
+ *
+ * @return The toolkit used to create this window.
+ *
+ * @specnote Unlike Component.getToolkit, this implementation always
+ * returns the value of Toolkit.getDefaultToolkit().
+ */
+ public Toolkit getToolkit()
+ {
+ return Toolkit.getDefaultToolkit();
+ }
+
+ /**
+ * Returns the warning string that will be displayed if this window is
+ * popped up by an unsecure applet or application.
+ *
+ * @return The unsecure window warning message.
+ */
+ public final String getWarningString()
+ {
+ return warningString;
+ }
+
+ /**
+ * Returns the locale that this window is configured for.
+ *
+ * @return The locale this window is configured for.
+ */
+ public Locale getLocale()
+ {
+ return locale == null ? Locale.getDefault() : locale;
+ }
+
+ /*
+ /** @since 1.2
+ public InputContext getInputContext()
+ {
+ // FIXME
+ }
+ */
+
+ /**
+ * Sets the cursor for this window to the specifiec cursor.
+ *
+ * @param cursor The new cursor for this window.
+ */
+ public void setCursor(Cursor cursor)
+ {
+ super.setCursor(cursor);
+ }
+
+ public Window getOwner()
+ {
+ return (Window) parent;
+ }
+
+ /** @since 1.2 */
+ public Window[] getOwnedWindows()
+ {
+ Window [] trimmedList;
+ synchronized (getTreeLock ())
+ {
+ // Windows with non-null weak references in ownedWindows.
+ Window [] validList = new Window [ownedWindows.size()];
+
+ Iterator e = ownedWindows.iterator();
+ int numValid = 0;
+ while (e.hasNext())
+ {
+ Window w = (Window)(((Reference) e.next()).get());
+ if (w != null)
+ validList[numValid++] = w;
+ else
+ // Remove null weak reference from ownedWindows.
+ e.remove();
+ }
+
+ if (numValid != validList.length)
+ {
+ trimmedList = new Window [numValid];
+ System.arraycopy (validList, 0, trimmedList, 0, numValid);
+ }
+ else
+ trimmedList = validList;
+ }
+ return trimmedList;
+ }
+
+ /**
+ * Adds the specified listener to the list of <code>WindowListeners</code>
+ * that will receive events for this window.
+ *
+ * @param listener The <code>WindowListener</code> to add.
+ */
+ public synchronized void addWindowListener(WindowListener listener)
+ {
+ windowListener = AWTEventMulticaster.add(windowListener, listener);
+ }
+
+ /**
+ * Removes the specified listener from the list of
+ * <code>WindowListeners</code> that will receive events for this window.
+ *
+ * @param listener The <code>WindowListener</code> to remove.
+ */
+ public synchronized void removeWindowListener(WindowListener listener)
+ {
+ windowListener = AWTEventMulticaster.remove(windowListener, listener);
+ }
+
+ /**
+ * Returns an array of all the window listeners registered on this window.
+ *
+ * @since 1.4
+ */
+ public synchronized WindowListener[] getWindowListeners()
+ {
+ return (WindowListener[])
+ AWTEventMulticaster.getListeners(windowListener,
+ WindowListener.class);
+ }
+
+ /**
+ * Returns an array of all the window focus listeners registered on this
+ * window.
+ *
+ * @since 1.4
+ */
+ public synchronized WindowFocusListener[] getWindowFocusListeners()
+ {
+ return (WindowFocusListener[])
+ AWTEventMulticaster.getListeners(windowFocusListener,
+ WindowFocusListener.class);
+ }
+
+ /**
+ * Returns an array of all the window state listeners registered on this
+ * window.
+ *
+ * @since 1.4
+ */
+ public synchronized WindowStateListener[] getWindowStateListeners()
+ {
+ return (WindowStateListener[])
+ AWTEventMulticaster.getListeners(windowStateListener,
+ WindowStateListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this window.
+ */
+ public void addWindowFocusListener (WindowFocusListener wfl)
+ {
+ windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
+ }
+
+ /**
+ * Adds the specified listener to this window.
+ *
+ * @since 1.4
+ */
+ public void addWindowStateListener (WindowStateListener wsl)
+ {
+ windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);
+ }
+
+ /**
+ * Removes the specified listener from this window.
+ */
+ public void removeWindowFocusListener (WindowFocusListener wfl)
+ {
+ windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
+ }
+
+ /**
+ * Removes the specified listener from this window.
+ *
+ * @since 1.4
+ */
+ public void removeWindowStateListener (WindowStateListener wsl)
+ {
+ windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this Window. FooListeners are registered using the addFooListener
+ * method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ if (listenerType == WindowListener.class)
+ return getWindowListeners();
+ return super.getListeners(listenerType);
+ }
+
+ void dispatchEventImpl(AWTEvent e)
+ {
+ // Make use of event id's in order to avoid multiple instanceof tests.
+ if (e.id <= WindowEvent.WINDOW_LAST
+ && e.id >= WindowEvent.WINDOW_FIRST
+ && (windowListener != null
+ || windowFocusListener != null
+ || windowStateListener != null
+ || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+ }
+
+ /**
+ * Processes the specified event for this window. If the event is an
+ * instance of <code>WindowEvent</code>, then
+ * <code>processWindowEvent()</code> is called to process the event,
+ * otherwise the superclass version of this method is invoked.
+ *
+ * @param evt The event to process.
+ */
+ protected void processEvent(AWTEvent evt)
+ {
+ if (evt instanceof WindowEvent)
+ processWindowEvent((WindowEvent) evt);
+ else
+ super.processEvent(evt);
+ }
+
+ /**
+ * Dispatches this event to any listeners that are listening for
+ * <code>WindowEvents</code> on this window. This method only gets
+ * invoked if it is enabled via <code>enableEvents()</code> or if
+ * a listener has been added.
+ *
+ * @param evt The event to process.
+ */
+ protected void processWindowEvent(WindowEvent evt)
+ {
+ int id = evt.getID();
+
+ if (id == WindowEvent.WINDOW_GAINED_FOCUS
+ || id == WindowEvent.WINDOW_LOST_FOCUS)
+ processWindowFocusEvent (evt);
+ else if (id == WindowEvent.WINDOW_STATE_CHANGED)
+ processWindowStateEvent (evt);
+ else
+ {
+ if (windowListener != null)
+ {
+ switch (evt.getID())
+ {
+ case WindowEvent.WINDOW_ACTIVATED:
+ windowListener.windowActivated(evt);
+ break;
+
+ case WindowEvent.WINDOW_CLOSED:
+ windowListener.windowClosed(evt);
+ break;
+
+ case WindowEvent.WINDOW_CLOSING:
+ windowListener.windowClosing(evt);
+ break;
+
+ case WindowEvent.WINDOW_DEACTIVATED:
+ windowListener.windowDeactivated(evt);
+ break;
+
+ case WindowEvent.WINDOW_DEICONIFIED:
+ windowListener.windowDeiconified(evt);
+ break;
+
+ case WindowEvent.WINDOW_ICONIFIED:
+ windowListener.windowIconified(evt);
+ break;
+
+ case WindowEvent.WINDOW_OPENED:
+ windowListener.windowOpened(evt);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Identifies if this window is active. The active window is a Frame or
+ * Dialog that has focus or owns the active window.
+ *
+ * @return true if active, else false.
+ * @since 1.4
+ */
+ public boolean isActive()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+ return manager.getActiveWindow() == this;
+ }
+
+ /**
+ * Identifies if this window is focused. A window is focused if it is the
+ * focus owner or it contains the focus owner.
+ *
+ * @return true if focused, else false.
+ * @since 1.4
+ */
+ public boolean isFocused()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+ return manager.getFocusedWindow() == this;
+ }
+
+ /**
+ * Returns the child window that has focus if this window is active.
+ * This method returns <code>null</code> if this window is not active
+ * or no children have focus.
+ *
+ * @return The component that has focus, or <code>null</code> if no
+ * component has focus.
+ */
+ public Component getFocusOwner ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ Window activeWindow = manager.getActiveWindow ();
+
+ // The currently-focused Component belongs to the active Window.
+ if (activeWindow == this)
+ return manager.getFocusOwner ();
+ else
+ return windowFocusOwner;
+ }
+
+ /**
+ * Set the focus owner for this window. This method is used to
+ * remember which component was focused when this window lost
+ * top-level focus, so that when it regains top-level focus the same
+ * child component can be refocused.
+ *
+ * @param windowFocusOwner the component in this window that owns
+ * the focus.
+ */
+ void setFocusOwner (Component windowFocusOwner)
+ {
+ this.windowFocusOwner = windowFocusOwner;
+ }
+
+ /**
+ * Post a Java 1.0 event to the event queue.
+ *
+ * @param e The event to post.
+ *
+ * @deprecated
+ */
+ public boolean postEvent(Event e)
+ {
+ return handleEvent (e);
+ }
+
+ /**
+ * Tests whether or not this window is visible on the screen.
+ *
+ * In contrast to the normal behaviour of Container, which is that
+ * a container is showing if its parent is visible and showing, a Window
+ * is even showing, if its parent (i.e. an invisible Frame) is not showing.
+ *
+ * @return <code>true</code> if this window is visible, <code>false</code>
+ * otherwise.
+ */
+ public boolean isShowing()
+ {
+ return isVisible();
+ }
+
+ public void setLocationRelativeTo (Component c)
+ {
+ if (c == null || !c.isShowing ())
+ {
+ int x = 0;
+ int y = 0;
+
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
+ Point center = ge.getCenterPoint ();
+ x = center.x - (width / 2);
+ y = center.y - (height / 2);
+ setLocation (x, y);
+ }
+ // FIXME: handle case where component is non-null.
+ }
+
+ /**
+ * A BltBufferStrategy for windows.
+ */
+ private class WindowBltBufferStrategy extends BltBufferStrategy
+ {
+ /**
+ * Creates a block transfer strategy for this window.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ * @param accelerated true if the buffer should be accelerated,
+ * false otherwise
+ */
+ WindowBltBufferStrategy(int numBuffers, boolean accelerated)
+ {
+ super(numBuffers,
+ new BufferCapabilities(new ImageCapabilities(accelerated),
+ new ImageCapabilities(accelerated),
+ BufferCapabilities.FlipContents.COPIED));
+ }
+ }
+
+ /**
+ * A FlipBufferStrategy for windows.
+ */
+ private class WindowFlipBufferStrategy extends FlipBufferStrategy
+ {
+ /**
+ * Creates a flip buffer strategy for this window.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ *
+ * @throws AWTException if the requested number of buffers is not
+ * supported
+ */
+ WindowFlipBufferStrategy(int numBuffers)
+ throws AWTException
+ {
+ super(numBuffers,
+ new BufferCapabilities(new ImageCapabilities(true),
+ new ImageCapabilities(true),
+ BufferCapabilities.FlipContents.COPIED));
+ }
+ }
+
+ /**
+ * Creates a buffering strategy that manages how this window is
+ * repainted. This method attempts to create the optimum strategy
+ * based on the desired number of buffers. Hardware or software
+ * acceleration may be used.
+ *
+ * createBufferStrategy attempts different levels of optimization,
+ * but guarantees that some strategy with the requested number of
+ * buffers will be created even if it is not optimal. First it
+ * attempts to create a page flipping strategy, then an accelerated
+ * blitting strategy, then an unaccelerated blitting strategy.
+ *
+ * Calling this method causes any existing buffer strategy to be
+ * destroyed.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ *
+ * @throws IllegalArgumentException if requested number of buffers
+ * is less than one
+ * @throws IllegalStateException if this window is not displayable
+ *
+ * @since 1.4
+ */
+ public void createBufferStrategy(int numBuffers)
+ {
+ if (numBuffers < 1)
+ throw new IllegalArgumentException("Window.createBufferStrategy: number"
+ + " of buffers is less than one");
+
+ if (!isDisplayable())
+ throw new IllegalStateException("Window.createBufferStrategy: window is"
+ + " not displayable");
+
+ BufferStrategy newStrategy = null;
+
+ // try a flipping strategy
+ try
+ {
+ newStrategy = new WindowFlipBufferStrategy(numBuffers);
+ }
+ catch (AWTException e)
+ {
+ }
+
+ // fall back to an accelerated blitting strategy
+ if (newStrategy == null)
+ newStrategy = new WindowBltBufferStrategy(numBuffers, true);
+
+ bufferStrategy = newStrategy;
+ }
+
+ /**
+ * Creates a buffering strategy that manages how this window is
+ * repainted. This method attempts to create a strategy based on
+ * the specified capabilities and throws an exception if the
+ * requested strategy is not supported.
+ *
+ * Calling this method causes any existing buffer strategy to be
+ * destroyed.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ * @param caps the requested buffering capabilities
+ *
+ * @throws AWTException if the requested capabilities are not
+ * supported
+ * @throws IllegalArgumentException if requested number of buffers
+ * is less than one or if caps is null
+ *
+ * @since 1.4
+ */
+ public void createBufferStrategy(int numBuffers,
+ BufferCapabilities caps)
+ {
+ if (numBuffers < 1)
+ throw new IllegalArgumentException("Window.createBufferStrategy: number"
+ + " of buffers is less than one");
+
+ if (caps == null)
+ throw new IllegalArgumentException("Window.createBufferStrategy:"
+ + " capabilities object is null");
+
+ // a flipping strategy was requested
+ if (caps.isPageFlipping())
+ {
+ try
+ {
+ bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
+ }
+ catch (AWTException e)
+ {
+ }
+ }
+ else
+ bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
+ }
+
+ /**
+ * Returns the buffer strategy used by the window.
+ *
+ * @return the buffer strategy.
+ * @since 1.4
+ */
+ public BufferStrategy getBufferStrategy()
+ {
+ return bufferStrategy;
+ }
+
+ /**
+ * @since 1.2
+ *
+ * @deprecated
+ */
+ public void applyResourceBundle(ResourceBundle rb)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ /**
+ * @since 1.2
+ *
+ * @deprecated
+ */
+ public void applyResourceBundle(String rbName)
+ {
+ ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
+ ClassLoader.getSystemClassLoader());
+ if (rb != null)
+ applyResourceBundle(rb);
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Window</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTWindow();
+ return accessibleContext;
+ }
+
+ /**
+ * Get graphics configuration. The implementation for Window will
+ * not ask any parent containers, since Window is a toplevel
+ * window and not actually embedded in the parent component.
+ */
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ if (graphicsConfiguration != null) return graphicsConfiguration;
+ if (peer != null) return peer.getGraphicsConfiguration();
+ return null;
+ }
+
+ protected void processWindowFocusEvent(WindowEvent event)
+ {
+ if (windowFocusListener != null)
+ {
+ switch (event.getID ())
+ {
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ windowFocusListener.windowGainedFocus (event);
+ break;
+
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ windowFocusListener.windowLostFocus (event);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected void processWindowStateEvent(WindowEvent event)
+ {
+ if (windowStateListener != null
+ && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
+ windowStateListener.windowStateChanged (event);
+ }
+
+ /**
+ * Returns whether this <code>Window</code> can get the focus or not.
+ *
+ * @since 1.4
+ */
+ public final boolean isFocusableWindow ()
+ {
+ if (getFocusableWindowState () == false)
+ return false;
+
+ if (this instanceof Dialog
+ || this instanceof Frame)
+ return true;
+
+ // FIXME: Implement more possible cases for returning true.
+
+ return false;
+ }
+
+ /**
+ * Returns the value of the focusableWindowState property.
+ *
+ * @since 1.4
+ */
+ public boolean getFocusableWindowState ()
+ {
+ return focusableWindowState;
+ }
+
+ /**
+ * Sets the value of the focusableWindowState property.
+ *
+ * @since 1.4
+ */
+ public void setFocusableWindowState (boolean focusableWindowState)
+ {
+ this.focusableWindowState = focusableWindowState;
+ }
+
+ // setBoundsCallback is needed so that when a user moves a window,
+ // the Window's location can be updated without calling the peer's
+ // setBounds method. When a user moves a window the peer window's
+ // location is updated automatically and the windowing system sends
+ // a message back to the application informing it of its updated
+ // dimensions. We must update the AWT Window class with these new
+ // dimensions. But we don't want to call the peer's setBounds
+ // method, because the peer's dimensions have already been updated.
+ // (Under X, having this method prevents Configure event loops when
+ // moving windows: Component.setBounds -> peer.setBounds ->
+ // postConfigureEvent -> Component.setBounds -> ... In some cases
+ // Configure event loops cause windows to jitter back and forth
+ // continuously).
+ void setBoundsCallback (int x, int y, int w, int h)
+ {
+ if (this.x == x && this.y == y && width == w && height == h)
+ return;
+ invalidate();
+ boolean resized = width != w || height != h;
+ boolean moved = this.x != x || this.y != y;
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ if (resized && isShowing ())
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ if (moved && isShowing ())
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this, ComponentEvent.COMPONENT_MOVED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ /**
+ * Generate a unique name for this window.
+ *
+ * @return A unique name for this window.
+ */
+ String generateName()
+ {
+ return "win" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_window_number++;
+ }
+}
diff --git a/libjava/classpath/java/awt/color/CMMException.java b/libjava/classpath/java/awt/color/CMMException.java
new file mode 100644
index 00000000000..ab328ec8492
--- /dev/null
+++ b/libjava/classpath/java/awt/color/CMMException.java
@@ -0,0 +1,63 @@
+/* CMMException.java -- error in the native CMM
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+/**
+ * Thrown when there is an error in the native CMM.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class CMMException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 5775558044142994965L;
+
+ /**
+ * Create a new instance with a specified detailed error message.
+ *
+ * @param message the message
+ */
+ public CMMException(String message)
+ {
+ super(message);
+ }
+} // class CMMException
diff --git a/libjava/classpath/java/awt/color/ColorSpace.java b/libjava/classpath/java/awt/color/ColorSpace.java
new file mode 100644
index 00000000000..79369da710f
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ColorSpace.java
@@ -0,0 +1,183 @@
+/* ColorSpace.java -- transforms between color spaces
+ Copyright (C) 2000, 2002 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.color;
+
+import java.io.Serializable;
+
+/**
+ * NEEDS DOCUMENTATION
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @since 1.2
+ */
+public abstract class ColorSpace implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -409452704308689724L;
+
+ public static final int TYPE_XYZ = 0;
+ public static final int TYPE_Lab = 1;
+ public static final int TYPE_Luv = 2;
+ public static final int TYPE_YCbCr = 3;
+ public static final int TYPE_Yxy = 4;
+ public static final int TYPE_RGB = 5;
+ public static final int TYPE_GRAY = 6;
+ public static final int TYPE_HSV = 7;
+ public static final int TYPE_HLS = 8;
+ public static final int TYPE_CMYK = 9;
+ // mysterious gap in the enumeration sequenece
+ public static final int TYPE_CMY = 11;
+ public static final int TYPE_2CLR = 12;
+ public static final int TYPE_3CLR = 13;
+ public static final int TYPE_4CLR = 14;
+ public static final int TYPE_5CLR = 15;
+ public static final int TYPE_6CLR = 16;
+ public static final int TYPE_7CLR = 17;
+ public static final int TYPE_8CLR = 18;
+ public static final int TYPE_9CLR = 19;
+ public static final int TYPE_ACLR = 20;
+ public static final int TYPE_BCLR = 21;
+ public static final int TYPE_CCLR = 22;
+ public static final int TYPE_DCLR = 23;
+ public static final int TYPE_ECLR = 24;
+ public static final int TYPE_FCLR = 25;
+
+ public static final int CS_sRGB = 1000;
+ public static final int CS_LINEAR_RGB = 1004;
+ public static final int CS_CIEXYZ = 1001;
+ public static final int CS_PYCC = 1002;
+ public static final int CS_GRAY = 1003;
+
+ private static final int CS_BASE = CS_sRGB;
+ private static final int CS_END = CS_LINEAR_RGB + 1;
+ private static final int CS_COUNT = CS_END - CS_BASE;
+
+ // Instances are lazily instantiated
+ private static final ColorSpace[] INSTANCES = new ColorSpace[CS_COUNT];
+
+ /**
+ * @serial
+ */
+ // Visible in subclass.
+ final int type;
+
+ /**
+ * @serial
+ */
+ // Visible in subclass.
+ final int numComponents;
+
+ protected ColorSpace(int type, int numcomponents)
+ {
+ this.type = type;
+ numComponents = numcomponents;
+ }
+
+ public static ColorSpace getInstance(int colorspace)
+ {
+ if ((colorspace >= CS_BASE) && (colorspace < CS_END))
+ {
+ int instanceIndex = colorspace - CS_BASE;
+ if (INSTANCES[instanceIndex] == null)
+ {
+ ICC_Profile profile = new ICC_Profile(colorspace);
+ INSTANCES[instanceIndex] = new ICC_ColorSpace(profile);
+ }
+ return INSTANCES[instanceIndex];
+ }
+ throw new IllegalArgumentException("unknown/unsupported colorspace");
+ }
+
+ public boolean isCS_sRGB()
+ {
+ return type == CS_sRGB;
+ }
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace into a value in
+ * the default CS_sRGB color space.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at least
+ * the number of components in this ColorSpace.
+ */
+ public abstract float[] toRGB(float[] colorvalue);
+
+ public abstract float[] fromRGB(float[] rgbvalue);
+
+ public abstract float[] toCIEXYZ(float[] colorvalue);
+
+ public abstract float[] fromCIEXYZ(float[] colorvalue);
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public int getNumComponents()
+ {
+ return numComponents;
+ }
+
+ public String getName(int idx)
+ {
+ return "type " + type;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public float getMinValue(int idx)
+ {
+ if (idx < 0 || idx >= numComponents)
+ throw new IllegalArgumentException();
+ return 0;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public float getMaxValue(int idx)
+ {
+ if (idx < 0 || idx >= numComponents)
+ throw new IllegalArgumentException();
+ return 1;
+ }
+} // class ColorSpace
diff --git a/libjava/classpath/java/awt/color/ICC_ColorSpace.java b/libjava/classpath/java/awt/color/ICC_ColorSpace.java
new file mode 100644
index 00000000000..b50048cf94b
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ICC_ColorSpace.java
@@ -0,0 +1,314 @@
+/* ICC_ColorSpace.java -- the canonical color space implementation
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+import gnu.java.awt.color.CieXyzConverter;
+import gnu.java.awt.color.ClutProfileConverter;
+import gnu.java.awt.color.ColorSpaceConverter;
+import gnu.java.awt.color.GrayProfileConverter;
+import gnu.java.awt.color.GrayScaleConverter;
+import gnu.java.awt.color.LinearRGBConverter;
+import gnu.java.awt.color.PyccConverter;
+import gnu.java.awt.color.RgbProfileConverter;
+import gnu.java.awt.color.SrgbConverter;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * ICC_ColorSpace - an implementation of ColorSpace
+ *
+ * While an ICC_Profile class abstracts the data in an ICC profile file
+ * an ICC_ColorSpace performs the color space conversions defined by
+ * an ICC_Profile instance.
+ *
+ * Typically, an ICC_Profile will either be created using getInstance,
+ * either from the built-in colorspaces, or from an ICC profile file.
+ * Then a ICC_Colorspace will be used to perform transforms from the
+ * device colorspace to and from the profile color space.
+ *
+ * The PCS used by ColorSpace is CIE XYZ relative a D50 white point.
+ * (Profiles using a CIE Lab PCS will have their input and output converted
+ * to D50 CIE XYZ accordingly.
+ *
+ * Note that a valid profile may not contain transforms in both directions,
+ * in which case the output may be undefined.
+ * All built-in colorspaces have bidirectional transforms, but developers
+ * using an ICC profile file may want to check the profile class using
+ * the ICC_Profile.getProfileClass() method. Input class profiles are
+ * guaranteed to have transforms to the PCS, output class profiles are
+ * guaranteed to have transforms from the PCS to device space.
+ *
+ * @author Sven de Marothy
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @since 1.2
+ */
+public class ICC_ColorSpace extends ColorSpace
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 3455889114070431483L;
+
+ /**
+ * @serial
+ */
+ private ICC_Profile thisProfile;
+
+ /**
+ * @serial
+ */
+ private float[] minVal;
+
+ /**
+ * @serial
+ */
+ private float[] maxVal;
+
+ /**
+ * @serial
+ */
+ private float[] diffMinMax;
+
+ /**
+ * @serial
+ */
+ private float[] invDiffMinMax;
+
+ /**
+ * @serial
+ */
+ private boolean needScaleInit;
+
+ /**
+ * Tells us if the PCS is CIE LAB (must be CIEXYZ otherwise)
+ */
+ private transient int type;
+ private transient int nComponents;
+ private transient ColorSpaceConverter converter;
+
+ /**
+ * Constructs a new ICC_ColorSpace from an ICC_Profile object.
+ *
+ * @exception IllegalArgumentException If profile is inappropriate for
+ * representing a ColorSpace.
+ */
+ public ICC_ColorSpace(ICC_Profile profile)
+ {
+ super(profile.getColorSpaceType(), profile.getNumComponents());
+
+ converter = getConverter(profile);
+ thisProfile = profile;
+ nComponents = profile.getNumComponents();
+ type = profile.getColorSpaceType();
+ makeArrays();
+ }
+
+ /**
+ * Return the profile
+ */
+ public ICC_Profile getProfile()
+ {
+ return thisProfile;
+ }
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace into a value in
+ * the default CS_sRGB color space.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at least
+ * the number of components in this ColorSpace.
+ */
+ public float[] toRGB(float[] colorvalue)
+ {
+ return converter.toRGB(colorvalue);
+ }
+
+ /**
+ * Transforms a color value assumed to be in the default CS_sRGB color space
+ * into this ColorSpace.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at
+ * least 3.
+ */
+ public float[] fromRGB(float[] rgbvalue)
+ {
+ return converter.fromRGB(rgbvalue);
+ }
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace into the
+ * CS_CIEXYZ conversion color space.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at
+ * least the number of components in this ColorSpace.
+ */
+ public float[] toCIEXYZ(float[] colorvalue)
+ {
+ return converter.toCIEXYZ(colorvalue);
+ }
+
+ /**
+ * Transforms a color value assumed to be in the CS_CIEXYZ conversion color
+ * space into this ColorSpace.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at
+ * least 3.
+ */
+ public float[] fromCIEXYZ(float[] colorvalue)
+ {
+ return converter.fromCIEXYZ(colorvalue);
+ }
+
+ public boolean isCS_sRGB()
+ {
+ return converter instanceof SrgbConverter;
+ }
+
+ /**
+ * Returns the minimum normalized color component value for the specified
+ * component.
+ *
+ * @exception IllegalArgumentException If component is less than 0 or greater
+ * than numComponents - 1.
+ *
+ * @since 1.4
+ */
+ public float getMinValue(int idx)
+ {
+ // FIXME: Not 100% certain of this.
+ if (type == ColorSpace.TYPE_Lab && (idx == 1 || idx == 2))
+ return -128f;
+
+ if (idx < 0 || idx >= nComponents)
+ throw new IllegalArgumentException();
+ return 0;
+ }
+
+ /**
+ * Returns the maximum normalized color component value for the specified
+ * component.
+ *
+ * @exception IllegalArgumentException If component is less than 0 or greater
+ * than numComponents - 1.
+ *
+ * @since 1.4
+ */
+ public float getMaxValue(int idx)
+ {
+ if (type == ColorSpace.TYPE_XYZ && idx >= 0 && idx <= 2)
+ return 1 + 32767 / 32768f;
+ else if (type == ColorSpace.TYPE_Lab)
+ {
+ if (idx == 0)
+ return 100;
+ if (idx == 1 || idx == 2)
+ return 127;
+ }
+ if (idx < 0 || idx >= nComponents)
+ throw new IllegalArgumentException();
+ return 1;
+ }
+
+ /**
+ * Returns a colorspace converter suitable for a given profile
+ */
+ private ColorSpaceConverter getConverter(ICC_Profile profile)
+ {
+ ColorSpaceConverter converter;
+ switch (profile.isPredefined())
+ {
+ case CS_sRGB:
+ converter = new SrgbConverter();
+ break;
+ case CS_CIEXYZ:
+ converter = new CieXyzConverter();
+ break;
+ case CS_GRAY:
+ converter = new GrayScaleConverter();
+ break;
+ case CS_LINEAR_RGB:
+ converter = new LinearRGBConverter();
+ break;
+ case CS_PYCC:
+ converter = new PyccConverter();
+ break;
+ default:
+ if (profile instanceof ICC_ProfileRGB)
+ converter = new RgbProfileConverter((ICC_ProfileRGB) profile);
+ else if (profile instanceof ICC_ProfileGray)
+ converter = new GrayProfileConverter((ICC_ProfileGray) profile);
+ else
+ converter = new ClutProfileConverter(profile);
+ break;
+ }
+ return converter;
+ }
+
+ /**
+ * Serialization compatibility requires these variable to be set,
+ * although we don't use them. Perhaps we should?
+ */
+ private void makeArrays()
+ {
+ minVal = new float[nComponents];
+ maxVal = new float[nComponents];
+
+ invDiffMinMax = diffMinMax = null;
+ for (int i = 0; i < nComponents; i++)
+ {
+ minVal[i] = getMinValue(i);
+ maxVal[i] = getMaxValue(i);
+ }
+ needScaleInit = true;
+ }
+
+ /**
+ * Deserializes the object
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ // set up objects
+ converter = getConverter(thisProfile);
+ nComponents = thisProfile.getNumComponents();
+ type = thisProfile.getColorSpaceType();
+ }
+} // class ICC_ColorSpace
diff --git a/libjava/classpath/java/awt/color/ICC_Profile.java b/libjava/classpath/java/awt/color/ICC_Profile.java
new file mode 100644
index 00000000000..75f55a1dacb
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ICC_Profile.java
@@ -0,0 +1,1244 @@
+/* ICC_Profile.java -- color space profiling
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+import gnu.java.awt.color.ProfileHeader;
+import gnu.java.awt.color.TagEntry;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * ICC Profile - represents an ICC Color profile.
+ * The ICC profile format is a standard file format which maps the transform
+ * from a device color space to a standard Profile Color Space (PCS), which
+ * can either be CIE L*a*b or CIE XYZ.
+ * (With the exception of device link profiles which map from one device space
+ * to another)
+ *
+ * ICC profiles calibrated to specific input/output devices are used when color
+ * fidelity is of importance.
+ *
+ * An instance of ICC_Profile can be created using the getInstance() methods,
+ * either using one of the predefined color spaces enumerated in ColorSpace,
+ * or from an ICC profile file, or from an input stream.
+ *
+ * An ICC_ColorSpace object can then be created to transform color values
+ * through the profile.
+ *
+ * The ICC_Profile class implements the version 2 format specified by
+ * International Color Consortium Specification ICC.1:1998-09,
+ * and its addendum ICC.1A:1999-04, April 1999
+ * (available at www.color.org)
+ *
+ * @author Sven de Marothy
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @since 1.2
+ */
+public class ICC_Profile implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -3938515861990936766L;
+
+ /**
+ * ICC Profile classes
+ */
+ public static final int CLASS_INPUT = 0;
+ public static final int CLASS_DISPLAY = 1;
+ public static final int CLASS_OUTPUT = 2;
+ public static final int CLASS_DEVICELINK = 3;
+ public static final int CLASS_COLORSPACECONVERSION = 4;
+ public static final int CLASS_ABSTRACT = 5;
+ public static final int CLASS_NAMEDCOLOR = 6;
+
+ /**
+ * ICC Profile class signatures
+ */
+ public static final int icSigInputClass = 0x73636e72; // 'scnr'
+ public static final int icSigDisplayClass = 0x6d6e7472; // 'mntr'
+ public static final int icSigOutputClass = 0x70727472; // 'prtr'
+ public static final int icSigLinkClass = 0x6c696e6b; // 'link'
+ public static final int icSigColorSpaceClass = 0x73706163; // 'spac'
+ public static final int icSigAbstractClass = 0x61627374; // 'abst'
+ public static final int icSigNamedColorClass = 0x6e6d636c; // 'nmcl'
+
+ /**
+ * Color space signatures
+ */
+ public static final int icSigXYZData = 0x58595A20; // 'XYZ '
+ public static final int icSigLabData = 0x4C616220; // 'Lab '
+ public static final int icSigLuvData = 0x4C757620; // 'Luv '
+ public static final int icSigYCbCrData = 0x59436272; // 'YCbr'
+ public static final int icSigYxyData = 0x59787920; // 'Yxy '
+ public static final int icSigRgbData = 0x52474220; // 'RGB '
+ public static final int icSigGrayData = 0x47524159; // 'GRAY'
+ public static final int icSigHsvData = 0x48535620; // 'HSV '
+ public static final int icSigHlsData = 0x484C5320; // 'HLS '
+ public static final int icSigCmykData = 0x434D594B; // 'CMYK'
+ public static final int icSigCmyData = 0x434D5920; // 'CMY '
+ public static final int icSigSpace2CLR = 0x32434C52; // '2CLR'
+ public static final int icSigSpace3CLR = 0x33434C52; // '3CLR'
+ public static final int icSigSpace4CLR = 0x34434C52; // '4CLR'
+ public static final int icSigSpace5CLR = 0x35434C52; // '5CLR'
+ public static final int icSigSpace6CLR = 0x36434C52; // '6CLR'
+ public static final int icSigSpace7CLR = 0x37434C52; // '7CLR'
+ public static final int icSigSpace8CLR = 0x38434C52; // '8CLR'
+ public static final int icSigSpace9CLR = 0x39434C52; // '9CLR'
+ public static final int icSigSpaceACLR = 0x41434C52; // 'ACLR'
+ public static final int icSigSpaceBCLR = 0x42434C52; // 'BCLR'
+ public static final int icSigSpaceCCLR = 0x43434C52; // 'CCLR'
+ public static final int icSigSpaceDCLR = 0x44434C52; // 'DCLR'
+ public static final int icSigSpaceECLR = 0x45434C52; // 'ECLR'
+ public static final int icSigSpaceFCLR = 0x46434C52; // 'FCLR'
+
+ /**
+ * Rendering intents
+ */
+ public static final int icPerceptual = 0;
+ public static final int icRelativeColorimetric = 1;
+ public static final int icSaturation = 2;
+ public static final int icAbsoluteColorimetric = 3;
+
+ /**
+ * Tag signatures
+ */
+ public static final int icSigAToB0Tag = 0x41324230; // 'A2B0'
+ public static final int icSigAToB1Tag = 0x41324231; // 'A2B1'
+ public static final int icSigAToB2Tag = 0x41324232; // 'A2B2'
+ public static final int icSigBlueColorantTag = 0x6258595A; // 'bXYZ'
+ public static final int icSigBlueTRCTag = 0x62545243; // 'bTRC'
+ public static final int icSigBToA0Tag = 0x42324130; // 'B2A0'
+ public static final int icSigBToA1Tag = 0x42324131; // 'B2A1'
+ public static final int icSigBToA2Tag = 0x42324132; // 'B2A2'
+ public static final int icSigCalibrationDateTimeTag = 0x63616C74; // 'calt'
+ public static final int icSigCharTargetTag = 0x74617267; // 'targ'
+ public static final int icSigCopyrightTag = 0x63707274; // 'cprt'
+ public static final int icSigCrdInfoTag = 0x63726469; // 'crdi'
+ public static final int icSigDeviceMfgDescTag = 0x646D6E64; // 'dmnd'
+ public static final int icSigDeviceModelDescTag = 0x646D6464; // 'dmdd'
+ public static final int icSigDeviceSettingsTag = 0x64657673; // 'devs'
+ public static final int icSigGamutTag = 0x67616D74; // 'gamt'
+ public static final int icSigGrayTRCTag = 0x6b545243; // 'kTRC'
+ public static final int icSigGreenColorantTag = 0x6758595A; // 'gXYZ'
+ public static final int icSigGreenTRCTag = 0x67545243; // 'gTRC'
+ public static final int icSigLuminanceTag = 0x6C756d69; // 'lumi'
+ public static final int icSigMeasurementTag = 0x6D656173; // 'meas'
+ public static final int icSigMediaBlackPointTag = 0x626B7074; // 'bkpt'
+ public static final int icSigMediaWhitePointTag = 0x77747074; // 'wtpt'
+ public static final int icSigNamedColor2Tag = 0x6E636C32; // 'ncl2'
+ public static final int icSigOutputResponseTag = 0x72657370; // 'resp'
+ public static final int icSigPreview0Tag = 0x70726530; // 'pre0'
+ public static final int icSigPreview1Tag = 0x70726531; // 'pre1'
+ public static final int icSigPreview2Tag = 0x70726532; // 'pre2'
+ public static final int icSigProfileDescriptionTag = 0x64657363; // 'desc'
+ public static final int icSigProfileSequenceDescTag = 0x70736571; // 'pseq'
+ public static final int icSigPs2CRD0Tag = 0x70736430; // 'psd0'
+ public static final int icSigPs2CRD1Tag = 0x70736431; // 'psd1'
+ public static final int icSigPs2CRD2Tag = 0x70736432; // 'psd2'
+ public static final int icSigPs2CRD3Tag = 0x70736433; // 'psd3'
+ public static final int icSigPs2CSATag = 0x70733273; // 'ps2s'
+ public static final int icSigPs2RenderingIntentTag = 0x70733269; // 'ps2i'
+ public static final int icSigRedColorantTag = 0x7258595A; // 'rXYZ'
+ public static final int icSigRedTRCTag = 0x72545243; // 'rTRC'
+ public static final int icSigScreeningDescTag = 0x73637264; // 'scrd'
+ public static final int icSigScreeningTag = 0x7363726E; // 'scrn'
+ public static final int icSigTechnologyTag = 0x74656368; // 'tech'
+ public static final int icSigUcrBgTag = 0x62666420; // 'bfd '
+ public static final int icSigViewingCondDescTag = 0x76756564; // 'vued'
+ public static final int icSigViewingConditionsTag = 0x76696577; // 'view'
+ public static final int icSigChromaticityTag = 0x6368726D; // 'chrm'
+
+ /**
+ * Non-ICC tag 'head' for use in retrieving the header with getData()
+ */
+ public static final int icSigHead = 0x68656164;
+
+ /**
+ * Header offsets
+ */
+ public static final int icHdrSize = 0;
+ public static final int icHdrCmmId = 4;
+ public static final int icHdrVersion = 8;
+ public static final int icHdrDeviceClass = 12;
+ public static final int icHdrColorSpace = 16;
+ public static final int icHdrPcs = 20;
+ public static final int icHdrDate = 24;
+ public static final int icHdrMagic = 36;
+ public static final int icHdrPlatform = 40;
+ public static final int icHdrFlags = 44;
+ public static final int icHdrManufacturer = 48;
+ public static final int icHdrModel = 52;
+ public static final int icHdrAttributes = 56;
+ public static final int icHdrRenderingIntent = 64;
+ public static final int icHdrIlluminant = 68;
+ public static final int icHdrCreator = 80;
+
+ /**
+ *
+ */
+ public static final int icTagType = 0;
+ public static final int icTagReserved = 4;
+ public static final int icCurveCount = 8;
+ public static final int icCurveData = 12;
+ public static final int icXYZNumberX = 8;
+
+ /**
+ * offset of the Tag table
+ */
+ private static final int tagTableOffset = 128;
+
+ /**
+ * @serial
+ */
+ private static final int iccProfileSerializedDataVersion = 1;
+
+ /**
+ * Constants related to generating profiles for
+ * built-in colorspace profiles
+ */
+ /**
+ * Copyright notice to stick into built-in-profile files.
+ */
+ private static final String copyrightNotice = "Generated by GNU Classpath.";
+
+ /**
+ * Resolution of the TRC to use for predefined profiles.
+ * 1024 should suffice.
+ */
+ private static final int TRC_POINTS = 1024;
+
+ /**
+ * CIE 1931 D50 white point (in Lab coordinates)
+ */
+ private static final float[] D50 = { 0.96422f, 1.00f, 0.82521f };
+
+ /**
+ * Color space profile ID
+ * Set to the predefined profile class (e.g. CS_sRGB) if a predefined
+ * color space is used, set to -1 otherwise.
+ * (or if the profile has been modified)
+ */
+ private transient int profileID;
+
+ /**
+ * The profile header data
+ */
+ private transient ProfileHeader header;
+
+ /**
+ * A hashtable containing the profile tags as TagEntry objects
+ */
+ private transient Hashtable tagTable;
+
+ /**
+ * Contructor for predefined colorspaces
+ */
+ ICC_Profile(int profileID)
+ {
+ header = null;
+ tagTable = null;
+ createProfile(profileID);
+ }
+
+ /**
+ * Constructs an ICC_Profile from a header and a table of loaded tags.
+ */
+ ICC_Profile(ProfileHeader h, Hashtable tags) throws IllegalArgumentException
+ {
+ header = h;
+ tagTable = tags;
+ profileID = -1; // Not a predefined color space
+ }
+
+ /**
+ * Constructs an ICC_Profile from a byte array of data.
+ */
+ ICC_Profile(byte[] data) throws IllegalArgumentException
+ {
+ // get header and verify it
+ header = new ProfileHeader(data);
+ header.verifyHeader(data.length);
+ tagTable = createTagTable(data);
+ profileID = -1; // Not a predefined color space
+ }
+
+ /**
+ * Free up the used memory.
+ */
+ protected void finalize()
+ {
+ }
+
+ /**
+ * Returns an ICC_Profile instance from a byte array of profile data.
+ *
+ * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+ * may be returned if appropriate.
+ *
+ * @throws IllegalArgumentException if the profile data is an invalid
+ * v2 profile.
+ *
+ * @param data - the profile data
+ * @return An ICC_Profile object
+ */
+ public static ICC_Profile getInstance(byte[] data)
+ {
+ ProfileHeader header = new ProfileHeader(data);
+
+ // verify it as a correct ICC header, including size
+ header.verifyHeader(data.length);
+
+ Hashtable tags = createTagTable(data);
+
+ if (isRGBProfile(header, tags))
+ return new ICC_ProfileRGB(data);
+ if (isGrayProfile(header, tags))
+ return new ICC_ProfileGray(data);
+
+ return new ICC_Profile(header, tags);
+ }
+
+ /**
+ * Returns an predefined ICC_Profile instance.
+ *
+ * This will construct an ICC_Profile instance from one of the predefined
+ * color spaces in the ColorSpace class. (e.g. CS_sRGB, CS_GRAY, etc)
+ *
+ * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+ * may be returned if appropriate.
+ *
+ * @return An ICC_Profile object
+ */
+ public static ICC_Profile getInstance(int cspace)
+ {
+ if (cspace == ColorSpace.CS_sRGB || cspace == ColorSpace.CS_LINEAR_RGB)
+ return new ICC_ProfileRGB(cspace);
+ if (cspace == ColorSpace.CS_GRAY)
+ return new ICC_ProfileGray(cspace);
+ return new ICC_Profile(cspace);
+ }
+
+ /**
+ * Returns an ICC_Profile instance from an ICC Profile file.
+ *
+ * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+ * may be returned if appropriate.
+ *
+ * @throws IllegalArgumentException if the profile data is an invalid
+ * v2 profile.
+ * @throws IOException if the file could not be read.
+ *
+ * @param filename - the file name of the profile file.
+ * @return An ICC_Profile object
+ */
+ public static ICC_Profile getInstance(String filename)
+ throws IOException
+ {
+ return getInstance(new FileInputStream(filename));
+ }
+
+ /**
+ * Returns an ICC_Profile instance from an InputStream.
+ *
+ * This method can be used for reading ICC profiles embedded in files
+ * which support this. (JPEG and SVG for instance).
+ *
+ * The stream is treated in the following way: The profile header
+ * (128 bytes) is read first, and the header is validated. If the profile
+ * header is valid, it will then attempt to read the rest of the profile
+ * from the stream. The stream is not closed after reading.
+ *
+ * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+ * may be returned if appropriate.
+ *
+ * @throws IllegalArgumentException if the profile data is an invalid
+ * v2 profile.
+ * @throws IOException if the stream could not be read.
+ *
+ * @param in - the input stream to read the profile from.
+ * @return An ICC_Profile object
+ */
+ public static ICC_Profile getInstance(InputStream in)
+ throws IOException
+ {
+ // read the header
+ byte[] headerData = new byte[ProfileHeader.HEADERSIZE];
+ if (in.read(headerData) != ProfileHeader.HEADERSIZE)
+ throw new IllegalArgumentException("Invalid profile header");
+
+ ProfileHeader header = new ProfileHeader(headerData);
+
+ // verify it as a correct ICC header, but do not verify the
+ // size as we are reading from a stream.
+ header.verifyHeader(-1);
+
+ // get the size
+ byte[] data = new byte[header.getSize()];
+ System.arraycopy(headerData, 0, data, 0, ProfileHeader.HEADERSIZE);
+
+ // read the rest
+ if (in.read(data, ProfileHeader.HEADERSIZE,
+ header.getSize() - ProfileHeader.HEADERSIZE) != header.getSize()
+ - ProfileHeader.HEADERSIZE)
+ throw new IOException("Incorrect profile size");
+
+ return getInstance(data);
+ }
+
+ /**
+ * Returns the major version number
+ */
+ public int getMajorVersion()
+ {
+ return header.getMajorVersion();
+ }
+
+ /**
+ * Returns the minor version number.
+ *
+ * Only the least-significant byte contains data, in BCD form:
+ * the least-significant nibble is the BCD bug fix revision,
+ * the most-significant nibble is the BCD minor revision number.
+ *
+ * (E.g. For a v2.1.0 profile this will return <code>0x10</code>)
+ */
+ public int getMinorVersion()
+ {
+ return header.getMinorVersion();
+ }
+
+ /**
+ * Returns the device class of this profile,
+ *
+ * (E.g. CLASS_INPUT for a scanner profile,
+ * CLASS_OUTPUT for a printer)
+ */
+ public int getProfileClass()
+ {
+ return header.getProfileClass();
+ }
+
+ /**
+ * Returns the color space of this profile, in terms
+ * of the color space constants defined in ColorSpace.
+ * (For example, it may be a ColorSpace.TYPE_RGB)
+ */
+ public int getColorSpaceType()
+ {
+ return header.getColorSpace();
+ }
+
+ /**
+ * Returns the color space of this profile's Profile Connection Space (OCS)
+ *
+ * In terms of the color space constants defined in ColorSpace.
+ * This may be TYPE_XYZ or TYPE_Lab
+ */
+ public int getPCSType()
+ {
+ return header.getProfileColorSpace();
+ }
+
+ /**
+ * Writes the profile data to an ICC profile file.
+ * @param filename - The name of the file to write
+ * @throws IOException if the write failed.
+ */
+ public void write(String filename) throws IOException
+ {
+ FileOutputStream out = new FileOutputStream(filename);
+ write(out);
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Writes the profile data in ICC profile file-format to a stream.
+ * This is useful for embedding ICC profiles in file formats which
+ * support this (such as JPEG and SVG).
+ *
+ * The stream is not closed after writing.
+ * @param out - The outputstream to which the profile data should be written
+ * @throws IOException if the write failed.
+ */
+ public void write(OutputStream out) throws IOException
+ {
+ out.write(getData());
+ }
+
+ /**
+ * Returns the data corresponding to this ICC_Profile as a byte array.
+ *
+ * @return The data in a byte array,
+ * where the first element corresponds to first byte of the profile file.
+ */
+ public byte[] getData()
+ {
+ int size = getSize();
+ byte[] data = new byte[size];
+
+ // Header
+ System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE);
+ // # of tags
+ byte[] tt = getTagTable();
+ System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length);
+
+ Enumeration e = tagTable.elements();
+ while (e.hasMoreElements())
+ {
+ TagEntry tag = (TagEntry) e.nextElement();
+ System.arraycopy(tag.getData(), 0,
+ data, tag.getOffset(), tag.getSize());
+ }
+ return data;
+ }
+
+ /**
+ * Returns the ICC profile tag data
+ * The non ICC-tag icSigHead is also permitted to request the header data.
+ *
+ * @param tagSignature The ICC signature of the requested tag
+ * @return A byte array containing the tag data
+ */
+ public byte[] getData(int tagSignature)
+ {
+ if (tagSignature == icSigHead)
+ return header.getData(getSize());
+
+ TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature));
+ if (t == null)
+ return null;
+ return t.getData();
+ }
+
+ /**
+ * Sets the ICC profile tag data.
+ *
+ * Note that an ICC profile can only contain one tag of each type, if
+ * a tag already exists with the given signature, it is replaced.
+ *
+ * @param tagSignature - The signature of the tag to set
+ * @param data - A byte array containing the tag data
+ */
+ public void setData(int tagSignature, byte[] data)
+ {
+ profileID = -1; // Not a predefined color space if modified.
+
+ if (tagSignature == icSigHead)
+ header = new ProfileHeader(data);
+ else
+ {
+ TagEntry t = new TagEntry(tagSignature, data);
+ tagTable.put(t.hashKey(), t);
+ }
+ }
+
+ /**
+ * Get the number of components in the profile's device color space.
+ */
+ public int getNumComponents()
+ {
+ int[] lookup =
+ {
+ ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3,
+ ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1,
+ ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3,
+ ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3,
+ ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3,
+ ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3,
+ ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4,
+ ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6,
+ ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8,
+ ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10,
+ ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12,
+ ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14,
+ ColorSpace.TYPE_FCLR, 15
+ };
+ for (int i = 0; i < lookup.length; i += 2)
+ if (header.getColorSpace() == lookup[i])
+ return lookup[i + 1];
+ return 3; // should never happen.
+ }
+
+ /**
+ * After deserializing we must determine if the class we want
+ * is really one of the more specialized ICC_ProfileRGB or
+ * ICC_ProfileGray classes.
+ */
+ protected Object readResolve() throws ObjectStreamException
+ {
+ if (isRGBProfile(header, tagTable))
+ return new ICC_ProfileRGB(getData());
+ if (isGrayProfile(header, tagTable))
+ return new ICC_ProfileGray(getData());
+ return this;
+ }
+
+ /**
+ * Deserializes an instance
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ String predef = (String) s.readObject();
+ byte[] data = (byte[]) s.readObject();
+
+ if (data != null)
+ {
+ header = new ProfileHeader(data);
+ tagTable = createTagTable(data);
+ profileID = -1; // Not a predefined color space
+ }
+
+ if (predef != null)
+ {
+ predef = predef.intern();
+ if (predef.equals("CS_sRGB"))
+ createProfile(ColorSpace.CS_sRGB);
+ if (predef.equals("CS_LINEAR_RGB"))
+ createProfile(ColorSpace.CS_LINEAR_RGB);
+ if (predef.equals("CS_CIEXYZ"))
+ createProfile(ColorSpace.CS_CIEXYZ);
+ if (predef.equals("CS_GRAY"))
+ createProfile(ColorSpace.CS_GRAY);
+ if (predef.equals("CS_PYCC"))
+ createProfile(ColorSpace.CS_PYCC);
+ }
+ }
+
+ /**
+ * Serializes an instance
+ * The format is a String and a byte array,
+ * The string is non-null if the instance is one of the built-in profiles.
+ * Otherwise the byte array is non-null and represents the profile data.
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ if (profileID == ColorSpace.CS_sRGB)
+ s.writeObject("CS_sRGB");
+ else if (profileID == ColorSpace.CS_LINEAR_RGB)
+ s.writeObject("CS_LINEAR_RGB");
+ else if (profileID == ColorSpace.CS_CIEXYZ)
+ s.writeObject("CS_CIEXYZ");
+ else if (profileID == ColorSpace.CS_GRAY)
+ s.writeObject("CS_GRAY");
+ else if (profileID == ColorSpace.CS_PYCC)
+ s.writeObject("CS_PYCC");
+ else
+ {
+ s.writeObject(null); // null string
+ s.writeObject(getData()); // data
+ return;
+ }
+ s.writeObject(null); // null data
+ }
+
+ /**
+ * Sorts a ICC profile byte array into TagEntry objects stored in
+ * a hash table.
+ */
+ private static Hashtable createTagTable(byte[] data)
+ throws IllegalArgumentException
+ {
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ int nTags = buf.getInt(tagTableOffset);
+
+ Hashtable tagTable = new Hashtable();
+ for (int i = 0; i < nTags; i++)
+ {
+ TagEntry te = new TagEntry(buf.getInt(tagTableOffset
+ + i * TagEntry.entrySize + 4),
+ buf.getInt(tagTableOffset
+ + i * TagEntry.entrySize + 8),
+ buf.getInt(tagTableOffset
+ + i * TagEntry.entrySize + 12),
+ data);
+
+ if (tagTable.put(te.hashKey(), te) != null)
+ throw new IllegalArgumentException("Duplicate tag in profile:" + te);
+ }
+ return tagTable;
+ }
+
+ /**
+ * Returns the total size of the padded, stored data
+ * Note: Tags must be stored on 4-byte aligned offsets.
+ */
+ private int getSize()
+ {
+ int totalSize = ProfileHeader.HEADERSIZE; // size of header
+
+ int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; // size of tag table
+ if ((tagTableSize & 0x0003) != 0)
+ tagTableSize += 4 - (tagTableSize & 0x0003); // pad
+ totalSize += tagTableSize;
+
+ Enumeration e = tagTable.elements();
+ while (e.hasMoreElements())
+ { // tag data
+ int tagSize = ((TagEntry) e.nextElement()).getSize();
+ if ((tagSize & 0x0003) != 0)
+ tagSize += 4 - (tagSize & 0x0003); // pad
+ totalSize += tagSize;
+ }
+ return totalSize;
+ }
+
+ /**
+ * Generates the tag index table
+ */
+ private byte[] getTagTable()
+ {
+ int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
+ if ((tagTableSize & 0x0003) != 0)
+ tagTableSize += 4 - (tagTableSize & 0x0003); // pad
+
+ int offset = 4;
+ int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize;
+ ByteBuffer buf = ByteBuffer.allocate(tagTableSize);
+ buf.putInt(tagTable.size()); // number of tags
+
+ Enumeration e = tagTable.elements();
+ while (e.hasMoreElements())
+ {
+ TagEntry tag = (TagEntry) e.nextElement();
+ buf.putInt(offset, tag.getSignature());
+ buf.putInt(offset + 4, tagOffset);
+ buf.putInt(offset + 8, tag.getSize());
+ tag.setOffset(tagOffset);
+ int tagSize = tag.getSize();
+ if ((tagSize & 0x0003) != 0)
+ tagSize += 4 - (tagSize & 0x0003); // pad
+ tagOffset += tagSize;
+ offset += 12;
+ }
+ return buf.array();
+ }
+
+ /**
+ * Returns if the criteria for an ICC_ProfileRGB are met.
+ * This means:
+ * Color space is TYPE_RGB
+ * (r,g,b)ColorantTags included
+ * (r,g,b)TRCTags included
+ * mediaWhitePointTag included
+ */
+ private static boolean isRGBProfile(ProfileHeader header, Hashtable tags)
+ {
+ if (header.getColorSpace() != ColorSpace.TYPE_RGB)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null)
+ return false;
+ return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
+ }
+
+ /**
+ * Returns if the criteria for an ICC_ProfileGray are met.
+ * This means:
+ * Colorspace is TYPE_GRAY
+ * grayTRCTag included
+ * mediaWhitePointTag included
+ */
+ private static boolean isGrayProfile(ProfileHeader header, Hashtable tags)
+ {
+ if (header.getColorSpace() != ColorSpace.TYPE_GRAY)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null)
+ return false;
+ return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
+ }
+
+ /**
+ * Returns curve data for a 'curv'-type tag
+ * If it's a gamma curve, a single entry will be returned with the
+ * gamma value (including 1.0 for linear response)
+ * Otherwise the TRC table is returned.
+ *
+ * (Package private - used by ICC_ProfileRGB and ICC_ProfileGray)
+ */
+ short[] getCurve(int signature)
+ {
+ byte[] data = getData(signature);
+ short[] curve;
+
+ // can't find tag?
+ if (data == null)
+ return null;
+
+ // not an curve type tag?
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ if (buf.getInt(0) != 0x63757276) // 'curv' type
+ return null;
+ int count = buf.getInt(8);
+ if (count == 0)
+ {
+ curve = new short[1];
+ curve[0] = 0x0100; // 1.00 in u8fixed8
+ return curve;
+ }
+ if (count == 1)
+ {
+ curve = new short[1];
+ curve[0] = buf.getShort(12); // other u8fixed8 gamma
+ return curve;
+ }
+ curve = new short[count];
+ for (int i = 0; i < count; i++)
+ curve[i] = buf.getShort(12 + i * 2);
+ return curve;
+ }
+
+ /**
+ * Returns XYZ tristimulus values for an 'XYZ ' type tag
+ * @return the XYZ values, or null if the tag was not an 'XYZ ' type tag.
+ *
+ * (Package private - used by ICC_ProfileXYZ and ICC_ProfileGray)
+ */
+ float[] getXYZData(int signature)
+ {
+ byte[] data = getData(signature);
+
+ // can't find tag?
+ if (data == null)
+ return null;
+
+ // not an XYZData type tag?
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ if (buf.getInt(0) != icSigXYZData) // 'XYZ ' type
+ return null;
+
+ float[] point = new float[3];
+
+ // get the X,Y,Z tristimulus values
+ point[0] = ((float) buf.getInt(8)) / 65536f;
+ point[1] = ((float) buf.getInt(12)) / 65536f;
+ point[2] = ((float) buf.getInt(16)) / 65536f;
+ return point;
+ }
+
+ /**
+ * Returns the profile ID if it's a predefined profile
+ * Or -1 for a profile loaded from an ICC profile
+ *
+ * (Package private - used by ICC_ColorSpace)
+ */
+ int isPredefined()
+ {
+ return profileID;
+ }
+
+ /**
+ * Creates a tag of XYZ-value type.
+ */
+ private byte[] makeXYZData(float[] values)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(20);
+ buf.putInt(0, icSigXYZData); // 'XYZ '
+ buf.putInt(4, 0);
+ buf.putInt(8, (int) (values[0] * 65536.0));
+ buf.putInt(12, (int) (values[1] * 65536.0));
+ buf.putInt(16, (int) (values[2] * 65536.0));
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of text type
+ */
+ private byte[] makeTextTag(String text)
+ {
+ int length = text.length();
+ ByteBuffer buf = ByteBuffer.allocate(8 + length + 1);
+ byte[] data;
+ try
+ {
+ data = text.getBytes("US-ASCII");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ data = new byte[length]; // shouldn't happen
+ }
+
+ buf.putInt(0, (int) 0x74657874); // 'text'
+ buf.putInt(4, 0);
+ for (int i = 0; i < length; i++)
+ buf.put(8 + i, data[i]);
+ buf.put(8 + length, (byte) 0); // null-terminate
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of textDescriptionType
+ */
+ private byte[] makeDescTag(String text)
+ {
+ int length = text.length();
+ ByteBuffer buf = ByteBuffer.allocate(90 + length + 1);
+ buf.putInt(0, (int) 0x64657363); // 'desc'
+ buf.putInt(4, 0); // reserved
+ buf.putInt(8, length + 1); // ASCII length, including null termination
+ byte[] data;
+
+ try
+ {
+ data = text.getBytes("US-ASCII");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ data = new byte[length]; // shouldn't happen
+ }
+
+ for (int i = 0; i < length; i++)
+ buf.put(12 + i, data[i]);
+ buf.put(12 + length, (byte) 0); // null-terminate
+
+ for (int i = 0; i < 39; i++)
+ buf.putShort(13 + length + (i * 2), (short) 0); // 78 bytes we can ignore
+
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of TRC type (linear curve)
+ */
+ private byte[] makeTRC()
+ {
+ ByteBuffer buf = ByteBuffer.allocate(12);
+ buf.putInt(0, 0x63757276); // 'curv' type
+ buf.putInt(4, 0); // reserved
+ buf.putInt(8, 0);
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of TRC type (single gamma value)
+ */
+ private byte[] makeTRC(float gamma)
+ {
+ short gammaValue = (short) (gamma * 256f);
+ ByteBuffer buf = ByteBuffer.allocate(14);
+ buf.putInt(0, 0x63757276); // 'curv' type
+ buf.putInt(4, 0); // reserved
+ buf.putInt(8, 1);
+ buf.putShort(12, gammaValue); // 1.00 in u8fixed8
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of TRC type (TRC curve points)
+ */
+ private byte[] makeTRC(float[] trc)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length);
+ buf.putInt(0, 0x63757276); // 'curv' type
+ buf.putInt(4, 0); // reserved
+ buf.putInt(8, trc.length); // number of points
+
+ // put the curve values
+ for (int i = 0; i < trc.length; i++)
+ buf.putShort(12 + i * 2, (short) (trc[i] * 65535f));
+
+ return buf.array();
+ }
+
+ /**
+ * Creates an identity color lookup table.
+ */
+ private byte[] makeIdentityClut()
+ {
+ final int nIn = 3;
+ final int nOut = 3;
+ final int nInEntries = 256;
+ final int nOutEntries = 256;
+ final int gridpoints = 16;
+
+ // gridpoints**nIn
+ final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints;
+ final int totalSize = clutSize + 2 * nInEntries * nIn
+ + 2 * nOutEntries * nOut + 52;
+
+ ByteBuffer buf = ByteBuffer.allocate(totalSize);
+ buf.putInt(0, 0x6D667432); // 'mft2'
+ buf.putInt(4, 0); // reserved
+ buf.put(8, (byte) nIn); // number input channels
+ buf.put(9, (byte) nOut); // number output channels
+ buf.put(10, (byte) gridpoints); // number gridpoints
+ buf.put(11, (byte) 0); // padding
+
+ // identity matrix
+ buf.putInt(12, 65536); // = 1 in s15.16 fixed point
+ buf.putInt(16, 0);
+ buf.putInt(20, 0);
+ buf.putInt(24, 0);
+ buf.putInt(28, 65536);
+ buf.putInt(32, 0);
+ buf.putInt(36, 0);
+ buf.putInt(40, 0);
+ buf.putInt(44, 65536);
+
+ buf.putShort(48, (short) nInEntries); // input table entries
+ buf.putShort(50, (short) nOutEntries); // output table entries
+
+ // write the linear input channels, unsigned 16.16 fixed point,
+ // from 0.0 to FF.FF
+ for (int channel = 0; channel < 3; channel++)
+ for (int i = 0; i < nInEntries; i++)
+ {
+ short n = (short) ((i << 8) | i); // assumes 256 entries
+ buf.putShort(52 + (channel * nInEntries + i) * 2, n);
+ }
+ int clutOffset = 52 + nInEntries * nIn * 2;
+
+ for (int x = 0; x < gridpoints; x++)
+ for (int y = 0; y < gridpoints; y++)
+ for (int z = 0; z < gridpoints; z++)
+ {
+ int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut
+ + x * gridpoints * gridpoints * 2 * nOut;
+ double xf = ((double) x) / ((double) gridpoints - 1.0);
+ double yf = ((double) y) / ((double) gridpoints - 1.0);
+ double zf = ((double) z) / ((double) gridpoints - 1.0);
+ buf.putShort(offset, (short) (xf * 65535.0));
+ buf.putShort(offset + 2, (short) (yf * 65535.0));
+ buf.putShort(offset + 4, (short) (zf * 65535.0));
+ }
+
+ for (int channel = 0; channel < 3; channel++)
+ for (int i = 0; i < nOutEntries; i++)
+ {
+ short n = (short) ((i << 8) | i); // assumes 256 entries
+ buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2,
+ n);
+ }
+
+ return buf.array();
+ }
+
+ /**
+ * Creates profile data corresponding to the built-in colorspaces.
+ */
+ private void createProfile(int colorSpace) throws IllegalArgumentException
+ {
+ this.profileID = colorSpace;
+ header = new ProfileHeader();
+ tagTable = new Hashtable();
+
+ switch (colorSpace)
+ {
+ case ColorSpace.CS_sRGB:
+ createRGBProfile();
+ return;
+ case ColorSpace.CS_LINEAR_RGB:
+ createLinearRGBProfile();
+ return;
+ case ColorSpace.CS_CIEXYZ:
+ createCIEProfile();
+ return;
+ case ColorSpace.CS_GRAY:
+ createGrayProfile();
+ return;
+ case ColorSpace.CS_PYCC:
+ createPyccProfile();
+ return;
+ default:
+ throw new IllegalArgumentException("Not a predefined color space!");
+ }
+ }
+
+ /**
+ * Creates an ICC_Profile representing the sRGB color space
+ */
+ private void createRGBProfile()
+ {
+ header.setColorSpace( ColorSpace.TYPE_RGB );
+ header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
+ ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+ float[] r = { 1f, 0f, 0f };
+ float[] g = { 0f, 1f, 0f };
+ float[] b = { 0f, 0f, 1f };
+ float[] black = { 0f, 0f, 0f };
+
+ // CIE 1931 D50 white point (in Lab coordinates)
+ float[] white = D50;
+
+ // Get tristimulus values (matrix elements)
+ r = cs.toCIEXYZ(r);
+ g = cs.toCIEXYZ(g);
+ b = cs.toCIEXYZ(b);
+
+ // Generate the sRGB TRC curve, this is the linear->nonlinear
+ // RGB transform.
+ cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB));
+ float[] points = new float[TRC_POINTS];
+ float[] in = new float[3];
+ for (int i = 0; i < TRC_POINTS; i++)
+ {
+ in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1);
+ in = cs.fromRGB(in);
+ // Note this value is the same for all components.
+ points[i] = in[0];
+ }
+
+ setData(icSigRedColorantTag, makeXYZData(r));
+ setData(icSigGreenColorantTag, makeXYZData(g));
+ setData(icSigBlueColorantTag, makeXYZData(b));
+ setData(icSigMediaWhitePointTag, makeXYZData(white));
+ setData(icSigMediaBlackPointTag, makeXYZData(black));
+ setData(icSigRedTRCTag, makeTRC(points));
+ setData(icSigGreenTRCTag, makeTRC(points));
+ setData(icSigBlueTRCTag, makeTRC(points));
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB"));
+ this.profileID = ColorSpace.CS_sRGB;
+ }
+
+ /**
+ * Creates an linear sRGB profile
+ */
+ private void createLinearRGBProfile()
+ {
+ header.setColorSpace(ColorSpace.TYPE_RGB);
+ header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+ ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+ float[] r = { 1f, 0f, 0f };
+ float[] g = { 0f, 1f, 0f };
+ float[] b = { 0f, 0f, 1f };
+ float[] black = { 0f, 0f, 0f };
+
+ float[] white = D50;
+
+ // Get tristimulus values (matrix elements)
+ r = cs.toCIEXYZ(r);
+ g = cs.toCIEXYZ(g);
+ b = cs.toCIEXYZ(b);
+
+ setData(icSigRedColorantTag, makeXYZData(r));
+ setData(icSigGreenColorantTag, makeXYZData(g));
+ setData(icSigBlueColorantTag, makeXYZData(b));
+
+ setData(icSigMediaWhitePointTag, makeXYZData(white));
+ setData(icSigMediaBlackPointTag, makeXYZData(black));
+
+ setData(icSigRedTRCTag, makeTRC());
+ setData(icSigGreenTRCTag, makeTRC());
+ setData(icSigBlueTRCTag, makeTRC());
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB"));
+ this.profileID = ColorSpace.CS_LINEAR_RGB;
+ }
+
+ /**
+ * Creates an CIE XYZ identity profile
+ */
+ private void createCIEProfile()
+ {
+ header.setColorSpace( ColorSpace.TYPE_XYZ );
+ header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
+ header.setProfileClass( CLASS_COLORSPACECONVERSION );
+ ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+ float[] white = D50;
+
+ setData(icSigMediaWhitePointTag, makeXYZData(white));
+ setData(icSigAToB0Tag, makeIdentityClut());
+ setData(icSigBToA0Tag, makeIdentityClut());
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile"));
+ this.profileID = ColorSpace.CS_CIEXYZ;
+ }
+
+ /**
+ * Creates a linear gray ICC_Profile
+ */
+ private void createGrayProfile()
+ {
+ header.setColorSpace(ColorSpace.TYPE_GRAY);
+ header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+
+ // CIE 1931 D50 white point (in Lab coordinates)
+ float[] white = D50;
+
+ setData(icSigMediaWhitePointTag, makeXYZData(white));
+ setData(icSigGrayTRCTag, makeTRC(1.0f));
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale"));
+ this.profileID = ColorSpace.CS_GRAY;
+ }
+
+ /**
+ * XXX Implement me
+ */
+ private void createPyccProfile()
+ {
+ header.setColorSpace(ColorSpace.TYPE_3CLR);
+ header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+
+ // Create CLUTs here. :-)
+
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC"));
+ this.profileID = ColorSpace.CS_PYCC;
+ }
+} // class ICC_Profile
diff --git a/libjava/classpath/java/awt/color/ICC_ProfileGray.java b/libjava/classpath/java/awt/color/ICC_ProfileGray.java
new file mode 100644
index 00000000000..3b5948dc8fc
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ICC_ProfileGray.java
@@ -0,0 +1,133 @@
+/* ICC_ProfileGray.java -- the ICC profile for a Gray colorspace
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+/**
+ * ICC_ProfileGray - a special case of ICC_Profiles.
+ *
+ * The ICC_Profile.getInstance() method will return an instance of the
+ * ICC_ProfileGray subclass when all the following conditions are met:
+ * The device color space of the profile is TYPE_GRAY.
+ * The profile contains a gray TRCTag.
+ * The profile contains a mediaWhitePointTag.
+ *
+ * As per the ICC specification, the color space conversion can then
+ * be done through the following method:
+ * linearGray = grayTRC[deviceGray]
+ *
+ * Note that if the profile contains a CLUT for the color space conversion,
+ * it should be used instead, and the TRC information ignored.
+ *
+ * @author Sven de Marothy
+ * @since 1.2
+ */
+public class ICC_ProfileGray extends ICC_Profile
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -1124721290732002649L;
+ private transient float[] whitePoint;
+
+ /**
+ * Package-private constructor used by ICC_ColorSpace for creating an
+ * ICC_ProfileGray from a predefined ColorSpace (CS_GRAY)
+ */
+ ICC_ProfileGray(int cspace)
+ {
+ super(cspace);
+ whitePoint = getXYZData(icSigMediaWhitePointTag);
+ }
+
+ /**
+ * Package-private constructor used by ICC_ColorSpace for creating an
+ * ICC_ProfileGray from profile data.
+ */
+ ICC_ProfileGray(byte[] data)
+ {
+ super(data);
+ whitePoint = getXYZData(icSigMediaWhitePointTag);
+ }
+
+
+ /**
+ * Returns the media white point of the profile.
+ */
+ public float[] getMediaWhitePoint()
+ {
+ float[] wp = new float[3];
+ wp[0] = whitePoint[0];
+ wp[1] = whitePoint[1];
+ wp[2] = whitePoint[2];
+ return wp;
+ }
+
+ /**
+ * Returns the TRC gamma value.
+ * @throws ProfileDataException if the TRC is described by a lookup
+ * table and not a gamma value.
+ */
+ public float getGamma()
+ {
+ short[] data = getCurve(icSigGrayTRCTag);
+ if (data == null)
+ throw new IllegalArgumentException("Couldn't read Gray TRC data.");
+ if (data.length != 1)
+ throw new ProfileDataException("TRC is a table, not a gamma value.");
+
+ // convert the unsigned 7.8 fixed-point gamma to a float.
+ double gamma = (double) (data[0] & (0xFFFF)) / 256.0;
+ return (float) gamma;
+ }
+
+ /**
+ * Returns the TRC lookup table.
+ * @throws ProfileDataException if the TRC is described by a gamma value
+ * and not a lookup table.
+ */
+ public short[] getTRC()
+ {
+ short[] data = getCurve(icSigGrayTRCTag);
+ if (data == null)
+ throw new IllegalArgumentException("Couldn't read Gray TRC data.");
+ if (data.length <= 1)
+ throw new ProfileDataException("Gamma value, not a TRC table.");
+ return data;
+ }
+} // class ICC_ProfileGray
diff --git a/libjava/classpath/java/awt/color/ICC_ProfileRGB.java b/libjava/classpath/java/awt/color/ICC_ProfileRGB.java
new file mode 100644
index 00000000000..00393328bbd
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ICC_ProfileRGB.java
@@ -0,0 +1,227 @@
+/* ICC_ProfileRGB.java -- the ICC profile for a RGB colorspace
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+/**
+ * ICC_ProfileRGB - a special case of ICC_Profiles.
+ *
+ * The ICC_Profile.getInstance() method will return an instance of the
+ * ICC_ProfileRGB subclass when all the following conditions are met:
+ * The device color space of the profile is TYPE_RGB.
+ * The profile contains red, green and blue ColorantTags.
+ * The profile contains red, green and blue TRCTags.
+ * The profile contains a mediaWhitePointTag included.
+ *
+ * As per the ICC specification, the color space conversion can then
+ * be done through the following method:
+ * linearR = redTRC[deviceR]
+ * linearG = greenTRC[deviceG]
+ * linearB = blueTRC[deviceB]
+ * TRC curves are either a single gamma value, or a 1-dimensional lookup table.
+ *
+ * Followed by the matrix transform:
+ * PCS = M*linear
+ *
+ * Where PCS is the vector of profile color space (must be XYZ) coordinates,
+ * linear is the vector of linear RGB coordinates, and the matrix M is
+ * constructed from the ColorantTags, where the columns are red, green and
+ * blue respectively, and the rows are X, Y and Z.
+ *
+ * Note that if the profile contains a CLUT for the color space conversion,
+ * it should be used instead, and the TRC information ignored.
+ *
+ * @author Sven de Marothy
+ * @since 1.2
+ */
+public class ICC_ProfileRGB extends ICC_Profile
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 8505067385152579334L;
+
+ public static final int REDCOMPONENT = 0;
+
+ public static final int GREENCOMPONENT = 1;
+
+ public static final int BLUECOMPONENT = 2;
+
+ private transient float[][] matrix;
+
+ private transient float[] gamma;
+
+ private transient float[] whitePoint;
+
+
+ /**
+ * Package-private constructor used by ICC_ColorSpace for creating an
+ * ICC_ProfileRGB from a predefined ColorSpace (CS_LINEAR_RGB and CS_sRGB)
+ */
+ ICC_ProfileRGB(int cspace)
+ {
+ super(cspace);
+ matrix = createMatrix();
+ whitePoint = getXYZData(icSigMediaWhitePointTag);
+ }
+
+ /**
+ * Package-private constructor used by ICC_ColorSpace for creating an
+ * ICC_ProfileRGB from profile data.
+ */
+ ICC_ProfileRGB(byte[] data)
+ {
+ super(data);
+ matrix = createMatrix();
+ whitePoint = getXYZData(icSigMediaWhitePointTag);
+ }
+
+ /**
+ * Returns the media white point of the profile.
+ */
+ public float[] getMediaWhitePoint()
+ {
+ float[] wp = new float[3];
+ wp[0] = whitePoint[0];
+ wp[1] = whitePoint[1];
+ wp[2] = whitePoint[2];
+ return wp;
+ }
+
+ /**
+ * Returns the colorant matrix of the conversion.
+ */
+ public float[][] getMatrix()
+ {
+ float[][] mat = new float[3][3];
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ mat[i][j] = matrix[i][j];
+ return mat;
+ }
+
+ /**
+ * Returns the gamma value of a component
+ * @throws ProfileDataException if the TRC is described by a lookup
+ * table and not a gamma value.
+ */
+ public float getGamma(int component)
+ {
+ short[] data;
+ switch (component)
+ {
+ case REDCOMPONENT:
+ data = getCurve(icSigRedTRCTag);
+ break;
+ case GREENCOMPONENT:
+ data = getCurve(icSigGreenTRCTag);
+ break;
+ case BLUECOMPONENT:
+ data = getCurve(icSigBlueTRCTag);
+ break;
+ default:
+ throw new IllegalArgumentException("Not a valid component");
+ }
+ if (data == null)
+ throw new IllegalArgumentException("Error reading TRC");
+
+ if (data.length != 1)
+ throw new ProfileDataException("Not a single-gamma TRC");
+
+ // convert the unsigned 7.8 fixed-point gamma to a float.
+ float gamma = (float) (((int) data[0] & 0xFF00) >> 8);
+ double fraction = ((int) data[0] & 0x00FF) / 256.0;
+ gamma += (float) fraction;
+ return gamma;
+ }
+
+ /**
+ * Returns the TRC lookup table for a component
+ * @throws ProfileDataException if the TRC is described by a gamma
+ * value and not a lookup table.
+ */
+ public short[] getTRC(int component)
+ {
+ short[] data;
+ switch (component)
+ {
+ case REDCOMPONENT:
+ data = getCurve(icSigRedTRCTag);
+ break;
+ case GREENCOMPONENT:
+ data = getCurve(icSigGreenTRCTag);
+ break;
+ case BLUECOMPONENT:
+ data = getCurve(icSigBlueTRCTag);
+ break;
+ default:
+ throw new IllegalArgumentException("Not a valid component");
+ }
+ if (data == null)
+ throw new IllegalArgumentException("Error reading TRC");
+
+ if (data.length <= 1)
+ throw new ProfileDataException("Gamma value, not a TRC table.");
+
+ return data;
+ }
+
+ /**
+ * Creates the colorspace conversion matrix from the RGB tristimulus
+ * values.
+ */
+ private float[][] createMatrix() throws IllegalArgumentException
+ {
+ float[][] mat = new float[3][3];
+ float[] r;
+ float[] g;
+ float[] b;
+ r = getXYZData(icSigRedColorantTag);
+ g = getXYZData(icSigGreenColorantTag);
+ b = getXYZData(icSigBlueColorantTag);
+ if (r == null || g == null || b == null)
+ throw new IllegalArgumentException("Error reading colorant tags!");
+ for (int i = 0; i < 3; i++)
+ {
+ mat[i][0] = r[i];
+ mat[i][1] = g[i];
+ mat[i][2] = b[i];
+ }
+ return mat;
+ }
+} // class ICC_ProfileRGB
diff --git a/libjava/classpath/java/awt/color/ProfileDataException.java b/libjava/classpath/java/awt/color/ProfileDataException.java
new file mode 100644
index 00000000000..1af23b1835c
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ProfileDataException.java
@@ -0,0 +1,64 @@
+/* ProfileDataException.java -- error in processing an ICC_Profile
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+/**
+ * Thrown when there is an error accessing or processing an
+ * <code>ICC_Profile</code>.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class ProfileDataException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 7286140888240322498L;
+
+ /**
+ * Create a new instance with a specified detailed error message.
+ *
+ * @param message the message
+ */
+ public ProfileDataException(String message)
+ {
+ super(message);
+ }
+} // class ProfileDataException
diff --git a/libjava/classpath/java/awt/color/package.html b/libjava/classpath/java/awt/color/package.html
new file mode 100644
index 00000000000..9a08577c199
--- /dev/null
+++ b/libjava/classpath/java/awt/color/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.color package.
+ Copyright (C) 2002 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 - java.awt.color</title></head>
+
+<body>
+<p>Classes to represent color spaces and profiles.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/datatransfer/Clipboard.java b/libjava/classpath/java/awt/datatransfer/Clipboard.java
new file mode 100644
index 00000000000..9953a724dba
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/Clipboard.java
@@ -0,0 +1,114 @@
+/* Clipboard.java -- Class for transferring data via cut and paste.
+ Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+/**
+ * This class allows data to be transferred using a cut and paste type
+ * mechanism.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Clipboard
+{
+ /**
+ * The data being transferred.
+ */
+ protected Transferable contents;
+
+ /**
+ * The owner of this clipboard.
+ */
+ protected ClipboardOwner owner;
+
+ // The clipboard name
+ private String name;
+
+ /**
+ * Initializes a new instance of <code>Clipboard</code> with the
+ * specified name.
+ *
+ * @param name The clipboard name.
+ */
+ public Clipboard(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * Returns the name of the clipboard.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns the contents of the clipboard.
+ *
+ * @param requestor The object requesting the contents.
+ *
+ * @exception IllegalStateException If the clipboard is currently unavailable
+ */
+ public synchronized Transferable getContents(Object requestor)
+ {
+ return contents;
+ }
+
+ /**
+ * Sets the content and owner of this clipboard.
+ * If the given owner is different from the current owner
+ * then lostOwnership is called on the current owner.
+ * XXX - is this called with the old or new contents.
+ *
+ * @param contents The new clipboard contents.
+ * @param owner The new clipboard owner
+ *
+ * @exception IllegalStateException If the clipboard is currently unavailable
+ */
+ public synchronized void setContents(Transferable contents, ClipboardOwner owner)
+ {
+ if (this.owner != owner)
+ if (this.owner != null)
+ this.owner.lostOwnership(this, contents);
+
+ this.owner = owner;
+ this.contents = contents;
+ }
+}
+
diff --git a/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java b/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java
new file mode 100644
index 00000000000..df758254a55
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java
@@ -0,0 +1,57 @@
+/* ClipboardOwner.java -- Interface for clipboard providers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+/**
+ * This interface is for classes that will own a clipboard object.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface ClipboardOwner
+{
+ /**
+ * This method is called to notify this object that it no longer
+ * has ownership of the specified <code>Clipboard</code>.
+ *
+ * @param clipboard The clipboard for which ownership was lost.
+ * @param contents The contents of the clipboard which are no longer owned.
+ */
+ void lostOwnership (Clipboard clipboard, Transferable contents);
+}
+
diff --git a/libjava/classpath/java/awt/datatransfer/DataFlavor.java b/libjava/classpath/java/awt/datatransfer/DataFlavor.java
new file mode 100644
index 00000000000..e5fbd240293
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/DataFlavor.java
@@ -0,0 +1,1034 @@
+/* DataFlavor.java -- A type of data to transfer via the clipboard.
+ Copyright (C) 1999, 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+/**
+ * This class represents a particular data format used for transferring
+ * data via the clipboard.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class DataFlavor implements java.io.Externalizable, Cloneable
+{
+ static final long serialVersionUID = 8367026044764648243L;
+
+ // FIXME: Serialization: Need to write methods for.
+
+/**
+ * This is the data flavor used for tranferring plain text. The MIME
+ * type is "text/plain; charset=unicode". The representation class
+ * is <code>java.io.InputStream</code>.
+ *
+ * @deprecated The charset unicode is platform specific and InputStream
+ * deals with bytes not chars. Use <code>getRederForText()</code>.
+ */
+public static final DataFlavor plainTextFlavor;
+
+/**
+ * This is the data flavor used for transferring Java strings. The
+ * MIME type is "application/x-java-serialized-object" and the
+ * representation class is <code>java.lang.String</code>.
+ */
+public static final DataFlavor stringFlavor;
+
+/**
+ * This is a data flavor used for transferring lists of files. The
+ * representation type is a <code>java.util.List</code>, with each element of
+ * the list being a <code>java.io.File</code>.
+ */
+public static final DataFlavor javaFileListFlavor;
+
+/**
+ * This is an image flavor used for transferring images. The
+ * representation type is a <code>java.awt.Image</code>.
+ */
+public static final DataFlavor imageFlavor;
+
+/**
+ * This is the MIME type used for transferring a serialized object.
+ * The representation class is the type of object be deserialized.
+ */
+public static final String javaSerializedObjectMimeType =
+ "application/x-java-serialized-object";
+
+/**
+ * This is the MIME type used to transfer a Java object reference within
+ * the same JVM. The representation class is the class of the object
+ * being transferred.
+ */
+public static final String javaJVMLocalObjectMimeType =
+ "application/x-java-jvm-local-objectref";
+
+/**
+ * This is the MIME type used to transfer a link to a remote object.
+ * The representation class is the type of object being linked to.
+ */
+public static final String javaRemoteObjectMimeType =
+ "application/x-java-remote-object";
+
+static
+{
+ plainTextFlavor
+ = new DataFlavor(java.io.InputStream.class,
+ "text/plain; charset=unicode",
+ "plain unicode text");
+
+ stringFlavor
+ = new DataFlavor(java.lang.String.class,
+ "Java Unicode String");
+
+ javaFileListFlavor
+ = new DataFlavor(java.util.List.class,
+ "Java File List");
+
+ // javaFileListFlavor.mimeType = "application/x-java-file-list";
+
+ imageFlavor
+ = new DataFlavor(java.awt.Image.class,
+ "Java Image");
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+// The MIME type for this flavor
+private final String mimeType;
+
+// The representation class for this flavor
+private final Class representationClass;
+
+// The human readable name of this flavor
+private String humanPresentableName;
+
+/*************************************************************************/
+
+/*
+ * Static Methods
+ */
+
+/**
+ * This method attempts to load the named class. The following class
+ * loaders are searched in order: the bootstrap class loader, the
+ * system class loader, the context class loader (if it exists), and
+ * the specified fallback class loader.
+ *
+ * @param className The name of the class to load.
+ * @param classLoader The class loader to use if all others fail, which
+ * may be <code>null</code>.
+ *
+ * @exception ClassNotFoundException If the class cannot be loaded.
+ */
+protected static final Class
+tryToLoadClass(String className, ClassLoader classLoader)
+ throws ClassNotFoundException
+{
+ try
+ {
+ return(Class.forName(className));
+ }
+ catch(Exception e) { ; }
+ // Commented out for Java 1.1
+ /*
+ try
+ {
+ return(className.getClass().getClassLoader().findClass(className));
+ }
+ catch(Exception e) { ; }
+
+ try
+ {
+ return(ClassLoader.getSystemClassLoader().findClass(className));
+ }
+ catch(Exception e) { ; }
+ */
+
+ // FIXME: What is the context class loader?
+ /*
+ try
+ {
+ }
+ catch(Exception e) { ; }
+ */
+
+ if (classLoader != null)
+ return(classLoader.loadClass(className));
+ else
+ throw new ClassNotFoundException(className);
+}
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Empty public constructor needed for externalization.
+ * Should not be used for normal instantiation.
+ */
+public
+DataFlavor()
+{
+ mimeType = null;
+ representationClass = null;
+ humanPresentableName = null;
+}
+
+/*************************************************************************/
+
+/**
+ * Private constructor.
+ */
+private
+DataFlavor(Class representationClass,
+ String mimeType,
+ String humanPresentableName)
+{
+ this.representationClass = representationClass;
+ this.mimeType = mimeType;
+ if (humanPresentableName != null)
+ this.humanPresentableName = humanPresentableName;
+ else
+ this.humanPresentableName = mimeType;
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>DataFlavor</code>. The class
+ * and human readable name are specified, the MIME type will be
+ * "application/x-java-serialized-object". If the human readable name
+ * is not specified (<code>null</code>) then the human readable name
+ * will be the same as the MIME type.
+ *
+ * @param representationClass The representation class for this object.
+ * @param humanPresentableName The display name of the object.
+ */
+public
+DataFlavor(Class representationClass, String humanPresentableName)
+{
+ this(representationClass,
+ "application/x-java-serialized-object"
+ + "; class="
+ + representationClass.getName(),
+ humanPresentableName);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>DataFlavor</code> with the
+ * specified MIME type and description. If the MIME type has a
+ * "class=&lt;rep class&gt;" parameter then the representation class will
+ * be the class name specified. Otherwise the class defaults to
+ * <code>java.io.InputStream</code>. If the human readable name
+ * is not specified (<code>null</code>) then the human readable name
+ * will be the same as the MIME type.
+ *
+ * @param mimeType The MIME type for this flavor.
+ * @param humanPresentableName The display name of this flavor.
+ * @param classLoader The class loader for finding classes if the default
+ * class loaders do not work.
+ *
+ * @exception IllegalArgumentException If the representation class
+ * specified cannot be loaded.
+ * @exception ClassNotFoundException If the class is not loaded.
+ */
+public
+DataFlavor(String mimeType, String humanPresentableName,
+ ClassLoader classLoader) throws ClassNotFoundException
+{
+ this(getRepresentationClassFromMime(mimeType, classLoader),
+ mimeType, humanPresentableName);
+}
+
+private static Class
+getRepresentationClassFromMime(String mimeString, ClassLoader classLoader)
+{
+ String classname = getParameter("class", mimeString);
+ if (classname != null)
+ {
+ try
+ {
+ return tryToLoadClass(classname, classLoader);
+ }
+ catch(Exception e)
+ {
+ throw new IllegalArgumentException("classname: " + e.getMessage());
+ }
+ }
+ else
+ {
+ return java.io.InputStream.class;
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>DataFlavor</code> with the
+ * specified MIME type and description. If the MIME type has a
+ * "class=&lt;rep class&gt;" parameter then the representation class will
+ * be the class name specified. Otherwise the class defaults to
+ * <code>java.io.InputStream</code>. If the human readable name
+ * is not specified (<code>null</code>) then the human readable name
+ * will be the same as the MIME type. This is the same as calling
+ * <code>new DataFlavor(mimeType, humanPresentableName, null)</code>.
+ *
+ * @param mimeType The MIME type for this flavor.
+ * @param humanPresentableName The display name of this flavor.
+ *
+ * @exception IllegalArgumentException If the representation class
+ * specified cannot be loaded.
+ */
+public
+DataFlavor(String mimeType, String humanPresentableName)
+{
+ this (getRepresentationClassFromMime (mimeType, null), humanPresentableName);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>DataFlavor</code> with the specified
+ * MIME type. This type can have a "class=" parameter to specify the
+ * representation class, and then the class must exist or an exception will
+ * be thrown. If there is no "class=" parameter then the representation class
+ * will be <code>java.io.InputStream</code>. This is the same as calling
+ * <code>new DataFlavor(mimeType, null)</code>.
+ *
+ * @param mimeType The MIME type for this flavor.
+ *
+ * @exception IllegalArgumentException If a class is not specified in
+ * the MIME type.
+ * @exception ClassNotFoundException If the class cannot be loaded.
+ */
+public
+DataFlavor(String mimeType) throws ClassNotFoundException
+{
+ this(mimeType, null);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the MIME type of this flavor.
+ *
+ * @return The MIME type for this flavor.
+ */
+public String
+getMimeType()
+{
+ return(mimeType);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the representation class for this flavor.
+ *
+ * @return The representation class for this flavor.
+ */
+public Class
+getRepresentationClass()
+{
+ return(representationClass);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the human presentable name for this flavor.
+ *
+ * @return The human presentable name for this flavor.
+ */
+public String
+getHumanPresentableName()
+{
+ return(humanPresentableName);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the primary MIME type for this flavor.
+ *
+ * @return The primary MIME type for this flavor.
+ */
+public String
+getPrimaryType()
+{
+ int idx = mimeType.indexOf("/");
+ if (idx == -1)
+ return(mimeType);
+
+ return(mimeType.substring(0, idx));
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the MIME subtype for this flavor.
+ *
+ * @return The MIME subtype for this flavor.
+ */
+public String
+getSubType()
+{
+ int idx = mimeType.indexOf("/");
+ if (idx == -1)
+ return("");
+
+ String subtype = mimeType.substring(idx + 1);
+
+ idx = subtype.indexOf(" ");
+ if (idx == -1)
+ return(subtype);
+ else
+ return(subtype.substring(0, idx));
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the value of the named MIME type parameter, or <code>null</code>
+ * if the parameter does not exist. Given the parameter name and the mime
+ * string.
+ *
+ * @param paramName The name of the parameter.
+ * @param mimeString The mime string from where the name should be found.
+ *
+ * @return The value of the parameter or null.
+ */
+private static String
+getParameter(String paramName, String mimeString)
+{
+ int idx = mimeString.indexOf(paramName + "=");
+ if (idx == -1)
+ return(null);
+
+ String value = mimeString.substring(idx + paramName.length() + 1);
+
+ idx = value.indexOf(" ");
+ if (idx == -1)
+ return(value);
+ else
+ return(value.substring(0, idx));
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the value of the named MIME type parameter, or <code>null</code>
+ * if the parameter does not exist.
+ *
+ * @param paramName The name of the paramter.
+ *
+ * @return The value of the parameter.
+ */
+public String
+getParameter(String paramName)
+{
+ return getParameter(paramName, mimeType);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the human presentable name to the specified value.
+ *
+ * @param humanPresentableName The new display name.
+ */
+public void
+setHumanPresentableName(String humanPresentableName)
+{
+ this.humanPresentableName = humanPresentableName;
+}
+
+/*************************************************************************/
+
+/**
+ * Tests the MIME type of this object for equality against the specified
+ * MIME type.
+ *
+ * @param mimeType The MIME type to test against.
+ *
+ * @return <code>true</code> if the MIME type is equal to this object's
+ * MIME type, <code>false</code> otherwise.
+ *
+ * @exception NullPointerException If mimeType is null.
+ */
+public boolean
+isMimeTypeEqual(String mimeType)
+{
+ // FIXME: Need to handle default attributes and parameters
+
+ return(this.mimeType.equals(mimeType));
+}
+
+/*************************************************************************/
+
+/**
+ * Tests the MIME type of this object for equality against the specified
+ * data flavor's MIME type
+ *
+ * @param flavor The flavor to test against.
+ *
+ * @return <code>true</code> if the flavor's MIME type is equal to this
+ * object's MIME type, <code>false</code> otherwise.
+ */
+public final boolean
+isMimeTypeEqual(DataFlavor flavor)
+{
+ return(isMimeTypeEqual(flavor.getMimeType()));
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this flavor represents a serialized object.
+ *
+ * @return <code>true</code> if this flavor represents a serialized
+ * object, <code>false</code> otherwise.
+ */
+public boolean
+isMimeTypeSerializedObject()
+{
+ return(mimeType.startsWith(javaSerializedObjectMimeType));
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this flavor has a representation class of
+ * <code>java.io.InputStream</code>.
+ *
+ * @return <code>true</code> if the representation class of this flavor
+ * is <code>java.io.InputStream</code>, <code>false</code> otherwise.
+ */
+public boolean
+isRepresentationClassInputStream()
+{
+ return(representationClass.getName().equals("java.io.InputStream"));
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether the representation class for this flavor is
+ * serializable.
+ *
+ * @return <code>true</code> if the representation class is serializable,
+ * <code>false</code> otherwise.
+ */
+public boolean
+isRepresentationClassSerializable()
+{
+ Class[] interfaces = representationClass.getInterfaces();
+
+ int i = 0;
+ while (i < interfaces.length)
+ {
+ if (interfaces[i].getName().equals("java.io.Serializable"))
+ return(true);
+ ++i;
+ }
+
+ return(false);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether the representation class for his flavor is remote.
+ *
+ * @return <code>true</code> if the representation class is remote,
+ * <code>false</code> otherwise.
+ */
+public boolean
+isRepresentationClassRemote()
+{
+ // FIXME: Implement
+ throw new RuntimeException("Not implemented");
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this flavor represents a serialized object.
+ *
+ * @return <code>true</code> if this flavor represents a serialized
+ * object, <code>false</code> otherwise.
+ */
+public boolean
+isFlavorSerializedObjectType()
+{
+ // FIXME: What is the diff between this and isMimeTypeSerializedObject?
+ return(mimeType.startsWith(javaSerializedObjectMimeType));
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this flavor represents a remote object.
+ *
+ * @return <code>true</code> if this flavor represents a remote object,
+ * <code>false</code> otherwise.
+ */
+public boolean
+isFlavorRemoteObjectType()
+{
+ return(mimeType.startsWith(javaRemoteObjectMimeType));
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this flavor represents a list of files.
+ *
+ * @return <code>true</code> if this flavor represents a list of files,
+ * <code>false</code> otherwise.
+ */
+public boolean
+isFlavorJavaFileListType()
+{
+ if (this.mimeType.equals(javaFileListFlavor.mimeType) &&
+ this.representationClass.equals(javaFileListFlavor.representationClass))
+ return(true);
+
+ return(false);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a copy of this object.
+ *
+ * @return A copy of this object.
+ *
+ * @exception CloneNotSupportedException If the object's class does not support
+ * the Cloneable interface. Subclasses that override the clone method can also
+ * throw this exception to indicate that an instance cannot be cloned.
+ */
+public Object clone () throws CloneNotSupportedException
+{
+ try
+ {
+ return(super.clone());
+ }
+ catch(Exception e)
+ {
+ return(null);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * This method test the specified <code>DataFlavor</code> for equality
+ * against this object. This will be true if the MIME type and
+ * representation type are the equal.
+ *
+ * @param flavor The <code>DataFlavor</code> to test against.
+ *
+ * @return <code>true</code> if the flavor is equal to this object,
+ * <code>false</code> otherwise.
+ */
+public boolean
+equals(DataFlavor flavor)
+{
+ if (flavor == null)
+ return(false);
+
+ if (!this.mimeType.toLowerCase().equals(flavor.mimeType.toLowerCase()))
+ return(false);
+
+ if (!this.representationClass.equals(flavor.representationClass))
+ return(false);
+
+ return(true);
+}
+
+/*************************************************************************/
+
+/**
+ * This method test the specified <code>Object</code> for equality
+ * against this object. This will be true if the following conditions
+ * are met:
+ * <p>
+ * <ul>
+ * <li>The object is not <code>null</code>.</li>
+ * <li>The object is an instance of <code>DataFlavor</code>.</li>
+ * <li>The object's MIME type and representation class are equal to
+ * this object's.</li>
+ * </ul>
+ *
+ * @param obj The <code>Object</code> to test against.
+ *
+ * @return <code>true</code> if the flavor is equal to this object,
+ * <code>false</code> otherwise.
+ */
+public boolean
+equals(Object obj)
+{
+ if (!(obj instanceof DataFlavor))
+ return(false);
+
+ return(equals((DataFlavor)obj));
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not the specified string is equal to the MIME type
+ * of this object.
+ *
+ * @param str The string to test against.
+ *
+ * @return <code>true</code> if the string is equal to this object's MIME
+ * type, <code>false</code> otherwise.
+ *
+ * @deprecated Not compatible with <code>hashCode()</code>.
+ * Use <code>isMimeTypeEqual()</code>
+ */
+public boolean
+equals(String str)
+{
+ return(isMimeTypeEqual(str));
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the hash code for this data flavor.
+ * The hash code is based on the (lower case) mime type and the
+ * representation class.
+ */
+public int
+hashCode()
+{
+ return(mimeType.toLowerCase().hashCode()^representationClass.hashCode());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns <code>true</code> when the given <code>DataFlavor</code>
+ * matches this one.
+ */
+public boolean
+match(DataFlavor dataFlavor)
+{
+ // XXX - How is this different from equals?
+ return(equals(dataFlavor));
+}
+
+/*************************************************************************/
+
+/**
+ * This method exists for backward compatibility. It simply returns
+ * the same name/value pair passed in.
+ *
+ * @param name The parameter name.
+ * @param value The parameter value.
+ *
+ * @return The name/value pair.
+ *
+ * @deprecated
+ */
+protected String
+normalizeMimeTypeParameter(String name, String value)
+{
+ return(name + "=" + value);
+}
+
+/*************************************************************************/
+
+/**
+ * This method exists for backward compatibility. It simply returns
+ * the MIME type string unchanged.
+ *
+ * @param type The MIME type.
+ *
+ * @return The MIME type.
+ *
+ * @deprecated
+ */
+protected String
+normalizeMimeType(String type)
+{
+ return(type);
+}
+
+/*************************************************************************/
+
+/**
+ * Serialize this class.
+ *
+ * @param stream The <code>ObjectOutput</code> stream to serialize to.
+ *
+ * @exception IOException If an error occurs.
+ */
+public void
+writeExternal(ObjectOutput stream) throws IOException
+{
+ // FIXME: Implement me
+}
+
+/*************************************************************************/
+
+/**
+ * De-serialize this class.
+ *
+ * @param stream The <code>ObjectInput</code> stream to deserialize from.
+ *
+ * @exception IOException If an error ocurs.
+ * @exception ClassNotFoundException If the class for an object being restored
+ * cannot be found.
+ */
+public void
+readExternal(ObjectInput stream) throws IOException, ClassNotFoundException
+{
+ // FIXME: Implement me
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this DataFlavor. Including the
+ * representation class name, MIME type and human presentable name.
+ */
+public String
+toString()
+{
+ return("DataFlavor[representationClass="
+ + representationClass.getName()
+ + ",mimeType="
+ + mimeType
+ + "humanPresentableName="
+ + humanPresentableName);
+}
+
+/*************************************************************************/
+
+/**
+ * XXX - Currently returns <code>plainTextFlavor</code>.
+ */
+public static final DataFlavor
+getTextPlainUnicodeFlavor()
+{
+ return(plainTextFlavor);
+}
+
+/*************************************************************************/
+
+/**
+ * XXX - Currently returns <code>java.io.InputStream</code>.
+ *
+ * @since 1.3
+ */
+public final Class
+getDefaultRepresentationClass()
+{
+ return(java.io.InputStream.class);
+}
+/*************************************************************************/
+
+/**
+ * XXX - Currently returns <code>java.io.InputStream</code>.
+ */
+public final String
+getDefaultRepresentationClassAsString()
+{
+ return(getDefaultRepresentationClass().getName());
+}
+
+/*************************************************************************/
+
+/**
+ * Selects the best supported text flavor on this implementation.
+ * Returns <code>null</code> when none of the given flavors is liked.
+ *
+ * The <code>DataFlavor</code> returned the first data flavor in the
+ * array that has either a representation class which is (a subclass of)
+ * <code>Reader</code> or <code>String</code>, or has a representation
+ * class which is (a subclass of) <code>InputStream</code> and has a
+ * primary MIME type of "text" and has an supported encoding.
+ */
+public static final DataFlavor
+selectBestTextFlavor(DataFlavor[] availableFlavors)
+{
+ for(int i=0; i<availableFlavors.length; i++)
+ {
+ DataFlavor df = availableFlavors[i];
+ Class c = df.representationClass;
+
+ // A Reader or String is good.
+ if ((Reader.class.isAssignableFrom(c))
+ || (String.class.isAssignableFrom(c)))
+ {
+ return df;
+ }
+
+ // A InputStream is good if the mime primary type is "text"
+ if ((InputStream.class.isAssignableFrom(c))
+ && ("text".equals(df.getPrimaryType())))
+ {
+ String encoding = availableFlavors[i].getParameter("charset");
+ if (encoding == null)
+ encoding = "us-ascii";
+ Reader r = null;
+ try
+ {
+ // Try to construct a dummy reader with the found encoding
+ r = new InputStreamReader
+ (new ByteArrayInputStream(new byte[0]), encoding);
+ }
+ catch(UnsupportedEncodingException uee) { /* ignore */ }
+ if (r != null)
+ return df;
+ }
+ }
+
+ // Nothing found
+ return(null);
+}
+
+/*************************************************************************/
+
+/**
+ * Creates a <code>Reader</code> for a given <code>Transferable</code>.
+ *
+ * If the representation class is a (subclass of) <code>Reader</code>
+ * then an instance of the representation class is returned. If the
+ * representatation class is a <code>String</code> then a
+ * <code>StringReader</code> is returned. And if the representation class
+ * is a (subclass of) <code>InputStream</code> and the primary MIME type
+ * is "text" then a <code>InputStreamReader</code> for the correct charset
+ * encoding is returned.
+ *
+ * @param transferable The <code>Transferable</code> for which a text
+ * <code>Reader</code> is requested.
+ *
+ * @exception IllegalArgumentException If the representation class is not one
+ * of the seven listed above or the Transferable has null data.
+ * @exception NullPointerException If the Transferable is null.
+ * @exception UnsupportedFlavorException when the transferable doesn't
+ * support this <code>DataFlavor</code>. Or if the representable class
+ * isn't a (subclass of) <code>Reader</code>, <code>String</code>,
+ * <code>InputStream</code> and/or the primary MIME type isn't "text".
+ * @exception IOException when any IOException occurs.
+ * @exception UnsupportedEncodingException if the "charset" isn't supported
+ * on this platform.
+ */
+public Reader getReaderForText(Transferable transferable)
+ throws UnsupportedFlavorException, IOException
+{
+ if (!transferable.isDataFlavorSupported(this))
+ throw new UnsupportedFlavorException(this);
+
+ if (Reader.class.isAssignableFrom(representationClass))
+ return((Reader)transferable.getTransferData(this));
+
+ if (String.class.isAssignableFrom(representationClass))
+ return(new StringReader((String)transferable.getTransferData(this)));
+
+ if (InputStream.class.isAssignableFrom(representationClass)
+ && "text".equals(getPrimaryType()))
+ {
+ InputStream in = (InputStream)transferable.getTransferData(this);
+ String encoding = getParameter("charset");
+ if (encoding == null)
+ encoding = "us-ascii";
+ return(new InputStreamReader(in, encoding));
+ }
+
+ throw new UnsupportedFlavorException(this);
+}
+
+ /**
+ * Returns whether the representation class for this DataFlavor is
+ * @see java.nio.ByteBuffer or a subclass thereof.
+ *
+ * @since 1.4
+ */
+ public boolean isRepresentationClassByteBuffer ()
+ {
+ return ByteBuffer.class.isAssignableFrom (representationClass);
+ }
+
+ /**
+ * Returns whether the representation class for this DataFlavor is
+ * @see java.nio.CharBuffer or a subclass thereof.
+ *
+ * @since 1.4
+ */
+ public boolean isRepresentationClassCharBuffer ()
+ {
+ return CharBuffer.class.isAssignableFrom (representationClass);
+ }
+
+ /**
+ * Returns whether the representation class for this DataFlavor is
+ * @see java.io.Reader or a subclass thereof.
+ *
+ * @since 1.4
+ */
+ public boolean isRepresentationClassReader ()
+ {
+ return Reader.class.isAssignableFrom (representationClass);
+ }
+
+} // class DataFlavor
+
diff --git a/libjava/classpath/java/awt/datatransfer/FlavorMap.java b/libjava/classpath/java/awt/datatransfer/FlavorMap.java
new file mode 100644
index 00000000000..59718c4513c
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/FlavorMap.java
@@ -0,0 +1,75 @@
+/* FlavorMap.java -- Maps between flavor names and MIME types.
+ Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.util.Map;
+
+/**
+ * This interface maps between native platform type names and DataFlavors.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface FlavorMap
+{
+ /**
+ * Maps the specified <code>DataFlavor</code> objects to the native
+ * data type name. The returned <code>Map</code> has keys that are
+ * the data flavors and values that are strings. The returned map
+ * may be modified. This can be useful for implementing nested mappings.
+ *
+ * @param flavors An array of data flavors to map
+ * or null for all data flavors.
+ *
+ * @return A <code>Map</code> of native data types.
+ */
+ Map getNativesForFlavors (DataFlavor[] flavors);
+
+ /**
+ * Maps the specified native type names to <code>DataFlavor</code>'s.
+ * The returned <code>Map</code> has keys that are strings and values
+ * that are <code>DataFlavor</code>'s. The returned map may be
+ * modified. This can be useful for implementing nested mappings.
+ *
+ * @param natives An array of native types to map
+ * or null for all native types.
+ *
+ * @return A <code>Map</code> of data flavors.
+ */
+ Map getFlavorsForNatives (String[] natives);
+}
diff --git a/libjava/classpath/java/awt/datatransfer/FlavorTable.java b/libjava/classpath/java/awt/datatransfer/FlavorTable.java
new file mode 100644
index 00000000000..11cdda06ca7
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/FlavorTable.java
@@ -0,0 +1,73 @@
+/* FlavorTable.java -- A relaxed mapping between flavors
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.util.List;
+
+/**
+ * A FlavorMap which no longer requires a 1-to-1 mapping between flavors. Any
+ * native can map to multiple flavors, and any flavor can map to multiple
+ * natives; although the mappings are usually symmetric.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface FlavorTable extends FlavorMap
+{
+ /**
+ * Returns a list of String natives corresponding to the given flavor. The
+ * list should be sorted from best to worst. The list must be modifiable
+ * without affecting this table.
+ *
+ * @param flavor the flavor to look up, or null to return all natives
+ * @return the sorted list of natives
+ */
+ List getNativesForFlavor(DataFlavor flavor);
+
+ /**
+ * Returns a list of flavors corresponding to the given String native. The
+ * list should be sorted from best to worst. The list must be modifiable
+ * without affecting this table.
+ *
+ * @param name the native name to look up, or null to return all flavors
+ * @return the sorted list of flavors
+ */
+ List getFlavorsForNative(String name);
+}
diff --git a/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java b/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java
new file mode 100644
index 00000000000..6113ab760b8
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java
@@ -0,0 +1,70 @@
+/* MimeTypeParseException.java -- thrown when MIME string couldn't be parsed
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+/**
+ * MIME string couldn't be parsed correctly.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @status updated to 1.4
+ */
+public class MimeTypeParseException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5604407764691570741L;
+
+ /**
+ * Create a new instance without any message.
+ */
+ public MimeTypeParseException()
+ {
+ }
+
+ /**
+ * Create a new instance with a specified detailed error message.
+ *
+ * @param message the message
+ */
+ public MimeTypeParseException(String message)
+ {
+ super(message);
+ }
+} // class MimeTypeParseException
diff --git a/libjava/classpath/java/awt/datatransfer/StringSelection.java b/libjava/classpath/java/awt/datatransfer/StringSelection.java
new file mode 100644
index 00000000000..b74f2fa6418
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/StringSelection.java
@@ -0,0 +1,158 @@
+/* StringSelection.java -- Clipboard handler for text.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+/**
+ * This class transfers a string as plain text using the clipboard.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class StringSelection implements Transferable, ClipboardOwner
+{
+
+/*
+ * Class Variables
+ */
+
+// List of flavors we support
+// XXX: DataFlavor.plainTextFlavor is deprecated.
+static final DataFlavor[] supported_flavors
+ = { DataFlavor.stringFlavor,
+ DataFlavor.plainTextFlavor };
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+// This is the data to transfer
+private String data;
+
+ /**
+ * Transfer the specfied string as text.
+ *
+ * @param data the data for the string selection
+ */
+ public StringSelection(String data)
+ {
+ this.data = data;
+ }
+
+/**
+ * Returns a list of supported data flavors.
+ *
+ * @return A list of supported data flavors.
+ */
+public DataFlavor[]
+getTransferDataFlavors()
+{
+ return(supported_flavors);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not the specified data flavor is supported.
+ *
+ * @param flavor The data flavor to test.
+ *
+ * @return <code>true</code> if the data flavor is supported,
+ * <code>false</code> otherwise.
+ */
+public boolean
+isDataFlavorSupported(DataFlavor flavor)
+{
+ for (int i = 0; i < supported_flavors.length; i++)
+ if (supported_flavors[i].equals(flavor))
+ return(true);
+
+ return(false);
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the data in the requested format.
+ *
+ * @param flavor The desired data flavor.
+ *
+ * @return The transferred data.
+ *
+ * @exception UnsupportedFlavorException If the specified flavor is not
+ * supported.
+ * @exception IOException If any other error occurs.
+ */
+public Object
+getTransferData(DataFlavor flavor) throws UnsupportedFlavorException,
+ IOException
+{
+ if (!isDataFlavorSupported(flavor))
+ throw new UnsupportedFlavorException(flavor);
+
+ if (DataFlavor.plainTextFlavor == flavor)
+ /* The behavior of this method for DataFlavor.plainTextFlavor and
+ equivalent DataFlavors is inconsistent with the definition of
+ DataFlavor.plainTextFlavor. We choose to do like Sun's implementation
+ and return a Reader instead of an InputString. */
+ /* return(new StringBufferInputStream(data)); */
+ return(new StringReader(data));
+ else // DataFlavor.stringFlavor
+ return data;
+}
+
+/*************************************************************************/
+
+/**
+ * Called when ownership of the clipboard object is lost.
+ *
+ * @param clipboard The affected clipboard.
+ * @param contents The clipboard contents.
+ */
+public void
+lostOwnership(Clipboard clipboard, Transferable contents)
+{
+ // FIXME: What does this do?
+}
+
+} // class StringSelection
+
diff --git a/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java b/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java
new file mode 100644
index 00000000000..f6530f5117c
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java
@@ -0,0 +1,169 @@
+/* SystemFlavorMap.java -- Maps between native flavor names and MIME types.
+ Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class maps between native platform type names and DataFlavors.
+ *
+ * XXX - The current implementation does no mapping at all.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ *
+ * @since 1.2
+ */
+public final class SystemFlavorMap implements FlavorMap, FlavorTable
+{
+ /**
+ * The default (instance) flavor map.
+ */
+ private static FlavorMap defaultFlavorMap;
+
+ /**
+ * Private constructor.
+ */
+ private SystemFlavorMap ()
+ {
+ }
+
+ /**
+ * Maps the specified <code>DataFlavor</code> objects to the native
+ * data type name. The returned <code>Map</code> has keys that are
+ * the data flavors and values that are strings. The returned map
+ * may be modified. This can be useful for implementing nested mappings.
+ *
+ * @param flavors An array of data flavors to map
+ * or null for all data flavors.
+ *
+ * @return A <code>Map</code> of native data types to data flavors.
+ */
+ public Map getNativesForFlavors (DataFlavor[] flavors)
+ {
+ return new HashMap();
+ }
+
+ /**
+ * Maps the specified native type names to <code>DataFlavor</code>'s.
+ * The returned <code>Map</code> has keys that are strings and values
+ * that are <code>DataFlavor</code>'s. The returned map may be
+ * modified. This can be useful for implementing nested mappings.
+ *
+ * @param natives An array of native types to map
+ * or null for all native types.
+ *
+ * @return A <code>Map</code> of data flavors to native type names.
+ */
+ public Map getFlavorsForNatives (String[] natives)
+ {
+ return new HashMap();
+ }
+
+ /**
+ * Returns the default (instance) (System)FlavorMap.
+ */
+ public static FlavorMap getDefaultFlavorMap ()
+ {
+ if (defaultFlavorMap == null)
+ defaultFlavorMap = new SystemFlavorMap ();
+
+ return defaultFlavorMap;
+ }
+
+ /**
+ * Returns the native type name for the given java mime type.
+ */
+ public static String encodeJavaMIMEType (String mime)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the native type name for the given data flavor.
+ */
+ public static String encodeDataFlavor (DataFlavor df)
+ {
+ return null;
+ }
+
+ /**
+ * Returns true if the native type name can be represented as
+ * a java mime type.
+ */
+ public static boolean isJavaMIMEType (String name)
+ {
+ return false;
+ }
+
+ /**
+ * Returns the java mime type for the given the native type name.
+ */
+ public static String decodeJavaMIMEType (String name)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the data flavor given the native type name
+ * or null when no such data flavor exists.
+ */
+ public static DataFlavor decodeDataFlavor (String name)
+ throws ClassNotFoundException
+ {
+ String javaMIMEType = decodeJavaMIMEType (name);
+
+ if (javaMIMEType != null)
+ return new DataFlavor (javaMIMEType);
+ else
+ return null;
+ }
+
+ public List getFlavorsForNative (String nat)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public List getNativesForFlavor (DataFlavor flav)
+ {
+ throw new Error ("Not implemented");
+ }
+
+} // class SystemFlavorMap
diff --git a/libjava/classpath/java/awt/datatransfer/Transferable.java b/libjava/classpath/java/awt/datatransfer/Transferable.java
new file mode 100644
index 00000000000..80753923618
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/Transferable.java
@@ -0,0 +1,83 @@
+/* Transferable.java -- Data transfer source
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.io.IOException;
+
+/**
+ * This interface is implemented by classes that can transfer data.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Transferable
+{
+ /**
+ * This method returns a list of available data flavors for the data being
+ * transferred. The array returned will be sorted from most preferred
+ * flavor at the beginning to least preferred at the end.
+ *
+ * @return adA list of data flavors for this data
+ */
+ DataFlavor[] getTransferDataFlavors();
+
+ /**
+ * Tests whether or not this data can be delivered in the specified data
+ * flavor.
+ *
+ * @param flavor the data flavor to test
+ * @return true if the data flavor is supported
+ */
+ boolean isDataFlavorSupported(DataFlavor flavor);
+
+ /**
+ * Returns the data in the specified <code>DataFlavor</code>.
+ *
+ * @param flavor the data flavor to return
+ * @return the data in the appropriate flavor
+ * @throws UnsupportedFlavorException if the flavor is not supported
+ * @throws IOException if the data is not available
+ * @see DataFlavor#getRepresentationClass
+ */
+ Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException;
+
+} // interface Transferable
+
diff --git a/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java b/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java
new file mode 100644
index 00000000000..1c1da0348c3
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java
@@ -0,0 +1,65 @@
+/* UnsupportedFlavorException.java -- ata flavor is not valid
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+/**
+ * The data flavor requested is not supported for the transfer data.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Transferable#getTransferData(DataFlavor)
+ * @status updated to 1.4
+ */
+public class UnsupportedFlavorException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5383814944251665601L;
+
+ /**
+ * Initializes a new instance of <code>UnsupportedDataFlavor</code>
+ * for the specified data flavor.
+ *
+ * @param flavor the data flavor that is not supported
+ */
+ public UnsupportedFlavorException(DataFlavor flavor)
+ {
+ super(flavor == null ? null : flavor.getHumanPresentableName());
+ }
+} // class UnsupportedFlavorException
diff --git a/libjava/classpath/java/awt/datatransfer/package.html b/libjava/classpath/java/awt/datatransfer/package.html
new file mode 100644
index 00000000000..5ab860cdc19
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.datatransfer package.
+ Copyright (C) 2002 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 - java.awt.datatransfer</title></head>
+
+<body>
+<p>Classes to represent different flavors of data for transferring native
+and system types through for example a clipboard.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/dnd/Autoscroll.java b/libjava/classpath/java/awt/dnd/Autoscroll.java
new file mode 100644
index 00000000000..ba4d4476cfc
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/Autoscroll.java
@@ -0,0 +1,70 @@
+/* Autoscroll.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Insets;
+import java.awt.Point;
+
+/**
+ * During DnD operations it is possible that a user may wish to drop the
+ * subject of the operation on a region of a scrollable GUI control that
+ * is not currently visible to the user.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Autoscroll
+{
+ /**
+ * This method returns the Insets describing the autoscrolling region or
+ * border relative to the geometry of the implementing Component
+ */
+ Insets getAutoscrollInsets ();
+
+ /**
+ * Notify the Component to autoscroll
+ *
+ * @param location A Point indicating the location of the cursor that
+ * triggered this operation
+ */
+ void autoscroll (Point location);
+
+} // interface Autoscroll
+
diff --git a/libjava/classpath/java/awt/dnd/DnDConstants.java b/libjava/classpath/java/awt/dnd/DnDConstants.java
new file mode 100644
index 00000000000..85c9c0528e6
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DnDConstants.java
@@ -0,0 +1,77 @@
+/* DnDConstants.java -- constants for drag-and-drop operations
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+/**
+ * This class contains various constants used in drag-and-drop operations.
+ * Why it is not an interface is beyond me.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class DnDConstants
+{
+ /** No action takes place. */
+ public static final int ACTION_NONE = 0;
+
+ /** The copy action. */
+ public static final int ACTION_COPY = 1;
+
+ /** The move action. */
+ public static final int ACTION_MOVE = 2;
+
+ /** Either a copy or a move. */
+ public static final int ACTION_COPY_OR_MOVE = 3;
+
+ /**
+ * A link action. This does not copy or move, but creates a reference back
+ * to the original. However, since platforms differ on how a reference should
+ * behave, this action is not recommended for common use.
+ */
+ public static final int ACTION_LINK = 1073741824;
+
+ /** A synonym for {@link #ACTION_LINK}. */
+ public static final int ACTION_REFERENCE = ACTION_LINK;
+
+ private DnDConstants()
+ {
+ // Do nothing here.
+ }
+}
diff --git a/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java b/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java
new file mode 100644
index 00000000000..d9f5ec00f1d
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java
@@ -0,0 +1,74 @@
+/* DnDEventMulticaster.java -- helper class for listener chains in java.awt.dnd
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.AWTEventMulticaster;
+import java.util.EventListener;
+
+class DnDEventMulticaster extends AWTEventMulticaster
+{
+ protected DnDEventMulticaster (EventListener a, EventListener b)
+ {
+ super (a, b);
+ }
+
+ public static DragSourceListener add (DragSourceListener a,
+ DragSourceListener b)
+ {
+ return (DragSourceListener) addInternal (a, b);
+ }
+
+ public static DragSourceMotionListener add (DragSourceMotionListener a,
+ DragSourceMotionListener b)
+ {
+ return (DragSourceMotionListener) addInternal (a, b);
+ }
+
+ public static DragSourceListener remove (DragSourceListener a,
+ DragSourceListener b)
+ {
+ return (DragSourceListener) removeInternal (a, b);
+ }
+
+ public static DragSourceMotionListener remove (DragSourceMotionListener a,
+ DragSourceMotionListener b)
+ {
+ return (DragSourceMotionListener) removeInternal (a, b);
+ }
+}
diff --git a/libjava/classpath/java/awt/dnd/DragGestureEvent.java b/libjava/classpath/java/awt/dnd/DragGestureEvent.java
new file mode 100644
index 00000000000..9f2bc7c98b8
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragGestureEvent.java
@@ -0,0 +1,156 @@
+/* DragGestureEvent.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.datatransfer.Transferable;
+import java.awt.event.InputEvent;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * STUBBED
+ * @see DragGestureRecognizer
+ * @see DragGestureListener
+ * @see DragSource
+ * @since 1.2
+ */
+public class DragGestureEvent extends EventObject
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 9080172649166731306L;
+
+ private DragSource dragSource;
+ private Component component;
+ private final Point origin;
+ private final int action;
+
+ public DragGestureEvent(DragGestureRecognizer dgr, int action, Point origin,
+ List events)
+ {
+ super(dgr);
+ if (origin == null || events == null)
+ throw new IllegalArgumentException();
+ this.origin = origin;
+ this.action = action;
+ }
+
+ public DragGestureRecognizer getSourceAsDragGestureRecognizer()
+ {
+ return (DragGestureRecognizer) source;
+ }
+ public Component getComponent()
+ {
+ return null;
+ }
+ public DragSource getDragSource()
+ {
+ return null;
+ }
+ public Point getDragOrigin()
+ {
+ return origin;
+ }
+ public Iterator iterator()
+ {
+ return null;
+ }
+ public Object[] toArray()
+ {
+ return null;
+ }
+ public Object[] toArray(Object[] array)
+ {
+ return array;
+ }
+ public int getDragAction()
+ {
+ return 0;
+ }
+ public InputEvent getTriggerEvent()
+ {
+ return null;
+ }
+
+ /**
+ * Starts the drag given the initial Cursor to display, the Transferable
+ * object, and the DragSourceListener to use.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(Cursor dragCursor, Transferable trans)
+ {
+ startDrag(dragCursor, null, null, trans, null);
+ }
+
+ /**
+ * Starts the drag given the initial Cursor to display, the Transferable
+ * object, and the DragSourceListener to use.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(Cursor dragCursor, Transferable trans,
+ DragSourceListener l)
+ {
+ startDrag(dragCursor, null, null, trans, l);
+ }
+
+ /**
+ * Starts the drag given the initial Cursor to display, the Transferable
+ * object, and the DragSourceListener to use.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(Cursor dragCursor, Image dragImage, Point imageOffset,
+ Transferable trans, DragSourceListener l)
+ {
+ }
+} // class DragGestureEvent
diff --git a/libjava/classpath/java/awt/dnd/DragGestureListener.java b/libjava/classpath/java/awt/dnd/DragGestureListener.java
new file mode 100644
index 00000000000..e8befe80f19
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragGestureListener.java
@@ -0,0 +1,63 @@
+/* DragGestureListener.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.util.EventListener;
+
+/**
+ * This is a listener for starting a drag-and-drop gesture. Upon receiving
+ * notification, the implementor then starts the drag operation.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see DragGestureRecognizer
+ * @see DragGestureEvent
+ * @see DragSource
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface DragGestureListener extends EventListener
+{
+ /**
+ * Called when the native platform notifies the virtual machine that a
+ * drag-and-drop has been initiated.
+ *
+ * @param e the event
+ */
+ void dragGestureRecognized(DragGestureEvent e);
+} // interface DragGestureListener
diff --git a/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java b/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java
new file mode 100644
index 00000000000..07b822e7a68
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java
@@ -0,0 +1,179 @@
+/* DragGestureRecognizer.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.event.InputEvent;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.TooManyListenersException;
+
+/**
+ * STUBBED
+ * @since 1.2
+ */
+public abstract class DragGestureRecognizer implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 8996673345831063337L;
+
+ protected DragSource dragSource;
+ protected Component component;
+ protected transient DragGestureListener dragGestureListener;
+ protected int sourceActions;
+ protected ArrayList events = new ArrayList();
+
+ protected DragGestureRecognizer(DragSource ds, Component c, int sa,
+ DragGestureListener dgl)
+ {
+ if (ds == null)
+ throw new IllegalArgumentException();
+ dragSource = ds;
+ component = c;
+ sourceActions = sa;
+ dragGestureListener = dgl;
+ }
+
+ protected DragGestureRecognizer(DragSource ds, Component c, int sa)
+ {
+ this(ds, c, sa, null);
+ }
+
+ protected DragGestureRecognizer(DragSource ds, Component c)
+ {
+ this(ds, c, 0, null);
+ }
+
+ protected DragGestureRecognizer(DragSource ds)
+ {
+ this(ds, null, 0, null);
+ }
+
+ protected abstract void registerListeners();
+
+ protected abstract void unregisterListeners();
+
+ public DragSource getDragSource()
+ {
+ return dragSource;
+ }
+
+ public Component getComponent()
+ {
+ return component;
+ }
+
+ public void setComponent(Component c)
+ {
+ component = c;
+ }
+
+ public int getSourceActions()
+ {
+ return sourceActions;
+ }
+
+ public void setSourceActions(int sa)
+ {
+ sourceActions = sa;
+ }
+
+ public InputEvent getTriggerEvent()
+ {
+ return events.size() > 0 ? (InputEvent) events.get(0) : null;
+ }
+
+ public void resetRecognizer()
+ {
+ throw new Error("not implemented");
+ }
+
+ /**
+ * Register a new DragGestureListener.
+ *
+ * @exception TooManyListenersException If a DragGestureListener has already
+ * been added.
+ */
+ public void addDragGestureListener(DragGestureListener dgl)
+ throws TooManyListenersException
+ {
+ if (dragGestureListener != null)
+ throw new TooManyListenersException();
+ dragGestureListener = dgl;
+ }
+
+ public void removeDragGestureListener(DragGestureListener dgl)
+ {
+ if (dragGestureListener != dgl)
+ throw new IllegalArgumentException();
+ dragGestureListener = null;
+ }
+
+ protected void fireDragGestureRecognized(int dragAction, Point p)
+ {
+ throw new Error("not implemented");
+ }
+
+ protected void appendEvent(InputEvent e)
+ {
+ if (e == null)
+ return;
+ events.add(e);
+ }
+
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject();
+ dragGestureListener = (DragGestureListener) s.readObject();
+ }
+
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ s.writeObject(dragGestureListener instanceof Serializable
+ ? dragGestureListener : null);
+ }
+} // class DragGestureRecognizer
diff --git a/libjava/classpath/java/awt/dnd/DragSource.java b/libjava/classpath/java/awt/dnd/DragSource.java
new file mode 100644
index 00000000000..13ffc961510
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSource.java
@@ -0,0 +1,257 @@
+/* DragSource.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.datatransfer.FlavorMap;
+import java.awt.datatransfer.SystemFlavorMap;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.io.Serializable;
+import java.util.EventListener;
+
+/**
+ * @since 1.2
+ */
+public class DragSource implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 6236096958971414066L;
+
+ public static final Cursor DefaultCopyDrop = null;
+ public static final Cursor DefaultMoveDrop = null;
+ public static final Cursor DefaultLinkDrop = null;
+ public static final Cursor DefaultCopyNoDrop = null;
+ public static final Cursor DefaultMoveNoDrop = null;
+ public static final Cursor DefaultLinkNoDrop = null;
+
+ private transient FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap ();
+
+ private transient DragSourceListener dragSourceListener;
+ private transient DragSourceMotionListener dragSourceMotionListener;
+
+ /**
+ * Initializes the drag source.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public DragSource()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+ }
+
+ /**
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public static DragSource getDefaultDragSource()
+ {
+ return null;
+ }
+
+ public static boolean isDragImageSupported()
+ {
+ return false;
+ }
+
+ /**
+ * Start a drag, given the DragGestureEvent that initiated the drag.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
+ Image dragImage, Point imageOffset,
+ Transferable trans, DragSourceListener dsl,
+ FlavorMap map)
+ {
+ }
+
+ /**
+ * Start a drag, given the DragGestureEvent that initiated the drag.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
+ Transferable trans, DragSourceListener dsl,
+ FlavorMap map)
+ {
+ startDrag(trigger, dragCursor, null, null, trans, dsl, map);
+ }
+
+ /**
+ * Start a drag, given the DragGestureEvent that initiated the drag.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
+ Image dragImage, Point imageOffset,
+ Transferable trans, DragSourceListener dsl)
+ {
+ startDrag(trigger, dragCursor, dragImage, imageOffset, trans, dsl, null);
+ }
+
+ /**
+ * Start a drag, given the DragGestureEvent that initiated the drag.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
+ Transferable trans, DragSourceListener dsl)
+ {
+ startDrag(trigger, dragCursor, null, null, trans, dsl, null);
+ }
+
+ /**
+ * Creates the DragSourceContext to handle this drag.
+ *
+ * @exception IllegalArgumentException FIXME
+ * @exception NullPointerException If dscp, dgl, dragImage or t is null.
+ */
+ protected DragSourceContext
+ createDragSourceContext(DragSourceContextPeer peer, DragGestureEvent dge,
+ Cursor cursor, Image image, Point offset,
+ Transferable t, DragSourceListener dsl)
+ {
+ return null;
+ }
+
+ public FlavorMap getFlavorMap()
+ {
+ return flavorMap;
+ }
+
+ public DragGestureRecognizer
+ createDragGestureRecognizer(Class recognizer, Component c, int actions,
+ DragGestureListener dgl)
+ {
+ return Toolkit.getDefaultToolkit ()
+ .createDragGestureRecognizer (recognizer, this, c, actions,
+ dgl);
+ }
+
+ public DragGestureRecognizer
+ createDefaultDragGestureRecognizer(Component c, int actions,
+ DragGestureListener dgl)
+ {
+ return createDragGestureRecognizer (MouseDragGestureRecognizer.class, c,
+ actions, dgl);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void addDragSourceListener(DragSourceListener l)
+ {
+ DnDEventMulticaster.add (dragSourceListener, l);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void removeDragSourceListener(DragSourceListener l)
+ {
+ DnDEventMulticaster.remove (dragSourceListener, l);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public DragSourceListener[] getDragSourceListeners()
+ {
+ return (DragSourceListener[]) getListeners (DragSourceListener.class);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void addDragSourceMotionListener(DragSourceMotionListener l)
+ {
+ DnDEventMulticaster.add (dragSourceMotionListener, l);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void removeDragSourceMotionListener(DragSourceMotionListener l)
+ {
+ DnDEventMulticaster.remove (dragSourceMotionListener, l);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public DragSourceMotionListener[] getDragSourceMotionListeners ()
+ {
+ return (DragSourceMotionListener[]) getListeners
+ (DragSourceMotionListener.class);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public EventListener[] getListeners (Class listenerType)
+ {
+ if (listenerType == DragSourceListener.class)
+ return DnDEventMulticaster.getListeners (dragSourceListener,
+ listenerType);
+
+ if (listenerType == DragSourceMotionListener.class)
+ return DnDEventMulticaster.getListeners (dragSourceMotionListener,
+ listenerType);
+
+ // Return an empty EventListener array.
+ return new EventListener [0];
+ }
+} // class DragSource
diff --git a/libjava/classpath/java/awt/dnd/DragSourceAdapter.java b/libjava/classpath/java/awt/dnd/DragSourceAdapter.java
new file mode 100644
index 00000000000..90d9a698347
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceAdapter.java
@@ -0,0 +1,126 @@
+/* DragSourceAdapter.java -- drag-and-drop listener adapter
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+/**
+ * This class implements <code>DragSourceListener</code> and
+ * <code>DragSourceMotionListener</code>, and implements all methods
+ * with empty bodies. This allows a listener interested in implementing only
+ * a subset of these interfaces to extend this class and override only the
+ * desired methods.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see DragSourceEvent
+ * @see DragSourceListener
+ * @see DragSourceMotionListener
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class DragSourceAdapter
+ implements DragSourceListener, DragSourceMotionListener
+{
+ /**
+ * Default constructor.
+ */
+ public DragSourceAdapter()
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot enters a drop site which will accept the
+ * drag.
+ *
+ * @param e the event
+ */
+ public void dragEnter(DragSourceDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot moves inside of a drop site which will
+ * accept the drag.
+ *
+ * @param e the event
+ */
+ public void dragOver(DragSourceDragEvent e)
+ {
+ }
+
+ /**
+ * Called whenever the mouse is moved during a drag-and-drop operation.
+ *
+ * @param e the event
+ */
+ public void dragMouseMoved(DragSourceDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the user modifies the drop gesture. This is often the case
+ * when additional mouse or key events are received during the drag.
+ *
+ * @param e the event
+ */
+ public void dropActionChanged(DragSourceDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot moves outside of a drop site which will
+ * accept the drag. This could also happen if the drop site is no longer
+ * active, or no longer accepts the drag.
+ *
+ * @param e the event
+ */
+ public void dragExit(DragSourceEvent e)
+ {
+ }
+
+ /**
+ * Called when the drag and drop operation is complete. After this event,
+ * <code>getDropSuccess</code> of the event is valid, and
+ * <code>getDropAction</code> holds the action requested by the drop site.
+ * Furthermore, the <code>DragSourceContext</code> is invalidated.
+ *
+ * @param e the event
+ */
+ public void dragDropEnd(DragSourceDropEvent e)
+ {
+ }
+} // class DragSourceAdapter
diff --git a/libjava/classpath/java/awt/dnd/DragSourceContext.java b/libjava/classpath/java/awt/dnd/DragSourceContext.java
new file mode 100644
index 00000000000..2cf0d6d0bc9
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceContext.java
@@ -0,0 +1,200 @@
+/* DragSourceContext.java --
+ Copyright (C) 2002 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.dnd;
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.io.Serializable;
+import java.util.TooManyListenersException;
+
+/**
+ * @since 1.2
+ */
+public class DragSourceContext
+ implements DragSourceListener, DragSourceMotionListener, Serializable
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ static final long serialVersionUID = -115407898692194719L;
+
+ protected static final int DEFAULT = 0;
+ protected static final int ENTER = 1;
+ protected static final int OVER = 2;
+ protected static final int CHANGED = 3;
+
+ private DragSourceContextPeer peer;
+ private Cursor cursor;
+ private Transferable transferable;
+ private DragGestureEvent trigger;
+ private DragSourceListener dragSourceListener;
+ private boolean useCustomCursor; // FIXME: currently unused but needed for serialization.
+ private int sourceActions; // FIXME: currently unused but needed for serialization.
+ private Image image;
+ private Point offset;
+
+ /**
+ * Initializes a drag source context.
+ *
+ * @exception IllegalArgumentException If Component or DragSource of trigger
+ * are null, the drag action for the trigger event is DnDConstants.ACTION_NONE
+ * or if the source actions for the DragGestureRecognizer associated with the
+ * trigger event are equal to DnDConstants.ACTION_NONE.
+ * @exception NullPointerException If peer or trigger is null.
+ */
+ public DragSourceContext (DragSourceContextPeer peer,
+ DragGestureEvent trigger, Cursor cursor,
+ Image image, Point offset, Transferable trans,
+ DragSourceListener dsl)
+ {
+ if (peer == null
+ || trigger == null)
+ throw new NullPointerException ();
+
+ if (trigger.getComponent () == null
+ || trigger.getDragSource () == null
+ || trigger.getDragAction () == DnDConstants.ACTION_NONE
+ || trigger.getSourceAsDragGestureRecognizer ()
+ .getSourceActions () == DnDConstants.ACTION_NONE)
+ throw new IllegalArgumentException ();
+
+ this.peer = peer;
+ this.trigger = trigger;
+ this.cursor = cursor;
+ this.image = image;
+ this.offset = offset;
+ this.transferable = trans;
+ this.dragSourceListener = dsl;
+
+ throw new Error ("not implemented");
+ }
+
+ public DragSource getDragSource()
+ {
+ return trigger.getDragSource ();
+ }
+
+ public Component getComponent()
+ {
+ return trigger.getComponent ();
+ }
+
+ public DragGestureEvent getTrigger()
+ {
+ return trigger;
+ }
+
+ public int getSourceActions()
+ {
+ return trigger.getSourceAsDragGestureRecognizer ().getSourceActions ();
+ }
+
+ public void setCursor (Cursor cursor)
+ {
+ this.cursor = cursor;
+ // FIXME: Check if we need to do more here
+ }
+
+ public Cursor getCursor()
+ {
+ return cursor;
+ }
+
+ /**
+ * Adds a <code>DragSourceListener</code>.
+ *
+ * @exception TooManyListenersException If a <code>DragSourceListener</code>
+ * has already been added.
+ */
+ public void addDragSourceListener (DragSourceListener dsl)
+ throws TooManyListenersException
+ {
+ if (dragSourceListener != null)
+ throw new TooManyListenersException ();
+
+ dragSourceListener = dsl;
+ }
+
+ public void removeDragSourceListener (DragSourceListener dsl)
+ {
+ if (dragSourceListener == dsl)
+ dragSourceListener = null;
+ }
+
+ public void transferablesFlavorsChanged()
+ {
+ }
+
+ public void dragEnter(DragSourceDragEvent e)
+ {
+ }
+
+ public void dragOver(DragSourceDragEvent e)
+ {
+ }
+
+ public void dragExit(DragSourceEvent e)
+ {
+ }
+
+ public void dropActionChanged(DragSourceDragEvent e)
+ {
+ }
+
+ public void dragDropEnd(DragSourceDropEvent e)
+ {
+ }
+
+ public void dragMouseMoved(DragSourceDragEvent e)
+ {
+ }
+
+ public Transferable getTransferable()
+ {
+ return transferable;
+ }
+
+ protected void updateCurrentCursor(int dropOp, int targetAct, int status)
+ {
+ }
+} // class DragSourceContext
diff --git a/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java b/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java
new file mode 100644
index 00000000000..511700b616d
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java
@@ -0,0 +1,102 @@
+/* DragSourceDragEvent.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import gnu.java.awt.EventModifier;
+
+/**
+ * @author Michael Koch
+ * @since 1.2
+ */
+public class DragSourceDragEvent extends DragSourceEvent
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = 481346297933902471L;
+
+ private final int dropAction;
+ private final int targetActions;
+ private final int gestureModifiers;
+
+ public DragSourceDragEvent(DragSourceContext context, int dropAction,
+ int actions, int modifiers)
+ {
+ super(context);
+ this.dropAction = dropAction;
+ targetActions = actions;
+ gestureModifiers = EventModifier.extend(modifiers);
+ }
+
+ public DragSourceDragEvent(DragSourceContext context, int dropAction,
+ int actions, int modifiers, int x, int y)
+ {
+ super(context, x, y);
+ this.dropAction = dropAction;
+ targetActions = actions;
+ gestureModifiers = EventModifier.extend(modifiers);
+ }
+
+ public int getTargetActions()
+ {
+ return targetActions;
+ }
+
+ public int getGestureModifiers()
+ {
+ return EventModifier.revert(gestureModifiers);
+ }
+
+ public int getGestureModifiersEx()
+ {
+ return gestureModifiers;
+ }
+
+ public int getUserAction()
+ {
+ return dropAction;
+ }
+
+ public int getDropAction()
+ {
+ return (dropAction
+ & targetActions
+ & ((DragSourceContext) source).getSourceActions());
+ }
+} // class DragSourceDragEvent
diff --git a/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java b/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java
new file mode 100644
index 00000000000..7621262d839
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java
@@ -0,0 +1,89 @@
+/* DragSourceDragEvent.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.2
+ *
+ * Written using JDK 1.4.1 Online API
+ * Status: JDK 1.4 complete
+ */
+public class DragSourceDropEvent extends DragSourceEvent
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = -5571321229470821891L;
+
+ private final int dropAction;
+ private final boolean dropSuccess;
+
+ public DragSourceDropEvent (DragSourceContext context)
+ {
+ super (context);
+ this.dropAction = 0;
+ this.dropSuccess = false;
+ }
+
+ public DragSourceDropEvent (DragSourceContext context, int dropAction,
+ boolean dropSuccess)
+ {
+ super (context);
+ this.dropAction = dropAction;
+ this.dropSuccess = dropSuccess;
+ }
+
+ public DragSourceDropEvent (DragSourceContext context, int dropAction,
+ boolean dropSuccess, int x, int y)
+ {
+ super (context, x, y);
+ this.dropAction = dropAction;
+ this.dropSuccess = dropSuccess;
+ }
+
+ public int getDropAction()
+ {
+ return dropAction & ((DragSourceContext) source).getSourceActions();
+ }
+
+ public boolean getDropSuccess()
+ {
+ return dropSuccess;
+ }
+} // class DragSourceDropEvent
diff --git a/libjava/classpath/java/awt/dnd/DragSourceEvent.java b/libjava/classpath/java/awt/dnd/DragSourceEvent.java
new file mode 100644
index 00000000000..c5cd42a4e2b
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceEvent.java
@@ -0,0 +1,93 @@
+/* DragSourceEvent.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Point;
+import java.util.EventObject;
+
+/**
+ * @since 1.2
+ */
+public class DragSourceEvent extends EventObject
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = -763287114604032641L;
+
+ private final boolean locationSpecified;
+ private final int x;
+ private final int y;
+
+ public DragSourceEvent(DragSourceContext context)
+ {
+ super(context);
+ locationSpecified = false;
+ x = 0;
+ y = 0;
+ }
+
+ public DragSourceEvent(DragSourceContext context, int x, int y)
+ {
+ super(context);
+ locationSpecified = true;
+ this.x = x;
+ this.y = y;
+ }
+
+ public DragSourceContext getDragSourceContext()
+ {
+ return (DragSourceContext) source;
+ }
+
+ public Point getLocation()
+ {
+ return locationSpecified ? new Point(x, y) : null;
+ }
+
+ public int getX()
+ {
+ return x;
+ }
+
+ public int getY()
+ {
+ return y;
+ }
+} // class DragSourceEvent
diff --git a/libjava/classpath/java/awt/dnd/DragSourceListener.java b/libjava/classpath/java/awt/dnd/DragSourceListener.java
new file mode 100644
index 00000000000..aac6e94ebe7
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceListener.java
@@ -0,0 +1,97 @@
+/* DragSourceListener.java -- listen to events during the drag
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.util.EventListener;
+
+/**
+ * This class allows an object to listen for drag and drop events. It can
+ * be used to provide appropriate feedback for "drag over" actions. You can
+ * also use a <code>DragSourceAdapter</code> to filter the events you are
+ * interested in.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface DragSourceListener extends EventListener
+{
+ /**
+ * Called when the cursor hotspot enters a drop site which will accept the
+ * drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragEnter(DragSourceDragEvent e);
+
+ /**
+ * Called when the cursor hotspot moves inside of a drop site which will
+ * accept the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragOver(DragSourceDragEvent e);
+
+ /**
+ * Called when the user modifies the drop gesture. This is often the case
+ * when additional mouse or key events are received during the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dropActionChanged(DragSourceDragEvent e);
+
+ /**
+ * Called when the cursor hotspot moves outside of a drop site which will
+ * accept the drag. This could also happen if the drop site is no longer
+ * active, or no longer accepts the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragExit(DragSourceEvent e);
+
+ /**
+ * Called when the drag and drop operation is complete. After this event,
+ * <code>getDropSuccess</code> of the event is valid, and
+ * <code>getDropAction</code> holds the action requested by the drop site.
+ * Furthermore, the <code>DragSourceContext</code> is invalidated.
+ *
+ * @param e the drag source drag event
+ */
+ void dragDropEnd(DragSourceDropEvent e);
+} // interface DragSourceListener
diff --git a/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java b/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java
new file mode 100644
index 00000000000..5d04c227100
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java
@@ -0,0 +1,64 @@
+/* DragSourceMotionListener.java -- tracks motion in the drag source
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.util.EventListener;
+
+/**
+ * This is a listener for mouse motion in the drag source before the drop
+ * event occurs. You can also use a <code>DragSourceAdapter</code> to filter
+ * the events you are interested in.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see DragSourceDragEvent
+ * @see DragSource
+ * @see DragSourceListener
+ * @see DragSourceAdapter
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface DragSourceMotionListener extends EventListener
+{
+ /**
+ * Called whenever the mouse is moved during a drag-and-drop operation.
+ *
+ * @param e the event
+ */
+ void dragMouseMoved(DragSourceDragEvent e);
+} // interface DragSourceMotionListener
diff --git a/libjava/classpath/java/awt/dnd/DropTarget.java b/libjava/classpath/java/awt/dnd/DropTarget.java
new file mode 100644
index 00000000000..9fd7ef896fb
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTarget.java
@@ -0,0 +1,293 @@
+/* DropTarget.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Point;
+import java.awt.datatransfer.FlavorMap;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.Serializable;
+import java.util.EventListener;
+import java.util.TooManyListenersException;
+
+/**
+ * @author Michael Koch
+ * @since 1.2
+ */
+public class DropTarget
+ implements DropTargetListener, EventListener, Serializable
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = -6283860791671019047L;
+
+ /** @specnote According to the online documentation, this is
+ * protected, but in reality it is public. */
+ public static class DropTargetAutoScroller
+ implements ActionListener
+ {
+ private Component component;
+ private Point point;
+
+ protected DropTargetAutoScroller (Component c, Point p)
+ {
+ component = c;
+ point = p;
+ }
+
+ protected void updateLocation (Point newLocn)
+ {
+ point = newLocn;
+ }
+
+ protected void stop ()
+ {
+ }
+
+ public void actionPerformed (ActionEvent e)
+ {
+ }
+ }
+
+ private Component component;
+ private FlavorMap flavorMap;
+ private int actions;
+ private DropTargetContext dropTargetContext;
+ private DropTargetListener dropTargetListener;
+ private boolean active = true;
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget ()
+ {
+ this (null, 0, null, true, null);
+ }
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget (Component c, DropTargetListener dtl)
+ {
+ this (c, 0, dtl, true, null);
+ }
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget (Component c, int i, DropTargetListener dtl)
+ {
+ this (c, i, dtl, true, null);
+ }
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget (Component c, int i, DropTargetListener dtl, boolean b)
+ {
+ this (c, i, dtl, b, null);
+ }
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget (Component c, int i, DropTargetListener dtl, boolean b,
+ FlavorMap fm)
+ {
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+
+ component = c;
+ actions = i;
+ dropTargetListener = dtl;
+ flavorMap = fm;
+
+ setActive (b);
+ }
+
+ /**
+ * Sets the component associated with this drop target object.
+ */
+ public void setComponent (Component c)
+ {
+ component = c;
+ }
+
+ /**
+ * Returns the component associated with this drop target object.
+ */
+ public Component getComponent ()
+ {
+ return component;
+ }
+
+ /**
+ * Sets the default actions.
+ */
+ public void setDefaultActions (int ops)
+ {
+ actions = ops;
+ }
+
+ /**
+ * Returns the default actions.
+ */
+ public int getDefaultActions ()
+ {
+ return actions;
+ }
+
+ public void setActive (boolean active)
+ {
+ this.active = active;
+ }
+
+ public boolean isActive()
+ {
+ return active;
+ }
+
+ /**
+ * Adds a new <code>DropTargetListener</code>.
+ *
+ * @exception TooManyListenersException Sun's JDK does not, despite
+ * documentation, throw this exception here when you install an additional
+ * <code>DropTargetListener</code>. So to be compatible, we do the same
+ * thing.
+ */
+ public void addDropTargetListener (DropTargetListener dtl)
+ throws TooManyListenersException
+ {
+ dropTargetListener = dtl;
+ }
+
+ public void removeDropTargetListener(DropTargetListener dtl)
+ {
+ // FIXME: Do we need to do something with dtl ?
+ dropTargetListener = null;
+ }
+
+ public void dragEnter(DropTargetDragEvent dtde)
+ {
+ }
+
+ public void dragOver(DropTargetDragEvent dtde)
+ {
+ }
+
+ public void dropActionChanged(DropTargetDragEvent dtde)
+ {
+ }
+
+ public void dragExit(DropTargetEvent dte)
+ {
+ }
+
+ public void drop(DropTargetDropEvent dtde)
+ {
+ }
+
+ public FlavorMap getFlavorMap()
+ {
+ return flavorMap;
+ }
+
+ public void setFlavorMap(FlavorMap fm)
+ {
+ flavorMap = fm;
+ }
+
+ public void addNotify(java.awt.peer.ComponentPeer peer)
+ {
+ }
+
+ public void removeNotify(java.awt.peer.ComponentPeer peer)
+ {
+ }
+
+ public DropTargetContext getDropTargetContext()
+ {
+ if (dropTargetContext == null)
+ dropTargetContext = createDropTargetContext ();
+
+ return dropTargetContext;
+ }
+
+ protected DropTargetContext createDropTargetContext()
+ {
+ return new DropTargetContext (this);
+ }
+
+ protected DropTarget.DropTargetAutoScroller createDropTargetAutoScroller
+ (Component c, Point p)
+ {
+ return new DropTarget.DropTargetAutoScroller (c, p);
+ }
+
+ protected void initializeAutoscrolling(Point p)
+ {
+ }
+
+ protected void updateAutoscroll(Point dragCursorLocn)
+ {
+ }
+
+ protected void clearAutoscroll()
+ {
+ }
+} // class DropTarget
diff --git a/libjava/classpath/java/awt/dnd/DropTargetAdapter.java b/libjava/classpath/java/awt/dnd/DropTargetAdapter.java
new file mode 100644
index 00000000000..13c6b9f4b6d
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetAdapter.java
@@ -0,0 +1,100 @@
+/* DragSourceAdapter.java -- drag-and-drop listener adapter
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+/**
+ * This class implements <code>DropTargetListener</code>, and implements all methods
+ * with empty bodies. This allows a listener interested in implementing only
+ * a subset of these interfaces to extend this class and override only the
+ * desired methods.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class DropTargetAdapter
+ implements DropTargetListener
+{
+ /**
+ * Default constructor.
+ */
+ public DropTargetAdapter()
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot enters a drop site which will accept the
+ * drag.
+ *
+ * @param e the event
+ */
+ public void dragEnter (DropTargetDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot moves inside of a drop site which will
+ * accept the drag.
+ *
+ * @param e the event
+ */
+ public void dragOver (DropTargetDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the user modifies the drop gesture. This is often the case
+ * when additional mouse or key events are received during the drag.
+ *
+ * @param e the event
+ */
+ public void dropActionChanged (DropTargetDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot moves outside of a drop site which will
+ * accept the drag. This could also happen if the drop site is no longer
+ * active, or no longer accepts the drag.
+ *
+ * @param e the event
+ */
+ public void dragExit(DropTargetEvent e)
+ {
+ }
+} // class DropTargetAdapter
diff --git a/libjava/classpath/java/awt/dnd/DropTargetContext.java b/libjava/classpath/java/awt/dnd/DropTargetContext.java
new file mode 100644
index 00000000000..d1fb66e6f35
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetContext.java
@@ -0,0 +1,188 @@
+/* DropTargetContext.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.2
+ */
+public class DropTargetContext implements Serializable
+{
+ static final long serialVersionUID = -634158968993743371L;
+
+ /** @specnote According to the online documentation, this is
+ * protected, but in reality it is public. */
+ public class TransferableProxy implements Transferable
+ {
+ protected boolean isLocal;
+ protected Transferable transferable;
+
+ TransferableProxy (Transferable t, boolean local)
+ {
+ this.transferable = t;
+ this.isLocal = local;
+ }
+
+ public DataFlavor[] getTransferDataFlavors ()
+ {
+ return transferable.getTransferDataFlavors ();
+ }
+
+ public boolean isDataFlavorSupported (DataFlavor flavor)
+ {
+ return transferable.isDataFlavorSupported (flavor);
+ }
+
+ public Object getTransferData (DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException
+ {
+ return transferable.getTransferData (flavor);
+ }
+ }
+
+ private DropTarget dropTarget;
+ private int targetActions;
+ private java.awt.dnd.peer.DropTargetContextPeer dtcp;
+
+ // package private
+ DropTargetContext (DropTarget dropTarget)
+ {
+ this.dropTarget = dropTarget;
+ }
+
+ public DropTarget getDropTarget ()
+ {
+ return dropTarget;
+ }
+
+ public Component getComponent ()
+ {
+ return dropTarget.getComponent ();
+ }
+
+ public void addNotify (java.awt.dnd.peer.DropTargetContextPeer dtcp)
+ {
+ this.dtcp = dtcp;
+ }
+
+ public void removeNotify ()
+ {
+ this.dtcp = null;
+ }
+
+ protected void setTargetActions (int actions)
+ {
+ targetActions = actions;
+ }
+
+ protected int getTargetActions()
+ {
+ return targetActions;
+ }
+
+ /**
+ * Signals that the drop is completed.
+ *
+ * @exception InvalidDnDOperationException If a drop is not outstanding.
+ */
+ public void dropComplete (boolean success)
+ {
+ // FIXME: implement this
+ }
+
+ protected void acceptDrag (int dragOperation)
+ {
+ // FIXME: implement this
+ }
+
+ protected void rejectDrag ()
+ {
+ // FIXME: implement this
+ }
+
+ protected void acceptDrop (int dropOperation)
+ {
+ // FIXME: implement this
+ }
+
+ protected void rejectDrop ()
+ {
+ // FIXME: implement this
+ }
+
+ protected DataFlavor[] getCurrentDataFlavors ()
+ {
+ // FIXME: implement this
+ return null;
+ }
+
+ protected List getCurrentDataFlavorsAsList ()
+ {
+ return Arrays.asList (getCurrentDataFlavors ());
+ }
+
+ protected boolean isDataFlavorSupported (DataFlavor flavor)
+ {
+ return getCurrentDataFlavorsAsList ().contains (flavor);
+ }
+
+ /**
+ * Return the <code>Transferable</code> operandof this operation.
+ *
+ * @exception InvalidDnDOperationException If a drag is not outstanding.
+ */
+ protected Transferable getTransferable() throws InvalidDnDOperationException
+ {
+ // FIXME: implement this
+ return null;
+ }
+
+ protected Transferable createTransferableProxy(Transferable t, boolean local)
+ {
+ return new TransferableProxy (t, local);
+ }
+} // class DropTargetContext
diff --git a/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java b/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java
new file mode 100644
index 00000000000..6cdc3a292be
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java
@@ -0,0 +1,140 @@
+/* DropTargetDragEvent.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Point;
+import java.awt.datatransfer.DataFlavor;
+import java.util.List;
+
+/**
+ * @since 1.2
+ */
+public class DropTargetDragEvent extends DropTargetEvent
+{
+ /**
+ * Compatible with 1.2+
+ */
+ private static final long serialVersionUID = -8422265619058953682L;
+
+ private final int dropAction;
+ private final int srcActions;
+ private final Point location;
+
+ /**
+ * Initializes a <code>DropTargetDragEvent</code>.
+ *
+ * @exception IllegalArgumentException If dropAction is not one of DnDConstants,
+ * srcActions is not a bitwise mask of DnDConstants, or dtc is null.
+ * @exception NullPointerException If location is null.
+ */
+ public DropTargetDragEvent (DropTargetContext context, Point location,
+ int dropAction, int srcActions)
+ {
+ super (context);
+
+ if (location == null)
+ throw new NullPointerException ();
+
+ if (context == null)
+ throw new IllegalArgumentException ();
+
+ if (dropAction != DnDConstants.ACTION_NONE
+ && dropAction != DnDConstants.ACTION_COPY
+ && dropAction != DnDConstants.ACTION_MOVE
+ && dropAction != DnDConstants.ACTION_COPY_OR_MOVE
+ && dropAction != DnDConstants.ACTION_LINK
+ && dropAction != DnDConstants.ACTION_REFERENCE)
+ throw new IllegalArgumentException ();
+
+ int srcActionsMask = DnDConstants.ACTION_NONE
+ | DnDConstants.ACTION_COPY
+ | DnDConstants.ACTION_MOVE
+ | DnDConstants.ACTION_COPY_OR_MOVE
+ | DnDConstants.ACTION_LINK
+ | DnDConstants.ACTION_REFERENCE;
+
+ if (~(srcActions ^ srcActionsMask) != 0)
+ throw new IllegalArgumentException ();
+
+ this.dropAction = dropAction;
+ this.srcActions = srcActions;
+ this.location = location;
+ }
+
+ public void acceptDrag (int dragOperation)
+ {
+ context.acceptDrag (dragOperation);
+ }
+
+ public DataFlavor[] getCurrentDataFlavors ()
+ {
+ return context.getCurrentDataFlavors ();
+ }
+
+ public List getCurrentDataFlavorsAsList ()
+ {
+ return context.getCurrentDataFlavorsAsList ();
+ }
+
+ public int getDropAction()
+ {
+ return 0;
+ //return dropAction & ((DropTargetContext) source).getTargetActions();
+ }
+
+ public Point getLocation ()
+ {
+ return location;
+ }
+
+ public int getSourceActions ()
+ {
+ return srcActions;
+ }
+
+ public boolean isDataFlavorSupported (DataFlavor df)
+ {
+ return context.isDataFlavorSupported (df);
+ }
+
+ public void rejectDrag ()
+ {
+ context.rejectDrag ();
+ }
+} // class DropTargetDragEvent
diff --git a/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java b/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java
new file mode 100644
index 00000000000..0c0777f78d0
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java
@@ -0,0 +1,170 @@
+/* DropTargetDropEvent.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+import java.awt.Point;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.util.List;
+
+/**
+ * @since 1.2
+ */
+public class DropTargetDropEvent extends DropTargetEvent
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = -1721911170440459322L;
+
+ private final int dropAction;
+ private final int actions;
+ private final Point location;
+ private final boolean isLocalTx;
+
+ /**
+ * Initializes a <code>DropTargetDropEvent</code>. By default this constructor
+ * assumes that the target is not int same JVM.
+ *
+ * @exception IllegalArgumentException If dropAction is not one of DnDConstants,
+ * actions is not a bitwise mask of DnDConstants, or dtc is null.
+ * @exception NullPointerException If location is null.
+ */
+ public DropTargetDropEvent (DropTargetContext dtc, Point location,
+ int dropAction, int actions)
+ {
+ this (dtc, location, dropAction, actions, false);
+ }
+
+ /**
+ * Initializes a <code>DropTargetDropEvent</code>.
+ *
+ * @exception IllegalArgumentException If dropAction is not one of DnDConstants,
+ * actions is not a bitwise mask of DnDConstants, or dtc is null.
+ * @exception NullPointerException If location is null.
+ */
+ public DropTargetDropEvent (DropTargetContext dtc, Point location,
+ int dropAction, int actions, boolean isLocalTx)
+ {
+ super (dtc);
+
+ if (location == null)
+ throw new NullPointerException ();
+
+ if (dtc == null)
+ throw new IllegalArgumentException ();
+
+ if (dropAction != DnDConstants.ACTION_NONE
+ && dropAction != DnDConstants.ACTION_COPY
+ && dropAction != DnDConstants.ACTION_MOVE
+ && dropAction != DnDConstants.ACTION_COPY_OR_MOVE
+ && dropAction != DnDConstants.ACTION_LINK
+ && dropAction != DnDConstants.ACTION_REFERENCE)
+ throw new IllegalArgumentException ();
+
+ int actionsMask = DnDConstants.ACTION_NONE
+ | DnDConstants.ACTION_COPY
+ | DnDConstants.ACTION_MOVE
+ | DnDConstants.ACTION_COPY_OR_MOVE
+ | DnDConstants.ACTION_LINK
+ | DnDConstants.ACTION_REFERENCE;
+
+ if (~(actions ^ actionsMask) != 0)
+ throw new IllegalArgumentException ();
+
+ this.dropAction = dropAction;
+ this.actions = actions;
+ this.location = location;
+ this.isLocalTx = isLocalTx;
+ }
+
+ public Point getLocation ()
+ {
+ return location;
+ }
+
+ public DataFlavor[] getCurrentDataFlavors ()
+ {
+ return context.getCurrentDataFlavors ();
+ }
+
+ public List getCurrentDataFlavorsAsList ()
+ {
+ return context.getCurrentDataFlavorsAsList ();
+ }
+
+ public boolean isDataFlavorSupported (DataFlavor flavor)
+ {
+ return context.isDataFlavorSupported (flavor);
+ }
+
+ public int getSourceActions ()
+ {
+ return actions;
+ }
+
+ public int getDropAction ()
+ {
+ return dropAction;
+ }
+
+ public Transferable getTransferable ()
+ {
+ return context.getTransferable ();
+ }
+
+ public void acceptDrop (int dropAction)
+ {
+ context.acceptDrop (dropAction);
+ }
+
+ public void rejectDrop ()
+ {
+ context.rejectDrop ();
+ }
+
+ public void dropComplete (boolean success)
+ {
+ // FIXME: implement this
+ }
+
+ public boolean isLocalTransfer()
+ {
+ return isLocalTx;
+ }
+} // class DropTargetDropEvent
diff --git a/libjava/classpath/java/awt/dnd/DropTargetEvent.java b/libjava/classpath/java/awt/dnd/DropTargetEvent.java
new file mode 100644
index 00000000000..56a4d481a16
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetEvent.java
@@ -0,0 +1,56 @@
+/* DropTarget.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+import java.util.EventObject;
+
+public class DropTargetEvent extends EventObject
+{
+ protected DropTargetContext context;
+
+ public DropTargetEvent (DropTargetContext context)
+ {
+ super (context);
+ this.context = context;
+ }
+
+ public DropTargetContext getDropTargetContext ()
+ {
+ return context;
+ }
+}
diff --git a/libjava/classpath/java/awt/dnd/DropTargetListener.java b/libjava/classpath/java/awt/dnd/DropTargetListener.java
new file mode 100644
index 00000000000..ceb839bac27
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetListener.java
@@ -0,0 +1,89 @@
+/* DropTargetListener.java -- listen to events during the drop
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.util.EventListener;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface DropTargetListener extends EventListener
+{
+ /**
+ * Called when the cursor hotspot enters a drop site which will accept the
+ * drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragEnter (DropTargetDragEvent e);
+
+ /**
+ * Called when the cursor hotspot moves inside of a drop site which will
+ * accept the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragOver (DropTargetDragEvent e);
+
+ /**
+ * Called when the user modifies the drop gesture. This is often the case
+ * when additional mouse or key events are received during the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dropActionChanged (DropTargetDragEvent e);
+
+ /**
+ * Called when the cursor hotspot moves outside of a drop site which will
+ * accept the drag. This could also happen if the drop site is no longer
+ * active, or no longer accepts the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragExit (DropTargetEvent e);
+
+ /**
+ * Called when the drag operation has terminated with a drop.
+ *
+ * @param e the drag source drag event
+ */
+ void drop (DropTargetDropEvent e);
+} // interface DropTargetListener
diff --git a/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java b/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java
new file mode 100644
index 00000000000..2fd9767e03d
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java
@@ -0,0 +1,73 @@
+/* InvalidDnDOperationException.java -- thrown when drag-and-drop fails
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+/**
+ * Thrown when a method in the java.awt.dnd package is unable to perform a
+ * requested operation, usually because the underlying DnD system is in the
+ * wrong state.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InvalidDnDOperationException extends IllegalStateException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -6062568741193956678L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public InvalidDnDOperationException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public InvalidDnDOperationException(String s)
+ {
+ super(s);
+ }
+} // class InvalidDnDOperationException
diff --git a/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java b/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java
new file mode 100644
index 00000000000..9a2a7bc4c79
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java
@@ -0,0 +1,131 @@
+/* MouseDragGestureRecognizer.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ */
+public abstract class MouseDragGestureRecognizer
+ extends DragGestureRecognizer
+ implements MouseListener, MouseMotionListener
+{
+ /**
+ * Creates a <code>MouseDragGestureRecognizer</code> object.
+ */
+ protected MouseDragGestureRecognizer (DragSource ds, Component c, int act,
+ DragGestureListener dgl)
+ {
+ super (ds, c, act, dgl);
+ }
+
+ /**
+ * Creates a <code>MouseDragGestureRecognizer</code> object.
+ */
+ protected MouseDragGestureRecognizer (DragSource ds, Component c, int act)
+ {
+ super (ds, c, act);
+ }
+
+ /**
+ * Creates a <code>MouseDragGestureRecognizer</code> object.
+ */
+ protected MouseDragGestureRecognizer (DragSource ds, Component c)
+ {
+ super (ds, c);
+ }
+
+ /**
+ * Creates a <code>MouseDragGestureRecognizer</code> object.
+ */
+ protected MouseDragGestureRecognizer (DragSource ds)
+ {
+ super (ds);
+ }
+
+ protected void registerListeners ()
+ {
+ component.addMouseListener (this);
+ component.addMouseMotionListener (this);
+ }
+
+ protected void unregisterListeners ()
+ {
+ component.removeMouseListener (this);
+ component.removeMouseMotionListener (this);
+ }
+
+ public void mouseClicked (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mousePressed (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseReleased (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseEntered (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseExited (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseDragged (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseMoved (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+} // class MouseDragGestureRecognizer
diff --git a/libjava/classpath/java/awt/dnd/package.html b/libjava/classpath/java/awt/dnd/package.html
new file mode 100644
index 00000000000..d1ae5215cb4
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.dnd package.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.dnd</title></head>
+
+<body>
+<p>Events and listeners for drag and drop sources and targets.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java b/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java
new file mode 100644
index 00000000000..8c134b623a7
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java
@@ -0,0 +1,57 @@
+/* DragSourceContextPeer.java -- interface for drag-and-drop peers
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd.peer;
+
+import java.awt.Cursor;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.dnd.DragSourceContext;
+import java.awt.dnd.InvalidDnDOperationException;
+
+/**
+ * STUBBED
+ */
+public interface DragSourceContextPeer
+{
+ void startDrag(DragSourceContext context, Cursor c, Image i, Point p)
+ throws InvalidDnDOperationException;
+ Cursor getCursor();
+ void setCursor(Cursor c) throws InvalidDnDOperationException;
+ void transferablesFlavorsChanged();
+} // interface DragSourceContextPeer
diff --git a/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java b/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java
new file mode 100644
index 00000000000..6eae29b3810
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java
@@ -0,0 +1,68 @@
+/* DropTargetContextPeer.java -- interface for drag-and-drop peers
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd.peer;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.InvalidDnDOperationException;
+
+
+/**
+ * Used to control state of recipient protocol from the
+ * <code>DropTargetListener</code>. Occurs when a <code>Component</code>
+ * with an associated <code>DropTarget</code> and visible geometry is first
+ * intersected by a logical cursor.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ */
+public interface DropTargetContextPeer
+{
+ void setTargetActions(int actions);
+ int getTargetActions();
+ DropTarget getDropTarget();
+ DataFlavor[] getTransferDataFlavors();
+ Transferable getTransferable() throws InvalidDnDOperationException;
+ boolean isTransferableJVMLocal();
+ void acceptDrag(int dragAction);
+ void rejectDrag();
+ void acceptDrop(int dropAction);
+ void rejectDrop();
+ void dropComplete(boolean success);
+}
diff --git a/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java b/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java
new file mode 100644
index 00000000000..ec17cbe4be9
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java
@@ -0,0 +1,48 @@
+/* DropTargetPeer.java -- interface for drag-and-drop peers
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd.peer;
+
+import java.awt.dnd.DropTarget;
+
+/**
+ */
+public interface DropTargetPeer
+{
+ void addDropTarget (DropTarget target);
+ void removeDropTarget (DropTarget target);
+} // interface DropTargetContextPeer
diff --git a/libjava/classpath/java/awt/dnd/peer/package.html b/libjava/classpath/java/awt/dnd/peer/package.html
new file mode 100644
index 00000000000..52ec19cb4f0
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/peer/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.dnd.peer package.
+ Copyright (C) 2002 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 - java.awt.dnd.peer</title></head>
+
+<body>
+<p>Interfaces for using native interface components.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/event/AWTEventListener.java b/libjava/classpath/java/awt/event/AWTEventListener.java
new file mode 100644
index 00000000000..079a91dd4c9
--- /dev/null
+++ b/libjava/classpath/java/awt/event/AWTEventListener.java
@@ -0,0 +1,65 @@
+/* AWTEventListener.java -- listen for all events in the AWT system
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Toolkit;
+import java.util.EventListener;
+
+/**
+ * This listener is for classes that need to listen to all events in the AWT
+ * system. In general, this should not be used except for classes like
+ * javax.accessibility or by event recorders.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see AWTEvent
+ * @see Toolkit#addAWTEventListener(AWTEventListener, long)
+ * @see Toolkit#removeAWTEventListener(AWTEventListener)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface AWTEventListener extends EventListener
+{
+ /**
+ * This method is called when any event in the AWT system is dispatched.
+ *
+ * @param event the AWTEvent that was dispatched
+ */
+ void eventDispatched(AWTEvent event);
+} // interface AWTEventListener
diff --git a/libjava/classpath/java/awt/event/AWTEventListenerProxy.java b/libjava/classpath/java/awt/event/AWTEventListenerProxy.java
new file mode 100644
index 00000000000..3d9958b1abd
--- /dev/null
+++ b/libjava/classpath/java/awt/event/AWTEventListenerProxy.java
@@ -0,0 +1,155 @@
+/* AWTEventListenerProxy.java -- wrapper/filter for AWTEventListener
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Toolkit;
+import java.util.EventListenerProxy;
+
+/**
+ * This class allows adding an AWTEventListener which only pays attention to
+ * a specific event mask.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Toolkit
+ * @see EventListenerProxy
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class AWTEventListenerProxy extends EventListenerProxy
+ implements AWTEventListener
+{
+ /** The event mask. */
+ private final long mask;
+
+ /**
+ * Construct an AWT Event Listener which only listens to events in the given
+ * mask, passing the work on to the real listener.
+ *
+ * @param eventMask the mask of events to listen to
+ * @param listener the wrapped listener
+ */
+ public AWTEventListenerProxy(long eventMask, AWTEventListener listener)
+ {
+ super(listener);
+ mask = eventMask;
+ }
+
+ /**
+ * Forwards events on to the delegate if they meet the event mask.
+ *
+ * @param event the property change event to filter
+ * @throws NullPointerException if the delegate this was created with is null
+ */
+ public void eventDispatched(AWTEvent event)
+ {
+ int id = event == null ? 0 : event.getID();
+ if (((mask & AWTEvent.ACTION_EVENT_MASK) != 0
+ && event instanceof ActionEvent)
+ || ((mask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0
+ && event instanceof AdjustmentEvent)
+ || ((mask & AWTEvent.COMPONENT_EVENT_MASK) != 0
+ && event instanceof ComponentEvent
+ && (id >= ComponentEvent.COMPONENT_FIRST
+ && id <= ComponentEvent.COMPONENT_LAST))
+ || ((mask & AWTEvent.CONTAINER_EVENT_MASK) != 0
+ && event instanceof ContainerEvent)
+ || ((mask & AWTEvent.FOCUS_EVENT_MASK) != 0
+ && event instanceof FocusEvent)
+ || ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
+ && event instanceof HierarchyEvent
+ && (id == HierarchyEvent.ANCESTOR_MOVED
+ || id == HierarchyEvent.ANCESTOR_RESIZED))
+ || ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0
+ && event instanceof HierarchyEvent
+ && id == HierarchyEvent.HIERARCHY_CHANGED)
+ || ((mask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0
+ && event instanceof InputMethodEvent)
+ || ((mask & AWTEvent.INVOCATION_EVENT_MASK) != 0
+ && event instanceof InvocationEvent)
+ || ((mask & AWTEvent.ITEM_EVENT_MASK) != 0
+ && event instanceof ItemEvent)
+ || ((mask & AWTEvent.KEY_EVENT_MASK) != 0
+ && event instanceof KeyEvent)
+ || ((mask & AWTEvent.MOUSE_EVENT_MASK) != 0
+ && event instanceof MouseEvent
+ && (id == MouseEvent.MOUSE_PRESSED
+ || id == MouseEvent.MOUSE_RELEASED
+ || id == MouseEvent.MOUSE_CLICKED
+ || id == MouseEvent.MOUSE_ENTERED
+ || id == MouseEvent.MOUSE_EXITED))
+ || ((mask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
+ && event instanceof MouseEvent
+ && (id == MouseEvent.MOUSE_MOVED
+ || id == MouseEvent.MOUSE_DRAGGED))
+ || ((mask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0
+ && event instanceof MouseWheelEvent)
+ || ((mask & AWTEvent.PAINT_EVENT_MASK) != 0
+ && event instanceof PaintEvent)
+ || ((mask & AWTEvent.TEXT_EVENT_MASK) != 0
+ && event instanceof TextEvent)
+ || ((mask & AWTEvent.WINDOW_EVENT_MASK) != 0
+ && event instanceof WindowEvent
+ && (id == WindowEvent.WINDOW_OPENED
+ || id == WindowEvent.WINDOW_CLOSING
+ || id == WindowEvent.WINDOW_CLOSED
+ || id == WindowEvent.WINDOW_ICONIFIED
+ || id == WindowEvent.WINDOW_DEICONIFIED
+ || id == WindowEvent.WINDOW_ACTIVATED
+ || id == WindowEvent.WINDOW_DEACTIVATED))
+ || ((mask & AWTEvent.WINDOW_FOCUS_EVENT_MASK) != 0
+ && event instanceof WindowEvent
+ && (id == WindowEvent.WINDOW_GAINED_FOCUS
+ || id == WindowEvent.WINDOW_LOST_FOCUS))
+ || ((mask & AWTEvent.WINDOW_STATE_EVENT_MASK) != 0
+ && event instanceof WindowEvent
+ && id == WindowEvent.WINDOW_STATE_CHANGED))
+ ((AWTEventListener) getListener()).eventDispatched(event);
+ }
+
+ /**
+ * This returns the event mask associated with this listener.
+ *
+ * @return the event mask
+ */
+ public long getEventMask()
+ {
+ return mask;
+ }
+} // class AWTEventListenerProxy
diff --git a/libjava/classpath/java/awt/event/ActionEvent.java b/libjava/classpath/java/awt/event/ActionEvent.java
new file mode 100644
index 00000000000..4bce7d45ce0
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ActionEvent.java
@@ -0,0 +1,226 @@
+/* ActionEvent.java -- an action has been triggered
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.EventQueue;
+
+/**
+ * This event is generated when an action on a component (such as a
+ * button press) occurs.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ActionListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ActionEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -7671078796273832149L;
+
+ /** Bit mask indicating the shift key was pressed. */
+ public static final int SHIFT_MASK = InputEvent.SHIFT_MASK;
+
+ /** Bit mask indicating the control key was pressed. */
+ public static final int CTRL_MASK = InputEvent.CTRL_MASK;
+
+ /** Bit mask indicating the that meta key was pressed. */
+ public static final int META_MASK = InputEvent.META_MASK;
+
+ /** Bit mask indicating that the alt key was pressed. */
+ public static final int ALT_MASK = InputEvent.ALT_MASK;
+
+ /** The first id number in the range of action id's. */
+ public static final int ACTION_FIRST = 1001;
+
+ /** The last id number in the range of action id's. */
+ public static final int ACTION_LAST = 1001;
+
+ /** An event id indicating that an action has occurred. */
+ public static final int ACTION_PERFORMED = 1001;
+
+ /**
+ * A nonlocalized string that gives more specific details of the event cause.
+ *
+ * @see #getActionCommand()
+ * @serial the command for this event
+ */
+ private final String actionCommand;
+
+ /**
+ * The bitmask of the modifiers that were pressed during the action.
+ *
+ * @see #getModifiers()
+ * @serial modifiers for this event
+ */
+ private final int modifiers;
+
+ /**
+ * The timestamp of this event; usually the same as the underlying input
+ * event.
+ *
+ * @see #getWhen()
+ * @serial the timestamp of the event
+ * @since 1.4
+ */
+ private final long when;
+
+ /**
+ * Initializes a new instance of <code>ActionEvent</code> with the
+ * specified source, id, and command. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the event source
+ * @param id the event id
+ * @param command the command string for this action
+ * @throws IllegalArgumentException if source is null
+ */
+ public ActionEvent(Object source, int id, String command)
+ {
+ this(source, id, command, EventQueue.getMostRecentEventTime(), 0);
+ }
+
+ /**
+ * Initializes a new instance of <code>ActionEvent</code> with the
+ * specified source, id, command, and modifiers. Note that an invalid id
+ * leads to unspecified results.
+ *
+ * @param source the event source
+ * @param id the event id
+ * @param command the command string for this action
+ * @param modifiers the bitwise or of modifier keys down during the action
+ * @throws IllegalArgumentException if source is null
+ */
+ public ActionEvent(Object source, int id, String command, int modifiers)
+ {
+ this(source, id, command, EventQueue.getMostRecentEventTime(), modifiers);
+ }
+
+ /**
+ * Initializes a new instance of <code>ActionEvent</code> with the
+ * specified source, id, command, and modifiers, and timestamp. Note that
+ * an invalid id leads to unspecified results.
+ *
+ * @param source the event source
+ * @param id the event id
+ * @param command the command string for this action
+ * @param when the timestamp of the event
+ * @param modifiers the bitwise or of modifier keys down during the action
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public ActionEvent(Object source, int id, String command, long when,
+ int modifiers)
+ {
+ super(source, id);
+ actionCommand = command;
+ this.when = when;
+ this.modifiers = modifiers;
+ }
+
+ /**
+ * Returns the command string associated with this action.
+ *
+ * @return the command string associated with this action
+ */
+ public String getActionCommand()
+ {
+ return actionCommand;
+ }
+
+ /**
+ * Gets the timestamp of when this action took place. Usually, this
+ * corresponds to the timestamp of the underlying InputEvent.
+ *
+ * @return the timestamp of this action
+ * @since 1.4
+ */
+ public long getWhen()
+ {
+ return when;
+ }
+
+ /**
+ * Returns the keys held down during the action. This value will be a
+ * combination of the bit mask constants defined in this class, or 0 if no
+ * modifiers were pressed.
+ *
+ * @return the modifier bits
+ */
+ public int getModifiers()
+ {
+ return modifiers;
+ }
+
+ /**
+ * Returns a string that identifies the action event. This is in the format
+ * <code>"ACTION_PERFORMED,cmd=" + getActionCommand() + ",when=" + getWhen()
+ * + ",modifiers=" + &lt;modifier string&gt;</code>, where the modifier
+ * string is in the order "Meta", "Ctrl", "Alt", "Shift", "Alt Graph", and
+ * "Button1", separated by '+', according to the bits set in getModifiers().
+ *
+ * @return a string identifying the event
+ */
+ public String paramString()
+ {
+ StringBuffer s = new StringBuffer(id == ACTION_PERFORMED
+ ? "ACTION_PERFORMED,cmd="
+ : "unknown type,cmd=");
+ s.append(actionCommand).append(",when=").append(when).append(",modifiers");
+ int len = s.length();
+ s.setLength(len + 1);
+ if ((modifiers & META_MASK) != 0)
+ s.append("+Meta");
+ if ((modifiers & CTRL_MASK) != 0)
+ s.append("+Ctrl");
+ if ((modifiers & ALT_MASK) != 0)
+ s.append("+Alt");
+ if ((modifiers & SHIFT_MASK) != 0)
+ s.append("+Shift");
+ if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0)
+ s.append("+Alt Graph");
+ if ((modifiers & InputEvent.BUTTON1_MASK) != 0)
+ s.append("+Button1");
+ s.setCharAt(len, '=');
+ return s.toString();
+ }
+} // class ActionEvent
diff --git a/libjava/classpath/java/awt/event/ActionListener.java b/libjava/classpath/java/awt/event/ActionListener.java
new file mode 100644
index 00000000000..4c302cca310
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ActionListener.java
@@ -0,0 +1,59 @@
+/* ActionListener.java -- listens for action events
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that listen for action events.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ActionEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface ActionListener extends EventListener
+{
+ /**
+ * This method is invoked when an action occurs.
+ *
+ * @param event the <code>ActionEvent</code> that occurred
+ */
+ void actionPerformed(ActionEvent event);
+}
diff --git a/libjava/classpath/java/awt/event/AdjustmentEvent.java b/libjava/classpath/java/awt/event/AdjustmentEvent.java
new file mode 100644
index 00000000000..867c577d356
--- /dev/null
+++ b/libjava/classpath/java/awt/event/AdjustmentEvent.java
@@ -0,0 +1,222 @@
+/* AdjustmentEvent.java -- an adjustable value was changed
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Adjustable;
+
+/**
+ * This class represents an event that is generated when an adjustable
+ * value is changed.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Adjustable
+ * @see AdjustmentListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class AdjustmentEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5700290645205279921L;
+
+ /** This is the first id in the range of ids used by adjustment events. */
+ public static final int ADJUSTMENT_FIRST = 601;
+
+ /** This is the last id in the range of ids used by adjustment events. */
+ public static final int ADJUSTMENT_LAST = 601;
+
+ /** This is the id indicating an adjustment value changed. */
+ public static final int ADJUSTMENT_VALUE_CHANGED = 601;
+
+ /** Adjustment type for unit increments. */
+ public static final int UNIT_INCREMENT = 1;
+
+ /** Adjustment type for unit decrements. */
+ public static final int UNIT_DECREMENT = 2;
+
+ /** Adjustment type for block decrements. */
+ public static final int BLOCK_DECREMENT = 3;
+
+ /** Adjustment type for block increments. */
+ public static final int BLOCK_INCREMENT = 4;
+
+ /** Adjustment type for tracking adjustments. */
+ public static final int TRACK = 5;
+
+ /**
+ * The adjustable object that caused the event.
+ *
+ * @see #getAdjustable()
+ * @serial the cause
+ */
+ private final Adjustable adjustable;
+
+ /**
+ * The type of adjustment, one of {@link #UNIT_INCREMENT},
+ * {@link #UNIT_DECREMENT}, {@link #BLOCK_INCREMENT},
+ * {@link #BLOCK_DECREMENT}, or {@link #TRACK}.
+ *
+ * @see #getAdjustmentType()
+ * @serial the adjustment type
+ */
+ private final int adjustmentType;
+
+ /**
+ * The new value of the adjustable; it should be in the range of the
+ * adjustable cause.
+ *
+ * @see #getValue()
+ * @serial the adjustment value
+ */
+ private final int value;
+
+ /**
+ * True if this is in a series of multiple adjustment events.
+ *
+ * @see #getValueIsAdjusting()
+ * @serial true if this is not the last adjustment
+ * @since 1.4
+ */
+ private final boolean isAdjusting;
+
+ /**
+ * Initializes an instance of <code>AdjustmentEvent</code> with the
+ * specified source, id, type, and value. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param type the event type, one of the constants of this class
+ * @param value the value of the adjustment
+ * @throws IllegalArgumentException if source is null
+ */
+ public AdjustmentEvent(Adjustable source, int id, int type, int value)
+ {
+ this(source, id, type, value, false);
+ }
+
+ /**
+ * Initializes an instance of <code>AdjustmentEvent</code> with the
+ * specified source, id, type, and value. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param type the event type, one of the constants of this class
+ * @param value the value of the adjustment
+ * @param isAdjusting if this event is in a chain of adjustments
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public AdjustmentEvent(Adjustable source, int id, int type, int value,
+ boolean isAdjusting)
+ {
+ super(source, id);
+ this.adjustmentType = type;
+ this.value = value;
+ adjustable = source;
+ this.isAdjusting = isAdjusting;
+ }
+
+ /**
+ * This method returns the source of the event as an <code>Adjustable</code>.
+ *
+ * @return the <code>Adjustable</code> source of the event
+ */
+ public Adjustable getAdjustable()
+ {
+ return adjustable;
+ }
+
+ /**
+ * Returns the new value of the adjustable object.
+ *
+ * @return the value of the event
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the type of the event, which will be one of
+ * {@link #UNIT_INCREMENT}, {@link #UNIT_DECREMENT},
+ * {@link #BLOCK_INCREMENT}, {@link #BLOCK_DECREMENT}, or {@link #TRACK}.
+ *
+ * @return the type of the event
+ */
+ public int getAdjustmentType()
+ {
+ return adjustmentType;
+ }
+
+ /**
+ * Test if this event is part of a sequence of multiple adjustements.
+ *
+ * @return true if this is not the last adjustment
+ * @since 1.4
+ */
+ public boolean getValueIsAdjusting()
+ {
+ return isAdjusting;
+ }
+
+ /**
+ * Returns a string that describes the event. This is in the format
+ * <code>"ADJUSTMENT_VALUE_CHANGED,adjType=" + &lt;type&gt; + ",value="
+ * + getValue() + ",isAdjusting=" + getValueIsAdjusting()</code>, where
+ * type is the name of the constant returned by getAdjustmentType().
+ *
+ * @return a string that describes the event
+ */
+ public String paramString()
+ {
+ return (id == ADJUSTMENT_VALUE_CHANGED
+ ? "ADJUSTMENT_VALUE_CHANGED,adjType=" : "unknown type,adjType=")
+ + (adjustmentType == UNIT_INCREMENT ? "UNIT_INCREMENT,value="
+ : adjustmentType == UNIT_DECREMENT ? "UNIT_DECREMENT,value="
+ : adjustmentType == BLOCK_INCREMENT ? "BLOCK_INCREMENT,value="
+ : adjustmentType == BLOCK_DECREMENT ? "BLOCK_DECREMENT,value="
+ : adjustmentType == TRACK ? "TRACK,value=" : "unknown type,value=")
+ + value + ",isAdjusting=" + isAdjusting;
+ }
+} // class AdjustmentEvent
diff --git a/libjava/classpath/java/awt/event/AdjustmentListener.java b/libjava/classpath/java/awt/event/AdjustmentListener.java
new file mode 100644
index 00000000000..1eb2e3bcfa1
--- /dev/null
+++ b/libjava/classpath/java/awt/event/AdjustmentListener.java
@@ -0,0 +1,58 @@
+/* AdjustmentListener.java -- listen for adjustment events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * Interface for classes that listen for adjustment events.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface AdjustmentListener extends EventListener
+{
+ /**
+ * This method is called when an adjustable value changes.
+ *
+ * @param event the <code>AdjustmentEvent</code> that occurred
+ */
+ void adjustmentValueChanged(AdjustmentEvent event);
+} // interface AdjustmentListener
diff --git a/libjava/classpath/java/awt/event/ComponentAdapter.java b/libjava/classpath/java/awt/event/ComponentAdapter.java
new file mode 100644
index 00000000000..6b4893f0fc2
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ComponentAdapter.java
@@ -0,0 +1,97 @@
+/* ComponentAdapter.java -- convenience class for writing component listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>ComponentListener</code> and implements
+ * all methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>ComponentListener</code>
+ * interface to extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ComponentEvent
+ * @see ComponentListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ComponentAdapter implements ComponentListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public ComponentAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentResized(ComponentEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentMoved(ComponentEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentShown(ComponentEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentHidden(ComponentEvent event)
+ {
+ }
+} // class ComponentAdapter
diff --git a/libjava/classpath/java/awt/event/ComponentEvent.java b/libjava/classpath/java/awt/event/ComponentEvent.java
new file mode 100644
index 00000000000..ba9c2a5b3f2
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ComponentEvent.java
@@ -0,0 +1,137 @@
+/* ComponentEvent.java -- notification of events for components
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+
+/**
+ * This class is for events generated when a component is moved, resized,
+ * hidden, or shown. These events normally do not need to be handled by the
+ * application, since the AWT system automatically takes care of them. This
+ * is also the superclass for other events on components, but
+ * ComponentListeners ignore such subclasses.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ComponentAdapter
+ * @see ComponentListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ComponentEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 8101406823902992965L;
+
+ /** This is the first id in the range of ids used by this class. */
+ public static final int COMPONENT_FIRST = 100;
+
+ /** This is the last id in the range of ids used by this class. */
+ public static final int COMPONENT_LAST = 103;
+
+ /** This id indicates that a component was moved. */
+ public static final int COMPONENT_MOVED = 100;
+
+ /** This id indicates that a component was resized. */
+ public static final int COMPONENT_RESIZED = 101;
+
+ /** This id indicates that a component was shown. */
+ public static final int COMPONENT_SHOWN = 102;
+
+ /** This id indicates that a component was hidden. */
+ public static final int COMPONENT_HIDDEN = 103;
+
+ /**
+ * Initializes a new instance of <code>ComponentEvent</code> with the
+ * specified source and id. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public ComponentEvent(Component source, int id)
+ {
+ super(source, id);
+ }
+
+ /**
+ * This method returns the event source as a <code>Component</code>. If the
+ * source has subsequently been modified to a non-Component, this returns
+ * null.
+ *
+ * @return the event source as a <code>Component</code>, or null
+ */
+ public Component getComponent()
+ {
+ return source instanceof Component ? (Component) source : null;
+ }
+
+ /**
+ * This method returns a string identifying this event. This is the field
+ * name of the id type, and for COMPONENT_MOVED or COMPONENT_RESIZED, the
+ * new bounding box of the component.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ // Unlike Sun, we don't throw NullPointerException or ClassCastException
+ // when source was illegally changed.
+ switch (id)
+ {
+ case COMPONENT_MOVED:
+ return "COMPONENT_MOVED "
+ + (source instanceof Component
+ ? ((Component) source).getBounds() : (Object) "");
+ case COMPONENT_RESIZED:
+ return "COMPONENT_RESIZED "
+ + (source instanceof Component
+ ? ((Component) source).getBounds() : (Object) "");
+ case COMPONENT_SHOWN:
+ return "COMPONENT_SHOWN";
+ case COMPONENT_HIDDEN:
+ return "COMPONENT_HIDDEN";
+ default:
+ return "unknown type";
+ }
+ }
+} // class ComponentEvent
diff --git a/libjava/classpath/java/awt/event/ComponentListener.java b/libjava/classpath/java/awt/event/ComponentListener.java
new file mode 100644
index 00000000000..b43faaed7ff
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ComponentListener.java
@@ -0,0 +1,84 @@
+/* ComponentListener.java -- receive all events for a component
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that receive all events from a component.
+ * Normally it is not necessary to process these events since the AWT
+ * handles them internally, taking all appropriate actions. To watch a subset
+ * of these events, use a ComponentAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ComponentAdapter
+ * @see ComponentEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface ComponentListener extends EventListener
+{
+ /**
+ * This method is called when the component is resized.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the resize
+ */
+ void componentResized(ComponentEvent event);
+
+ /**
+ * This method is called when the component is moved.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the move
+ */
+ void componentMoved(ComponentEvent event);
+
+ /**
+ * This method is called when the component is made visible.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the visibility
+ */
+ void componentShown(ComponentEvent event);
+
+ /**
+ * This method is called when the component is hidden.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the visibility
+ */
+ void componentHidden(ComponentEvent event);
+} // interface ComponentListener
diff --git a/libjava/classpath/java/awt/event/ContainerAdapter.java b/libjava/classpath/java/awt/event/ContainerAdapter.java
new file mode 100644
index 00000000000..c847adfa211
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ContainerAdapter.java
@@ -0,0 +1,79 @@
+/* ContainerAdapter.java -- convenience class for writing container listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>ContainerListener</code> and implements
+ * all methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>ContainerListener</code>
+ * interface to extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ContainerEvent
+ * @see ContainerListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ContainerAdapter implements ContainerListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public ContainerAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentAdded(ContainerEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentRemoved(ContainerEvent event)
+ {
+ }
+} // class ContainerAdapter
diff --git a/libjava/classpath/java/awt/event/ContainerEvent.java b/libjava/classpath/java/awt/event/ContainerEvent.java
new file mode 100644
index 00000000000..3c401fe1a04
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ContainerEvent.java
@@ -0,0 +1,135 @@
+/* ContainerEvent.java -- components added/removed from a container
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Component;
+import java.awt.Container;
+
+/**
+ * This event is generated when a component is added or removed from a
+ * container. Applications do not ordinarily need to handle these events
+ * since the AWT system handles them internally.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ContainerAdapter
+ * @see ContainerListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ContainerEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -4114942250539772041L;
+
+ /** This is the first id in the id range used by this class. */
+ public static final int CONTAINER_FIRST = 300;
+
+ /** This is the last id in the id range used by this class. */
+ public static final int CONTAINER_LAST = 301;
+
+ /** This id indicates a component was added to the container. */
+ public static final int COMPONENT_ADDED = 300;
+
+ /** This id indicates a component was removed from the container. */
+ public static final int COMPONENT_REMOVED = 301;
+
+ /**
+ * The non-null child component that was added or removed.
+ *
+ * @serial the child component that changed
+ */
+ private final Component child;
+
+ /**
+ * Initializes a new instance of <code>ContainerEvent</code> with the
+ * specified source and id. Additionally, the affected child component
+ * is also passed as a parameter. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source container of the event
+ * @param id the event id
+ * @param child the child component affected by this event
+ * @throws IllegalArgumentException if source is null
+ */
+ public ContainerEvent(Component source, int id, Component child)
+ {
+ super(source, id);
+ this.child = child;
+ }
+
+ /**
+ * Returns the source of this event as a <code>Container</code>.
+ *
+ * @return the source of the event
+ * @throws ClassCastException if the source is changed to a non-Container
+ */
+ public Container getContainer()
+ {
+ return (Container) source;
+ }
+
+ /**
+ * This method returns the child object that was added or removed from
+ * the container.
+ *
+ * @return the child object added or removed
+ */
+ public Component getChild()
+ {
+ return child;
+ }
+
+ /**
+ * This method returns a string identifying this event. It is formatted as:
+ * <code>(getID() == COMPONENT_ADDED ? "COMPONENT_ADDED"
+ * : "COMPONENT_REMOVED") + ",child=" + getChild().getName()</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ // Unlike Sun, we don't throw NullPointerException if child is illegally
+ // null.
+ return (id == COMPONENT_ADDED ? "COMPONENT_ADDED,child="
+ : id == COMPONENT_REMOVED ? "COMPONENT_REMOVED,child="
+ : "unknown type,child=") + (child == null ? "" : child.getName());
+ }
+} // class ContainerEvent
diff --git a/libjava/classpath/java/awt/event/ContainerListener.java b/libjava/classpath/java/awt/event/ContainerListener.java
new file mode 100644
index 00000000000..b37d4340839
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ContainerListener.java
@@ -0,0 +1,70 @@
+/* ContainerListener.java -- listen for container events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to listen for all events from
+ * container objects. This is normally not necessary since the AWT system
+ * listens for and processes these events. To watch a subset of these events,
+ * use a ContainerAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ContainerAdapter
+ * @see ContainerEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface ContainerListener extends EventListener
+{
+ /**
+ * This method is called when a component is added to the container.
+ *
+ * @param event the <code>ContainerEvent</code> indicating component addition
+ */
+ void componentAdded(ContainerEvent event);
+
+ /**
+ * This method is called when a component is removed from the container.
+ *
+ * @param event the <code>ContainerEvent</code> indicating component removal
+ */
+ void componentRemoved(ContainerEvent event);
+} // interface ContainerListener
diff --git a/libjava/classpath/java/awt/event/FocusAdapter.java b/libjava/classpath/java/awt/event/FocusAdapter.java
new file mode 100644
index 00000000000..fb0532a3a91
--- /dev/null
+++ b/libjava/classpath/java/awt/event/FocusAdapter.java
@@ -0,0 +1,79 @@
+/* FocusAdapter.java -- convenience class for writing focus listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>FocusListener</code> and implements all
+ * methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>FocusListener</code> interface to
+ * extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see FocusEvent
+ * @see FocusListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class FocusAdapter implements FocusListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public FocusAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void focusGained(FocusEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void focusLost(FocusEvent event)
+ {
+ }
+} // class FocusAdapter
diff --git a/libjava/classpath/java/awt/event/FocusEvent.java b/libjava/classpath/java/awt/event/FocusEvent.java
new file mode 100644
index 00000000000..a44284aea75
--- /dev/null
+++ b/libjava/classpath/java/awt/event/FocusEvent.java
@@ -0,0 +1,181 @@
+/* FocusEvent.java -- generated for a focus change
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Component;
+
+/**
+ * This class represents an event generated when a focus change occurs for a
+ * component. There are both temporary changes, such as when focus is stolen
+ * during a sroll then returned, and permanent changes, such as when the user
+ * TABs through focusable components.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see FocusAdapter
+ * @see FocusListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class FocusEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 523753786457416396L;
+
+ /** This is the first id in the range of ids used by this class. */
+ public static final int FOCUS_FIRST = 1004;
+
+ /** This is the last id in the range of ids used by this class. */
+ public static final int FOCUS_LAST = 1005;
+
+ /** This is the event id for a focus gained event. */
+ public static final int FOCUS_GAINED = 1004;
+
+ /** This is the event id for a focus lost event. */
+ public static final int FOCUS_LOST = 1005;
+
+ /**
+ * Indicates whether or not the focus change is temporary.
+ *
+ * @see #isTemporary()
+ * @serial true if the focus change is temporary
+ */
+ private final boolean temporary;
+
+ /**
+ * The other component which is giving up or stealing focus from this
+ * component, if known.
+ *
+ * @see #getOppositeComponent()
+ * @serial the component with the opposite focus event, or null
+ * @since 1.4
+ */
+ private final Component opposite;
+
+ /**
+ * Initializes a new instance of <code>FocusEvent</code> with the
+ * specified source, id, temporary status, and opposite counterpart. Note
+ * that an invalid id leads to unspecified results.
+ *
+ * @param source the component that is gaining or losing focus
+ * @param id the event id
+ * @param temporary true if the focus change is temporary
+ * @param opposite the component receiving the opposite focus event, or null
+ * @throws IllegalArgumentException if source is null
+ */
+ public FocusEvent(Component source, int id, boolean temporary,
+ Component opposite)
+ {
+ super(source, id);
+ this.temporary = temporary;
+ this.opposite = opposite;
+ }
+
+ /**
+ * Initializes a new instance of <code>FocusEvent</code> with the
+ * specified source, id, and temporary status. Note that an invalid id
+ * leads to unspecified results.
+ *
+ * @param source the component that is gaining or losing focus
+ * @param id the event id
+ * @param temporary true if the focus change is temporary
+ * @throws IllegalArgumentException if source is null
+ */
+ public FocusEvent(Component source, int id, boolean temporary)
+ {
+ this(source, id, temporary, null);
+ }
+
+ /**
+ * Initializes a new instance of <code>FocusEvent</code> with the
+ * specified source and id. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the component that is gaining or losing focus
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public FocusEvent(Component source, int id)
+ {
+ this(source, id, false, null);
+ }
+
+ /**
+ * This method tests whether or not the focus change is temporary or
+ * permanent.
+ *
+ * @return true if the focus change is temporary
+ */
+ public boolean isTemporary()
+ {
+ return temporary;
+ }
+
+ /**
+ * Returns the component which received the opposite focus event. If this
+ * component gained focus, the opposite lost focus; likewise if this
+ * component is giving up focus, the opposite is gaining it. If this
+ * information is unknown, perhaps because the opposite is a native
+ * application, this returns null.
+ *
+ * @return the component with the focus opposite, or null
+ * @since 1.4
+ */
+ public Component getOppositeComponent()
+ {
+ return opposite;
+ }
+
+ /**
+ * Returns a string identifying this event. This is formatted as:
+ * <code>(getID() == FOCUS_GAINED ? "FOCUS_GAINED" : "FOCUS_LOST")
+ * + (isTemporary() ? ",temporary," : ",permanent,") + "opposite="
+ * + getOppositeComponent()</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return (id == FOCUS_GAINED ? "FOCUS_GAINED"
+ : id == FOCUS_LOST ? "FOCUS_LOST" : "unknown type")
+ + (temporary ? ",temporary,opposite=" : ",permanent,opposite=")
+ + opposite;
+ }
+} // class FocusEvent
diff --git a/libjava/classpath/java/awt/event/FocusListener.java b/libjava/classpath/java/awt/event/FocusListener.java
new file mode 100644
index 00000000000..1f7201825a7
--- /dev/null
+++ b/libjava/classpath/java/awt/event/FocusListener.java
@@ -0,0 +1,69 @@
+/* FocusListener.java -- listen for focus changes
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to be notified of changes of
+ * keyboard focus for a component. To watch a subset of these events, use a
+ * FocusAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see FocusAdapter
+ * @see FocusEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface FocusListener extends EventListener
+{
+ /**
+ * This method is called when a component gains the keyboard focus.
+ *
+ * @param event the <code>FocusEvent</code> indicating that focus was gained
+ */
+ void focusGained(FocusEvent event);
+
+ /**
+ * This method is invoked when a component loses the keyboard focus.
+ *
+ * @param event the <code>FocusEvent</code> indicating that focus was lost
+ */
+ void focusLost(FocusEvent event);
+} // interface FocusListener
diff --git a/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java b/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java
new file mode 100644
index 00000000000..340cf01edf1
--- /dev/null
+++ b/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java
@@ -0,0 +1,78 @@
+/* HierarchyBoundsAdapter.java -- convenience class for writing listeners
+ Copyright (C) 2000, 2002 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.event;
+
+/**
+ * This class implements <code>HierarchyBoundsListener</code> and implements
+ * all methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>HierarchyBoundsListener</code>
+ * interface to extend this class and override only the desired methods.
+ *
+ * @author Bryce McKinlay
+ * @see HierarchyBoundsListener
+ * @see HierarchyEvent
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public abstract class HierarchyBoundsAdapter implements HierarchyBoundsListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public HierarchyBoundsAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void ancestorMoved(HierarchyEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void ancestorResized(HierarchyEvent event)
+ {
+ }
+}
diff --git a/libjava/classpath/java/awt/event/HierarchyBoundsListener.java b/libjava/classpath/java/awt/event/HierarchyBoundsListener.java
new file mode 100644
index 00000000000..689623744e3
--- /dev/null
+++ b/libjava/classpath/java/awt/event/HierarchyBoundsListener.java
@@ -0,0 +1,70 @@
+/* HierarchyBoundsListener.java -- listens to bounds changes of parents
+ Copyright (C) 2000, 2002 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.event;
+
+import java.util.EventListener;
+
+/**
+ * This listens for changes in an ancestors size or location. Normally it is
+ * not necessary to process these events since the AWT handles them
+ * internally, taking all appropriate actions. To watch a subset of these
+ * events, use a HierarchyBoundsAdapter.
+ *
+ * @author Bryce McKinlay
+ * @see HierarchyBoundsAdapter
+ * @see HierarchyEvent
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface HierarchyBoundsListener extends EventListener
+{
+ /**
+ * Called when an ancestor component of the source is moved.
+ *
+ * @param e the event describing the ancestor's motion
+ */
+ void ancestorMoved(HierarchyEvent e);
+
+ /**
+ * Called when an ancestor component is resized.
+ *
+ * @param e the event describing the ancestor's resizing
+ */
+ void ancestorResized(HierarchyEvent e);
+} // interface HierarchyBoundsListener
diff --git a/libjava/classpath/java/awt/event/HierarchyEvent.java b/libjava/classpath/java/awt/event/HierarchyEvent.java
new file mode 100644
index 00000000000..e10cefbefcb
--- /dev/null
+++ b/libjava/classpath/java/awt/event/HierarchyEvent.java
@@ -0,0 +1,253 @@
+/* HierarchyEvent.java -- generated for a change in hierarchy
+ Copyright (C) 2000, 2002 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.event;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+
+/**
+ * This class represents an event generated for an ancestor component which
+ * may affect this component. These events normally do not need to be handled
+ * by the application, since the AWT system automatically takes care of them.
+ *
+ * <p>There are two types of hierarchy events. The first type is handled by
+ * HierarchyListener, and includes addition or removal of an ancestor, or
+ * an ancestor changing its on-screen status (visible and/or displayble). The
+ * second type is handled by HierarchyBoundsListener, and includes resizing
+ * or moving of an ancestor.
+ *
+ * @author Bryce McKinlay
+ * @see HierarchyListener
+ * @see HierarchyBoundsAdapter
+ * @see HierarchyBoundsListener
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public class HierarchyEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = -5337576970038043990L;
+
+ /** This is the first id in the range of ids used by this class. */
+ public static final int HIERARCHY_FIRST = 1400;
+
+ /** This id indicates that the hierarchy tree changed. */
+ public static final int HIERARCHY_CHANGED = 1400;
+
+ /** This id indicates that an ancestor was moved. */
+ public static final int ANCESTOR_MOVED = 1401;
+
+ /** This id indicates that an ancestor was resized. */
+ public static final int ANCESTOR_RESIZED = 1402;
+
+ /** This is the last id in the range of ids used by this class. */
+ public static final int HIERARCHY_LAST = 1402;
+
+ /** This indicates that the HIERARCHY_CHANGED is a changed parent. */
+ public static final int PARENT_CHANGED = 1;
+
+ /**
+ * This indicates that the HIERARCHY_CHANGED is caused by a change in
+ * displayability.
+ *
+ * @see Component#isDisplayable()
+ * @see Component#addNotify()
+ * @see Component#removeNotify()
+ */
+ public static final int DISPLAYABILITY_CHANGED = 2;
+
+ /**
+ * This indicates that the HIERARCHY_CHANGED is a changed visibility.
+ *
+ * @see Component#isShowing()
+ * @see Component#addNotify()
+ * @see Component#removeNotify()
+ * @see Component#show()
+ * @see Component#hide()
+ */
+ public static final int SHOWING_CHANGED = 4;
+
+ /**
+ * The component at the top of the changed hierarchy.
+ *
+ * @serial the top component changed
+ */
+ private final Component changed;
+
+ /**
+ * The parent of this component, either before or after the change depending
+ * on the type of change.
+ *
+ * @serial the parent component changed
+ */
+ private final Container changedParent;
+
+ /**
+ * The bitmask of HIERARCHY_CHANGED event types.
+ *
+ * @serial the change flags
+ */
+ private final long changeFlags;
+
+ /**
+ * Initializes a new instance of <code>HierarchyEvent</code> with the
+ * specified parameters. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the component whose hierarchy changed
+ * @param id the event id
+ * @param changed the top component in the tree of changed hierarchy
+ * @param changedParent the updated parent of this object
+ * @throws IllegalArgumentException if source is null
+ */
+ public HierarchyEvent(Component source, int id, Component changed,
+ Container changedParent)
+ {
+ this(source, id, changed, changedParent, 0);
+ }
+
+ /**
+ * Initializes a new instance of <code>HierarchyEvent</code> with the
+ * specified parameters. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the component whose hierarchy changed
+ * @param id the event id
+ * @param changed the top component in the tree of changed hierarchy
+ * @param changedParent the updated parent of this object
+ * @param changeFlags the bitmask of specific HIERARCHY_CHANGED events
+ * @throws IllegalArgumentException if source is null
+ */
+ public HierarchyEvent(Component source, int id, Component changed,
+ Container changedParent, long changeFlags)
+ {
+ super(source, id);
+ this.changed = changed;
+ this.changedParent = changedParent;
+ this.changeFlags = changeFlags;
+ }
+
+ /**
+ * This method returns the event source as a <code>Component</code>. If the
+ * source has subsequently been modified to a non-Component, this returns
+ * null.
+ *
+ * @return the event source as a <code>Component</code>, or null
+ */
+ public Component getComponent()
+ {
+ return source instanceof Component ? (Component) source : null;
+ }
+
+ /**
+ * Returns the component at the top of the hierarchy which changed.
+ *
+ * @return the top changed component
+ */
+ public Component getChanged()
+ {
+ return changed;
+ }
+
+ /**
+ * Returns the parent of the component listed in <code>getChanged()</code>.
+ * If the cause of this event was <code>Container.add</code>, this is the
+ * new parent; if the cause was <code>Container.remove</code>, this is the
+ * old parent; otherwise it is the unchanged parent.
+ *
+ * @return the parent container of the changed component
+ */
+ public Container getChangedParent()
+ {
+ return changedParent;
+ }
+
+ /**
+ * If this is a HIERARCHY_CHANGED event, this returns a bitmask of the
+ * types of changes that took place.
+ *
+ * @return the bitwise or of hierarchy change types, or 0
+ * @see #PARENT_CHANGED
+ * @see #DISPLAYABILITY_CHANGED
+ * @see #SHOWING_CHANGED
+ */
+ public long getChangeFlags()
+ {
+ return changeFlags;
+ }
+
+ /**
+ * This method returns a string identifying this event. This is the field
+ * name of the id type, followed by a parenthesized listing of the changed
+ * component and its parent container. In addition, if the type is
+ * HIERARCHY_CHANGED, the flags preceed the changed component, in the
+ * order PARENT_CHANGED, DISPLAYABILITY_CHANGED, and SHOWING_CHANGED.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ StringBuffer r = new StringBuffer();
+ switch (id)
+ {
+ case HIERARCHY_CHANGED:
+ r.append("HIERARCHY_CHANGED (");
+ if ((changeFlags & PARENT_CHANGED) != 0)
+ r.append("PARENT_CHANGED,");
+ if ((changeFlags & DISPLAYABILITY_CHANGED) != 0)
+ r.append("DISPLAYABILITY_CHANGED,");
+ if ((changeFlags & SHOWING_CHANGED) != 0)
+ r.append("SHOWING_CHANGED,");
+ break;
+ case ANCESTOR_MOVED:
+ r.append("ANCESTOR_MOVED (");
+ break;
+ case ANCESTOR_RESIZED:
+ r.append("ANCESTOR_RESIZED (");
+ break;
+ default:
+ return "unknown type";
+ }
+ r.append(changed).append(',').append(changedParent).append(')');
+ return r.toString();
+ }
+} // class HierarchyEvent
diff --git a/libjava/classpath/java/awt/event/HierarchyListener.java b/libjava/classpath/java/awt/event/HierarchyListener.java
new file mode 100644
index 00000000000..f90414b866b
--- /dev/null
+++ b/libjava/classpath/java/awt/event/HierarchyListener.java
@@ -0,0 +1,62 @@
+/* HierarchyListener.java -- listens to changes in the component hierarchy
+ Copyright (C) 2000, 2002 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.event;
+
+import java.util.EventListener;
+
+/**
+ * This listens for changes in the hierarchy tree of components. Normally it is
+ * not necessary to process these events since the AWT handles them
+ * internally, taking all appropriate actions.
+ *
+ * @author Bryce McKinlay
+ * @see HierarchyEvent
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface HierarchyListener extends EventListener
+{
+ /**
+ * Called when the hierarchy of this component changes. Use
+ * <code>getChangeFlags()</code> on the event to see what exactly changed.
+ *
+ * @param e the event describing the change
+ */
+ void hierarchyChanged(HierarchyEvent e);
+} // interface HierarchyListener
diff --git a/libjava/classpath/java/awt/event/InputEvent.java b/libjava/classpath/java/awt/event/InputEvent.java
new file mode 100644
index 00000000000..8f9aed611f8
--- /dev/null
+++ b/libjava/classpath/java/awt/event/InputEvent.java
@@ -0,0 +1,381 @@
+/* InputEvent.java -- common superclass of component input events
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.awt.EventModifier;
+
+import java.awt.Component;
+
+/**
+ * This is the common superclass for all component input classes. These are
+ * passed to listeners before the component, so that listeners can consume
+ * the event before it does its default behavior.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see KeyEvent
+ * @see KeyAdapter
+ * @see MouseEvent
+ * @see MouseAdapter
+ * @see MouseMotionAdapter
+ * @see MouseWheelEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class InputEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -2482525981698309786L;
+
+ /**
+ * This is the bit mask which indicates the shift key is down. It is
+ * recommended that SHIFT_DOWN_MASK be used instead.
+ *
+ * @see #SHIFT_DOWN_MASK
+ */
+ public static final int SHIFT_MASK = 1;
+
+ /**
+ * This is the bit mask which indicates the control key is down. It is
+ * recommended that CTRL_DOWN_MASK be used instead.
+ *
+ * @see #CTRL_DOWN_MASK
+ */
+ public static final int CTRL_MASK = 2;
+
+ /**
+ * This is the bit mask which indicates the meta key is down. It is
+ * recommended that META_DOWN_MASK be used instead.
+ *
+ * @see #META_DOWN_MASK
+ */
+ public static final int META_MASK = 4;
+
+ /**
+ * This is the bit mask which indicates the alt key is down. It is
+ * recommended that ALT_DOWN_MASK be used instead.
+ *
+ * @see #ALT_DOWN_MASK
+ */
+ public static final int ALT_MASK = 8;
+
+ /**
+ * This is the bit mask which indicates the alt-graph modifier is in effect.
+ * It is recommended that ALT_GRAPH_DOWN_MASK be used instead.
+ *
+ * @see #ALT_GRAPH_DOWN_MASK
+ */
+ public static final int ALT_GRAPH_MASK = 0x20;
+
+ /**
+ * This bit mask indicates mouse button one is down. It is recommended that
+ * BUTTON1_DOWN_MASK be used instead.
+ *
+ * @see #BUTTON1_DOWN_MASK
+ */
+ public static final int BUTTON1_MASK = 0x10;
+
+ /**
+ * This bit mask indicates mouse button two is down. It is recommended that
+ * BUTTON2_DOWN_MASK be used instead.
+ *
+ * @see #BUTTON2_DOWN_MASK
+ */
+ public static final int BUTTON2_MASK = 8;
+
+ /**
+ * This bit mask indicates mouse button three is down. It is recommended
+ * that BUTTON3_DOWN_MASK be used instead.
+ *
+ * @see #BUTTON3_DOWN_MASK
+ */
+ public static final int BUTTON3_MASK = 4;
+
+ /**
+ * The SHIFT key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int SHIFT_DOWN_MASK = 0x0040;
+
+ /**
+ * The CTRL key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int CTRL_DOWN_MASK = 0x0080;
+
+ /**
+ * The META key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int META_DOWN_MASK = 0x0100;
+
+ /**
+ * The ALT key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int ALT_DOWN_MASK = 0x0200;
+
+ /**
+ * The mouse button1 key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int BUTTON1_DOWN_MASK = 0x0400;
+
+ /**
+ * The mouse button2 extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int BUTTON2_DOWN_MASK = 0x0800;
+
+ /**
+ * The mouse button3 extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int BUTTON3_DOWN_MASK = 0x1000;
+
+ /**
+ * The ALT_GRAPH key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int ALT_GRAPH_DOWN_MASK = 0x2000;
+
+ /** The mask to convert new to old, package visible for use in subclasses. */
+ static final int CONVERT_MASK
+ = EventModifier.NEW_MASK & ~(BUTTON2_DOWN_MASK | BUTTON3_DOWN_MASK);
+
+ /**
+ * The timestamp when this event occurred.
+ *
+ * @see #getWhen()
+ * @serial the timestamp
+ */
+ private final long when;
+
+ /**
+ * The modifiers in effect for this event. Package visible for use by
+ * subclasses. The old style (bitmask 0x3f) should not be mixed with the
+ * new style (bitmasks 0xffffffc0).
+ *
+ * @see #getModifiers()
+ * @see MouseEvent
+ * @serial the modifier state, stored in the new style
+ */
+ int modifiers;
+
+ /**
+ * Initializes a new instance of <code>InputEvent</code> with the specified
+ * source, id, timestamp, and modifiers. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp when the event occurred
+ * @param modifiers the modifiers in effect for this event, old or new style
+ * @throws IllegalArgumentException if source is null
+ */
+ InputEvent(Component source, int id, long when, int modifiers)
+ {
+ super(source, id);
+ this.when = when;
+ this.modifiers = EventModifier.extend(modifiers);
+ }
+
+ /**
+ * This method tests whether or not the shift key was down during the event.
+ *
+ * @return true if the shift key is down
+ */
+ public boolean isShiftDown()
+ {
+ return (modifiers & SHIFT_DOWN_MASK) != 0;
+ }
+
+ /**
+ * This method tests whether or not the control key was down during the
+ * event.
+ *
+ * @return true if the control key is down
+ */
+ public boolean isControlDown()
+ {
+ return (modifiers & CTRL_DOWN_MASK) != 0;
+ }
+
+ /**
+ * This method tests whether or not the meta key was down during the event.
+ *
+ * @return true if the meta key is down
+ */
+ public boolean isMetaDown()
+ {
+ return (modifiers & META_DOWN_MASK) != 0;
+ }
+
+ /**
+ * This method tests whether or not the alt key was down during the event.
+ *
+ * @return true if the alt key is down
+ */
+ public boolean isAltDown()
+ {
+ return (modifiers & ALT_DOWN_MASK) != 0;
+ }
+
+ /**
+ * This method tests whether or not the alt-graph modifier was in effect
+ * during the event.
+ *
+ * @return true if the alt-graph modifier is down
+ */
+ public boolean isAltGraphDown()
+ {
+ return (modifiers & ALT_GRAPH_DOWN_MASK) != 0;
+ }
+
+ /**
+ * This method returns the timestamp when this event occurred.
+ *
+ * @return the timestamp when this event occurred
+ */
+ public long getWhen()
+ {
+ return when;
+ }
+
+ /**
+ * This method returns the old-style modifiers in effect for this event.
+ * Note that this is ambiguous between button2 and alt, and between
+ * button3 and meta. Also, code which generated these modifiers tends to
+ * only list the modifier that just changed, even if others were down at
+ * the time. Consider using getModifiersEx instead. This will be a union
+ * of the bit masks defined in this class that are applicable to the event.
+ *
+ * @return the modifiers in effect for this event
+ * @see #getModifiersEx()
+ */
+ public int getModifiers()
+ {
+ return EventModifier.revert(modifiers);
+ }
+
+ /**
+ * Returns the extended modifiers (new-style) for this event. This represents
+ * the state of all modal keys and mouse buttons at the time of the event,
+ * and does not suffer from the problems mentioned in getModifiers.
+ *
+ * <p>For an example of checking multiple modifiers, this code will return
+ * true only if SHIFT and BUTTON1 were pressed and CTRL was not:
+ * <pre>
+ * int onmask = InputEvent.SHIFT_DOWN_MASK | InputEvent.BUTTON1_DOWN_MASK;
+ * int offmask = InputEvent.CTRL_DOWN_MASK;
+ * return (event.getModifiersEx() & (onmask | offmask)) == onmask;
+ * </pre>
+ *
+ * @return the bitwise or of all modifiers pressed during the event
+ * @since 1.4
+ */
+ public int getModifiersEx()
+ {
+ return modifiers;
+ }
+
+ /**
+ * Consumes this event. A consumed event is not processed further by the AWT
+ * system.
+ */
+ public void consume()
+ {
+ consumed = true;
+ }
+
+ /**
+ * This method tests whether or not this event has been consumed.
+ *
+ * @return true if this event has been consumed
+ */
+ public boolean isConsumed()
+ {
+ return consumed;
+ }
+
+ /**
+ * Convert the extended modifier bitmask into a String, such as "Shift" or
+ * "Ctrl+Button1".
+ *
+ * XXX Sun claims this can be localized via the awt.properties file - how
+ * do we implement that?
+ *
+ * @param modifiers the modifiers
+ * @return a string representation of the modifiers in this bitmask
+ * @since 1.4
+ */
+ public static String getModifiersExText(int modifiers)
+ {
+ modifiers &= EventModifier.NEW_MASK;
+ if (modifiers == 0)
+ return "";
+ StringBuffer s = new StringBuffer();
+ if ((modifiers & META_DOWN_MASK) != 0)
+ s.append("Meta+");
+ if ((modifiers & CTRL_DOWN_MASK) != 0)
+ s.append("Ctrl+");
+ if ((modifiers & ALT_DOWN_MASK) != 0)
+ s.append("Alt+");
+ if ((modifiers & SHIFT_DOWN_MASK) != 0)
+ s.append("Shift+");
+ if ((modifiers & ALT_GRAPH_DOWN_MASK) != 0)
+ s.append("Alt Graph+");
+ if ((modifiers & BUTTON1_DOWN_MASK) != 0)
+ s.append("Button1+");
+ if ((modifiers & BUTTON2_DOWN_MASK) != 0)
+ s.append("Button2+");
+ if ((modifiers & BUTTON3_DOWN_MASK) != 0)
+ s.append("Button3+");
+ return s.substring(0, s.length() - 1);
+ }
+} // class InputEvent
diff --git a/libjava/classpath/java/awt/event/InputMethodEvent.java b/libjava/classpath/java/awt/event/InputMethodEvent.java
new file mode 100644
index 00000000000..f6711a8fa5a
--- /dev/null
+++ b/libjava/classpath/java/awt/event/InputMethodEvent.java
@@ -0,0 +1,303 @@
+/* InputMethodEvent.java -- events from a text input method
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.font.TextHitInfo;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.text.AttributedCharacterIterator;
+
+/**
+ * This class is for event generated by change in a text input method.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see InputMethodListener
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InputMethodEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 4727190874778922661L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int INPUT_METHOD_FIRST = 1100;
+
+ /** This event id indicates that the text in the input method has changed. */
+ public static final int INPUT_METHOD_TEXT_CHANGED = 1100;
+
+ /** This event id indicates that the input method curor point has changed. */
+ public static final int CARET_POSITION_CHANGED = 1101;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int INPUT_METHOD_LAST = 1101;
+
+ /**
+ * The timestamp when this event was created.
+ *
+ * @serial the timestamp
+ * @since 1.4
+ */
+ private long when;
+
+ /** The input method text. */
+ private final transient AttributedCharacterIterator text;
+
+ /** The number of committed characters in the text. */
+ private final transient int committedCharacterCount;
+
+ /** The caret. */
+ private final transient TextHitInfo caret;
+
+ /** The most important position to be visible. */
+ private final transient TextHitInfo visiblePosition;
+
+ /**
+ * Initializes a new instance of <code>InputMethodEvent</code> with the
+ * specified source, id, timestamp, text, char count, caret, and visible
+ * position.
+ *
+ * @param source the source that generated the event
+ * @param id the event id
+ * @param when the timestamp of the event
+ * @param text the input text
+ * @param committedCharacterCount the number of committed characters
+ * @param caret the caret position
+ * @param visiblePosition the position most important to make visible
+ * @throws IllegalArgumentException if source is null, id is invalid, id is
+ * CARET_POSITION_CHANGED and text is non-null, or if
+ * committedCharacterCount is out of range
+ * @since 1.4
+ */
+ public InputMethodEvent(Component source, int id, long when,
+ AttributedCharacterIterator text,
+ int committedCharacterCount, TextHitInfo caret,
+ TextHitInfo visiblePosition)
+ {
+ super(source, id);
+ this.when = when;
+ this.text = text;
+ this.committedCharacterCount = committedCharacterCount;
+ this.caret = caret;
+ this.visiblePosition = visiblePosition;
+ if (id < INPUT_METHOD_FIRST || id > INPUT_METHOD_LAST
+ || (id == CARET_POSITION_CHANGED && text != null)
+ || committedCharacterCount < 0
+ || (committedCharacterCount
+ > (text == null ? 0 : text.getEndIndex() - text.getBeginIndex())))
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Initializes a new instance of <code>InputMethodEvent</code> with the
+ * specified source, id, text, char count, caret, and visible position.
+ *
+ * @param source the source that generated the event
+ * @param id the event id
+ * @param text the input text
+ * @param committedCharacterCount the number of committed characters
+ * @param caret the caret position
+ * @param visiblePosition the position most important to make visible
+ * @throws IllegalArgumentException if source is null, id is invalid, id is
+ * CARET_POSITION_CHANGED and text is non-null, or if
+ * committedCharacterCount is out of range
+ * @since 1.4
+ */
+ public InputMethodEvent(Component source, int id,
+ AttributedCharacterIterator text,
+ int committedCharacterCount, TextHitInfo caret,
+ TextHitInfo visiblePosition)
+ {
+ this(source, id, EventQueue.getMostRecentEventTime(), text,
+ committedCharacterCount, caret, visiblePosition);
+ }
+
+ /**
+ * Initializes a new instance of <code>InputMethodEvent</code> with the
+ * specified source, id, caret, and visible position, and with a null
+ * text and char count.
+ *
+ * @param source the source that generated the event
+ * @param id the event id
+ * @param caret the caret position
+ * @param visiblePosition the position most important to make visible
+ * @throws IllegalArgumentException if source is null or id is invalid
+ * @since 1.4
+ */
+ public InputMethodEvent(Component source, int id, TextHitInfo caret,
+ TextHitInfo visiblePosition)
+ {
+ this(source, id, EventQueue.getMostRecentEventTime(), null, 0, caret,
+ visiblePosition);
+ }
+
+ /**
+ * This method returns the input method text. This can be <code>null</code>,
+ * and will always be null for <code>CARET_POSITION_CHANGED</code> events.
+ * Characters from 0 to <code>getCommittedCharacterCount()-1</code> have
+ * been committed, the remaining characters are composed text.
+ *
+ * @return the input method text, or null
+ */
+ public AttributedCharacterIterator getText()
+ {
+ return text;
+ }
+
+ /**
+ * Returns the number of committed characters in the input method text.
+ *
+ * @return the number of committed characters in the input method text
+ */
+ public int getCommittedCharacterCount()
+ {
+ return committedCharacterCount;
+ }
+
+ /**
+ * Returns the caret position. The caret offset is relative to the composed
+ * text of the most recent <code>INPUT_METHOD_TEXT_CHANGED</code> event.
+ *
+ * @return the caret position, or null
+ */
+ public TextHitInfo getCaret()
+ {
+ return caret;
+ }
+
+ /**
+ * Returns the position that is most important to be visible, or null if
+ * such a hint is not necessary. The caret offset is relative to the composed
+ * text of the most recent <code>INPUT_METHOD_TEXT_CHANGED</code> event.
+ *
+ * @return the position that is most important to be visible
+ */
+ public TextHitInfo getVisiblePosition()
+ {
+ return visiblePosition;
+ }
+
+ /**
+ * This method consumes the event. A consumed event is not processed
+ * in the default manner by the component that generated it.
+ */
+ public void consume()
+ {
+ consumed = true;
+ }
+
+ /**
+ * This method tests whether or not this event has been consumed.
+ *
+ * @return true if the event has been consumed
+ */
+ public boolean isConsumed()
+ {
+ return consumed;
+ }
+
+ /**
+ * Return the timestamp of this event.
+ *
+ * @return the timestamp
+ * @since 1.4
+ */
+ public long getWhen()
+ {
+ return when;
+ }
+
+ /**
+ * This method returns a string identifying the event. This contains the
+ * event ID, the committed and composed characters separated by '+', the
+ * number of committed characters, the caret, and the visible position.
+ *
+ * @return a string identifying the event
+ */
+ public String paramString()
+ {
+ StringBuffer s
+ = new StringBuffer(80 + (text == null ? 0
+ : text.getEndIndex() - text.getBeginIndex()));
+ s.append(id == INPUT_METHOD_TEXT_CHANGED ? "INPUT_METHOD_TEXT_CHANGED, "
+ : "CARET_POSITION_CHANGED, ");
+ if (text == null)
+ s.append("no text, 0 characters committed, caret: ");
+ else
+ {
+ s.append('"');
+ int i = text.getBeginIndex();
+ int j = committedCharacterCount;
+ while (--j >= 0)
+ s.append(text.setIndex(i++));
+ s.append("\" + \"");
+ j = text.getEndIndex() - i;
+ while (--j >= 0)
+ s.append(text.setIndex(i++));
+ s.append("\", ").append(committedCharacterCount)
+ .append(" characters committed, caret: ");
+ }
+ s.append(caret == null ? (Object) "no caret" : caret).append(", ")
+ .append(visiblePosition == null ? (Object) "no visible position"
+ : visiblePosition);
+ return s.toString();
+ }
+
+ /**
+ * Reads in the object from a serial stream, updating when to
+ * {@link EventQueue#getMostRecentEventTime()} if necessary.
+ *
+ * @param s the stream to read from
+ * @throws IOException if deserialization fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData default, except for updating when
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ if (when == 0)
+ when = EventQueue.getMostRecentEventTime();
+ }
+} // class InputMethodEvent
diff --git a/libjava/classpath/java/awt/event/InputMethodListener.java b/libjava/classpath/java/awt/event/InputMethodListener.java
new file mode 100644
index 00000000000..e2f6a4e6755
--- /dev/null
+++ b/libjava/classpath/java/awt/event/InputMethodListener.java
@@ -0,0 +1,70 @@
+/* InputMethodListener.java -- listen for input method events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.im.InputMethodRequests;
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive events from an input
+ * method. For a text component to use input methods, it must also install
+ * an InputMethodRequests handler.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see InputMethodEvent
+ * @see InputMethodRequests
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface InputMethodListener extends EventListener
+{
+ /**
+ * This method is called when the text is changed.
+ *
+ * @param event the <code>InputMethodEvent</code> indicating the text change
+ */
+ void inputMethodTextChanged(InputMethodEvent event);
+
+ /**
+ * This method is called when the cursor position within the text is changed.
+ *
+ * @param event the <code>InputMethodEvent</code> indicating the change
+ */
+ void caretPositionChanged(InputMethodEvent event);
+} // interface InputMethodListener
diff --git a/libjava/classpath/java/awt/event/InvocationEvent.java b/libjava/classpath/java/awt/event/InvocationEvent.java
new file mode 100644
index 00000000000..75feb62bd94
--- /dev/null
+++ b/libjava/classpath/java/awt/event/InvocationEvent.java
@@ -0,0 +1,237 @@
+/* InvocationEvent.java -- call a runnable when dispatched
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.ActiveEvent;
+import java.awt.EventQueue;
+
+/**
+ * This event executes {@link Runnable#run()} of a target object when it is
+ * dispatched. This class is used by calls to <code>invokeLater</code> and
+ * <code>invokeAndWait</code>, so client code can use this fact to avoid
+ * writing special-casing AWTEventListener objects.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ActiveEvent
+ * @see EventQueue#invokeLater(Runnable)
+ * @see EventQueue#invokeAndWait(Runnable)
+ * @see AWTEventListener
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InvocationEvent extends AWTEvent implements ActiveEvent
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 436056344909459450L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int INVOCATION_FIRST = 1200;
+
+ /** This is the default id for this event type. */
+ public static final int INVOCATION_DEFAULT = 1200;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int INVOCATION_LAST = 1200;
+
+ /**
+ * This is the <code>Runnable</code> object to call when dispatched.
+ *
+ * @serial the runnable to execute
+ */
+ protected Runnable runnable;
+
+ /**
+ * This is the object to call <code>notifyAll()</code> on when
+ * the call to <code>run()</code> returns, or <code>null</code> if no
+ * object is to be notified.
+ *
+ * @serial the object to notify
+ */
+ protected Object notifier;
+
+ /**
+ * This variable is set to <code>true</code> if exceptions are caught
+ * and stored in a variable during the call to <code>run()</code>, otherwise
+ * exceptions are ignored and propagate up.
+ *
+ * @serial true to catch exceptions
+ */
+ protected boolean catchExceptions;
+
+ /**
+ * This is the caught exception thrown in the <code>run()</code> method. It
+ * is null if exceptions are ignored, the run method hasn't completed, or
+ * there were no exceptions.
+ *
+ * @serial the caught exception, if any
+ */
+ private Exception exception;
+
+ /**
+ * The timestamp when this event was created.
+ *
+ * @see #getWhen()
+ * @serial the timestamp
+ * @since 1.4
+ */
+ private final long when = EventQueue.getMostRecentEventTime();
+
+ /**
+ * Initializes a new instance of <code>InvocationEvent</code> with the
+ * specified source and runnable.
+ *
+ * @param source the source of the event
+ * @param runnable the <code>Runnable</code> object to invoke
+ * @throws IllegalArgumentException if source is null
+ */
+ public InvocationEvent(Object source, Runnable runnable)
+ {
+ this(source, INVOCATION_DEFAULT, runnable, null, false);
+ }
+
+ /**
+ * Initializes a new instance of <code>InvocationEvent</code> with the
+ * specified source, runnable, and notifier. It will also catch exceptions
+ * if specified. If notifier is non-null, this will call notifyAll() on
+ * the object when the runnable is complete. If catchExceptions is true,
+ * this traps any exception in the runnable, otherwise it lets the exception
+ * propagate up the Event Dispatch thread.
+ *
+ * @param source the source of the event
+ * @param runnable the <code>Runnable</code> object to invoke
+ * @param notifier the object to notify, or null
+ * @param catchExceptions true to catch exceptions from the runnable
+ */
+ public InvocationEvent(Object source, Runnable runnable, Object notifier,
+ boolean catchExceptions)
+ {
+ this(source, INVOCATION_DEFAULT, runnable, notifier, catchExceptions);
+ }
+
+ /**
+ * Initializes a new instance of <code>InvocationEvent</code> with the
+ * specified source, runnable, and notifier. It will also catch exceptions
+ * if specified. If notifier is non-null, this will call notifyAll() on
+ * the object when the runnable is complete. If catchExceptions is true,
+ * this traps any exception in the runnable, otherwise it lets the exception
+ * propagate up the Event Dispatch thread. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param runnable the <code>Runnable</code> object to invoke
+ * @param notifier the object to notify, or null
+ * @param catchExceptions true to catch exceptions from the runnable
+ */
+ protected InvocationEvent(Object source, int id, Runnable runnable,
+ Object notifier, boolean catchExceptions)
+ {
+ super(source, id);
+ this.runnable = runnable;
+ this.notifier = notifier;
+ this.catchExceptions = catchExceptions;
+ }
+
+ /**
+ * This method calls the <code>run()</code> method of the runnable, traps
+ * exceptions if instructed to do so, and calls <code>notifyAll()</code>
+ * on any notifier if all worked successfully.
+ */
+ public void dispatch()
+ {
+ if (catchExceptions)
+ try
+ {
+ runnable.run();
+ }
+ catch (Exception e)
+ {
+ exception = e;
+ }
+ else
+ runnable.run();
+
+ Object o = notifier;
+ if (o != null)
+ synchronized(o)
+ {
+ o.notifyAll();
+ }
+ }
+
+ /**
+ * This method returns the exception that occurred during the execution of
+ * the runnable, or <code>null</code> if not exception was thrown or
+ * exceptions were not caught.
+ *
+ * @return the exception thrown by the runnable
+ */
+ public Exception getException()
+ {
+ return exception;
+ }
+
+ /**
+ * Gets the timestamp of when this event was created.
+ *
+ * @return the timestamp of this event
+ * @since 1.4
+ */
+ public long getWhen()
+ {
+ return when;
+ }
+
+ /**
+ * This method returns a string identifying this event. This is formatted as:
+ * <code>"INVOCATION_DEFAULT,runnable=" + runnable + ",notifier=" + notifier
+ * + ",catchExceptions=" + catchExceptions + ",when=" + getWhen()</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return (id == INVOCATION_DEFAULT ? "INVOCATION_DEFAULT,runnable="
+ : "unknown type,runnable=") + runnable + ",notifier=" + notifier
+ + ",catchExceptions=" + catchExceptions + ",when=" + when;
+ }
+} // class InvocationEvent
diff --git a/libjava/classpath/java/awt/event/ItemEvent.java b/libjava/classpath/java/awt/event/ItemEvent.java
new file mode 100644
index 00000000000..467815b1608
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ItemEvent.java
@@ -0,0 +1,155 @@
+/* ItemEvent.java -- event for item state changes
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.ItemSelectable;
+
+/**
+ * This event is generated when a selection item changes state. This is an
+ * abstraction that distills a large number of individual mouse or keyboard
+ * events into a simpler "item selected" and "item deselected" events.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ItemSelectable
+ * @see ItemListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ItemEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -608708132447206933L;
+
+ /** This is the first id in the event id range used by this class. */
+ public static final int ITEM_FIRST = 701;
+
+ /** This is the last id in the event id range used by this class. */
+ public static final int ITEM_LAST = 701;
+
+ /** This event id indicates a state change occurred. */
+ public static final int ITEM_STATE_CHANGED = 701;
+
+ /** This type indicates that the item was selected. */
+ public static final int SELECTED = 1;
+
+ /** This type indicates that the item was deselected. */
+ public static final int DESELECTED = 2;
+
+ /**
+ * The item affected by this event.
+ *
+ * @serial the item of the selection
+ */
+ private final Object item;
+
+ /**
+ * The state change direction, one of {@link #SELECTED} or
+ * {@link #DESELECTED}.
+ *
+ * @serial the selection state
+ */
+ private final int stateChange;
+
+ /**
+ * Initializes a new instance of <code>ItemEvent</code> with the specified
+ * source, id, and state change constant. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param item the item affected by the state change
+ * @param stateChange one of {@link #SELECTED} or {@link #DESELECTED}
+ */
+ public ItemEvent(ItemSelectable source, int id, Object item, int stateChange)
+ {
+ super(source, id);
+ this.item = item;
+ this.stateChange = stateChange;
+ }
+
+ /**
+ * This method returns the event source as an <code>ItemSelectable</code>.
+ *
+ * @return the event source as an <code>ItemSelected</code>
+ * @throws ClassCastException if source is changed to a non-ItemSelectable
+ */
+ public ItemSelectable getItemSelectable()
+ {
+ return (ItemSelectable) source;
+ }
+
+ /**
+ * Returns the item affected by this state change.
+ *
+ * @return the item affected by this state change
+ */
+ public Object getItem()
+ {
+ return item;
+ }
+
+ /**
+ * Returns the type of state change, either {@link #SELECTED} or
+ * {@link #DESELECTED}.
+ *
+ * @return the type of state change
+ */
+ public int getStateChange()
+ {
+ return stateChange;
+ }
+
+ /**
+ * Returns a string identifying this event. This is in the format:
+ * <code>"ITEM_STATE_CHANGED,item=" + item + ",stateChange="
+ * + (getStateChange() == DESELECTED ? "DESELECTED" : "SELECTED")</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return (id == ITEM_STATE_CHANGED ? "ITEM_STATE_CHANGED,item="
+ : "unknown type,item=") + item + ",stateChange="
+ + (stateChange == SELECTED ? "SELECTED"
+ : stateChange == DESELECTED ? "DESELECTED" : "unknown type");
+ }
+} // class ItemEvent
diff --git a/libjava/classpath/java/awt/event/ItemListener.java b/libjava/classpath/java/awt/event/ItemListener.java
new file mode 100644
index 00000000000..fa5f3aad3fb
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ItemListener.java
@@ -0,0 +1,62 @@
+/* ItemListener.java -- listen for item events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.ItemSelectable;
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive events when an
+ * item's selection state changes.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ItemSelectable
+ * @see ItemEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface ItemListener extends EventListener
+{
+ /**
+ * This method is called when an item's state is changed.
+ *
+ * @param event the <code>ItemEvent</code> indicating the change
+ */
+ void itemStateChanged(ItemEvent event);
+} // interface ItemListener
diff --git a/libjava/classpath/java/awt/event/KeyAdapter.java b/libjava/classpath/java/awt/event/KeyAdapter.java
new file mode 100644
index 00000000000..c01d61ff339
--- /dev/null
+++ b/libjava/classpath/java/awt/event/KeyAdapter.java
@@ -0,0 +1,88 @@
+/* KeyAdapter.java -- convenience class for writing key listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>KeyListener</code> and implements all methods
+ * with empty bodies. This allows a listener interested in implementing only
+ * a subset of the <code>KeyListener</code> interface to extend this class
+ * and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see KeyEvent
+ * @see KeyListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class KeyAdapter implements KeyListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public KeyAdapter()
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void keyTyped(KeyEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void keyPressed(KeyEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void keyReleased(KeyEvent event)
+ {
+ }
+} // class KeyAdapter
diff --git a/libjava/classpath/java/awt/event/KeyEvent.java b/libjava/classpath/java/awt/event/KeyEvent.java
new file mode 100644
index 00000000000..a40a8e15c04
--- /dev/null
+++ b/libjava/classpath/java/awt/event/KeyEvent.java
@@ -0,0 +1,1740 @@
+/* KeyEvent.java -- event for key presses
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.awt.EventModifier;
+
+import java.awt.Component;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * This event is generated when a key is pressed or released. There are two
+ * categories of key events:
+ *
+ * <p><em>"Key typed" events</em> are higher-level, and have already
+ * compensated for modifiers and keyboard layout to generate a single Unicode
+ * character. It may take several key press events to generate one key typed.
+ * The <code>getKeyCode</code> method will return <code>VK_UNDEFINED</code>,
+ * and <code>getKeyChar</code> will return a valid Unicode character or
+ * <code>CHAR_UNDEFINED</code>.
+ *
+ * <p><em>"Key pressed" and "key released" events</em> are lower-level, and
+ * are platform and keyboard dependent. They correspond to the actaul motion
+ * on a keyboard, and return a virtual key code which labels the key that was
+ * pressed. The <code>getKeyCode</code> method will return one of the
+ * <code>VK_*</code> constants (except VK_UNDEFINED), and the
+ * <code>getKeyChar</code> method is undefined.
+ *
+ * <p>Some keys do not generate key typed events, such as the F1 or HELP keys.
+ * Not all keyboards can generate all virtual keys, and no attempt is made to
+ * simulate the ones that can't be typed. Virtual keys correspond to the
+ * keyboard layout, so for example, VK_Q in English is VK_A in French. Also,
+ * there are some additional virtual keys to ease handling of actions, such
+ * as VK_ALL_CANDIDATES in place of ALT+VK_CONVERT. Do not rely on the value
+ * of the VK_* constants, except for VK_ENTER, VK_BACK_SPACE, and VK_TAB.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see KeyAdapter
+ * @see KeyListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class KeyEvent extends InputEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -2352130953028126954L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int KEY_FIRST = 400;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int KEY_LAST = 402;
+
+ /**
+ * This event id indicates a key was typed, which is a key press followed
+ * by a key release to generate an actual Unicode character. It may take
+ * several key presses to generate one key typed event, and some action
+ * keys have no corresponding key typed.
+ */
+ public static final int KEY_TYPED = 400;
+
+ /** This event id indicates a key was pressed. */
+ public static final int KEY_PRESSED = 401;
+
+ /** This event it indicates a key was released. */
+ public static final int KEY_RELEASED = 402;
+
+ /** The virtual key Enter, which will always map to '\n'. */
+ public static final int VK_ENTER = '\n';
+
+ /** The virtual key Backspace, which will always map to '\b'. */
+ public static final int VK_BACK_SPACE = '\b';
+
+ /** The virtual key Tab, which will always map to '\t'. */
+ public static final int VK_TAB = '\t';
+
+ /** The virtual key Cancel. */
+ public static final int VK_CANCEL = 3;
+
+ /** The virtual key VK_CLEAR. */
+ public static final int VK_CLEAR = 12;
+
+ /** The virtual key VK_SHIFT. */
+ public static final int VK_SHIFT = 16;
+
+ /** The virtual key VK_CONTROL. */
+ public static final int VK_CONTROL = 17;
+
+ /** The virtual key VK_ALT. */
+ public static final int VK_ALT = 18;
+
+ /** The virtual key VK_PAUSE. */
+ public static final int VK_PAUSE = 19;
+
+ /** The virtual key VK_CAPS_LOCK. */
+ public static final int VK_CAPS_LOCK = 20;
+
+ /** The virtual key VK_ESCAPE. */
+ public static final int VK_ESCAPE = 27;
+
+ /** The virtual key VK_SPACE. */
+ public static final int VK_SPACE = ' ';
+
+ /** The virtual key VK_PAGE_UP. */
+ public static final int VK_PAGE_UP = 33;
+
+ /** The virtual key VK_PAGE_DOWN. */
+ public static final int VK_PAGE_DOWN = 34;
+
+ /** The virtual key VK_END. */
+ public static final int VK_END = 35;
+
+ /** The virtual key VK_HOME. */
+ public static final int VK_HOME = 36;
+
+ /**
+ * The virtual key for the non-numpad VK_LEFT.
+ *
+ * @see #VK_KP_LEFT
+ */
+ public static final int VK_LEFT = 37;
+
+ /**
+ * The virtual key for the non-numpad VK_UP.
+ *
+ * @see #VK_KP_UP
+ */
+ public static final int VK_UP = 38;
+
+ /**
+ * The virtual key for the non-numpad VK_RIGHT.
+ *
+ * @see #VK_KP_RIGHT
+ */
+ public static final int VK_RIGHT = 39;
+
+ /**
+ * The virtual key for the non-numpad VK_DOWN.
+ *
+ * @see #VK_KP_DOWN
+ */
+ public static final int VK_DOWN = 40;
+
+ /** The virtual key VK_COMMA. */
+ public static final int VK_COMMA = ',';
+
+ /**
+ * The virtual key VK_MINUS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_MINUS = '-';
+
+ /** The virtual key VK_PERIOD. */
+ public static final int VK_PERIOD = '.';
+
+ /** The virtual key VK_SLASH. */
+ public static final int VK_SLASH = '/';
+
+ /** The virtual key VK_0. */
+ public static final int VK_0 = '0';
+
+ /** The virtual key VK_1. */
+ public static final int VK_1 = '1';
+
+ /** The virtual key VK_2. */
+ public static final int VK_2 = '2';
+
+ /** The virtual key VK_3. */
+ public static final int VK_3 = '3';
+
+ /** The virtual key VK_4. */
+ public static final int VK_4 = '4';
+
+ /** The virtual key VK_5. */
+ public static final int VK_5 = '5';
+
+ /** The virtual key VK_6. */
+ public static final int VK_6 = '6';
+
+ /** The virtual key VK_7. */
+ public static final int VK_7 = '7';
+
+ /** The virtual key VK_8. */
+ public static final int VK_8 = '8';
+
+ /** The virtual key VK_9. */
+ public static final int VK_9 = '9';
+
+ /** The virtual key VK_SEMICOLON. */
+ public static final int VK_SEMICOLON = ';';
+
+ /** The virtual key VK_EQUALS. */
+ public static final int VK_EQUALS = '=';
+
+ /** The virtual key VK_A. */
+ public static final int VK_A = 'A';
+
+ /** The virtual key VK_B. */
+ public static final int VK_B = 'B';
+
+ /** The virtual key VK_C. */
+ public static final int VK_C = 'C';
+
+ /** The virtual key VK_D. */
+ public static final int VK_D = 'D';
+
+ /** The virtual key VK_E. */
+ public static final int VK_E = 'E';
+
+ /** The virtual key VK_F. */
+ public static final int VK_F = 'F';
+
+ /** The virtual key VK_G. */
+ public static final int VK_G = 'G';
+
+ /** The virtual key VK_H. */
+ public static final int VK_H = 'H';
+
+ /** The virtual key VK_I. */
+ public static final int VK_I = 'I';
+
+ /** The virtual key VK_J. */
+ public static final int VK_J = 'J';
+
+ /** The virtual key VK_K. */
+ public static final int VK_K = 'K';
+
+ /** The virtual key VK_L. */
+ public static final int VK_L = 'L';
+
+ /** The virtual key VK_M. */
+ public static final int VK_M = 'M';
+
+ /** The virtual key VK_N. */
+ public static final int VK_N = 'N';
+
+ /** The virtual key VK_O. */
+ public static final int VK_O = 'O';
+
+ /** The virtual key VK_P. */
+ public static final int VK_P = 'P';
+
+ /** The virtual key VK_Q. */
+ public static final int VK_Q = 'Q';
+
+ /** The virtual key VK_R. */
+ public static final int VK_R = 'R';
+
+ /** The virtual key VK_S. */
+ public static final int VK_S = 'S';
+
+ /** The virtual key VK_T. */
+ public static final int VK_T = 'T';
+
+ /** The virtual key VK_U. */
+ public static final int VK_U = 'U';
+
+ /** The virtual key VK_V. */
+ public static final int VK_V = 'V';
+
+ /** The virtual key VK_W. */
+ public static final int VK_W = 'W';
+
+ /** The virtual key VK_X. */
+ public static final int VK_X = 'X';
+
+ /** The virtual key VK_Y. */
+ public static final int VK_Y = 'Y';
+
+ /** The virtual key VK_Z. */
+ public static final int VK_Z = 'Z';
+
+ /** The virtual key VK_OPEN_BRACKET. */
+ public static final int VK_OPEN_BRACKET = '[';
+
+ /** The virtual key VK_BACK_SLASH. */
+ public static final int VK_BACK_SLASH = '\\';
+
+ /** The virtual key VK_CLOSE_BRACKET. */
+ public static final int VK_CLOSE_BRACKET = ']';
+
+ /** The virtual key VK_NUMPAD0. */
+ public static final int VK_NUMPAD0 = 96;
+
+ /** The virtual key VK_NUMPAD1. */
+ public static final int VK_NUMPAD1 = 97;
+
+ /** The virtual key VK_NUMPAD2. */
+ public static final int VK_NUMPAD2 = 98;
+
+ /** The virtual key VK_NUMPAD3. */
+ public static final int VK_NUMPAD3 = 99;
+
+ /** The virtual key VK_NUMPAD4. */
+ public static final int VK_NUMPAD4 = 100;
+
+ /** The virtual key VK_NUMPAD5. */
+ public static final int VK_NUMPAD5 = 101;
+
+ /** The virtual key VK_NUMPAD6. */
+ public static final int VK_NUMPAD6 = 102;
+
+ /** The virtual key VK_NUMPAD7. */
+ public static final int VK_NUMPAD7 = 103;
+
+ /** The virtual key VK_NUMPAD8. */
+ public static final int VK_NUMPAD8 = 104;
+
+ /** The virtual key VK_NUMPAD9. */
+ public static final int VK_NUMPAD9 = 105;
+
+ /** The virtual key VK_MULTIPLY. */
+ public static final int VK_MULTIPLY = 106;
+
+ /** The virtual key VK_ADD. */
+ public static final int VK_ADD = 107;
+
+ /**
+ * The virtual key VK_SEPARATOR, handily mispelled for those who can't
+ * figure it out.
+ *
+ * @deprecated use {@link #VK_SEPARATOR}
+ */
+ public static final int VK_SEPARATER = 108;
+
+ /**
+ * The virtual key VK_SEPARATOR.
+ *
+ * @since 1.4
+ */
+ public static final int VK_SEPARATOR = 108;
+
+ /** The virtual key VK_SUBTRACT. */
+ public static final int VK_SUBTRACT = 109;
+
+ /** The virtual key VK_DECIMAL. */
+ public static final int VK_DECIMAL = 110;
+
+ /** The virtual key VK_DIVIDE. */
+ public static final int VK_DIVIDE = 111;
+
+ /** The virtual key VK_DELETE. */
+ public static final int VK_DELETE = 127;
+
+ /** The virtual key VK_NUM_LOCK. */
+ public static final int VK_NUM_LOCK = 144;
+
+ /** The virtual key VK_SCROLL_LOCK. */
+ public static final int VK_SCROLL_LOCK = 145;
+
+ /** The virtual key VK_F1. */
+ public static final int VK_F1 = 112;
+
+ /** The virtual key VK_F2. */
+ public static final int VK_F2 = 113;
+
+ /** The virtual key VK_F3. */
+ public static final int VK_F3 = 114;
+
+ /** The virtual key VK_F4. */
+ public static final int VK_F4 = 115;
+
+ /** The virtual key VK_F5. */
+ public static final int VK_F5 = 116;
+
+ /** The virtual key VK_F6. */
+ public static final int VK_F6 = 117;
+
+ /** The virtual key VK_F7. */
+ public static final int VK_F7 = 118;
+
+ /** The virtual key VK_F8. */
+ public static final int VK_F8 = 119;
+
+ /** The virtual key VK_F9. */
+ public static final int VK_F9 = 120;
+
+ /** The virtual key VK_F10. */
+ public static final int VK_F10 = 121;
+
+ /** The virtual key VK_F11. */
+ public static final int VK_F11 = 122;
+
+ /** The virtual key VK_F12. */
+ public static final int VK_F12 = 123;
+
+ /**
+ * The virtual key VK_F13.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F13 = 61440;
+
+ /**
+ * The virtual key VK_F14.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F14 = 61441;
+
+ /**
+ * The virtual key VK_F15.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F15 = 61442;
+
+ /**
+ * The virtual key VK_F16.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F16 = 61443;
+
+ /**
+ * The virtual key VK_F17.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F17 = 61444;
+
+ /**
+ * The virtual key VK_F18.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F18 = 61445;
+
+ /**
+ * The virtual key VK_F19.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F19 = 61446;
+
+ /**
+ * The virtual key VK_F20.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F20 = 61447;
+
+ /**
+ * The virtual key VK_F21.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F21 = 61448;
+
+ /**
+ * The virtual key VK_F22.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F22 = 61449;
+
+ /**
+ * The virtual key VK_F23.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F23 = 61450;
+
+ /**
+ * The virtual key VK_F24.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F24 = 61451;
+
+ /** The virtual key VK_PRINTSCREEN. */
+ public static final int VK_PRINTSCREEN = 154;
+
+ /** The virtual key VK_INSERT. */
+ public static final int VK_INSERT = 155;
+
+ /** The virtual key VK_HELP. */
+ public static final int VK_HELP = 156;
+
+ /** The virtual key VK_META. */
+ public static final int VK_META = 157;
+
+ /** The virtual key VK_BACK_QUOTE. */
+ public static final int VK_BACK_QUOTE = 192;
+
+ /** The virtual key VK_QUOTE. */
+ public static final int VK_QUOTE = 222;
+
+ /**
+ * The virtual key for the numpad VK_KP_UP.
+ *
+ * @see #VK_UP
+ * @since 1.2
+ */
+ public static final int VK_KP_UP = 224;
+
+ /**
+ * The virtual key for the numpad VK_KP_DOWN.
+ *
+ * @see #VK_DOWN
+ * @since 1.2
+ */
+ public static final int VK_KP_DOWN = 225;
+
+ /**
+ * The virtual key for the numpad VK_KP_LEFT.
+ *
+ * @see #VK_LEFT
+ * @since 1.2
+ */
+ public static final int VK_KP_LEFT = 226;
+
+ /**
+ * The virtual key for the numpad VK_KP_RIGHT.
+ *
+ * @see #VK_RIGHT
+ * @since 1.2
+ */
+ public static final int VK_KP_RIGHT = 227;
+
+ /**
+ * The virtual key VK_DEAD_GRAVE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_GRAVE = 128;
+
+ /**
+ * The virtual key VK_DEAD_ACUTE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_ACUTE = 129;
+
+ /**
+ * The virtual key VK_DEAD_CIRCUMFLEX.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_CIRCUMFLEX = 130;
+
+ /**
+ * The virtual key VK_DEAD_TILDE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_TILDE = 131;
+
+ /**
+ * The virtual key VK_DEAD_MACRON.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_MACRON = 132;
+
+ /**
+ * The virtual key VK_DEAD_BREVE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_BREVE = 133;
+
+ /**
+ * The virtual key VK_DEAD_ABOVEDOT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_ABOVEDOT = 134;
+
+ /**
+ * The virtual key VK_DEAD_DIAERESIS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_DIAERESIS = 135;
+
+ /**
+ * The virtual key VK_DEAD_ABOVERING.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_ABOVERING = 136;
+
+ /**
+ * The virtual key VK_DEAD_DOUBLEACUTE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_DOUBLEACUTE = 137;
+
+ /**
+ * The virtual key VK_DEAD_CARON.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_CARON = 138;
+
+ /**
+ * The virtual key VK_DEAD_CEDILLA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_CEDILLA = 139;
+
+ /**
+ * The virtual key VK_DEAD_OGONEK.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_OGONEK = 140;
+
+ /**
+ * The virtual key VK_DEAD_IOTA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_IOTA = 141;
+
+ /**
+ * The virtual key VK_DEAD_VOICED_SOUND.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_VOICED_SOUND = 142;
+
+ /**
+ * The virtual key VK_DEAD_SEMIVOICED_SOUND.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_SEMIVOICED_SOUND = 143;
+
+ /**
+ * The virtual key VK_AMPERSAND.
+ *
+ * @since 1.2
+ */
+ public static final int VK_AMPERSAND = 150;
+
+ /**
+ * The virtual key VK_ASTERISK.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ASTERISK = 151;
+
+ /**
+ * The virtual key VK_QUOTEDBL.
+ *
+ * @since 1.2
+ */
+ public static final int VK_QUOTEDBL = 152;
+
+ /**
+ * The virtual key VK_LESS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_LESS = 153;
+
+ /**
+ * The virtual key VK_GREATER.
+ *
+ * @since 1.2
+ */
+ public static final int VK_GREATER = 160;
+
+ /**
+ * The virtual key VK_BRACELEFT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_BRACELEFT = 161;
+
+ /**
+ * The virtual key VK_BRACERIGHT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_BRACERIGHT = 162;
+
+ /**
+ * The virtual key VK_AT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_AT = 512;
+
+ /**
+ * The virtual key VK_COLON.
+ *
+ * @since 1.2
+ */
+ public static final int VK_COLON = 513;
+
+ /**
+ * The virtual key VK_CIRCUMFLEX.
+ *
+ * @since 1.2
+ */
+ public static final int VK_CIRCUMFLEX = 514;
+
+ /**
+ * The virtual key VK_DOLLAR.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DOLLAR = 515;
+
+ /**
+ * The virtual key VK_EURO_SIGN.
+ *
+ * @since 1.2
+ */
+ public static final int VK_EURO_SIGN = 516;
+
+ /**
+ * The virtual key VK_EXCLAMATION_MARK.
+ *
+ * @since 1.2
+ */
+ public static final int VK_EXCLAMATION_MARK = 517;
+
+ /**
+ * The virtual key VK_INVERTED_EXCLAMATION_MARK.
+ *
+ * @since 1.2
+ */
+ public static final int VK_INVERTED_EXCLAMATION_MARK = 518;
+
+ /**
+ * The virtual key VK_LEFT_PARENTHESIS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_LEFT_PARENTHESIS = 519;
+
+ /**
+ * The virtual key VK_NUMBER_SIGN.
+ *
+ * @since 1.2
+ */
+ public static final int VK_NUMBER_SIGN = 520;
+
+ /**
+ * The virtual key VK_PLUS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_PLUS = 521;
+
+ /**
+ * The virtual key VK_RIGHT_PARENTHESIS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_RIGHT_PARENTHESIS = 522;
+
+ /**
+ * The virtual key VK_UNDERSCORE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_UNDERSCORE = 523;
+
+ /** The virtual key VK_FINAL. */
+ public static final int VK_FINAL = 24;
+
+ /** The virtual key VK_CONVERT. */
+ public static final int VK_CONVERT = 28;
+
+ /** The virtual key VK_NONCONVERT. */
+ public static final int VK_NONCONVERT = 29;
+
+ /** The virtual key VK_ACCEPT. */
+ public static final int VK_ACCEPT = 30;
+
+ /** The virtual key VK_MODECHANGE. */
+ public static final int VK_MODECHANGE = 31;
+
+ /** The virtual key VK_KANA. */
+ public static final int VK_KANA = 21;
+
+ /** The virtual key VK_KANJI. */
+ public static final int VK_KANJI = 25;
+
+ /**
+ * The virtual key VK_ALPHANUMERIC.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ALPHANUMERIC = 240;
+
+ /**
+ * The virtual key VK_KATAKANA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_KATAKANA = 241;
+
+ /**
+ * The virtual key VK_HIRAGANA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_HIRAGANA = 242;
+
+ /**
+ * The virtual key VK_FULL_WIDTH.
+ *
+ * @since 1.2
+ */
+ public static final int VK_FULL_WIDTH = 243;
+
+ /**
+ * The virtual key VK_HALF_WIDTH.
+ *
+ * @since 1.2
+ */
+ public static final int VK_HALF_WIDTH = 244;
+
+ /**
+ * The virtual key VK_ROMAN_CHARACTERS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ROMAN_CHARACTERS = 245;
+
+ /**
+ * The virtual key VK_ALL_CANDIDATES.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ALL_CANDIDATES = 256;
+
+ /**
+ * The virtual key VK_PREVIOUS_CANDIDATE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_PREVIOUS_CANDIDATE = 257;
+
+ /**
+ * The virtual key VK_CODE_INPUT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_CODE_INPUT = 258;
+
+ /**
+ * The virtual key VK_JAPANESE_KATAKANA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_JAPANESE_KATAKANA = 259;
+
+ /**
+ * The virtual key VK_JAPANESE_HIRAGANA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_JAPANESE_HIRAGANA = 260;
+
+ /**
+ * The virtual key VK_JAPANESE_ROMAN.
+ *
+ * @since 1.2
+ */
+ public static final int VK_JAPANESE_ROMAN = 261;
+
+ /**
+ * The virtual key VK_KANA_LOCK.
+ *
+ * @since 1.3
+ */
+ public static final int VK_KANA_LOCK = 262;
+
+ /**
+ * The virtual key VK_INPUT_METHOD_ON_OFF.
+ *
+ * @since 1.3
+ */
+ public static final int VK_INPUT_METHOD_ON_OFF = 263;
+
+ /**
+ * The virtual key VK_CUT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_CUT = 65489;
+
+ /**
+ * The virtual key VK_COPY.
+ *
+ * @since 1.2
+ */
+ public static final int VK_COPY = 65485;
+
+ /**
+ * The virtual key VK_PASTE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_PASTE = 65487;
+
+ /**
+ * The virtual key VK_UNDO.
+ *
+ * @since 1.2
+ */
+ public static final int VK_UNDO = 65483;
+
+ /**
+ * The virtual key VK_AGAIN.
+ *
+ * @since 1.2
+ */
+ public static final int VK_AGAIN = 65481;
+
+ /**
+ * The virtual key VK_FIND.
+ *
+ * @since 1.2
+ */
+ public static final int VK_FIND = 65488;
+
+ /**
+ * The virtual key VK_PROPS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_PROPS = 65482;
+
+ /**
+ * The virtual key VK_STOP.
+ *
+ * @since 1.2
+ */
+ public static final int VK_STOP = 65480;
+
+ /**
+ * The virtual key VK_COMPOSE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_COMPOSE = 65312;
+
+ /**
+ * The virtual key VK_ALT_GRAPH.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ALT_GRAPH = 65406;
+
+ /**
+ * The virtual key VK_UNDEFINED. This is used for key typed events, which
+ * do not have a virtual key.
+ */
+ public static final int VK_UNDEFINED = 0;
+
+ /**
+ * The only char with no valid Unicode interpretation. This is used for
+ * key pressed and key released events which do not have a valid keyChar.
+ */
+ public static final char CHAR_UNDEFINED = '\uffff';
+
+ /**
+ * Indicates unknown or irrelavent key location. This is also used for
+ * key typed events, which do not need a location.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_UNKNOWN = 0;
+
+ /**
+ * Indicates a standard key location, with no left/right variants and not
+ * on the numeric pad.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_STANDARD = 1;
+
+ /**
+ * Indicates the key is on the left side of the keyboard, such as the left
+ * shift.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_LEFT = 2;
+
+ /**
+ * Indicates the key is on the right side of the keyboard, such as the right
+ * shift.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_RIGHT = 3;
+
+ /**
+ * Indicates the key is on the numeric pad, such as the numpad 0.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_NUMPAD = 4;
+
+ /**
+ * The code assigned to the physical keyboard location (as adjusted by the
+ * keyboard layout). Use the symbolic VK_* names instead of numbers.
+ *
+ * @see #getKeyCode()
+ * @serial the VK_ code for this key
+ */
+ private int keyCode;
+
+ /**
+ * The Unicode character produced by the key type event. This has no meaning
+ * for key pressed and key released events.
+ *
+ * @see #getKeyChar()
+ * @serial the Unicode value for this key
+ */
+ private char keyChar;
+
+ /**
+ * The keyboard location of the key. One of {@link #KEY_LOCATION_UNKNOWN},
+ * {@link #KEY_LOCATION_STANDARD}, {@link #KEY_LOCATION_LEFT},
+ * {@link #KEY_LOCATION_RIGHT}, or {@link #KEY_LOCATION_NUMPAD}.
+ *
+ * @see #getKeyLocation()
+ * @serial the key location
+ * @since 1.4
+ */
+ private final int keyLocation;
+
+ /**
+ * Stores the state of the native event dispatching system, to correctly
+ * dispatch in Component#dispatchEventImpl when a proxy is active.
+ *
+ * XXX Does this matter in Classpath?
+ *
+ * @serial whether the proxy is active
+ */
+ private boolean isProxyActive;
+
+
+ /**
+ * Initializes a new instance of <code>KeyEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the component that generated this event
+ * @param id the event id
+ * @param when the timestamp when the even occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param keyCode the integer constant for the virtual key type
+ * @param keyChar the Unicode value of the key
+ * @param keyLocation the location of the key
+ * @throws IllegalArgumentException if source is null, if keyLocation is
+ * invalid, or if (id == KEY_TYPED && (keyCode != VK_UNDEFINED
+ * || keyChar == CHAR_UNDEFINED))
+ */
+ public KeyEvent(Component source, int id, long when, int modifiers,
+ int keyCode, char keyChar, int keyLocation)
+ {
+ super(source, id, when, modifiers);
+ this.keyCode = keyCode;
+ this.keyChar = keyChar;
+ this.keyLocation = keyLocation;
+ if ((id == KEY_TYPED && (keyCode != VK_UNDEFINED
+ || keyChar == CHAR_UNDEFINED))
+ || keyLocation < KEY_LOCATION_UNKNOWN
+ || keyLocation > KEY_LOCATION_NUMPAD)
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Initializes a new instance of <code>KeyEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the component that generated this event
+ * @param id the event id
+ * @param when the timestamp when the even occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param keyCode the integer constant for the virtual key type
+ * @param keyChar the Unicode value of the key
+ * @throws IllegalArgumentException if source is null, or if
+ * (id == KEY_TYPED && (keyCode != VK_UNDEFINED
+ * || keyChar == CHAR_UNDEFINED))
+ */
+ public KeyEvent(Component source, int id, long when, int modifiers,
+ int keyCode, char keyChar)
+ {
+ this(source, id, when, modifiers, keyCode, keyChar, KEY_LOCATION_UNKNOWN);
+ }
+
+ /**
+ * Initializes a new instance of <code>KeyEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the component that generated this event
+ * @param id the event id
+ * @param when the timestamp when the even occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param keyCode the integer constant for the virtual key type
+ * @throws IllegalArgumentException if source is null, or if
+ * id == KEY_TYPED but keyCode != VK_UNDEFINED
+ *
+ * @deprecated
+ */
+ public KeyEvent(Component source, int id, long when, int modifiers,
+ int keyCode)
+ {
+ this(source, id, when, modifiers, keyCode, '\0', KEY_LOCATION_UNKNOWN);
+ }
+
+ /**
+ * Returns the key code for the event key. This will be one of the
+ * <code>VK_*</code> constants defined in this class. If the event type is
+ * KEY_TYPED, the result will be VK_UNDEFINED.
+ *
+ * @return the key code for this event
+ */
+ public int getKeyCode()
+ {
+ return keyCode;
+ }
+
+ /**
+ * Sets the key code for this event. This must be one of the
+ * <code>VK_*</code> constants defined in this class.
+ *
+ * @param keyCode the new key code for this event
+ */
+ public void setKeyCode(int keyCode)
+ {
+ this.keyCode = keyCode;
+ }
+
+ /**
+ * Returns the Unicode value for the event key. This will be
+ * <code>CHAR_UNDEFINED</code> if there is no Unicode equivalent for
+ * this key, usually when this is a KEY_PRESSED or KEY_RELEASED event.
+ *
+ * @return the Unicode character for this event
+ */
+ public char getKeyChar()
+ {
+ return keyChar;
+ }
+
+ /**
+ * Sets the Unicode character for this event to the specified value.
+ *
+ * @param keyChar the new Unicode character for this event
+ */
+ public void setKeyChar(char keyChar)
+ {
+ this.keyChar = keyChar;
+ }
+
+ /**
+ * Sets the modifier keys to the specified value. This should be a union
+ * of the bit mask constants from <code>InputEvent</code>. The use of this
+ * method is not recommended, particularly for KEY_TYPED events, which do
+ * not check if the modifiers were changed.
+ *
+ * @param modifiers the new modifier value, in either old or new style
+ * @see InputEvent
+ *
+ * @deprecated
+ */
+ public void setModifiers(int modifiers)
+ {
+ this.modifiers = EventModifier.extend(modifiers);
+ }
+
+ /**
+ * Returns the keyboard location of the key that generated this event. This
+ * provides a way to distinguish between keys like left and right shift
+ * which share a common key code. The result will be one of
+ * {@link #KEY_LOCATION_UNKNOWN}, {@link #KEY_LOCATION_STANDARD},
+ * {@link #KEY_LOCATION_LEFT}, {@link #KEY_LOCATION_RIGHT}, or
+ * {@link #KEY_LOCATION_NUMPAD}.
+ *
+ * @return the key location
+ * @since 1.4
+ */
+ public int getKeyLocation()
+ {
+ return keyLocation;
+ }
+
+ /**
+ * Returns the text name of key code, such as "HOME", "F1", or "A".
+ *
+ * XXX Sun claims this can be localized via the awt.properties file - how
+ * do we implement that?
+ *
+ * @return the text name of the key code
+ */
+ public static String getKeyText(int keyCode)
+ {
+ switch (keyCode)
+ {
+ case VK_CANCEL:
+ return "Cancel";
+ case VK_BACK_SPACE:
+ return "Backspace";
+ case VK_TAB:
+ return "Tab";
+ case VK_ENTER:
+ return "Enter";
+ case VK_CLEAR:
+ return "Clear";
+ case VK_SHIFT:
+ return "Shift";
+ case VK_CONTROL:
+ return "Ctrl";
+ case VK_ALT:
+ return "Alt";
+ case VK_PAUSE:
+ return "Pause";
+ case VK_CAPS_LOCK:
+ return "Caps Lock";
+ case VK_KANA:
+ return "Kana";
+ case VK_FINAL:
+ return "Final";
+ case VK_KANJI:
+ return "Kanji";
+ case VK_ESCAPE:
+ return "Escape";
+ case VK_CONVERT:
+ return "Convert";
+ case VK_NONCONVERT:
+ return "No Convert";
+ case VK_ACCEPT:
+ return "Accept";
+ case VK_MODECHANGE:
+ return "Mode Change";
+ case VK_SPACE:
+ return "Space";
+ case VK_PAGE_UP:
+ return "Page Up";
+ case VK_PAGE_DOWN:
+ return "Page Down";
+ case VK_END:
+ return "End";
+ case VK_HOME:
+ return "Home";
+ case VK_LEFT:
+ case VK_KP_LEFT:
+ return "Left";
+ case VK_UP:
+ case VK_KP_UP:
+ return "Up";
+ case VK_RIGHT:
+ case VK_KP_RIGHT:
+ return "Right";
+ case VK_DOWN:
+ case VK_KP_DOWN:
+ return "Down";
+ case VK_MINUS:
+ return "Minus";
+ case VK_MULTIPLY:
+ return "NumPad *";
+ case VK_ADD:
+ return "NumPad +";
+ case VK_SEPARATOR:
+ return "NumPad ,";
+ case VK_SUBTRACT:
+ return "NumPad -";
+ case VK_DECIMAL:
+ return "NumPad .";
+ case VK_DIVIDE:
+ return "NumPad /";
+ case VK_DELETE:
+ return "Delete";
+ case VK_DEAD_GRAVE:
+ return "Dead Grave";
+ case VK_DEAD_ACUTE:
+ return "Dead Acute";
+ case VK_DEAD_CIRCUMFLEX:
+ return "Dead Circumflex";
+ case VK_DEAD_TILDE:
+ return "Dead Tilde";
+ case VK_DEAD_MACRON:
+ return "Dead Macron";
+ case VK_DEAD_BREVE:
+ return "Dead Breve";
+ case VK_DEAD_ABOVEDOT:
+ return "Dead Above Dot";
+ case VK_DEAD_DIAERESIS:
+ return "Dead Diaeresis";
+ case VK_DEAD_ABOVERING:
+ return "Dead Above Ring";
+ case VK_DEAD_DOUBLEACUTE:
+ return "Dead Double Acute";
+ case VK_DEAD_CARON:
+ return "Dead Caron";
+ case VK_DEAD_CEDILLA:
+ return "Dead Cedilla";
+ case VK_DEAD_OGONEK:
+ return "Dead Ogonek";
+ case VK_DEAD_IOTA:
+ return "Dead Iota";
+ case VK_DEAD_VOICED_SOUND:
+ return "Dead Voiced Sound";
+ case VK_DEAD_SEMIVOICED_SOUND:
+ return "Dead Semivoiced Sound";
+ case VK_NUM_LOCK:
+ return "Num Lock";
+ case VK_SCROLL_LOCK:
+ return "Scroll Lock";
+ case VK_AMPERSAND:
+ return "Ampersand";
+ case VK_ASTERISK:
+ return "Asterisk";
+ case VK_QUOTEDBL:
+ return "Double Quote";
+ case VK_LESS:
+ return "Less";
+ case VK_PRINTSCREEN:
+ return "Print Screen";
+ case VK_INSERT:
+ return "Insert";
+ case VK_HELP:
+ return "Help";
+ case VK_META:
+ return "Meta";
+ case VK_GREATER:
+ return "Greater";
+ case VK_BRACELEFT:
+ return "Left Brace";
+ case VK_BRACERIGHT:
+ return "Right Brace";
+ case VK_BACK_QUOTE:
+ return "Back Quote";
+ case VK_QUOTE:
+ return "Quote";
+ case VK_ALPHANUMERIC:
+ return "Alphanumeric";
+ case VK_KATAKANA:
+ return "Katakana";
+ case VK_HIRAGANA:
+ return "Hiragana";
+ case VK_FULL_WIDTH:
+ return "Full-Width";
+ case VK_HALF_WIDTH:
+ return "Half-Width";
+ case VK_ROMAN_CHARACTERS:
+ return "Roman Characters";
+ case VK_ALL_CANDIDATES:
+ return "All Candidates";
+ case VK_PREVIOUS_CANDIDATE:
+ return "Previous Candidate";
+ case VK_CODE_INPUT:
+ return "Code Input";
+ case VK_JAPANESE_KATAKANA:
+ return "Japanese Katakana";
+ case VK_JAPANESE_HIRAGANA:
+ return "Japanese Hiragana";
+ case VK_JAPANESE_ROMAN:
+ return "Japanese Roman";
+ case VK_KANA_LOCK:
+ return "Kana Lock";
+ case VK_INPUT_METHOD_ON_OFF:
+ return "Input Method On/Off";
+ case VK_AT:
+ return "At";
+ case VK_COLON:
+ return "Colon";
+ case VK_CIRCUMFLEX:
+ return "Circumflex";
+ case VK_DOLLAR:
+ return "Dollar";
+ case VK_EURO_SIGN:
+ return "Euro";
+ case VK_EXCLAMATION_MARK:
+ return "Exclamation Mark";
+ case VK_INVERTED_EXCLAMATION_MARK:
+ return "Inverted Exclamation Mark";
+ case VK_LEFT_PARENTHESIS:
+ return "Left Parenthesis";
+ case VK_NUMBER_SIGN:
+ return "Number Sign";
+ case VK_PLUS:
+ return "Plus";
+ case VK_RIGHT_PARENTHESIS:
+ return "Right Parenthesis";
+ case VK_UNDERSCORE:
+ return "Underscore";
+ case VK_COMPOSE:
+ return "Compose";
+ case VK_ALT_GRAPH:
+ return "Alt Graph";
+ case VK_STOP:
+ return "Stop";
+ case VK_AGAIN:
+ return "Again";
+ case VK_PROPS:
+ return "Props";
+ case VK_UNDO:
+ return "Undo";
+ case VK_COPY:
+ return "Copy";
+ case VK_PASTE:
+ return "Paste";
+ case VK_FIND:
+ return "Find";
+ case VK_CUT:
+ return "Cut";
+ case VK_COMMA:
+ case VK_PERIOD:
+ case VK_SLASH:
+ case VK_0:
+ case VK_1:
+ case VK_2:
+ case VK_3:
+ case VK_4:
+ case VK_5:
+ case VK_6:
+ case VK_7:
+ case VK_8:
+ case VK_9:
+ case VK_SEMICOLON:
+ case VK_EQUALS:
+ case VK_A:
+ case VK_B:
+ case VK_C:
+ case VK_D:
+ case VK_E:
+ case VK_F:
+ case VK_G:
+ case VK_H:
+ case VK_I:
+ case VK_J:
+ case VK_K:
+ case VK_L:
+ case VK_M:
+ case VK_N:
+ case VK_O:
+ case VK_P:
+ case VK_Q:
+ case VK_R:
+ case VK_S:
+ case VK_T:
+ case VK_U:
+ case VK_V:
+ case VK_W:
+ case VK_X:
+ case VK_Y:
+ case VK_Z:
+ case VK_OPEN_BRACKET:
+ case VK_BACK_SLASH:
+ case VK_CLOSE_BRACKET:
+ return "" + (char) keyCode;
+ case VK_NUMPAD0:
+ case VK_NUMPAD1:
+ case VK_NUMPAD2:
+ case VK_NUMPAD3:
+ case VK_NUMPAD4:
+ case VK_NUMPAD5:
+ case VK_NUMPAD6:
+ case VK_NUMPAD7:
+ case VK_NUMPAD8:
+ case VK_NUMPAD9:
+ return "NumPad-" + (keyCode - VK_NUMPAD0);
+ case VK_F1:
+ case VK_F2:
+ case VK_F3:
+ case VK_F4:
+ case VK_F5:
+ case VK_F6:
+ case VK_F7:
+ case VK_F8:
+ case VK_F9:
+ case VK_F10:
+ case VK_F11:
+ case VK_F12:
+ return "F" + (keyCode - (VK_F1 - 1));
+ case VK_F13:
+ case VK_F14:
+ case VK_F15:
+ case VK_F16:
+ case VK_F17:
+ case VK_F18:
+ case VK_F19:
+ case VK_F20:
+ case VK_F21:
+ case VK_F22:
+ case VK_F23:
+ case VK_F24:
+ return "F" + (keyCode - (VK_F13 - 13));
+ default:
+ // This is funky on negative numbers, but that's Sun's fault.
+ return "Unknown keyCode: 0x" + (keyCode < 0 ? "-" : "")
+ + Integer.toHexString(Math.abs(keyCode));
+ }
+ }
+
+ /**
+ * Returns a string describing the modifiers, such as "Shift" or
+ * "Ctrl+Button1".
+ *
+ * XXX Sun claims this can be localized via the awt.properties file - how
+ * do we implement that?
+ *
+ * @param modifiers the old-style modifiers to convert to text
+ * @return a string representation of the modifiers in this bitmask
+ */
+ public static String getKeyModifiersText(int modifiers)
+ {
+ return getModifiersExText(EventModifier.extend(modifiers
+ & EventModifier.OLD_MASK));
+ }
+
+ /**
+ * Tests whether or not this key is an action key. An action key typically
+ * does not fire a KEY_TYPED event, and is not a modifier.
+ *
+ * @return true if this is an action key
+ */
+ public boolean isActionKey()
+ {
+ switch (keyCode)
+ {
+ case VK_PAUSE:
+ case VK_CAPS_LOCK:
+ case VK_KANA:
+ case VK_FINAL:
+ case VK_KANJI:
+ case VK_CONVERT:
+ case VK_NONCONVERT:
+ case VK_ACCEPT:
+ case VK_MODECHANGE:
+ case VK_PAGE_UP:
+ case VK_PAGE_DOWN:
+ case VK_END:
+ case VK_HOME:
+ case VK_LEFT:
+ case VK_UP:
+ case VK_RIGHT:
+ case VK_DOWN:
+ case VK_F1:
+ case VK_F2:
+ case VK_F3:
+ case VK_F4:
+ case VK_F5:
+ case VK_F6:
+ case VK_F7:
+ case VK_F8:
+ case VK_F9:
+ case VK_F10:
+ case VK_F11:
+ case VK_F12:
+ case VK_NUM_LOCK:
+ case VK_SCROLL_LOCK:
+ case VK_PRINTSCREEN:
+ case VK_INSERT:
+ case VK_HELP:
+ case VK_KP_UP:
+ case VK_KP_DOWN:
+ case VK_KP_LEFT:
+ case VK_KP_RIGHT:
+ case VK_ALPHANUMERIC:
+ case VK_KATAKANA:
+ case VK_HIRAGANA:
+ case VK_FULL_WIDTH:
+ case VK_HALF_WIDTH:
+ case VK_ROMAN_CHARACTERS:
+ case VK_ALL_CANDIDATES:
+ case VK_PREVIOUS_CANDIDATE:
+ case VK_CODE_INPUT:
+ case VK_JAPANESE_KATAKANA:
+ case VK_JAPANESE_HIRAGANA:
+ case VK_JAPANESE_ROMAN:
+ case VK_KANA_LOCK:
+ case VK_INPUT_METHOD_ON_OFF:
+ case VK_F13:
+ case VK_F14:
+ case VK_F15:
+ case VK_F16:
+ case VK_F17:
+ case VK_F18:
+ case VK_F19:
+ case VK_F20:
+ case VK_F21:
+ case VK_F22:
+ case VK_F23:
+ case VK_F24:
+ case VK_STOP:
+ case VK_AGAIN:
+ case VK_PROPS:
+ case VK_UNDO:
+ case VK_COPY:
+ case VK_PASTE:
+ case VK_FIND:
+ case VK_CUT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Returns a string identifying the event. This is formatted as the
+ * field name of the id type, followed by the keyCode, then the
+ * keyChar, modifiers (if any), extModifiers (if any), and
+ * keyLocation.
+ *
+ * @return a string identifying the event
+ */
+ public String paramString()
+ {
+ StringBuffer s = new StringBuffer();
+
+ switch (id)
+ {
+ case KEY_PRESSED:
+ s.append("KEY_PRESSED");
+ break;
+ case KEY_RELEASED:
+ s.append("KEY_RELEASED");
+ break;
+ case KEY_TYPED:
+ s.append("KEY_TYPED");
+ break;
+ default:
+ s.append("unknown type");
+ }
+
+ s.append(",keyCode=").append(keyCode);
+
+ s.append(",keyText=").append(getKeyText(keyCode));
+
+ s.append(",keyChar=");
+ if (isActionKey()
+ || keyCode == VK_SHIFT
+ || keyCode == VK_CONTROL
+ || keyCode == VK_ALT)
+ s.append("Undefined keyChar");
+ else
+ {
+ /* This output string must be selected by examining keyChar
+ * rather than keyCode, because key code information is not
+ * included in KEY_TYPED events.
+ */
+ if (keyChar == VK_BACK_SPACE
+ || keyChar == VK_TAB
+ || keyChar == VK_ENTER
+ || keyChar == VK_ESCAPE
+ || keyChar == VK_DELETE)
+ s.append(getKeyText(keyChar));
+ else
+ s.append("'").append(keyChar).append("'");
+ }
+
+ if ((modifiers & CONVERT_MASK) != 0)
+ s.append(",modifiers=").append(getModifiersExText(modifiers
+ & CONVERT_MASK));
+ if (modifiers != 0)
+ s.append(",extModifiers=").append(getModifiersExText(modifiers));
+
+ s.append(",keyLocation=KEY_LOCATION_");
+ switch (keyLocation)
+ {
+ case KEY_LOCATION_UNKNOWN:
+ s.append("UNKNOWN");
+ break;
+ case KEY_LOCATION_STANDARD:
+ s.append("STANDARD");
+ break;
+ case KEY_LOCATION_LEFT:
+ s.append("LEFT");
+ break;
+ case KEY_LOCATION_RIGHT:
+ s.append("RIGHT");
+ break;
+ case KEY_LOCATION_NUMPAD:
+ s.append("NUMPAD");
+ }
+
+ return s.toString();
+ }
+
+ /**
+ * Reads in the object from a serial stream.
+ *
+ * @param s the stream to read from
+ * @throws IOException if deserialization fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData default, except that the modifiers are converted to new style
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ modifiers = EventModifier.extend(modifiers);
+ }
+} // class KeyEvent
diff --git a/libjava/classpath/java/awt/event/KeyListener.java b/libjava/classpath/java/awt/event/KeyListener.java
new file mode 100644
index 00000000000..5c0a640f67e
--- /dev/null
+++ b/libjava/classpath/java/awt/event/KeyListener.java
@@ -0,0 +1,77 @@
+/* KeyListener.java -- listen for keyboard presses
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive keyboard events. To
+ * watch a subset of these events, use a KeyAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see KeyAdapter
+ * @see KeyEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface KeyListener extends EventListener
+{
+ /**
+ * This method is called when a key is typed. A key is considered typed
+ * when it and all modifiers have been pressed and released, mapping to
+ * a single virtual key.
+ *
+ * @param event the <code>KeyEvent</code> indicating that a key was typed
+ */
+ void keyTyped(KeyEvent event);
+
+ /**
+ * This method is called when a key is pressed.
+ *
+ * @param event the <code>KeyEvent</code> indicating the key press
+ */
+ void keyPressed(KeyEvent event);
+
+ /**
+ * This method is called when a key is released.
+ *
+ * @param event the <code>KeyEvent</code> indicating the key release
+ */
+ void keyReleased(KeyEvent event);
+} // interface KeyListener
diff --git a/libjava/classpath/java/awt/event/MouseAdapter.java b/libjava/classpath/java/awt/event/MouseAdapter.java
new file mode 100644
index 00000000000..9f40c285ac7
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseAdapter.java
@@ -0,0 +1,106 @@
+/* MouseAdapter.java -- convenience class for writing mouse listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>MouseListener</code> and implements all methods
+ * with empty bodies. This allows a listener interested in implementing only
+ * a subset of the <code>MouseListener</code> interface to extend this class
+ * and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see MouseEvent
+ * @see MouseListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class MouseAdapter implements MouseListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public MouseAdapter()
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseClicked(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mousePressed(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseReleased(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseEntered(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseExited(MouseEvent event)
+ {
+ }
+} // class MouseAdapter
diff --git a/libjava/classpath/java/awt/event/MouseEvent.java b/libjava/classpath/java/awt/event/MouseEvent.java
new file mode 100644
index 00000000000..249c3d112e4
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseEvent.java
@@ -0,0 +1,432 @@
+/* MouseEvent.java -- a mouse event
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.awt.EventModifier;
+
+import java.awt.Component;
+import java.awt.Point;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * This event is generated for a mouse event. There are three main categories
+ * of mouse events: Regular events include pressing, releasing, and clicking
+ * buttons, as well as moving over the boundary of the unobscured portion of
+ * a component. Motion events include movement and dragging. Wheel events are
+ * covered separately by the subclass MouseWheelEvent.
+ *
+ * <p>A mouse event is tied to the unobstructed visible component that the
+ * mouse cursor was over at the time of the action. The button that was
+ * most recently pressed is the only one that shows up in
+ * <code>getModifiers</code>, and is returned by <code>getButton</code>,
+ * while all buttons that are down show up in <code>getModifiersEx</code>.
+ *
+ * <p>Drag events may be cut short if native drag-and-drop operations steal
+ * the event. Likewise, if a mouse drag exceeds the bounds of a window or
+ * virtual device, some platforms may clip the path to fit in the bounds of
+ * the component.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see MouseAdapter
+ * @see MouseListener
+ * @see MouseMotionAdapter
+ * @see MouseMotionListener
+ * @see MouseWheelListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class MouseEvent extends InputEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -991214153494842848L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int MOUSE_FIRST = 500;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int MOUSE_LAST = 507;
+
+ /** This event id indicates that the mouse was clicked. */
+ public static final int MOUSE_CLICKED = 500;
+
+ /** This event id indicates that the mouse was pressed. */
+ public static final int MOUSE_PRESSED = 501;
+
+ /** This event id indicates that the mouse was released. */
+ public static final int MOUSE_RELEASED = 502;
+
+ /** This event id indicates that the mouse was moved. */
+ public static final int MOUSE_MOVED = 503;
+
+ /** This event id indicates that the mouse entered a component. */
+ public static final int MOUSE_ENTERED = 504;
+
+ /** This event id indicates that the mouse exited a component. */
+ public static final int MOUSE_EXITED = 505;
+
+ /**
+ * This indicates that no button changed state.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ public static final int NOBUTTON = 0;
+
+ /**
+ * This indicates that button 1 changed state.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ public static final int BUTTON1 = 1;
+
+ /**
+ * This indicates that button 2 changed state.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ public static final int BUTTON2 = 2;
+
+ /**
+ * This indicates that button 3 changed state.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ public static final int BUTTON3 = 3;
+
+ /** This event id indicates that the mouse was dragged over a component. */
+ public static final int MOUSE_DRAGGED = 506;
+
+ /**
+ * This event id indicates that the mouse wheel was rotated.
+ *
+ * @since 1.4
+ */
+ public static final int MOUSE_WHEEL = 507;
+
+ /**
+ * The X coordinate of the mouse cursor at the time of the event.
+ *
+ * @see #getX()
+ * @serial the x coordinate
+ */
+ private int x;
+
+ /**
+ * The Y coordinate of the mouse cursor at the time of the event.
+ *
+ * @see #getY()
+ * @serial the y coordinate
+ */
+ private int y;
+
+ /**
+ * The number of clicks that took place. For MOUSE_CLICKED, MOUSE_PRESSED,
+ * and MOUSE_RELEASED, this will be at least 1; otherwise it is 0.
+ *
+ * see #getClickCount()
+ * @serial the number of clicks
+ */
+ private final int clickCount;
+
+ /**
+ * Indicates which mouse button changed state. Can only be one of
+ * {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or
+ * {@link #BUTTON3}.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ private int button;
+
+ /**
+ * Whether or not this event should trigger a popup menu.
+ *
+ * @see PopupMenu
+ * @see #isPopupTrigger()
+ * @serial true if this is a popup trigger
+ */
+ private final boolean popupTrigger;
+
+ /**
+ * Initializes a new instance of <code>MouseEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp of when the event occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param x the X coordinate of the mouse point
+ * @param y the Y coordinate of the mouse point
+ * @param clickCount the number of mouse clicks for this event
+ * @param popupTrigger true if this event triggers a popup menu
+ * @param button the most recent mouse button to change state
+ * @throws IllegalArgumentException if source is null or button is invalid
+ * @since 1.4
+ */
+ public MouseEvent(Component source, int id, long when, int modifiers,
+ int x, int y, int clickCount, boolean popupTrigger,
+ int button)
+ {
+ super(source, id, when, modifiers);
+ this.x = x;
+ this.y = y;
+ this.clickCount = clickCount;
+ this.popupTrigger = popupTrigger;
+ this.button = button;
+ if (button < NOBUTTON || button > BUTTON3)
+ throw new IllegalArgumentException();
+ if ((modifiers & EventModifier.OLD_MASK) != 0)
+ {
+ if ((modifiers & BUTTON1_MASK) != 0)
+ this.button = BUTTON1;
+ else if ((modifiers & BUTTON2_MASK) != 0)
+ this.button = BUTTON2;
+ else if ((modifiers & BUTTON3_MASK) != 0)
+ this.button = BUTTON3;
+ }
+ }
+
+ /**
+ * Initializes a new instance of <code>MouseEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp of when the event occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param x the X coordinate of the mouse point
+ * @param y the Y coordinate of the mouse point
+ * @param clickCount the number of mouse clicks for this event
+ * @param popupTrigger true if this event triggers a popup menu
+ * @throws IllegalArgumentException if source is null
+ */
+ public MouseEvent(Component source, int id, long when, int modifiers,
+ int x, int y, int clickCount, boolean popupTrigger)
+ {
+ this(source, id, when, modifiers, x, y, clickCount, popupTrigger,
+ NOBUTTON);
+ }
+
+ /**
+ * This method returns the X coordinate of the mouse position. This is
+ * relative to the source component.
+ *
+ * @return the x coordinate
+ */
+ public int getX()
+ {
+ return x;
+ }
+
+ /**
+ * This method returns the Y coordinate of the mouse position. This is
+ * relative to the source component.
+ *
+ * @return the y coordinate
+ */
+ public int getY()
+ {
+ return y;
+ }
+
+ /**
+ * This method returns a <code>Point</code> for the x,y position of
+ * the mouse pointer. This is relative to the source component.
+ *
+ * @return a <code>Point</code> for the event position
+ */
+ public Point getPoint()
+ {
+ return new Point(x, y);
+ }
+
+ /**
+ * Translates the event coordinates by the specified x and y offsets.
+ *
+ * @param dx the value to add to the X coordinate of this event
+ * @param dy the value to add to the Y coordiante of this event
+ */
+ public void translatePoint(int dx, int dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ /**
+ * This method returns the number of mouse clicks associated with this
+ * event.
+ *
+ * @return the number of mouse clicks for this event
+ */
+ public int getClickCount()
+ {
+ return clickCount;
+ }
+
+ /**
+ * Returns which button, if any, was the most recent to change state. This
+ * will be one of {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or
+ * {@link #BUTTON3}.
+ *
+ * @return the button that changed state
+ * @since 1.4
+ */
+ public int getButton()
+ {
+ return button;
+ }
+
+ /**
+ * This method tests whether or not the event is a popup menu trigger. This
+ * should be checked in both MousePressed and MouseReleased to be
+ * cross-platform compatible, as different systems have different popup
+ * triggers.
+ *
+ * @return true if the event is a popup menu trigger
+ */
+ public boolean isPopupTrigger()
+ {
+ return popupTrigger;
+ }
+
+ /**
+ * Returns a string describing the modifiers, such as "Shift" or
+ * "Ctrl+Button1".
+ *
+ * XXX Sun claims this can be localized via the awt.properties file - how
+ * do we implement that?
+ *
+ * @param modifiers the old-style modifiers to convert to text
+ * @return a string representation of the modifiers in this bitmask
+ */
+ public static String getMouseModifiersText(int modifiers)
+ {
+ modifiers &= EventModifier.OLD_MASK;
+ if ((modifiers & BUTTON2_MASK) != 0)
+ modifiers |= BUTTON2_DOWN_MASK;
+ if ((modifiers & BUTTON3_MASK) != 0)
+ modifiers |= BUTTON3_DOWN_MASK;
+ return getModifiersExText(EventModifier.extend(modifiers));
+ }
+
+ /**
+ * Returns a string identifying this event. This is formatted as the field
+ * name of the id type, followed by the (x,y) point, the most recent button
+ * changed, modifiers (if any), extModifiers (if any), and clickCount.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ StringBuffer s = new StringBuffer();
+ switch (id)
+ {
+ case MOUSE_CLICKED:
+ s.append("MOUSE_CLICKED,(");
+ break;
+ case MOUSE_PRESSED:
+ s.append("MOUSE_PRESSED,(");
+ break;
+ case MOUSE_RELEASED:
+ s.append("MOUSE_RELEASED,(");
+ break;
+ case MOUSE_MOVED:
+ s.append("MOUSE_MOVED,(");
+ break;
+ case MOUSE_ENTERED:
+ s.append("MOUSE_ENTERED,(");
+ break;
+ case MOUSE_EXITED:
+ s.append("MOUSE_EXITED,(");
+ break;
+ case MOUSE_DRAGGED:
+ s.append("MOUSE_DRAGGED,(");
+ break;
+ case MOUSE_WHEEL:
+ s.append("MOUSE_WHEEL,(");
+ break;
+ default:
+ s.append("unknown type,(");
+ }
+ s.append(x).append(',').append(y).append("),button=").append(button);
+ if ((modifiers & EventModifier.NEW_MASK) != 0)
+ {
+ int mod = modifiers;
+ if ((mod & (ALT_DOWN_MASK | BUTTON2_DOWN_MASK)) != 0)
+ mod |= ALT_DOWN_MASK | BUTTON2_DOWN_MASK;
+ if ((mod & (META_DOWN_MASK | BUTTON3_DOWN_MASK)) != 0)
+ mod |= META_DOWN_MASK | BUTTON3_DOWN_MASK;
+ s.append(",modifiers=").append(getModifiersExText(mod));
+ }
+ if (modifiers != 0)
+ s.append(",extModifiers=").append(getModifiersExText(modifiers));
+ return s.append(",clickCount=").append(clickCount).toString();
+ }
+
+ /**
+ * Reads in the object from a serial stream.
+ *
+ * @param s the stream to read from
+ * @throws IOException if deserialization fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData default, except that the modifiers are converted to new style
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ if ((modifiers & EventModifier.OLD_MASK) != 0)
+ {
+ if ((modifiers & BUTTON1_MASK) != 0)
+ button = BUTTON1;
+ else if ((modifiers & BUTTON2_MASK) != 0)
+ button = BUTTON2;
+ else if ((modifiers & BUTTON3_MASK) != 0)
+ button = BUTTON3;
+ modifiers = EventModifier.extend(modifiers);
+ }
+ }
+} // class MouseEvent
diff --git a/libjava/classpath/java/awt/event/MouseListener.java b/libjava/classpath/java/awt/event/MouseListener.java
new file mode 100644
index 00000000000..4508019e108
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseListener.java
@@ -0,0 +1,94 @@
+/* MouseListener.java -- listen for mouse clicks and crossing component edges
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive mouse events other than
+ * simple motion events. This includes clicks (but not mouse wheel events),
+ * and crossing component boundaries without change in button status. To
+ * track moves and drags, use MouseMotionListener, and to track wheel events,
+ * use MouseWheelListener. To watch a subset of these events, use a
+ * MouseAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see MouseAdapter
+ * @see MouseEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface MouseListener extends EventListener
+{
+ /**
+ * This method is called when the mouse is clicked (pressed and released
+ * in short succession) on a component.
+ *
+ * @param event the <code>MouseEvent</code> indicating the click
+ */
+ void mouseClicked(MouseEvent event);
+
+ /**
+ * This method is called when the mouse is pressed over a component.
+ *
+ * @param event the <code>MouseEvent</code> for the press
+ */
+ void mousePressed(MouseEvent event);
+
+ /**
+ * This method is called when the mouse is released over a component.
+ *
+ * @param event the <code>MouseEvent</code> for the release
+ */
+ void mouseReleased(MouseEvent event);
+
+ /**
+ * This method is called when the mouse enters a component.
+ *
+ * @param event the <code>MouseEvent</code> for the entry
+ */
+ void mouseEntered(MouseEvent event);
+
+ /**
+ * This method is called when the mouse exits a component.
+ *
+ * @param event the <code>MouseEvent</code> for the exit
+ */
+ void mouseExited(MouseEvent event);
+} // interface MouseListener
diff --git a/libjava/classpath/java/awt/event/MouseMotionAdapter.java b/libjava/classpath/java/awt/event/MouseMotionAdapter.java
new file mode 100644
index 00000000000..8a295f66cc0
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseMotionAdapter.java
@@ -0,0 +1,79 @@
+/* MouseMotionAdapter.java -- convenience class for mouse motion listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>MouseMotionListener</code> and implements all
+ * methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>MouseMotionListener</code>
+ * interface to extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see MouseEvent
+ * @see MouseMotionListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class MouseMotionAdapter implements MouseMotionListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public MouseMotionAdapter()
+ {
+ }
+
+ /**
+ * Implement this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseDragged(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implement this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseMoved(MouseEvent event)
+ {
+ }
+} // class MouseMotionAdapter
diff --git a/libjava/classpath/java/awt/event/MouseMotionListener.java b/libjava/classpath/java/awt/event/MouseMotionListener.java
new file mode 100644
index 00000000000..ba2c5698b11
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseMotionListener.java
@@ -0,0 +1,72 @@
+/* MouseMotionListener.java -- listen to mouse motion events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to be notified of mouse movements.
+ * This includes moves and drags, but not crossing component boundaries. To
+ * track other mouse events, use MouseListener or MouseWheelListener. To
+ * watch a subset of these events, use a MouseMotionAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see MouseMotionAdapter
+ * @see MouseEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface MouseMotionListener extends EventListener
+{
+ /**
+ * This method is called when the mouse is moved over a component
+ * while a button has been pressed.
+ *
+ * @param event the <code>MouseEvent</code> indicating the motion
+ */
+ void mouseDragged(MouseEvent event);
+
+ /**
+ * This method is called when the mouse is moved over a component
+ * while no button is pressed.
+ *
+ * @param event the <code>MouseEvent</code> indicating the motion
+ */
+ void mouseMoved(MouseEvent event);
+} // interface MouseMotionListener
diff --git a/libjava/classpath/java/awt/event/MouseWheelEvent.java b/libjava/classpath/java/awt/event/MouseWheelEvent.java
new file mode 100644
index 00000000000..bc603aaa979
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseWheelEvent.java
@@ -0,0 +1,232 @@
+/* MouseWheelEvent.java -- a mouse wheel event
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Adjustable;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.ScrollPane;
+
+import javax.swing.JScrollPane;
+import javax.swing.Scrollable;
+
+/**
+ * This event is generated for a mouse wheel rotation. The wheel (the middle
+ * mouse button on most modern mice) can be rotated towards or away from the
+ * user, and is ofteh used for scrolling.
+ *
+ * <p>Because of the special use for scrolling components, MouseWheelEvents
+ * often affect a different component than the one located at the point of
+ * the event. If the component under the mouse cursor does not accept wheel
+ * events, the event is passed to the first ancestor container which does. This
+ * is often a ScrollPane, which knows how to scroll. If an AWT component is
+ * built from a native widget that knows how to use mouse wheel events, that
+ * component will consume the event.
+ *
+ * <p>The two most common scroll types are "units" (lines at a time) or
+ * "blocks" (pages at a time). The initial setting is taken from the platform,
+ * although the user can adjust the setting at any time.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see MouseWheelListener
+ * @see ScrollPane
+ * @see ScrollPane#setWheelScrollingEnabled(boolean)
+ * @see JScrollPane
+ * @see JScrollPane#setWheelScrollingEnabled(boolean)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class MouseWheelEvent extends MouseEvent
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 6459879390515399677L;
+
+ /**
+ * Indicates scrolling by units (lines).
+ *
+ * @see #getScrollType()
+ */
+ public static final int WHEEL_UNIT_SCROLL = 0;
+
+ /**
+ * Indicates scrolling by blocks (pages).
+ *
+ * @see #getScrollType()
+ */
+ public static final int WHEEL_BLOCK_SCROLL = 1;
+
+ /**
+ * Indicates what scroll type should take place. This should be limited
+ * to {@link #WHEEL_UNIT_SCROLL} and {@link #WHEEL_BLOCK_SCROLL}.
+ *
+ * @serial the scroll type
+ */
+ private final int scrollType;
+
+ /**
+ * Indicates the scroll amount. This is only meaningful if scrollType is
+ * WHEEL_UNIT_SCROLL.
+ *
+ * @serial the number of lines to scroll
+ */
+ private final int scrollAmount;
+
+ /**
+ * Indicates how far the mouse wheel was rotated.
+ *
+ * @serial the rotation amount
+ */
+ private final int wheelRotation;
+
+ /**
+ * Initializes a new instance of <code>MouseWheelEvent</code> with the
+ * specified information. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp of when the event occurred
+ * @param modifiers any modifier bits for this event
+ * @param x the X coordinate of the mouse point
+ * @param y the Y coordinate of the mouse point
+ * @param clickCount the number of mouse clicks for this event
+ * @param popupTrigger true if this event triggers a popup menu
+ * @param scrollType one of {@link #WHEEL_UNIT_SCROLL},
+ * {@link #WHEEL_BLOCK_SCROLL}
+ * @param scrollAmount the number of units to scroll, ignored for block type
+ * @param wheelRotation the number of rotation "clicks"
+ * @throws IllegalArgumentException if source is null
+ * @see MouseEvent#MouseEvent(Component, int, long, int, int, int, int,
+ * boolean)
+ */
+ public MouseWheelEvent(Component source, int id, long when, int modifiers,
+ int x, int y, int clickCount, boolean popupTrigger,
+ int scrollType, int scrollAmount, int wheelRotation)
+ {
+ super(source, id, when, modifiers, x, y, clickCount, popupTrigger);
+ this.scrollType = scrollType;
+ this.scrollAmount = scrollAmount;
+ this.wheelRotation = wheelRotation;
+ }
+
+ /**
+ * This method returns the scrolling pattern this event requests. Legal
+ * values are {@link #WHEEL_UNIT_SCROLL} and {@link #WHEEL_BLOCK_SCROLL}.
+ *
+ * @return the scroll type
+ * @see Adjustable#getUnitIncrement()
+ * @see Adjustable#getBlockIncrement()
+ * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int)
+ * @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int)
+ */
+ public int getScrollType()
+ {
+ return scrollType;
+ }
+
+ /**
+ * Returns the number of units to scroll in response to this event. This
+ * only makes sense when the scroll type is WHEEL_UNIT_SCROLL.
+ *
+ * @return the number of scroll units, if defined
+ * @see #getScrollType()
+ */
+ public int getScrollAmount()
+ {
+ return scrollAmount;
+ }
+
+ /**
+ * Gets the number of "clicks" the wheel was rotated. Negative values move
+ * up (away) from the user, positive values move down (towards) the user.
+ *
+ * @return the number of rotation clicks
+ */
+ public int getWheelRotation()
+ {
+ return wheelRotation;
+ }
+
+ /**
+ * This is a convenience method which aids in a common listener for scrolling
+ * a scrollpane (although this is already built into ScrollPane and
+ * JScrollPane). This method only makes sense when getScrollType() returns
+ * WHEEL_UNIT_SCROLL.
+ *
+ * <p>This accounts for direction of scroll and amount of wheel movement, as
+ * interpreted by the platform settings.
+ *
+ * @return the number of units to scroll
+ * @see #getScrollType()
+ * @see #getScrollAmount()
+ * @see MouseWheelListener
+ * @see Adjustable
+ * @see Adjustable#getUnitIncrement()
+ * @see Scrollable
+ * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int)
+ * @see ScrollPane
+ * @see ScrollPane#setWheelScrollingEnabled(boolean)
+ * @see JScrollPane
+ * @see JScrollPane#setWheelScrollingEnabled(boolean)
+ */
+ public int getUnitsToScroll()
+ {
+ return wheelRotation * scrollAmount;
+ }
+
+ /**
+ * Returns a string identifying this event. For mouse wheel events, this
+ * is <code>super.paramString() + ",scrollType=WHEEL_" +
+ * (getScrollType() == WHEEL_UNIT_SCROLL ? "UNIT" : "BLOCK")
+ * + "_SCROLL,scrollAmount=" + getScrollAmount() + ",wheelRotation="
+ * + getWheelRotation()</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return super.paramString() + ",scrollType="
+ + (scrollType == WHEEL_UNIT_SCROLL ? "WHEEL_UNIT_SCROLL"
+ : scrollType == WHEEL_BLOCK_SCROLL ? "WHEEL_BLOCK_SCROLL"
+ : "unknown scroll type")
+ + ",scrollAmount=" + scrollAmount + ",wheelRotation=" + wheelRotation;
+ }
+} // class MouseWheelEvent
diff --git a/libjava/classpath/java/awt/event/MouseWheelListener.java b/libjava/classpath/java/awt/event/MouseWheelListener.java
new file mode 100644
index 00000000000..1125582e1df
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseWheelListener.java
@@ -0,0 +1,60 @@
+/* MouseWheelListener.java -- listen for mouse wheel events
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive mouse wheel events. For
+ * other events, use MouseListener or MouseMotionListener.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see MouseWheelEvent
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface MouseWheelListener extends EventListener
+{
+ /**
+ * This method is called when the mouse wheel is rotated.
+ *
+ * @param event the <code>MouseWheelEvent</code> indicating the rotation
+ */
+ void mouseWheelMoved(MouseWheelEvent event);
+} // interface MouseWheelListener
diff --git a/libjava/classpath/java/awt/event/PaintEvent.java b/libjava/classpath/java/awt/event/PaintEvent.java
new file mode 100644
index 00000000000..bb89c3722b5
--- /dev/null
+++ b/libjava/classpath/java/awt/event/PaintEvent.java
@@ -0,0 +1,127 @@
+/* PaintEvent.java -- an area of the screen needs to be repainted
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Component;
+import java.awt.Rectangle;
+
+/**
+ * This event is generated when an area of the screen needs to be painted.
+ * This event is not meant for users, but exists to allow proper serialization
+ * behavior in the EventQueue with user-accessible events.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class PaintEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 1267492026433337593L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int PAINT_FIRST = 800;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int PAINT_LAST = 801;
+
+ /** This id is for paint event types. */
+ public static final int PAINT = 800;
+
+ /** This id is for update event types. */
+ public static final int UPDATE = 801;
+
+ /**
+ * This is the rectange to be painted or updated.
+ *
+ * @see #getUpdateRect()
+ * @see #setUpdateRect(Rectangle)
+ * @serial the non-null rectangle to be painted
+ */
+ private Rectangle updateRect;
+
+ /**
+ * Initializes a new instance of <code>PaintEvent</code> with the specified
+ * source, id, and update region. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the event source
+ * @param id the event id
+ * @param updateRect the rectangle to repaint
+ * @throws IllegalArgumentException if source is null
+ */
+ public PaintEvent(Component source, int id, Rectangle updateRect)
+ {
+ super(source, id);
+ this.updateRect = updateRect;
+ }
+
+ /**
+ * Returns the rectange to be updated for this event.
+ *
+ * @return the rectangle to update
+ */
+ public Rectangle getUpdateRect()
+ {
+ return updateRect;
+ }
+
+ /**
+ * Sets the rectangle to be updated for this event.
+ *
+ * @param updateRect the new update rectangle for this event
+ */
+ public void setUpdateRect(Rectangle updateRect)
+ {
+ this.updateRect = updateRect;
+ }
+
+ /**
+ * Returns a string identifying this event.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return (id == PAINT ? "PAINT,updateRect=" : id == UPDATE
+ ? "UPDATE,updateRect=" : "unknown type,updateRect=") + updateRect;
+ }
+} // class PaintEvent
diff --git a/libjava/classpath/java/awt/event/TextEvent.java b/libjava/classpath/java/awt/event/TextEvent.java
new file mode 100644
index 00000000000..0288abbb752
--- /dev/null
+++ b/libjava/classpath/java/awt/event/TextEvent.java
@@ -0,0 +1,93 @@
+/* TextEvent.java -- event for text changes
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.TextComponent;
+
+/**
+ * This event is generated when a text box changes contents. This is an
+ * abstraction that distills a large number of individual mouse or keyboard
+ * events into a simpler "text changed" event.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see TextComponent
+ * @see TextListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class TextEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 6269902291250941179L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int TEXT_FIRST = 900;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int TEXT_LAST = 900;
+
+ /** This event id indicates that the text of an object has changed. */
+ public static final int TEXT_VALUE_CHANGED = 900;
+
+ /**
+ * Initializes a new instance of <code>TextEvent</code> with the specified
+ * source and id. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the (TextComponent) object that generated this event
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public TextEvent(Object source, int id)
+ {
+ super(source, id);
+ }
+
+ /**
+ * Returns a string identifying this event. This is "TEXT_VALUE_CHANGED".
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return id == TEXT_VALUE_CHANGED ? "TEXT_VALUE_CHANGED" : "unknown type";
+ }
+} // class TextEvent
diff --git a/libjava/classpath/java/awt/event/TextListener.java b/libjava/classpath/java/awt/event/TextListener.java
new file mode 100644
index 00000000000..bcdd7fa7a11
--- /dev/null
+++ b/libjava/classpath/java/awt/event/TextListener.java
@@ -0,0 +1,60 @@
+/* TextListener.java -- listen for text changes
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to be notified when text changes
+ * in a component.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see TextEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface TextListener extends EventListener
+{
+ /**
+ * This method is called when the text being monitored changes.
+ *
+ * @param event the <code>TextEvent</code> indicating the change
+ */
+ void textValueChanged(TextEvent event);
+} // interface TextListener
diff --git a/libjava/classpath/java/awt/event/WindowAdapter.java b/libjava/classpath/java/awt/event/WindowAdapter.java
new file mode 100644
index 00000000000..708de588c05
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowAdapter.java
@@ -0,0 +1,156 @@
+/* WindowAdapter.java -- convenience class for writing window listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>WindowListener</code>,
+ * <code>WindowStateListener</code>, and <code>WindowFocusListener</code>, and
+ * implements all methods with empty bodies. This allows a listener
+ * interested in listening to only a subset of any <code>WindowEvent</code>
+ * actions to extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ComponentEvent
+ * @see ComponentListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class WindowAdapter
+ implements WindowListener, WindowStateListener, WindowFocusListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public WindowAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowOpened(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowClosing(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowClosed(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowIconified(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowDeiconified(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowActivated(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowDeactivated(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ * @since 1.4
+ */
+ public void windowStateChanged(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ * @since 1.4
+ */
+ public void windowGainedFocus(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ * @since 1.4
+ */
+ public void windowLostFocus(WindowEvent event)
+ {
+ }
+} // class WindowAdapter
diff --git a/libjava/classpath/java/awt/event/WindowEvent.java b/libjava/classpath/java/awt/event/WindowEvent.java
new file mode 100644
index 00000000000..2186889e601
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowEvent.java
@@ -0,0 +1,312 @@
+/* WindowEvent.java -- window change event
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Frame;
+import java.awt.Window;
+
+/**
+ * This event is generated when there is a change in a window. This includes
+ * creation, closing, iconification, activation, and focus changes. There
+ * are three listeners, for three types of events: WindowListeners deal with
+ * the lifecycle of a window, WindowStateListeners deal with window state
+ * like maximization, and WindowFocusListeners deal with focus switching to
+ * or from a window.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see WindowAdapter
+ * @see WindowListener
+ * @see WindowFocusListener
+ * @see WindowStateListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class WindowEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -1567959133147912127L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int WINDOW_FIRST = 200;
+
+ /** This is the id for a window that is opened. */
+ public static final int WINDOW_OPENED = 200;
+
+ /** This is the id for a window that is about to close. */
+ public static final int WINDOW_CLOSING = 201;
+
+ /** This is the id for a window that finished closing. */
+ public static final int WINDOW_CLOSED = 202;
+
+ /** This is the id for a window that is iconified. */
+ public static final int WINDOW_ICONIFIED = 203;
+
+ /** This is the id for a window that is de-iconified. */
+ public static final int WINDOW_DEICONIFIED = 204;
+
+ /** This is the id for a window that is activated. */
+ public static final int WINDOW_ACTIVATED = 205;
+
+ /** This is the id for a window that is de-activated. */
+ public static final int WINDOW_DEACTIVATED = 206;
+
+ /**
+ * This is the id for a window becoming the focused window.
+ *
+ * @since 1.4
+ */
+ public static final int WINDOW_GAINED_FOCUS = 207;
+
+ /**
+ * This is the id for a window losing all focus.
+ *
+ * @since 1.4
+ */
+ public static final int WINDOW_LOST_FOCUS = 208;
+
+ /**
+ * This is the id for a window state change, such as maximization.
+ *
+ * @since 1.4
+ */
+ public static final int WINDOW_STATE_CHANGED = 209;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int WINDOW_LAST = 209;
+
+ /**
+ * The other Window involved in a focus or activation change. For
+ * WINDOW_ACTIVATED and WINDOW_GAINED_FOCUS events, this is the window that
+ * lost focus; for WINDOW_DEACTIVATED and WINDOW_LOST_FOCUS, this is the
+ * window that stole focus; and for other events (or when native
+ * implementation does not have the data available), this is null.
+ *
+ * @see #getOppositeWindow()
+ * @serial the opposite window, or null
+ * @since 1.4
+ */
+ private final Window opposite;
+
+ /**
+ * The former state of the window.
+ *
+ * @serial bitmask of the old window state
+ * @since 1.4
+ */
+ private final int oldState;
+
+ /**
+ * The present state of the window.
+ *
+ * @serial bitmask of the new window state
+ * @since 1.4
+ */
+ private final int newState;
+
+ /**
+ * Initializes a new instance of <code>WindowEvent</code> with the specified
+ * parameters. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the window that generated this event
+ * @param id the event id
+ * @param opposite the window that received the opposite event, or null
+ * @param oldState the previous state of this window
+ * @param newState the new state of this window
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public WindowEvent(Window source, int id, Window opposite,
+ int oldState, int newState)
+ {
+ super(source, id);
+ this.opposite = opposite;
+ this.oldState = oldState;
+ this.newState = newState;
+ }
+
+ /**
+ * Initializes a new instance of <code>WindowEvent</code> with the specified
+ * parameters. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the window that generated this event
+ * @param id the event id
+ * @param opposite the window that received the opposite event, or null
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public WindowEvent(Window source, int id, Window opposite)
+ {
+ this(source, id, opposite, 0, 0);
+ }
+
+ /**
+ * Initializes a new instance of <code>WindowEvent</code> with the specified
+ * parameters. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the window that generated this event
+ * @param id the event id
+ * @param oldState the previous state of this window
+ * @param newState the new state of this window
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public WindowEvent(Window source, int id, int oldState, int newState)
+ {
+ this(source, id, null, oldState, newState);
+ }
+
+ /**
+ * Initializes a new instance of <code>WindowEvent</code> with the specified
+ * parameters. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the window that generated this event
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public WindowEvent(Window source, int id)
+ {
+ this(source, id, null, 0, 0);
+ }
+
+ /**
+ * Returns the event source as a <code>Window</code>. If the source has
+ * subsequently been modified to a non-Window, this returns null.
+ *
+ * @return the event source as a <code>Window</code>
+ */
+ public Window getWindow()
+ {
+ return source instanceof Window ? (Window) source : null;
+ }
+
+ /**
+ * Returns the opposite window if this window was involved in an activation
+ * or focus change. For WINDOW_ACTIVATED and WINDOW_GAINED_FOCUS events,
+ * this is the window that lost focus; for WINDOW_DEACTIVATED and
+ * WINDOW_LOST_FOCUS, this is the window that stole focus; and for other
+ * events (or when native implementation does not have the data available),
+ * this is null.
+ *
+ * @return the opposite window, or null
+ * @since 1.4
+ */
+ public Window getOppositeWindow()
+ {
+ return opposite;
+ }
+
+ /**
+ * Returns the state of this window before the event. This is the bitwise
+ * or of fields in Frame: NORMAL, ICONIFIED, MAXIMIZED_HORIZ, MAXIMIZED_VERT,
+ * and MAXIMIZED_BOTH.
+ *
+ * @return the former state
+ * @see Frame#getExtendedState()
+ * @since 1.4
+ */
+ public int getOldState()
+ {
+ return oldState;
+ }
+
+ /**
+ * Returns the state of this window after the event. This is the bitwise
+ * or of fields in Frame: NORMAL, ICONIFIED, MAXIMIZED_HORIZ, MAXIMIZED_VERT,
+ * and MAXIMIZED_BOTH.
+ *
+ * @return the updated state
+ * @see Frame#getExtendedState()
+ * @since 1.4
+ */
+ public int getNewState()
+ {
+ return newState;
+ }
+
+ /**
+ * Returns a string that identifies this event. This is formatted as the
+ * field name of the id, followed by the opposite window, old state, and
+ * new state.
+ *
+ * @return a string that identifies this event
+ */
+ public String paramString()
+ {
+ StringBuffer s = new StringBuffer();
+ switch (id)
+ {
+ case WINDOW_OPENED:
+ s.append("WINDOW_OPENED,opposite=");
+ break;
+ case WINDOW_CLOSING:
+ s.append("WINDOW_CLOSING,opposite=");
+ break;
+ case WINDOW_CLOSED:
+ s.append("WINDOW_CLOSED,opposite=");
+ break;
+ case WINDOW_ICONIFIED:
+ s.append("WINDOW_ICONIFIED,opposite=");
+ break;
+ case WINDOW_DEICONIFIED:
+ s.append("WINDOW_DEICONIFIED,opposite=");
+ break;
+ case WINDOW_ACTIVATED:
+ s.append("WINDOW_ACTIVATED,opposite=");
+ break;
+ case WINDOW_DEACTIVATED:
+ s.append("WINDOW_DEACTIVATED,opposite=");
+ break;
+ case WINDOW_GAINED_FOCUS:
+ s.append("WINDOW_GAINED_FOCUS,opposite=");
+ break;
+ case WINDOW_LOST_FOCUS:
+ s.append("WINDOW_LOST_FOCUS,opposite=");
+ break;
+ case WINDOW_STATE_CHANGED:
+ s.append("WINDOW_STATE_CHANGED,opposite=");
+ break;
+ default:
+ s.append("unknown type,opposite=");
+ }
+ return s.append(opposite).append(",oldState=").append(oldState)
+ .append(",newState=").append(newState).toString();
+ }
+} // class WindowEvent
diff --git a/libjava/classpath/java/awt/event/WindowFocusListener.java b/libjava/classpath/java/awt/event/WindowFocusListener.java
new file mode 100644
index 00000000000..738425353e3
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowFocusListener.java
@@ -0,0 +1,68 @@
+/* WindowFocusListener.java -- listens for window focus events
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to monitor events for window
+ * focus changes. To watch a subset of these events, use a WindowAdapter.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see WindowAdapter
+ * @see WindowEvent
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface WindowFocusListener extends EventListener
+{
+ /**
+ * This method is called when a window gains focus.
+ *
+ * @param event the <code>WindowEvent</code> indicating the focus change
+ */
+ void windowGainedFocus(WindowEvent event);
+
+ /**
+ * This method is called when a window loses focus.
+ *
+ * @param event the <code>WindowEvent</code> indicating the focus change
+ */
+ void windowLostFocus(WindowEvent event);
+} // interface WindowFocusListener
diff --git a/libjava/classpath/java/awt/event/WindowListener.java b/libjava/classpath/java/awt/event/WindowListener.java
new file mode 100644
index 00000000000..52213eb3d8c
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowListener.java
@@ -0,0 +1,109 @@
+/* WindowListener.java -- listens for window events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Frame;
+import java.awt.Image;
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to monitor events for window
+ * changes. To watch a subset of these events, use a WindowAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see WindowAdapter
+ * @see WindowEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface WindowListener extends EventListener
+{
+ /**
+ * This method is called when the window is made visible.
+ *
+ * @param event the <code>WindowEvent</code> indicating the change
+ */
+ void windowOpened(WindowEvent event);
+
+ /**
+ * This method is called when the user calls the system menu close
+ * function, giving the program a chance to cancel the close.
+ *
+ * @param event the <code>WindowEvent</code> indicating the close attempt
+ */
+ void windowClosing(WindowEvent event);
+
+ /**
+ * This method is called when the window is closed.
+ *
+ * @param event the <code>WindowEvent</code> indicating the dispose
+ */
+ void windowClosed(WindowEvent event);
+
+ /**
+ * This method is called when the window is iconified.
+ *
+ * @param event the <code>WindowEvent</code> indicating the iconification
+ * @see Frame#setIconImage(Image)
+ */
+ void windowIconified(WindowEvent event);
+
+ /**
+ * This method is called when the window is deiconified.
+ *
+ * @param event the <code>WindowEvent</code> indicating the deiconification
+ */
+ void windowDeiconified(WindowEvent event);
+
+ /**
+ * This method is called when a window is activated. Only Frames and Dialogs
+ * can be active, and the active window always contains the component with
+ * focus.
+ *
+ * @param event the <code>WindowEvent</code> indicating the activation
+ */
+ void windowActivated(WindowEvent event);
+
+ /**
+ * This method is called when the window is deactivated.
+ *
+ * @param event the <code>WindowEvent</code> indicating the deactivation
+ */
+ void windowDeactivated(WindowEvent event);
+} // interface WindowListener
diff --git a/libjava/classpath/java/awt/event/WindowStateListener.java b/libjava/classpath/java/awt/event/WindowStateListener.java
new file mode 100644
index 00000000000..9bc6174fda1
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowStateListener.java
@@ -0,0 +1,62 @@
+/* WindowStateListener.java -- listens for window state changes
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to monitor events for window
+ * state changes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see WindowAdapter
+ * @see WindowEvent
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface WindowStateListener extends EventListener
+{
+ /**
+ * This method is called when the window state is changed, because of
+ * iconification or maximization.
+ *
+ * @param event the <code>WindowEvent</code> indicating the change
+ */
+ void windowStateChanged(WindowEvent event);
+} // interface WindowStateListener
diff --git a/libjava/classpath/java/awt/event/package.html b/libjava/classpath/java/awt/event/package.html
new file mode 100644
index 00000000000..77662a3fb81
--- /dev/null
+++ b/libjava/classpath/java/awt/event/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.event package.
+ Copyright (C) 2002 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 - java.awt.event</title></head>
+
+<body>
+<p>Listeners and adapters for different kinds of AWT events.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/font/FontRenderContext.java b/libjava/classpath/java/awt/font/FontRenderContext.java
new file mode 100644
index 00000000000..78564a647da
--- /dev/null
+++ b/libjava/classpath/java/awt/font/FontRenderContext.java
@@ -0,0 +1,126 @@
+/* FontRenderContext.java
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.geom.AffineTransform;
+
+/**
+ * @author Michael Koch
+ */
+public class FontRenderContext
+{
+ private AffineTransform affineTransform;
+ private boolean isAntiAliased;
+ private boolean usesFractionalMetrics;
+
+ /**
+ * Construct a new <code>FontRenderContext</code>.
+ */
+ protected FontRenderContext()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Construct a new <code>FontRenderContext</code>.
+ */
+ public FontRenderContext (AffineTransform tx, boolean isAntiAliased,
+ boolean usesFractionalMetrics)
+ {
+ if (tx != null
+ && !tx.isIdentity ())
+ {
+ this.affineTransform = new AffineTransform (tx);
+ }
+
+ this.isAntiAliased = isAntiAliased;
+ this.usesFractionalMetrics = usesFractionalMetrics;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof FontRenderContext))
+ return false;
+
+ return equals ((FontRenderContext) obj);
+ }
+
+ public boolean equals (FontRenderContext rhs)
+ {
+ return (affineTransform.equals (rhs.getTransform ())
+ && isAntiAliased == rhs.isAntiAliased ()
+ && usesFractionalMetrics == rhs.usesFractionalMetrics ());
+ }
+
+
+ /**
+ * Retrieves the affine transform for scaling typographical points
+ * to raster pixels.
+ *
+ * @return a clone of the transform object.
+ */
+ public AffineTransform getTransform ()
+ {
+ if (affineTransform == null)
+ return new AffineTransform ();
+ else
+ return new AffineTransform (affineTransform);
+ }
+
+
+ /**
+ * Returns the hash code of the font render context.
+ */
+ public int hashCode ()
+ {
+ // FIXME: check what SUN does here.
+ return affineTransform == null ? 0 : affineTransform.hashCode ();
+ }
+
+ public boolean isAntiAliased ()
+ {
+ return isAntiAliased;
+ }
+
+ public boolean usesFractionalMetrics ()
+ {
+ return usesFractionalMetrics;
+ }
+}
+
diff --git a/libjava/classpath/java/awt/font/GlyphJustificationInfo.java b/libjava/classpath/java/awt/font/GlyphJustificationInfo.java
new file mode 100644
index 00000000000..5f45fd58498
--- /dev/null
+++ b/libjava/classpath/java/awt/font/GlyphJustificationInfo.java
@@ -0,0 +1,77 @@
+/* GlyphJustificationInfo.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+/**
+ * @author Michael Koch
+ */
+public final class GlyphJustificationInfo
+{
+ public static final int PRIORITY_KASHIDA = 0;
+ public static final int PRIORITY_WHITESPACE = 1;
+ public static final int PRIORITY_INTERCHAR = 2;
+ public static final int PRIORITY_NONE = 3;
+
+ public final float weight;
+ public final int growPriority;
+ public final boolean growAbsorb;
+ public final float growLeftLimit;
+ public final float growRightLimit;
+ public final int shrinkPriority;
+ public final boolean shrinkAbsorb;
+ public final float shrinkLeftLimit;
+ public final float shrinkRightLimit;
+
+ public GlyphJustificationInfo (float weight, boolean growAbsorb,
+ int growPriority, float growLeftLimit,
+ float growRightLimit, boolean shrinkAbsorb,
+ int shrinkPriority, float shrinkLeftLimit,
+ float shrinkRightLimit)
+ {
+ this.weight = weight;
+ this.growAbsorb = growAbsorb;
+ this.growPriority = growPriority;
+ this.growLeftLimit = growLeftLimit;
+ this.growRightLimit = growRightLimit;
+ this.shrinkAbsorb = shrinkAbsorb;
+ this.shrinkPriority = shrinkPriority;
+ this.shrinkLeftLimit = shrinkLeftLimit;
+ this.shrinkRightLimit = shrinkRightLimit;
+ }
+}
diff --git a/libjava/classpath/java/awt/font/GlyphMetrics.java b/libjava/classpath/java/awt/font/GlyphMetrics.java
new file mode 100644
index 00000000000..28b2088cf8e
--- /dev/null
+++ b/libjava/classpath/java/awt/font/GlyphMetrics.java
@@ -0,0 +1,134 @@
+/* GlyphMetrics.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.geom.Rectangle2D;
+
+/**
+ * @author Michael Koch
+ */
+public final class GlyphMetrics
+{
+ public static final byte COMBINING = 2;
+ public static final byte COMPONENT = 3;
+ public static final byte LIGATURE = 1;
+ public static final byte STANDARD = 0;
+ public static final byte WHITESPACE = 4;
+
+ private boolean horizontal;
+ private float advanceX;
+ private float advanceY;
+ private Rectangle2D bounds;
+ private byte glyphType;
+
+ public GlyphMetrics (boolean horizontal, float advanceX, float advanceY,
+ Rectangle2D bounds, byte glyphType)
+ {
+ this.horizontal = horizontal;
+ this.advanceX = advanceX;
+ this.advanceY = advanceY;
+ this.bounds = bounds;
+ this.glyphType = glyphType;
+ }
+
+ public GlyphMetrics (float advance, Rectangle2D bounds, byte glyphType)
+ {
+ this (true, advance, advance, bounds, glyphType);
+ }
+
+ public float getAdvance ()
+ {
+ return horizontal ? advanceX : advanceY;
+ }
+
+ public float getAdvanceX ()
+ {
+ return advanceX;
+ }
+
+ public float getAdvanceY ()
+ {
+ return advanceY;
+ }
+
+ public Rectangle2D getBounds2D ()
+ {
+ return bounds;
+ }
+
+ public float getLSB ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public float getRSB ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int getType ()
+ {
+ return glyphType;
+ }
+
+ public boolean isCombining ()
+ {
+ return (glyphType == COMBINING);
+ }
+
+ public boolean isComponent ()
+ {
+ return (glyphType == COMPONENT);
+ }
+
+ public boolean isLigature()
+ {
+ return (glyphType == LIGATURE);
+ }
+
+ public boolean isStandard()
+ {
+ return (glyphType == STANDARD);
+ }
+
+ public boolean isWhitespace()
+ {
+ return (glyphType == WHITESPACE);
+ }
+}
diff --git a/libjava/classpath/java/awt/font/GlyphVector.java b/libjava/classpath/java/awt/font/GlyphVector.java
new file mode 100644
index 00000000000..57e2581edb4
--- /dev/null
+++ b/libjava/classpath/java/awt/font/GlyphVector.java
@@ -0,0 +1,145 @@
+/* GlyphVector.java
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Font;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * @author Michael Koch
+ */
+public abstract class GlyphVector implements Cloneable
+{
+ public static final int FLAG_COMPLEX_GLYPHS = 8;
+ public static final int FLAG_HAS_POSITION_ADJUSTMENTS = 2;
+ public static final int FLAG_HAS_TRANSFORMS = 1;
+ public static final int FLAG_MASK = 15;
+ public static final int FLAG_RUN_RTL = 4;
+
+ /**
+ * Constructs a <code>GlyphVector</code> object.
+ */
+ public GlyphVector ()
+ {
+ }
+
+ public abstract boolean equals (GlyphVector set);
+
+ public abstract Font getFont ();
+
+ public abstract FontRenderContext getFontRenderContext ();
+
+ public int getGlyphCharIndex (int glyphIndex)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int[] getGlyphCharIndices (int beginGlyphIndex, int numEntries,
+ int[] codeReturn)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public abstract int getGlyphCode (int glyphIndex);
+
+ public abstract int[] getGlyphCodes (int beginGlyphIndex, int numEntries,
+ int[] codeReturn);
+
+ public abstract GlyphJustificationInfo getGlyphJustificationInfo
+ (int glyphIndex);
+
+ public abstract Shape getGlyphLogicalBounds (int glyphIndex);
+
+ public abstract GlyphMetrics getGlyphMetrics (int glyphIndex);
+
+ public abstract Shape getGlyphOutline (int glyphIndex);
+
+ public Shape getGlyphOutline (int glyphIndex, float x, float y)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public Rectangle getGlyphPixelBounds (int index, FontRenderContext renderFRC,
+ float x, float y)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public abstract Point2D getGlyphPosition (int glyphIndex);
+
+ public abstract float[] getGlyphPositions (int beginGlyphIndex,
+ int numEntries,
+ float[] positionReturn);
+
+ public abstract AffineTransform getGlyphTransform (int glyphIndex);
+
+ public abstract Shape getGlyphVisualBounds (int glyphIndex);
+
+ public int getLayoutFlags ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public abstract Rectangle2D getLogicalBounds ();
+
+ public abstract int getNumGlyphs ();
+
+ public abstract Shape getOutline ();
+
+ public abstract Shape getOutline (float x, float y);
+
+ public Rectangle getPixelBounds (FontRenderContext renderFRC,
+ float x, float y)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public abstract Rectangle2D getVisualBounds ();
+
+ public abstract void performDefaultLayout ();
+
+ public abstract void setGlyphPosition (int glyphIndex, Point2D newPos);
+
+ public abstract void setGlyphTransform (int glyphIndex,
+ AffineTransform newTX);
+}
diff --git a/libjava/classpath/java/awt/font/GraphicAttribute.java b/libjava/classpath/java/awt/font/GraphicAttribute.java
new file mode 100644
index 00000000000..79eae9955f5
--- /dev/null
+++ b/libjava/classpath/java/awt/font/GraphicAttribute.java
@@ -0,0 +1,84 @@
+/* GraphicAttribute.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * @author Michael Koch
+ */
+public abstract class GraphicAttribute
+{
+ public static final int BOTTOM_ALIGNMENT = -2;
+ public static final int CENTER_BASELINE = 1;
+ public static final int HANGING_BASELINE = 2;
+ public static final int ROMAN_BASELINE = 0;
+ public static final int TOP_ALIGNMENT = -1;
+
+ private int alignment;
+
+ protected GraphicAttribute (int alignment)
+ {
+ this.alignment = alignment;
+ }
+
+ public abstract void draw (Graphics2D graphics, float x, float y);
+
+ public abstract float getAdvance ();
+
+ public final int getAlignment ()
+ {
+ return alignment;
+ }
+
+ public abstract float getAscent ();
+
+ public Rectangle2D getBounds ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public abstract float getDescent ();
+
+ public GlyphJustificationInfo getJustificationInfo ()
+ {
+ throw new Error ("not implemented");
+ }
+}
diff --git a/libjava/classpath/java/awt/font/ImageGraphicAttribute.java b/libjava/classpath/java/awt/font/ImageGraphicAttribute.java
new file mode 100644
index 00000000000..77413f95dfc
--- /dev/null
+++ b/libjava/classpath/java/awt/font/ImageGraphicAttribute.java
@@ -0,0 +1,109 @@
+/* ImageGraphicAttribute.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * @author Michael Koch
+ */
+public final class ImageGraphicAttribute extends GraphicAttribute
+{
+ private Image image;
+
+ public ImageGraphicAttribute (Image image, int alignment)
+ {
+ super (alignment);
+ this.image = image;
+ }
+
+ public ImageGraphicAttribute (Image image, int alignment, float originX,
+ float originY)
+ {
+ super (alignment);
+ this.image = image;
+
+ throw new Error ("not implemented");
+ }
+
+ public void draw (Graphics2D graphics, float x, float y)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof ImageGraphicAttribute))
+ return false;
+
+ return equals ((ImageGraphicAttribute) obj);
+ }
+
+ public boolean equals (ImageGraphicAttribute rhs)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public float getAdvance ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public float getAscent ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public Rectangle2D getBounds ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public float getDescent ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int hashCode ()
+ {
+ throw new Error ("not implemented");
+ }
+}
diff --git a/libjava/classpath/java/awt/font/LineBreakMeasurer.java b/libjava/classpath/java/awt/font/LineBreakMeasurer.java
new file mode 100644
index 00000000000..0a6a96922bd
--- /dev/null
+++ b/libjava/classpath/java/awt/font/LineBreakMeasurer.java
@@ -0,0 +1,113 @@
+/* LineBreakMeasurer.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.text.AttributedCharacterIterator;
+import java.text.BreakIterator;
+
+public final class LineBreakMeasurer
+{
+ private AttributedCharacterIterator ci;
+ private FontRenderContext frc;
+ private BreakIterator bi;
+
+ /**
+ * Constructs a <code>LineBreakMeasurer</code> object.
+ */
+ public LineBreakMeasurer (AttributedCharacterIterator text,
+ FontRenderContext frc)
+ {
+ this (text, null, frc);
+ }
+
+ /**
+ * Constructs a <code>LineBreakMeasurer</code> object.
+ */
+ public LineBreakMeasurer (AttributedCharacterIterator text,
+ BreakIterator breakIter, FontRenderContext frc)
+ {
+ this.ci = text;
+ this.bi = breakIter;
+ this.frc = frc;
+ }
+
+ public void deleteChar (AttributedCharacterIterator newParagraph,
+ int deletePos)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int getPosition ()
+ {
+ return ci.getIndex ();
+ }
+
+ public void insertChar (AttributedCharacterIterator newParagraph,
+ int insertPos)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public TextLayout nextLayout (float wrappingWidth)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public TextLayout nextLayout (float wrappingWidth, int offsetLimit,
+ boolean requireNextWord)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int nextOffset (float wrappingWidth)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int nextOffset (float wrappingWidth, int offsetLimit,
+ boolean requireNextWord)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public void setPosition (int newPosition)
+ {
+ ci.setIndex (newPosition);
+ }
+}
diff --git a/libjava/classpath/java/awt/font/LineMetrics.java b/libjava/classpath/java/awt/font/LineMetrics.java
new file mode 100644
index 00000000000..3c45ad19a6e
--- /dev/null
+++ b/libjava/classpath/java/awt/font/LineMetrics.java
@@ -0,0 +1,67 @@
+/* LineMetrics.java -- Information about about a line display characteristics
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+/**
+ * @author Michael Koch
+ */
+public abstract class LineMetrics
+{
+ public abstract float getAscent();
+
+ public abstract int getBaselineIndex();
+
+ public abstract float[] getBaselineOffsets();
+
+ public abstract float getDescent();
+
+ public abstract float getHeight();
+
+ public abstract float getLeading();
+
+ public abstract int getNumChars();
+
+ public abstract float getStrikethroughOffset();
+
+ public abstract float getStrikethroughThickness();
+
+ public abstract float getUnderlineOffset();
+
+ public abstract float getUnderlineThickness();
+}
diff --git a/libjava/classpath/java/awt/font/MultipleMaster.java b/libjava/classpath/java/awt/font/MultipleMaster.java
new file mode 100644
index 00000000000..57417ea6010
--- /dev/null
+++ b/libjava/classpath/java/awt/font/MultipleMaster.java
@@ -0,0 +1,61 @@
+/* MultipleMaster.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Font;
+
+/**
+ * @author Michael Koch
+ */
+public interface MultipleMaster
+{
+ Font deriveMMFont (float[] axes);
+
+ Font deriveMMFont (float[] glyphWidths, float avgStemWidth,
+ float typicalCapHeight, float typicalXHeight,
+ float italicAngle);
+
+ float[] getDesignAxisDefaults();
+
+ String[] getDesignAxisNames();
+
+ float[] getDesignAxisRanges();
+
+ int getNumDesignAxes();
+}
diff --git a/libjava/classpath/java/awt/font/NumericShaper.java b/libjava/classpath/java/awt/font/NumericShaper.java
new file mode 100644
index 00000000000..efbdcd49dc4
--- /dev/null
+++ b/libjava/classpath/java/awt/font/NumericShaper.java
@@ -0,0 +1,137 @@
+/* NumericShaper.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.io.Serializable;
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public final class NumericShaper implements Serializable
+{
+ private static final long serialVersionUID = -8022764705923730308L;
+
+ public static final int ALL_RANGES = 524287;
+ public static final int ARABIC = 2;
+ public static final int BENGALI = 16;
+ public static final int DEVANAGARI = 8;
+ public static final int EASTERN_ARABIC = 4;
+ public static final int ETHIOPIC = 65536;
+ public static final int EUROPEAN = 1;
+ public static final int GUJARATI = 64;
+ public static final int GURMUKHI = 32;
+ public static final int KANNADA = 1024;
+ public static final int KHMER = 131072;
+ public static final int LAO = 8192;
+ public static final int MALAYALAM = 2048;
+ public static final int MONGOLIAN = 262144;
+ public static final int MYANMAR = 32768;
+ public static final int ORIYA = 128;
+ public static final int TAMIL = 256;
+ public static final int TELUGU = 512;
+ public static final int THAI = 4096;
+ public static final int TIBETAN = 16384;
+
+ private int ranges;
+ private int context;
+
+ private NumericShaper (int ranges, int context)
+ {
+ this.ranges = ranges;
+ this.context = context;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof NumericShaper))
+ return false;
+
+ NumericShaper tmp = (NumericShaper) obj;
+
+ return (ranges == tmp.ranges
+ && context == tmp.context);
+ }
+
+ public static NumericShaper getContextualShaper (int ranges)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public static NumericShaper getContextualShaper (int ranges,
+ int defaultContext)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int getRanges ()
+ {
+ return ranges;
+ }
+
+ public static NumericShaper getShaper (int singleRange)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int hashCode ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public boolean isContextual ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public void shape (char[] text, int start, int count)
+ {
+ shape (text, start, count, context);
+ }
+
+ public void shape (char[] text, int start, int count, int context)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public String toString ()
+ {
+ throw new Error ("not implemented");
+ }
+}
diff --git a/libjava/classpath/java/awt/font/OpenType.java b/libjava/classpath/java/awt/font/OpenType.java
new file mode 100644
index 00000000000..ece3279cc7f
--- /dev/null
+++ b/libjava/classpath/java/awt/font/OpenType.java
@@ -0,0 +1,111 @@
+/* OpenType.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+/**
+ * @author Michael Koch
+ */
+public interface OpenType
+{
+ int TAG_ACNT = 1633906292;
+ int TAG_AVAR = 1635148146;
+ int TAG_BASE = 1111577413;
+ int TAG_BDAT = 1650745716;
+ int TAG_BLOC = 1651273571;
+ int TAG_BSLN = 1651731566;
+ int TAG_CFF = 1128678944;
+ int TAG_CMAP = 1668112752;
+ int TAG_CVAR = 1668702578;
+ int TAG_CVT = 1668707360;
+ int TAG_DSIG = 1146308935;
+ int TAG_EBDT = 1161970772;
+ int TAG_EBLC = 1161972803;
+ int TAG_EBSC = 1161974595;
+ int TAG_FDSC = 1717859171;
+ int TAG_FEAT = 1717920116;
+ int TAG_FMTX = 1718449272;
+ int TAG_FPGM = 1718642541;
+ int TAG_FVAR = 1719034226;
+ int TAG_GASP = 1734439792;
+ int TAG_GDEF = 1195656518;
+ int TAG_GLYF = 1735162214;
+ int TAG_GPOS = 1196445523;
+ int TAG_GSUB = 1196643650;
+ int TAG_GVAR = 1735811442;
+ int TAG_HDMX = 1751412088;
+ int TAG_HEAD = 1751474532;
+ int TAG_HHEA = 1751672161;
+ int TAG_HMTX = 1752003704;
+ int TAG_JSTF = 1246975046;
+ int TAG_JUST = 1786082164;
+ int TAG_KERN = 1801810542;
+ int TAG_LCAR = 1818452338;
+ int TAG_LOCA = 1819239265;
+ int TAG_LTSH = 1280594760;
+ int TAG_MAXP = 1835104368;
+ int TAG_MMFX = 1296909912;
+ int TAG_MMSD = 1296913220;
+ int TAG_MORT = 1836020340;
+ int TAG_NAME = 1851878757;
+ int TAG_OPBD = 1836020340;
+ int TAG_OS2 = 1330851634;
+ int TAG_PCLT = 1346587732;
+ int TAG_POST = 1886352244;
+ int TAG_PREP = 1886545264;
+ int TAG_PROP = 1886547824;
+ int TAG_TRAK = 1953653099;
+ int TAG_TYP1 = 1954115633;
+ int TAG_VDMX = 1447316824;
+ int TAG_VHEA = 1986553185;
+ int TAG_VMTX = 1986884728;
+
+ byte[] getFontTable (int sfntTag);
+
+ byte[] getFontTable (int sfntTag, int offset, int count);
+
+ byte[] getFontTable (String strSfntTag);
+
+ byte[] getFontTable (String strSfntTag, int offset, int count);
+
+ int getFontTableSize (int sfntTag);
+
+ int getFontTableSize (String strSfntTag);
+
+ int getVersion ();
+}
diff --git a/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java b/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java
new file mode 100644
index 00000000000..6d64dece5d8
--- /dev/null
+++ b/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java
@@ -0,0 +1,105 @@
+/* ShapeGraphicAttribute.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+
+public final class ShapeGraphicAttribute extends GraphicAttribute
+{
+ public static final boolean FILL = false;
+ public static final boolean STROKE = true;
+
+ private Shape shape;
+ private boolean stroke;
+
+ public ShapeGraphicAttribute (Shape shape, int alignment, boolean stroke)
+ {
+ super (alignment);
+ this.shape = shape;
+ this.stroke = stroke;
+ }
+
+ public void draw (Graphics2D graphics, float x, float y)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof ShapeGraphicAttribute))
+ return false;
+
+ return equals ((ShapeGraphicAttribute) obj);
+ }
+
+ public boolean equals (ShapeGraphicAttribute rhs)
+ {
+ return (shape.equals (rhs.shape)
+ && getAlignment () == rhs.getAlignment ()
+ && stroke == rhs.stroke);
+ }
+
+ public float getAdvance ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public float getAscent ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public Rectangle2D getBounds ()
+ {
+ return shape.getBounds2D ();
+ }
+
+ public float getDescent ()
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int hashCode ()
+ {
+ // FIXME: Check what SUN does here
+ return shape.hashCode ();
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TextAttribute.java b/libjava/classpath/java/awt/font/TextAttribute.java
new file mode 100644
index 00000000000..6f5ed59f915
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TextAttribute.java
@@ -0,0 +1,309 @@
+/* TextAttribute.java --
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.io.InvalidObjectException;
+import java.text.AttributedCharacterIterator;
+
+/**
+ * Attributes (and associated values) that can be used to define an
+ * {@link java.text.AttributedString}.
+ */
+public final class TextAttribute extends AttributedCharacterIterator.Attribute
+{
+ private static final long serialVersionUID = 7744112784117861702L;
+
+ /** A key for the background paint attribute. */
+ public static final TextAttribute BACKGROUND =
+ new TextAttribute("background");
+
+ /** A key for the BIDI_EMBEDDING attribute. */
+ public static final TextAttribute BIDI_EMBEDDING =
+ new TextAttribute("bidi_embedding");
+
+ /** A key for the CHAR_REPLACEMENT attribute. */
+ public static final TextAttribute CHAR_REPLACEMENT =
+ new TextAttribute("char_replacement");
+
+ /** A key for the FAMILY attribute. */
+ public static final TextAttribute FAMILY = new TextAttribute("family");
+
+ /** A key for the font attribute. */
+ public static final TextAttribute FONT = new TextAttribute("font");
+
+ /** A key for the foreground paint attribute. */
+ public static final TextAttribute FOREGROUND =
+ new TextAttribute("foreground");
+
+ /** A key for the INPUT_METHOD_HIGHLIGHT attribute. */
+ public static final TextAttribute INPUT_METHOD_HIGHLIGHT =
+ new TextAttribute("input method highlight");
+
+ /** A key for the INPUT_METHOD_UNDERLINE attribute. */
+ public static final TextAttribute INPUT_METHOD_UNDERLINE =
+ new TextAttribute("input method underline");
+
+ /** A key for the text justification attribute. */
+ public static final TextAttribute JUSTIFICATION =
+ new TextAttribute("justification");
+
+ /**
+ * A value that can be used with the {@link #JUSTIFICATION} attribute to
+ * indicate full justification of the text.
+ */
+ public static final Float JUSTIFICATION_FULL = new Float(1.0);
+
+ /**
+ * A value that can be used with the {@link #JUSTIFICATION} attribute to
+ * indicate no justification of the text.
+ */
+ public static final Float JUSTIFICATION_NONE = new Float(0.0);
+
+ /** A key for the NUMERIC_SHAPING attribute. */
+ public static final TextAttribute NUMERIC_SHAPING =
+ new TextAttribute("numeric_shaping");
+
+ /** A key for the POSTURE attribute. */
+ public static final TextAttribute POSTURE = new TextAttribute("posture");
+
+ /** A value that can be used with the {@link #POSTURE} attribute. */
+ public static final Float POSTURE_OBLIQUE = new Float(0.2);
+
+ /** A value that can be used with the {@link #POSTURE} attribute. */
+ public static final Float POSTURE_REGULAR = new Float(0.0);
+
+ /** A key for the RUN_DIRECTION attribute. */
+ public static final TextAttribute RUN_DIRECTION =
+ new TextAttribute("run_direction");
+
+ /** A value that can be used with the {@link #RUN_DIRECTION} attribute. */
+ public static final Boolean RUN_DIRECTION_LTR = Boolean.FALSE;
+
+ /** A value that can be used with the {@link #RUN_DIRECTION} attribute. */
+ public static final Boolean RUN_DIRECTION_RTL = Boolean.TRUE;
+
+ /** A key for the text size attribute. */
+ public static final TextAttribute SIZE = new TextAttribute("size");
+
+ /** A key for the STRIKETHROUGH attribute. */
+ public static final TextAttribute STRIKETHROUGH =
+ new TextAttribute("strikethrough");
+
+ /** A value that can be used with the {@link #STRIKETHROUGH} attribute. */
+ public static final Boolean STRIKETHROUGH_ON = Boolean.TRUE;
+
+ /** A key for the SUPERSCRIPT attribute. */
+ public static final TextAttribute SUPERSCRIPT =
+ new TextAttribute("superscript");
+
+ /** A value that can be used with the {@link #SUPERSCRIPT} attribute. */
+ public static final Integer SUPERSCRIPT_SUB = new Integer(-1);
+
+ /** A value that can be used with the {@link #SUPERSCRIPT} attribute. */
+ public static final Integer SUPERSCRIPT_SUPER = new Integer(1);
+
+ /** A key for the SWAP_COLORS attribute. */
+ public static final TextAttribute SWAP_COLORS =
+ new TextAttribute("swap_colors");
+
+ /** A value that can be used with the {@link #SWAP_COLORS} attribute. */
+ public static final Boolean SWAP_COLORS_ON = Boolean.TRUE;
+
+ /** A key for the TRANFORM attribute. */
+ public static final TextAttribute TRANSFORM = new TextAttribute("transform");
+
+ /** A key for the UNDERLINE attribute. */
+ public static final TextAttribute UNDERLINE = new TextAttribute("underline");
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_DASHED = new Integer(5);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_DOTTED = new Integer(3);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_GRAY = new Integer(4);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_ONE_PIXEL = new Integer(1);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_TWO_PIXEL = new Integer(2);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_ON = new Integer(0);
+
+ /** A key for the WEIGHT attribute. */
+ public static final TextAttribute WEIGHT = new TextAttribute("weight");
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_BOLD = new Float(2.0);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_DEMIBOLD = new Float(1.75);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_DEMILIGHT = new Float(0.875);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_EXTRA_LIGHT = new Float(0.5);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_EXTRABOLD = new Float(2.5);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_HEAVY = new Float(2.25);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_LIGHT = new Float(0.75);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_MEDIUM = new Float(1.5);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_REGULAR = new Float(1.0);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_SEMIBOLD = new Float(1.25);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_ULTRABOLD = new Float(2.75);
+
+ /** A key for the WIDTH attribute. */
+ public static final TextAttribute WIDTH = new TextAttribute("width");
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_CONDENSED = new Float(0.75);
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_EXTENDED = new Float(1.5);
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_REGULAR = new Float(1.0);
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_SEMI_CONDENSED = new Float(0.875);
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_SEMI_EXTENDED = new Float(1.25);
+
+ /**
+ * Creates a new attribute.
+ *
+ * @param name the name.
+ */
+ protected TextAttribute(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * After deserialization, this method ensures that only one instance of
+ * each attribute is used.
+ *
+ * @return The (single) attribute instance.
+ *
+ * @throws InvalidObjectException if the attribute is not recognised.
+ */
+ protected Object readResolve()
+ throws InvalidObjectException
+ {
+ if (this.getName().equals("background"))
+ return BACKGROUND;
+
+ if (this.getName().equals("bidi_embedding"))
+ return BIDI_EMBEDDING;
+
+ if (this.getName().equals("char_replacement"))
+ return CHAR_REPLACEMENT;
+
+ if (this.getName().equals("family"))
+ return FAMILY;
+
+ if (this.getName().equals("font"))
+ return FONT;
+
+ if (this.getName().equals("foreground"))
+ return FOREGROUND;
+
+ if (this.getName().equals("input method highlight"))
+ return INPUT_METHOD_HIGHLIGHT;
+
+ if (this.getName().equals("input method underline"))
+ return INPUT_METHOD_UNDERLINE;
+
+ if (this.getName().equals("justification"))
+ return JUSTIFICATION;
+
+ if (this.getName().equals("numeric_shaping"))
+ return NUMERIC_SHAPING;
+
+ if (this.getName().equals("posture"))
+ return POSTURE;
+
+ if (this.getName().equals("run_direction"))
+ return RUN_DIRECTION;
+
+ if (this.getName().equals("size"))
+ return SIZE;
+
+ if (this.getName().equals("strikethrough"))
+ return STRIKETHROUGH;
+
+ if (this.getName().equals("superscript"))
+ return SUPERSCRIPT;
+
+ if (this.getName().equals("swap_colors"))
+ return SWAP_COLORS;
+
+ if (this.getName().equals("transform"))
+ return TRANSFORM;
+
+ if (this.getName().equals("underline"))
+ return UNDERLINE;
+
+ if (this.getName().equals("weight"))
+ return WEIGHT;
+
+ if (this.getName().equals("width"))
+ return WIDTH;
+
+ throw new InvalidObjectException("Can't resolve Attribute: " + getName());
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TextHitInfo.java b/libjava/classpath/java/awt/font/TextHitInfo.java
new file mode 100644
index 00000000000..2b23e1963cd
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TextHitInfo.java
@@ -0,0 +1,125 @@
+/* TextHitInfo.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.font;
+
+/**
+ * @author John Leuner (jewel@debian.org)
+ */
+public final class TextHitInfo
+{
+ private int charIndex;
+ private boolean leadingEdge;
+
+ TextHitInfo (int charIndex, boolean leadingEdge)
+ {
+ this.charIndex = charIndex;
+ this.leadingEdge = leadingEdge;
+ }
+
+ public int getCharIndex()
+ {
+ return charIndex;
+ }
+
+ public boolean isLeadingEdge()
+ {
+ return leadingEdge;
+ }
+
+ public int getInsertionIndex()
+ {
+ return (leadingEdge ? charIndex : charIndex + 1);
+ }
+
+ public int hashCode()
+ {
+ return charIndex;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if(obj instanceof TextHitInfo)
+ return this.equals((TextHitInfo) obj);
+
+ return false;
+ }
+
+ public boolean equals(TextHitInfo hitInfo)
+ {
+ return (charIndex == hitInfo.getCharIndex ())
+ && (leadingEdge == hitInfo.isLeadingEdge ());
+ }
+
+ public static TextHitInfo leading(int charIndex)
+ {
+ return new TextHitInfo (charIndex, true);
+ }
+
+ public static TextHitInfo trailing(int charIndex)
+ {
+ return new TextHitInfo (charIndex, false);
+ }
+
+ public static TextHitInfo beforeOffset(int offset)
+ {
+ return new TextHitInfo (offset, false);
+ }
+
+ public static TextHitInfo afterOffset(int offset)
+ {
+ return new TextHitInfo (offset, true);
+ }
+
+ public TextHitInfo getOtherHit()
+ {
+ return (leadingEdge ? trailing (charIndex - 1) : leading (charIndex + 1));
+ }
+
+ public TextHitInfo getOffsetHit(int offset)
+ {
+ return new TextHitInfo (charIndex + offset, leadingEdge);
+ }
+
+ public String toString()
+ {
+ return "TextHitInfo["
+ + charIndex
+ + (leadingEdge ? "L" : "T" )
+ + "]";
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TextLayout.java b/libjava/classpath/java/awt/font/TextLayout.java
new file mode 100644
index 00000000000..bb641614a92
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TextLayout.java
@@ -0,0 +1,332 @@
+/* TextLayout.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.peer.ClasspathTextLayoutPeer;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.Map;
+
+/**
+ * @author Michael Koch
+ */
+public final class TextLayout implements Cloneable
+{
+ public static final CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy ();
+ ClasspathTextLayoutPeer peer;
+
+ public static class CaretPolicy
+ {
+ public CaretPolicy ()
+ {
+ // Do nothing here.
+ }
+
+ public TextHitInfo getStrongCaret (TextHitInfo hit1, TextHitInfo hit2,
+ TextLayout layout)
+ {
+ return layout.peer.getStrongCaret(hit1, hit2);
+ }
+ }
+
+ public TextLayout (AttributedCharacterIterator text, FontRenderContext frc)
+ {
+ AttributedString as = new AttributedString (text);
+ ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
+ peer = tk.getClasspathTextLayoutPeer(as, frc);
+ }
+
+ public TextLayout (String string, Font font, FontRenderContext frc)
+ {
+ AttributedString as = new AttributedString (string);
+ as.addAttribute (TextAttribute.FONT, font);
+ ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
+ peer = tk.getClasspathTextLayoutPeer(as, frc);
+ }
+
+ public TextLayout (String string, Map attributes, FontRenderContext frc)
+ {
+ AttributedString as = new AttributedString (string, attributes);
+ ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
+ peer = tk.getClasspathTextLayoutPeer(as, frc);
+ }
+
+ protected Object clone ()
+ {
+ try
+ {
+ TextLayout tl = (TextLayout) super.clone ();
+ tl.peer = (ClasspathTextLayoutPeer) this.peer.clone();
+ return tl;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // This should never occur
+ throw new InternalError ();
+ }
+ }
+
+
+ public void draw (Graphics2D g2, float x, float y)
+ {
+ peer.draw(g2, x, y);
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof TextLayout))
+ return false;
+
+ return equals ((TextLayout) obj);
+ }
+
+ public boolean equals (TextLayout tl)
+ {
+ return this.peer.equals(tl.peer);
+ }
+
+ public float getAdvance ()
+ {
+ return peer.getAdvance();
+ }
+
+ public float getAscent ()
+ {
+ return peer.getAscent();
+ }
+
+ public byte getBaseline ()
+ {
+ return peer.getBaseline();
+ }
+
+ public float[] getBaselineOffsets ()
+ {
+ return peer.getBaselineOffsets();
+ }
+
+ public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint)
+ {
+ return peer.getBlackBoxBounds(firstEndpoint, secondEndpoint);
+ }
+
+ public Rectangle2D getBounds()
+ {
+ return peer.getBounds();
+ }
+
+ public float[] getCaretInfo (TextHitInfo hit)
+ {
+ return getCaretInfo(hit, getBounds());
+ }
+
+ public float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds)
+ {
+ return peer.getCaretInfo(hit, bounds);
+ }
+
+ public Shape getCaretShape (TextHitInfo hit)
+ {
+ return getCaretShape(hit, getBounds());
+ }
+
+ public Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds)
+ {
+ return peer.getCaretShape(hit, bounds);
+ }
+
+ public Shape[] getCaretShapes (int offset)
+ {
+ return getCaretShapes(offset, getBounds());
+ }
+
+ public Shape[] getCaretShapes (int offset, Rectangle2D bounds)
+ {
+ return getCaretShapes(offset, getBounds(), DEFAULT_CARET_POLICY);
+ }
+
+ public Shape[] getCaretShapes (int offset, Rectangle2D bounds,
+ TextLayout.CaretPolicy policy)
+ {
+ return peer.getCaretShapes(offset, bounds, policy);
+ }
+
+ public int getCharacterCount ()
+ {
+ return peer.getCharacterCount();
+ }
+
+ public byte getCharacterLevel (int index)
+ {
+ return peer.getCharacterLevel(index);
+ }
+
+ public float getDescent ()
+ {
+ return peer.getDescent();
+ }
+
+ public TextLayout getJustifiedLayout (float justificationWidth)
+ {
+ return peer.getJustifiedLayout(justificationWidth);
+ }
+
+ public float getLeading ()
+ {
+ return peer.getLeading();
+ }
+
+ public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint)
+ {
+ return getLogicalHighlightShape (firstEndpoint, secondEndpoint, getBounds());
+ }
+
+ public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint,
+ Rectangle2D bounds)
+ {
+ return peer.getLogicalHighlightShape(firstEndpoint, secondEndpoint, bounds);
+ }
+
+ public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint,
+ TextHitInfo secondEndpoint)
+ {
+ return peer.getLogicalRangesForVisualSelection(firstEndpoint, secondEndpoint);
+ }
+
+ public TextHitInfo getNextLeftHit (int offset)
+ {
+ return getNextLeftHit(offset, DEFAULT_CARET_POLICY);
+ }
+
+ public TextHitInfo getNextLeftHit (int offset, TextLayout.CaretPolicy policy)
+ {
+ return peer.getNextLeftHit(offset, policy);
+ }
+
+ public TextHitInfo getNextLeftHit (TextHitInfo hit)
+ {
+ return getNextLeftHit(hit.getCharIndex());
+ }
+
+ public TextHitInfo getNextRightHit (int offset)
+ {
+ return getNextRightHit(offset, DEFAULT_CARET_POLICY);
+ }
+
+ public TextHitInfo getNextRightHit (int offset, TextLayout.CaretPolicy policy)
+ {
+ return peer.getNextRightHit(offset, policy);
+ }
+
+ public TextHitInfo getNextRightHit (TextHitInfo hit)
+ {
+ return getNextRightHit(hit.getCharIndex());
+ }
+
+ public Shape getOutline (AffineTransform tx)
+ {
+ return peer.getOutline(tx);
+ }
+
+ public float getVisibleAdvance ()
+ {
+ return peer.getVisibleAdvance();
+ }
+
+ public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
+ TextHitInfo secondEndpoint)
+ {
+ return getVisualHighlightShape(firstEndpoint, secondEndpoint, getBounds());
+ }
+
+ public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
+ TextHitInfo secondEndpoint,
+ Rectangle2D bounds)
+ {
+ return peer.getVisualHighlightShape(firstEndpoint, secondEndpoint, bounds);
+ }
+
+ public TextHitInfo getVisualOtherHit (TextHitInfo hit)
+ {
+ return peer.getVisualOtherHit(hit);
+ }
+
+ protected void handleJustify (float justificationWidth)
+ {
+ peer.handleJustify(justificationWidth);
+ }
+
+ public int hashCode ()
+ {
+ return peer.hashCode();
+ }
+
+ public TextHitInfo hitTestChar (float x, float y)
+ {
+ return hitTestChar(x, y, getBounds());
+ }
+
+ public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds)
+ {
+ return peer.hitTestChar(x, y, bounds);
+ }
+
+ public boolean isLeftToRight ()
+ {
+ return peer.isLeftToRight();
+ }
+
+ public boolean isVertical ()
+ {
+ return peer.isVertical();
+ }
+
+ public String toString ()
+ {
+ return peer.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TextMeasurer.java b/libjava/classpath/java/awt/font/TextMeasurer.java
new file mode 100644
index 00000000000..7fcdc87a83c
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TextMeasurer.java
@@ -0,0 +1,97 @@
+/* TextMeasurer.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.text.AttributedCharacterIterator;
+
+/**
+ * @author Michael Koch
+ * @since 1.3
+ */
+public final class TextMeasurer implements Cloneable
+{
+ private AttributedCharacterIterator ci;
+ private FontRenderContext frc;
+
+ public TextMeasurer (AttributedCharacterIterator text, FontRenderContext frc)
+ {
+ this.ci = text;
+ this.frc = frc;
+ }
+
+ protected Object clone ()
+ {
+ try
+ {
+ return super.clone ();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // This may never occur
+ throw new InternalError ();
+ }
+ }
+
+ public void deleteChar (AttributedCharacterIterator newParagraph,
+ int deletePos)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public float getAdvanceBetween (int start, int limit)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public TextLayout getLayout (int start, int limit)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public int getLineBreakIndex (int start, float maxAdvance)
+ {
+ throw new Error ("not implemented");
+ }
+
+ public void insertChar (AttributedCharacterIterator newParagraph,
+ int insertPos)
+ {
+ throw new Error ("not implemented");
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TransformAttribute.java b/libjava/classpath/java/awt/font/TransformAttribute.java
new file mode 100644
index 00000000000..977cafa032e
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TransformAttribute.java
@@ -0,0 +1,100 @@
+/* TransformAttribute.java --
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.geom.AffineTransform;
+import java.io.Serializable;
+
+/**
+ * This class provides a mechanism for using an {@link AffineTransform} as
+ * an <i>immutable</i> attribute (for example, in the
+ * {@link java.text.AttributedString} class). Any transform passed to
+ * this class is copied before being stored, and any transform handed out
+ * by this class is a copy of the stored transform. In this way, it is
+ * not possible to modify the stored transform.
+ *
+ * @author Michael Koch
+ */
+public final class TransformAttribute implements Serializable
+{
+ private static final long serialVersionUID = 3356247357827709530L;
+
+ private AffineTransform affineTransform;
+
+ /**
+ * Creates a new attribute that contains a copy of the given transform.
+ *
+ * @param transform the transform (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>transform</code> is
+ * <code>null</code>.
+ */
+ public TransformAttribute (AffineTransform transform)
+ {
+ if (transform == null)
+ {
+ throw new IllegalArgumentException("Null 'transform' not permitted.");
+ }
+ this.affineTransform = new AffineTransform (transform);
+ }
+
+ /**
+ * Returns a copy of the transform contained by this attribute.
+ *
+ * @return A copy of the transform.
+ */
+ public AffineTransform getTransform ()
+ {
+ return (AffineTransform) affineTransform.clone();
+ }
+
+ /**
+ * Returns <code>true</code> if the transform contained by this attribute is
+ * an identity transform, and <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the transform contained by this attribute is
+ * an identity transform, and <code>false</code> otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isIdentity ()
+ {
+ return (affineTransform == null ? false : affineTransform.isIdentity ());
+ }
+}
diff --git a/libjava/classpath/java/awt/font/package.html b/libjava/classpath/java/awt/font/package.html
new file mode 100644
index 00000000000..8c3c61a40bd
--- /dev/null
+++ b/libjava/classpath/java/awt/font/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.font package.
+ Copyright (C) 2002 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 - java.awt.font</title></head>
+
+<body>
+<p>Representations of different kind of characters and fonts.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/geom/AffineTransform.java b/libjava/classpath/java/awt/geom/AffineTransform.java
new file mode 100644
index 00000000000..4d1a4d6d5d4
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/AffineTransform.java
@@ -0,0 +1,1487 @@
+/* AffineTransform.java -- transform coordinates between two 2-D spaces
+ Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+import java.awt.Shape;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+/**
+ * This class represents an affine transformation between two coordinate
+ * spaces in 2 dimensions. Such a transform preserves the "straightness"
+ * and "parallelness" of lines. The transform is built from a sequence of
+ * translations, scales, flips, rotations, and shears.
+ *
+ * <p>The transformation can be represented using matrix math on a 3x3 array.
+ * Given (x,y), the transformation (x',y') can be found by:
+ * <pre>
+ * [ x'] [ m00 m01 m02 ] [ x ] [ m00*x + m01*y + m02 ]
+ * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10*x + m11*y + m12 ]
+ * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
+ * </pre>
+ * The bottom row of the matrix is constant, so a transform can be uniquely
+ * represented (as in {@link #toString()}) by
+ * "[[m00, m01, m02], [m10, m11, m12]]".
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status partially updated to 1.4, still has some problems
+ */
+public class AffineTransform implements Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 1330973210523860834L;
+
+ /**
+ * The transformation is the identity (x' = x, y' = y). All other transforms
+ * have either a combination of the appropriate transform flag bits for
+ * their type, or the type GENERAL_TRANSFORM.
+ *
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #getType()
+ */
+ public static final int TYPE_IDENTITY = 0;
+
+ /**
+ * The transformation includes a translation - shifting in the x or y
+ * direction without changing length or angles.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #getType()
+ */
+ public static final int TYPE_TRANSLATION = 1;
+
+ /**
+ * The transformation includes a uniform scale - length is scaled in both
+ * the x and y directions by the same amount, without affecting angles.
+ * This is mutually exclusive with TYPE_GENERAL_SCALE.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #TYPE_MASK_SCALE
+ * @see #getType()
+ */
+ public static final int TYPE_UNIFORM_SCALE = 2;
+
+ /**
+ * The transformation includes a general scale - length is scaled in either
+ * or both the x and y directions, but by different amounts; without
+ * affecting angles. This is mutually exclusive with TYPE_UNIFORM_SCALE.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #TYPE_MASK_SCALE
+ * @see #getType()
+ */
+ public static final int TYPE_GENERAL_SCALE = 4;
+
+ /**
+ * This constant checks if either variety of scale transform is performed.
+ *
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ */
+ public static final int TYPE_MASK_SCALE = 6;
+
+ /**
+ * The transformation includes a flip about an axis, swapping between
+ * right-handed and left-handed coordinate systems. In a right-handed
+ * system, the positive x-axis rotates counter-clockwise to the positive
+ * y-axis; in a left-handed system it rotates clockwise.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #getType()
+ */
+ public static final int TYPE_FLIP = 64;
+
+ /**
+ * The transformation includes a rotation of a multiple of 90 degrees (PI/2
+ * radians). Angles are rotated, but length is preserved. This is mutually
+ * exclusive with TYPE_GENERAL_ROTATION.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #TYPE_MASK_ROTATION
+ * @see #getType()
+ */
+ public static final int TYPE_QUADRANT_ROTATION = 8;
+
+ /**
+ * The transformation includes a rotation by an arbitrary angle. Angles are
+ * rotated, but length is preserved. This is mutually exclusive with
+ * TYPE_QUADRANT_ROTATION.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #TYPE_MASK_ROTATION
+ * @see #getType()
+ */
+ public static final int TYPE_GENERAL_ROTATION = 16;
+
+ /**
+ * This constant checks if either variety of rotation is performed.
+ *
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ */
+ public static final int TYPE_MASK_ROTATION = 24;
+
+ /**
+ * The transformation is an arbitrary conversion of coordinates which
+ * could not be decomposed into the other TYPEs.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #getType()
+ */
+ public static final int TYPE_GENERAL_TRANSFORM = 32;
+
+ /**
+ * The X coordinate scaling element of the transform matrix.
+ *
+ * @serial matrix[0,0]
+ */
+ private double m00;
+
+ /**
+ * The Y coordinate shearing element of the transform matrix.
+ *
+ * @serial matrix[1,0]
+ */
+ private double m10;
+
+ /**
+ * The X coordinate shearing element of the transform matrix.
+ *
+ * @serial matrix[0,1]
+ */
+ private double m01;
+
+ /**
+ * The Y coordinate scaling element of the transform matrix.
+ *
+ * @serial matrix[1,1]
+ */
+ private double m11;
+
+ /**
+ * The X coordinate translation element of the transform matrix.
+ *
+ * @serial matrix[0,2]
+ */
+ private double m02;
+
+ /**
+ * The Y coordinate translation element of the transform matrix.
+ *
+ * @serial matrix[1,2]
+ */
+ private double m12;
+
+ /** The type of this transform. */
+ private transient int type;
+
+ /**
+ * Construct a new identity transform:
+ * <pre>
+ * [ 1 0 0 ]
+ * [ 0 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ */
+ public AffineTransform()
+ {
+ m00 = m11 = 1;
+ }
+
+ /**
+ * Create a new transform which copies the given one.
+ *
+ * @param tx the transform to copy
+ * @throws NullPointerException if tx is null
+ */
+ public AffineTransform(AffineTransform tx)
+ {
+ setTransform(tx);
+ }
+
+ /**
+ * Construct a transform with the given matrix entries:
+ * <pre>
+ * [ m00 m01 m02 ]
+ * [ m10 m11 m12 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param m00 the x scaling component
+ * @param m10 the y shearing component
+ * @param m01 the x shearing component
+ * @param m11 the y scaling component
+ * @param m02 the x translation component
+ * @param m12 the y translation component
+ */
+ public AffineTransform(float m00, float m10,
+ float m01, float m11,
+ float m02, float m12)
+ {
+ this.m00 = m00;
+ this.m10 = m10;
+ this.m01 = m01;
+ this.m11 = m11;
+ this.m02 = m02;
+ this.m12 = m12;
+ updateType();
+ }
+
+ /**
+ * Construct a transform from a sequence of float entries. The array must
+ * have at least 4 entries, which has a translation factor of 0; or 6
+ * entries, for specifying all parameters:
+ * <pre>
+ * [ f[0] f[2] (f[4]) ]
+ * [ f[1] f[3] (f[5]) ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param f the matrix to copy from, with at least 4 (6) entries
+ * @throws NullPointerException if f is null
+ * @throws ArrayIndexOutOfBoundsException if f is too small
+ */
+ public AffineTransform(float[] f)
+ {
+ m00 = f[0];
+ m10 = f[1];
+ m01 = f[2];
+ m11 = f[3];
+ if (f.length >= 6)
+ {
+ m02 = f[4];
+ m12 = f[5];
+ }
+ updateType();
+ }
+
+ /**
+ * Construct a transform with the given matrix entries:
+ * <pre>
+ * [ m00 m01 m02 ]
+ * [ m10 m11 m12 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param m00 the x scaling component
+ * @param m10 the y shearing component
+ * @param m01 the x shearing component
+ * @param m11 the y scaling component
+ * @param m02 the x translation component
+ * @param m12 the y translation component
+ */
+ public AffineTransform(double m00, double m10, double m01,
+ double m11, double m02, double m12)
+ {
+ this.m00 = m00;
+ this.m10 = m10;
+ this.m01 = m01;
+ this.m11 = m11;
+ this.m02 = m02;
+ this.m12 = m12;
+ updateType();
+ }
+
+ /**
+ * Construct a transform from a sequence of double entries. The array must
+ * have at least 4 entries, which has a translation factor of 0; or 6
+ * entries, for specifying all parameters:
+ * <pre>
+ * [ d[0] d[2] (d[4]) ]
+ * [ d[1] d[3] (d[5]) ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param d the matrix to copy from, with at least 4 (6) entries
+ * @throws NullPointerException if d is null
+ * @throws ArrayIndexOutOfBoundsException if d is too small
+ */
+ public AffineTransform(double[] d)
+ {
+ m00 = d[0];
+ m10 = d[1];
+ m01 = d[2];
+ m11 = d[3];
+ if (d.length >= 6)
+ {
+ m02 = d[4];
+ m12 = d[5];
+ }
+ updateType();
+ }
+
+ /**
+ * Returns a translation transform:
+ * <pre>
+ * [ 1 0 tx ]
+ * [ 0 1 ty ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param tx the x translation distance
+ * @param ty the y translation distance
+ * @return the translating transform
+ */
+ public static AffineTransform getTranslateInstance(double tx, double ty)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToTranslation(tx, ty);
+ return t;
+ }
+
+ /**
+ * Returns a rotation transform. A positive angle (in radians) rotates
+ * the positive x-axis to the positive y-axis:
+ * <pre>
+ * [ cos(theta) -sin(theta) 0 ]
+ * [ sin(theta) cos(theta) 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param theta the rotation angle
+ * @return the rotating transform
+ */
+ public static AffineTransform getRotateInstance(double theta)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToRotation(theta);
+ return t;
+ }
+
+ /**
+ * Returns a rotation transform about a point. A positive angle (in radians)
+ * rotates the positive x-axis to the positive y-axis. This is the same
+ * as calling:
+ * <pre>
+ * AffineTransform tx = new AffineTransform();
+ * tx.setToTranslation(x, y);
+ * tx.rotate(theta);
+ * tx.translate(-x, -y);
+ * </pre>
+ *
+ * <p>The resulting matrix is:
+ * <pre>
+ * [ cos(theta) -sin(theta) x-x*cos+y*sin ]
+ * [ sin(theta) cos(theta) y-x*sin-y*cos ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param theta the rotation angle
+ * @param x the x coordinate of the pivot point
+ * @param y the y coordinate of the pivot point
+ * @return the rotating transform
+ */
+ public static AffineTransform getRotateInstance(double theta,
+ double x, double y)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToTranslation(x, y);
+ t.rotate(theta);
+ t.translate(-x, -y);
+ return t;
+ }
+
+ /**
+ * Returns a scaling transform:
+ * <pre>
+ * [ sx 0 0 ]
+ * [ 0 sy 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param sx the x scaling factor
+ * @param sy the y scaling factor
+ * @return the scaling transform
+ */
+ public static AffineTransform getScaleInstance(double sx, double sy)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToScale(sx, sy);
+ return t;
+ }
+
+ /**
+ * Returns a shearing transform (points are shifted in the x direction based
+ * on a factor of their y coordinate, and in the y direction as a factor of
+ * their x coordinate):
+ * <pre>
+ * [ 1 shx 0 ]
+ * [ shy 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param shx the x shearing factor
+ * @param shy the y shearing factor
+ * @return the shearing transform
+ */
+ public static AffineTransform getShearInstance(double shx, double shy)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToShear(shx, shy);
+ return t;
+ }
+
+ /**
+ * Returns the type of this transform. The result is always valid, although
+ * it may not be the simplest interpretation (in other words, there are
+ * sequences of transforms which reduce to something simpler, which this
+ * does not always detect). The result is either TYPE_GENERAL_TRANSFORM,
+ * or a bit-wise combination of TYPE_TRANSLATION, the mutually exclusive
+ * TYPE_*_ROTATIONs, and the mutually exclusive TYPE_*_SCALEs.
+ *
+ * @return The type.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ */
+ public int getType()
+ {
+ return type;
+ }
+
+ /**
+ * Return the determinant of this transform matrix. If the determinant is
+ * non-zero, the transform is invertible; otherwise operations which require
+ * an inverse throw a NoninvertibleTransformException. A result very near
+ * zero, due to rounding errors, may indicate that inversion results do not
+ * carry enough precision to be meaningful.
+ *
+ * <p>If this is a uniform scale transformation, the determinant also
+ * represents the squared value of the scale. Otherwise, it carries little
+ * additional meaning. The determinant is calculated as:
+ * <pre>
+ * | m00 m01 m02 |
+ * | m10 m11 m12 | = m00 * m11 - m01 * m10
+ * | 0 0 1 |
+ * </pre>
+ *
+ * @return the determinant
+ * @see #createInverse()
+ */
+ public double getDeterminant()
+ {
+ return m00 * m11 - m01 * m10;
+ }
+
+ /**
+ * Return the matrix of values used in this transform. If the matrix has
+ * fewer than 6 entries, only the scale and shear factors are returned;
+ * otherwise the translation factors are copied as well. The resulting
+ * values are:
+ * <pre>
+ * [ d[0] d[2] (d[4]) ]
+ * [ d[1] d[3] (d[5]) ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param d the matrix to store the results into; with 4 (6) entries
+ * @throws NullPointerException if d is null
+ * @throws ArrayIndexOutOfBoundsException if d is too small
+ */
+ public void getMatrix(double[] d)
+ {
+ d[0] = m00;
+ d[1] = m10;
+ d[2] = m01;
+ d[3] = m11;
+ if (d.length >= 6)
+ {
+ d[4] = m02;
+ d[5] = m12;
+ }
+ }
+
+ /**
+ * Returns the X coordinate scaling factor of the matrix.
+ *
+ * @return m00
+ * @see #getMatrix(double[])
+ */
+ public double getScaleX()
+ {
+ return m00;
+ }
+
+ /**
+ * Returns the Y coordinate scaling factor of the matrix.
+ *
+ * @return m11
+ * @see #getMatrix(double[])
+ */
+ public double getScaleY()
+ {
+ return m11;
+ }
+
+ /**
+ * Returns the X coordinate shearing factor of the matrix.
+ *
+ * @return m01
+ * @see #getMatrix(double[])
+ */
+ public double getShearX()
+ {
+ return m01;
+ }
+
+ /**
+ * Returns the Y coordinate shearing factor of the matrix.
+ *
+ * @return m10
+ * @see #getMatrix(double[])
+ */
+ public double getShearY()
+ {
+ return m10;
+ }
+
+ /**
+ * Returns the X coordinate translation factor of the matrix.
+ *
+ * @return m02
+ * @see #getMatrix(double[])
+ */
+ public double getTranslateX()
+ {
+ return m02;
+ }
+
+ /**
+ * Returns the Y coordinate translation factor of the matrix.
+ *
+ * @return m12
+ * @see #getMatrix(double[])
+ */
+ public double getTranslateY()
+ {
+ return m12;
+ }
+
+ /**
+ * Concatenate a translation onto this transform. This is equivalent, but
+ * more efficient than
+ * <code>concatenate(AffineTransform.getTranslateInstance(tx, ty))</code>.
+ *
+ * @param tx the x translation distance
+ * @param ty the y translation distance
+ * @see #getTranslateInstance(double, double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void translate(double tx, double ty)
+ {
+ m02 += tx * m00 + ty * m01;
+ m12 += tx * m10 + ty * m11;
+ updateType();
+ }
+
+ /**
+ * Concatenate a rotation onto this transform. This is equivalent, but
+ * more efficient than
+ * <code>concatenate(AffineTransform.getRotateInstance(theta))</code>.
+ *
+ * @param theta the rotation angle
+ * @see #getRotateInstance(double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void rotate(double theta)
+ {
+ double c = Math.cos(theta);
+ double s = Math.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;
+ updateType();
+ }
+
+ /**
+ * Concatenate a rotation about a point onto this transform. This is
+ * equivalent, but more efficient than
+ * <code>concatenate(AffineTransform.getRotateInstance(theta, x, y))</code>.
+ *
+ * @param theta the rotation angle
+ * @param x the x coordinate of the pivot point
+ * @param y the y coordinate of the pivot point
+ * @see #getRotateInstance(double, double, double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void rotate(double theta, double x, double y)
+ {
+ translate(x, y);
+ rotate(theta);
+ translate(-x, -y);
+ }
+
+ /**
+ * Concatenate a scale onto this transform. This is equivalent, but more
+ * efficient than
+ * <code>concatenate(AffineTransform.getScaleInstance(sx, sy))</code>.
+ *
+ * @param sx the x scaling factor
+ * @param sy the y scaling factor
+ * @see #getScaleInstance(double, double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void scale(double sx, double sy)
+ {
+ m00 *= sx;
+ m01 *= sy;
+ m10 *= sx;
+ m11 *= sy;
+ updateType();
+ }
+
+ /**
+ * Concatenate a shearing onto this transform. This is equivalent, but more
+ * efficient than
+ * <code>concatenate(AffineTransform.getShearInstance(sx, sy))</code>.
+ *
+ * @param shx the x shearing factor
+ * @param shy the y shearing factor
+ * @see #getShearInstance(double, double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void shear(double shx, double shy)
+ {
+ double n00 = m00 + (shy * m01);
+ double n01 = m01 + (shx * m00);
+ double n10 = m10 + (shy * m11);
+ double n11 = m11 + (shx * m10);
+ m00 = n00;
+ m01 = n01;
+ m10 = n10;
+ m11 = n11;
+ updateType();
+ }
+
+ /**
+ * Reset this transform to the identity (no transformation):
+ * <pre>
+ * [ 1 0 0 ]
+ * [ 0 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ */
+ public void setToIdentity()
+ {
+ m00 = m11 = 1;
+ m01 = m02 = m10 = m12 = 0;
+ type = TYPE_IDENTITY;
+ }
+
+ /**
+ * Set this transform to a translation:
+ * <pre>
+ * [ 1 0 tx ]
+ * [ 0 1 ty ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param tx the x translation distance
+ * @param ty the y translation distance
+ */
+ public void setToTranslation(double tx, double ty)
+ {
+ m00 = m11 = 1;
+ m01 = m10 = 0;
+ m02 = tx;
+ m12 = ty;
+ type = (tx == 0 && ty == 0) ? TYPE_UNIFORM_SCALE : TYPE_TRANSLATION;
+ }
+
+ /**
+ * Set this transform to a rotation. A positive angle (in radians) rotates
+ * the positive x-axis to the positive y-axis:
+ * <pre>
+ * [ cos(theta) -sin(theta) 0 ]
+ * [ sin(theta) cos(theta) 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param theta the rotation angle
+ */
+ public void setToRotation(double theta)
+ {
+ double c = Math.cos(theta);
+ double s = Math.sin(theta);
+ m00 = c;
+ m01 = -s;
+ m02 = 0;
+ m10 = s;
+ m11 = c;
+ m12 = 0;
+ type = (c == 1 ? TYPE_IDENTITY
+ : c == 0 || c == -1 ? TYPE_QUADRANT_ROTATION
+ : TYPE_GENERAL_ROTATION);
+ }
+
+ /**
+ * Set this transform to a rotation about a point. A positive angle (in
+ * radians) rotates the positive x-axis to the positive y-axis. This is the
+ * same as calling:
+ * <pre>
+ * tx.setToTranslation(x, y);
+ * tx.rotate(theta);
+ * tx.translate(-x, -y);
+ * </pre>
+ *
+ * <p>The resulting matrix is:
+ * <pre>
+ * [ cos(theta) -sin(theta) x-x*cos+y*sin ]
+ * [ sin(theta) cos(theta) y-x*sin-y*cos ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param theta the rotation angle
+ * @param x the x coordinate of the pivot point
+ * @param y the y coordinate of the pivot point
+ */
+ public void setToRotation(double theta, double x, double y)
+ {
+ double c = Math.cos(theta);
+ double s = Math.sin(theta);
+ m00 = c;
+ m01 = -s;
+ m02 = x - x * c + y * s;
+ m10 = s;
+ m11 = c;
+ m12 = y - x * s - y * c;
+ updateType();
+ }
+
+ /**
+ * Set this transform to a scale:
+ * <pre>
+ * [ sx 0 0 ]
+ * [ 0 sy 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param sx the x scaling factor
+ * @param sy the y scaling factor
+ */
+ public void setToScale(double sx, double sy)
+ {
+ m00 = sx;
+ m01 = m02 = m10 = m12 = 0;
+ m11 = sy;
+ type = (sx != sy ? TYPE_GENERAL_SCALE
+ : sx == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE);
+ }
+
+ /**
+ * Set this transform to a shear (points are shifted in the x direction based
+ * on a factor of their y coordinate, and in the y direction as a factor of
+ * their x coordinate):
+ * <pre>
+ * [ 1 shx 0 ]
+ * [ shy 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param shx the x shearing factor
+ * @param shy the y shearing factor
+ */
+ public void setToShear(double shx, double shy)
+ {
+ m00 = m11 = 1;
+ m01 = shx;
+ m10 = shy;
+ m02 = m12 = 0;
+ updateType();
+ }
+
+ /**
+ * Set this transform to a copy of the given one.
+ *
+ * @param tx the transform to copy
+ * @throws NullPointerException if tx is null
+ */
+ public void setTransform(AffineTransform tx)
+ {
+ m00 = tx.m00;
+ m01 = tx.m01;
+ m02 = tx.m02;
+ m10 = tx.m10;
+ m11 = tx.m11;
+ m12 = tx.m12;
+ type = tx.type;
+ }
+
+ /**
+ * Set this transform to the given values:
+ * <pre>
+ * [ m00 m01 m02 ]
+ * [ m10 m11 m12 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param m00 the x scaling component
+ * @param m10 the y shearing component
+ * @param m01 the x shearing component
+ * @param m11 the y scaling component
+ * @param m02 the x translation component
+ * @param m12 the y translation component
+ */
+ public void setTransform(double m00, double m10, double m01,
+ double m11, double m02, double m12)
+ {
+ this.m00 = m00;
+ this.m10 = m10;
+ this.m01 = m01;
+ this.m11 = m11;
+ this.m02 = m02;
+ this.m12 = m12;
+ updateType();
+ }
+
+ /**
+ * Set this transform to the result of performing the original version of
+ * this followed by tx. This is commonly used when chaining transformations
+ * from one space to another. In matrix form:
+ * <pre>
+ * [ this ] = [ this ] x [ tx ]
+ * </pre>
+ *
+ * @param tx the transform to concatenate
+ * @throws NullPointerException if tx is null
+ * @see #preConcatenate(AffineTransform)
+ */
+ public void concatenate(AffineTransform tx)
+ {
+ double n00 = m00 * tx.m00 + m01 * tx.m10;
+ double n01 = m00 * tx.m01 + m01 * tx.m11;
+ double n02 = m00 * tx.m02 + m01 * tx.m12 + m02;
+ double n10 = m10 * tx.m00 + m11 * tx.m10;
+ double n11 = m10 * tx.m01 + m11 * tx.m11;
+ double n12 = m10 * tx.m02 + m11 * tx.m12 + m12;
+ m00 = n00;
+ m01 = n01;
+ m02 = n02;
+ m10 = n10;
+ m11 = n11;
+ m12 = n12;
+ updateType();
+ }
+
+ /**
+ * Set this transform to the result of performing tx followed by the
+ * original version of this. This is less common than normal concatenation,
+ * but can still be used to chain transformations from one space to another.
+ * In matrix form:
+ * <pre>
+ * [ this ] = [ tx ] x [ this ]
+ * </pre>
+ *
+ * @param tx the transform to concatenate
+ * @throws NullPointerException if tx is null
+ * @see #concatenate(AffineTransform)
+ */
+ public void preConcatenate(AffineTransform tx)
+ {
+ double n00 = tx.m00 * m00 + tx.m01 * m10;
+ double n01 = tx.m00 * m01 + tx.m01 * m11;
+ double n02 = tx.m00 * m02 + tx.m01 * m12 + tx.m02;
+ double n10 = tx.m10 * m00 + tx.m11 * m10;
+ double n11 = tx.m10 * m01 + tx.m11 * m11;
+ double n12 = tx.m10 * m02 + tx.m11 * m12 + tx.m12;
+ m00 = n00;
+ m01 = n01;
+ m02 = n02;
+ m10 = n10;
+ m11 = n11;
+ m12 = n12;
+ updateType();
+ }
+
+ /**
+ * Returns a transform, which if concatenated to this one, will result in
+ * the identity transform. This is useful for undoing transformations, but
+ * is only possible if the original transform has an inverse (ie. does not
+ * map multiple points to the same line or point). A transform exists only
+ * if getDeterminant() has a non-zero value.
+ *
+ * The inverse is calculated as:
+ *
+ * <pre>
+ *
+ * Let A be the matrix for which we want to find the inverse:
+ *
+ * A = [ m00 m01 m02 ]
+ * [ m10 m11 m12 ]
+ * [ 0 0 1 ]
+ *
+ *
+ * 1
+ * inverse (A) = --- x adjoint(A)
+ * det
+ *
+ *
+ *
+ * = 1 [ m11 -m01 m01*m12-m02*m11 ]
+ * --- x [ -m10 m00 -m00*m12+m10*m02 ]
+ * det [ 0 0 m00*m11-m10*m01 ]
+ *
+ *
+ *
+ * = [ m11/det -m01/det m01*m12-m02*m11/det ]
+ * [ -m10/det m00/det -m00*m12+m10*m02/det ]
+ * [ 0 0 1 ]
+ *
+ *
+ * </pre>
+ *
+ *
+ *
+ * @return a new inverse transform
+ * @throws NoninvertibleTransformException if inversion is not possible
+ * @see #getDeterminant()
+ */
+ public AffineTransform createInverse()
+ throws NoninvertibleTransformException
+ {
+ double det = getDeterminant();
+ if (det == 0)
+ throw new NoninvertibleTransformException("can't invert transform");
+
+ double im00 = m11 / det;
+ double im10 = -m10 / det;
+ double im01 = -m01 / det;
+ double im11 = m00 / det;
+ double im02 = (m01 * m12 - m02 * m11) / det;
+ double im12 = (-m00 * m12 + m10 * m02) / det;
+
+ return new AffineTransform (im00, im10, im01, im11, im02, im12);
+ }
+
+ /**
+ * Perform this transformation on the given source point, and store the
+ * result in the destination (creating it if necessary). It is safe for
+ * src and dst to be the same.
+ *
+ * @param src the source point
+ * @param dst the destination, or null
+ * @return the transformation of src, in dst if it was non-null
+ * @throws NullPointerException if src is null
+ */
+ public Point2D transform(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ dst = new Point2D.Double();
+ double x = src.getX();
+ double y = src.getY();
+ double nx = m00 * x + m01 * y + m02;
+ double ny = m10 * x + m11 * y + m12;
+ dst.setLocation(nx, ny);
+ return dst;
+ }
+
+ /**
+ * Perform this transformation on an array of points, storing the results
+ * in another (possibly same) array. This will not create a destination
+ * array, but will create points for the null entries of the destination.
+ * The transformation is done sequentially. While having a single source
+ * and destination point be the same is safe, you should be aware that
+ * duplicate references to the same point in the source, and having the
+ * source overlap the destination, may result in your source points changing
+ * from a previous transform before it is their turn to be evaluated.
+ *
+ * @param src the array of source points
+ * @param srcOff the starting offset into src
+ * @param dst the array of destination points (may have null entries)
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null, or src has null
+ * entries
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ * @throws ArrayStoreException if new points are incompatible with dst
+ */
+ public void transform(Point2D[] src, int srcOff,
+ Point2D[] dst, int dstOff, int num)
+ {
+ while (--num >= 0)
+ dst[dstOff] = transform(src[srcOff++], dst[dstOff++]);
+ }
+
+ /**
+ * Perform this transformation on an array of points, in (x,y) pairs,
+ * storing the results in another (possibly same) array. This will not
+ * create a destination array. All sources are copied before the
+ * transformation, so that no result will overwrite a point that has not yet
+ * been evaluated.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void transform(float[] srcPts, int srcOff,
+ float[] dstPts, int dstOff, int num)
+ {
+ if (srcPts == dstPts && dstOff > srcOff
+ && num > 1 && srcOff + 2 * num > dstOff)
+ {
+ float[] f = new float[2 * num];
+ System.arraycopy(srcPts, srcOff, f, 0, 2 * num);
+ srcPts = f;
+ }
+ while (--num >= 0)
+ {
+ float x = srcPts[srcOff++];
+ float y = srcPts[srcOff++];
+ dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02);
+ dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12);
+ }
+ }
+
+ /**
+ * Perform this transformation on an array of points, in (x,y) pairs,
+ * storing the results in another (possibly same) array. This will not
+ * create a destination array. All sources are copied before the
+ * transformation, so that no result will overwrite a point that has not yet
+ * been evaluated.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void transform(double[] srcPts, int srcOff,
+ double[] dstPts, int dstOff, int num)
+ {
+ if (srcPts == dstPts && dstOff > srcOff
+ && num > 1 && srcOff + 2 * num > dstOff)
+ {
+ double[] d = new double[2 * num];
+ System.arraycopy(srcPts, srcOff, d, 0, 2 * num);
+ srcPts = d;
+ }
+ while (--num >= 0)
+ {
+ double x = srcPts[srcOff++];
+ double y = srcPts[srcOff++];
+ dstPts[dstOff++] = m00 * x + m01 * y + m02;
+ dstPts[dstOff++] = m10 * x + m11 * y + m12;
+ }
+ }
+
+ /**
+ * Perform this transformation on an array of points, in (x,y) pairs,
+ * storing the results in another array. This will not create a destination
+ * array.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void transform(float[] srcPts, int srcOff,
+ double[] dstPts, int dstOff, int num)
+ {
+ while (--num >= 0)
+ {
+ float x = srcPts[srcOff++];
+ float y = srcPts[srcOff++];
+ dstPts[dstOff++] = m00 * x + m01 * y + m02;
+ dstPts[dstOff++] = m10 * x + m11 * y + m12;
+ }
+ }
+
+ /**
+ * Perform this transformation on an array of points, in (x,y) pairs,
+ * storing the results in another array. This will not create a destination
+ * array.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void transform(double[] srcPts, int srcOff,
+ float[] dstPts, int dstOff, int num)
+ {
+ while (--num >= 0)
+ {
+ double x = srcPts[srcOff++];
+ double y = srcPts[srcOff++];
+ dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02);
+ dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12);
+ }
+ }
+
+ /**
+ * Perform the inverse of this transformation on the given source point,
+ * and store the result in the destination (creating it if necessary). It
+ * is safe for src and dst to be the same.
+ *
+ * @param src the source point
+ * @param dst the destination, or null
+ * @return the inverse transformation of src, in dst if it was non-null
+ * @throws NullPointerException if src is null
+ * @throws NoninvertibleTransformException if the inverse does not exist
+ * @see #getDeterminant()
+ */
+ public Point2D inverseTransform(Point2D src, Point2D dst)
+ throws NoninvertibleTransformException
+ {
+ return createInverse().transform(src, dst);
+ }
+
+ /**
+ * Perform the inverse of this transformation on an array of points, in
+ * (x,y) pairs, storing the results in another (possibly same) array. This
+ * will not create a destination array. All sources are copied before the
+ * transformation, so that no result will overwrite a point that has not yet
+ * been evaluated.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ * @throws NoninvertibleTransformException if the inverse does not exist
+ * @see #getDeterminant()
+ */
+ public void inverseTransform(double[] srcPts, int srcOff,
+ double[] dstPts, int dstOff, int num)
+ throws NoninvertibleTransformException
+ {
+ createInverse().transform(srcPts, srcOff, dstPts, dstOff, num);
+ }
+
+ /**
+ * Perform this transformation, less any translation, on the given source
+ * point, and store the result in the destination (creating it if
+ * necessary). It is safe for src and dst to be the same. The reduced
+ * transform is equivalent to:
+ * <pre>
+ * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ]
+ * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ]
+ * </pre>
+ *
+ * @param src the source point
+ * @param dst the destination, or null
+ * @return the delta transformation of src, in dst if it was non-null
+ * @throws NullPointerException if src is null
+ */
+ public Point2D deltaTransform(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ dst = new Point2D.Double();
+ double x = src.getX();
+ double y = src.getY();
+ double nx = m00 * x + m01 * y;
+ double ny = m10 * x + m11 * y;
+ dst.setLocation(nx, ny);
+ return dst;
+ }
+
+ /**
+ * Perform this transformation, less any translation, on an array of points,
+ * in (x,y) pairs, storing the results in another (possibly same) array.
+ * This will not create a destination array. All sources are copied before
+ * the transformation, so that no result will overwrite a point that has
+ * not yet been evaluated. The reduced transform is equivalent to:
+ * <pre>
+ * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ]
+ * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ]
+ * </pre>
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void deltaTransform(double[] srcPts, int srcOff,
+ double[] dstPts, int dstOff,
+ int num)
+ {
+ if (srcPts == dstPts && dstOff > srcOff
+ && num > 1 && srcOff + 2 * num > dstOff)
+ {
+ double[] d = new double[2 * num];
+ System.arraycopy(srcPts, srcOff, d, 0, 2 * num);
+ srcPts = d;
+ }
+ while (--num >= 0)
+ {
+ double x = srcPts[srcOff++];
+ double y = srcPts[srcOff++];
+ dstPts[dstOff++] = m00 * x + m01 * y;
+ dstPts[dstOff++] = m10 * x + m11 * y;
+ }
+ }
+
+ /**
+ * Return a new Shape, based on the given one, where the path of the shape
+ * has been transformed by this transform. Notice that this uses GeneralPath,
+ * which only stores points in float precision.
+ *
+ * @param src the shape source to transform
+ * @return the shape, transformed by this, <code>null</code> if src is
+ * <code>null</code>.
+ * @see GeneralPath#transform(AffineTransform)
+ */
+ public Shape createTransformedShape(Shape src)
+ {
+ if(src == null)
+ return null;
+ GeneralPath p = new GeneralPath(src);
+ p.transform(this);
+ return p;
+ }
+
+ /**
+ * Returns a string representation of the transform, in the format:
+ * <code>"AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], ["
+ * + m10 + ", " + m11 + ", " + m12 + "]]"</code>.
+ *
+ * @return the string representation
+ */
+ public String toString()
+ {
+ return "AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], ["
+ + m10 + ", " + m11 + ", " + m12 + "]]";
+ }
+
+ /**
+ * Tests if this transformation is the identity:
+ * <pre>
+ * [ 1 0 0 ]
+ * [ 0 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @return true if this is the identity transform
+ */
+ public boolean isIdentity()
+ {
+ // Rather than rely on type, check explicitly.
+ return (m00 == 1 && m01 == 0 && m02 == 0
+ && m10 == 0 && m11 == 1 && m12 == 0);
+ }
+
+ /**
+ * Create a new transform of the same run-time type, with the same
+ * transforming properties as this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Return the hashcode for this transformation. The formula is not
+ * 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(getTranslateY());
+ * return (int) ((l >> 32) ^ l);
+ * </pre>
+ *
+ * @return the hashcode
+ */
+ 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);
+ return (int) ((l >> 32) ^ l);
+ }
+
+ /**
+ * Compares two transforms for equality. This returns true if they have the
+ * same matrix values.
+ *
+ * @param obj the transform to compare
+ * @return true if it is equal
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof AffineTransform))
+ return false;
+ AffineTransform t = (AffineTransform) obj;
+ return (m00 == t.m00 && m01 == t.m01 && m02 == t.m02
+ && m10 == t.m10 && m11 == t.m11 && m12 == t.m12);
+ }
+
+ /**
+ * Helper to decode the type from the matrix. This is not guaranteed
+ * to find the optimal type, but at least it will be valid.
+ */
+ private void updateType()
+ {
+ double det = getDeterminant();
+ if (det == 0)
+ {
+ type = TYPE_GENERAL_TRANSFORM;
+ return;
+ }
+ // Scale (includes rotation by PI) or translation.
+ if (m01 == 0 && m10 == 0)
+ {
+ if (m00 == m11)
+ type = m00 == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE;
+ else
+ type = TYPE_GENERAL_SCALE;
+ if (m02 != 0 || m12 != 0)
+ type |= TYPE_TRANSLATION;
+ }
+ // Rotation.
+ else if (m00 == m11 && m01 == -m10)
+ {
+ type = m00 == 0 ? TYPE_QUADRANT_ROTATION : TYPE_GENERAL_ROTATION;
+ if (det != 1)
+ type |= TYPE_UNIFORM_SCALE;
+ if (m02 != 0 || m12 != 0)
+ type |= TYPE_TRANSLATION;
+ }
+ else
+ type = TYPE_GENERAL_TRANSFORM;
+ }
+
+ /**
+ * Reads a transform from an object stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if there is a problem deserializing
+ * @throws IOException if there is a problem deserializing
+ */
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject();
+ updateType();
+ }
+} // class AffineTransform
diff --git a/libjava/classpath/java/awt/geom/Arc2D.java b/libjava/classpath/java/awt/geom/Arc2D.java
new file mode 100644
index 00000000000..eff34a08144
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Arc2D.java
@@ -0,0 +1,1399 @@
+/* Arc2D.java -- represents an arc in 2-D space
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+
+/**
+ * This class represents all arcs (segments of an ellipse in 2-D space). The
+ * arcs are defined by starting angle and extent (arc length) in degrees, as
+ * opposed to radians (like the rest of Java), and can be open, chorded, or
+ * wedge shaped. The angles are skewed according to the ellipse, so that 45
+ * degrees always points to the upper right corner (positive x, negative y)
+ * of the bounding rectangle. A positive extent draws a counterclockwise arc,
+ * and while the angle can be any value, the path iterator only traverses the
+ * first 360 degrees. Storage is up to the subclasses.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sven de Marothy (sven@physto.se)
+ * @since 1.2
+ */
+public abstract class Arc2D extends RectangularShape
+{
+ /**
+ * An open arc, with no segment connecting the endpoints. This type of
+ * arc still contains the same points as a chorded version.
+ */
+ public static final int OPEN = 0;
+
+ /**
+ * A closed arc with a single segment connecting the endpoints (a chord).
+ */
+ public static final int CHORD = 1;
+
+ /**
+ * A closed arc with two segments, one from each endpoint, meeting at the
+ * center of the ellipse.
+ */
+ public static final int PIE = 2;
+
+ /** The closure type of this arc. This is package-private to avoid an
+ * accessor method. */
+ int type;
+
+ /**
+ * Create a new arc, with the specified closure type.
+ *
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
+ * @throws IllegalArgumentException if type is invalid
+ */
+ protected Arc2D(int type)
+ {
+ if (type < OPEN || type > PIE)
+ throw new IllegalArgumentException();
+ this.type = type;
+ }
+
+ /**
+ * Get the starting angle of the arc in degrees.
+ *
+ * @return the starting angle
+ * @see #setAngleStart(double)
+ */
+ public abstract double getAngleStart();
+
+ /**
+ * Get the extent angle of the arc in degrees.
+ *
+ * @return the extent angle
+ * @see #setAngleExtent(double)
+ */
+ public abstract double getAngleExtent();
+
+ /**
+ * Return the closure type of the arc.
+ *
+ * @return the closure type
+ * @see #OPEN
+ * @see #CHORD
+ * @see #PIE
+ * @see #setArcType(int)
+ */
+ public int getArcType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the starting point of the arc.
+ *
+ * @return the start point
+ */
+ public Point2D getStartPoint()
+ {
+ double angle = Math.toRadians(getAngleStart());
+ double rx = getWidth() / 2;
+ double ry = getHeight() / 2;
+ double x = getX() + rx + rx * Math.cos(angle);
+ double y = getY() + ry - ry * Math.sin(angle);
+ return new Point2D.Double(x, y);
+ }
+
+ /**
+ * Returns the ending point of the arc.
+ *
+ * @return the end point
+ */
+ public Point2D getEndPoint()
+ {
+ double angle = Math.toRadians(getAngleStart() + getAngleExtent());
+ double rx = getWidth() / 2;
+ double ry = getHeight() / 2;
+ double x = getX() + rx + rx * Math.cos(angle);
+ double y = getY() + ry - ry * Math.sin(angle);
+ return new Point2D.Double(x, y);
+ }
+
+ /**
+ * Set the parameters of the arc. The angles are in degrees, and a positive
+ * extent sweeps counterclockwise (from the positive x-axis to the negative
+ * y-axis).
+ *
+ * @param x the new x coordinate of the upper left of the bounding box
+ * @param y the new y coordinate of the upper left of the bounding box
+ * @param w the new width of the bounding box
+ * @param h the new height of the bounding box
+ * @param start the start angle, in degrees
+ * @param extent the arc extent, in degrees
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public abstract void setArc(double x, double y, double w, double h,
+ double start, double extent, int type);
+
+ /**
+ * Set the parameters of the arc. The angles are in degrees, and a positive
+ * extent sweeps counterclockwise (from the positive x-axis to the negative
+ * y-axis).
+ *
+ * @param p the upper left point of the bounding box
+ * @param d the dimensions of the bounding box
+ * @param start the start angle, in degrees
+ * @param extent the arc extent, in degrees
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @throws NullPointerException if p or d is null
+ */
+ public void setArc(Point2D p, Dimension2D d, double start, double extent,
+ int type)
+ {
+ setArc(p.getX(), p.getY(), d.getWidth(), d.getHeight(), start, extent, type);
+ }
+
+ /**
+ * Set the parameters of the arc. The angles are in degrees, and a positive
+ * extent sweeps counterclockwise (from the positive x-axis to the negative
+ * y-axis).
+ *
+ * @param r the new bounding box
+ * @param start the start angle, in degrees
+ * @param extent the arc extent, in degrees
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @throws NullPointerException if r is null
+ */
+ public void setArc(Rectangle2D r, double start, double extent, int type)
+ {
+ setArc(r.getX(), r.getY(), r.getWidth(), r.getHeight(), start, extent, type);
+ }
+
+ /**
+ * Set the parameters of the arc from the given one.
+ *
+ * @param a the arc to copy
+ * @throws NullPointerException if a is null
+ */
+ public void setArc(Arc2D a)
+ {
+ setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), a.getAngleStart(),
+ a.getAngleExtent(), a.getArcType());
+ }
+
+ /**
+ * Set the parameters of the arc. The angles are in degrees, and a positive
+ * extent sweeps counterclockwise (from the positive x-axis to the negative
+ * y-axis). This controls the center point and radius, so the arc will be
+ * circular.
+ *
+ * @param x the x coordinate of the center of the circle
+ * @param y the y coordinate of the center of the circle
+ * @param r the radius of the circle
+ * @param start the start angle, in degrees
+ * @param extent the arc extent, in degrees
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public void setArcByCenter(double x, double y, double r, double start,
+ double extent, int type)
+ {
+ setArc(x - r, y - r, r + r, r + r, start, extent, type);
+ }
+
+ /**
+ * Sets the parameters of the arc by finding the tangents of two lines, and
+ * using the specified radius. The arc will be circular, will begin on the
+ * tangent point of the line extending from p1 to p2, and will end on the
+ * tangent point of the line extending from p2 to p3.
+ *
+ * XXX What happens if the points are colinear, or the radius negative?
+ *
+ * @param p1 the first point
+ * @param p2 the tangent line intersection point
+ * @param p3 the third point
+ * @param r the radius of the arc
+ * @throws NullPointerException if any point is null
+ */
+ public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, double r)
+ {
+ if ((p2.getX() - p1.getX()) * (p3.getY() - p1.getY())
+ - (p3.getX() - p1.getX()) * (p2.getY() - p1.getY()) > 0)
+ {
+ Point2D p = p3;
+ p3 = p1;
+ p1 = p;
+ }
+
+ // normalized tangent vectors
+ double dx1 = (p1.getX() - p2.getX()) / p1.distance(p2);
+ double dy1 = (p1.getY() - p2.getY()) / p1.distance(p2);
+ double dx2 = (p2.getX() - p3.getX()) / p3.distance(p2);
+ double dy2 = (p2.getY() - p3.getY()) / p3.distance(p2);
+ double theta1 = Math.atan2(dx1, dy1);
+ double theta2 = Math.atan2(dx2, dy2);
+
+ double dx = r * Math.cos(theta2) - r * Math.cos(theta1);
+ double dy = -r * Math.sin(theta2) + r * Math.sin(theta1);
+
+ if (theta1 < 0)
+ theta1 += 2 * Math.PI;
+ if (theta2 < 0)
+ theta2 += 2 * Math.PI;
+ if (theta2 < theta1)
+ theta2 += 2 * Math.PI;
+
+ // Vectors of the lines, not normalized, note we change
+ // the direction of line 2.
+ dx1 = p1.getX() - p2.getX();
+ dy1 = p1.getY() - p2.getY();
+ dx2 = p3.getX() - p2.getX();
+ dy2 = p3.getY() - p2.getY();
+
+ // Calculate the tangent point to the second line
+ double t2 = -(dx1 * dy - dy1 * dx) / (dx2 * dy1 - dx1 * dy2);
+ double x2 = t2 * (p3.getX() - p2.getX()) + p2.getX();
+ double y2 = t2 * (p3.getY() - p2.getY()) + p2.getY();
+
+ // calculate the center point
+ double x = x2 - r * Math.cos(theta2);
+ double y = y2 + r * Math.sin(theta2);
+
+ setArc(x - r, y - r, 2 * r, 2 * r, Math.toDegrees(theta1),
+ Math.toDegrees(theta2 - theta1), getArcType());
+ }
+
+ /**
+ * Set the start, in degrees.
+ *
+ * @param start the new start angle
+ * @see #getAngleStart()
+ */
+ public abstract void setAngleStart(double start);
+
+ /**
+ * Set the extent, in degrees.
+ *
+ * @param extent the new extent angle
+ * @see #getAngleExtent()
+ */
+ public abstract void setAngleExtent(double extent);
+
+ /**
+ * Sets the starting angle to the angle of the given point relative to
+ * the center of the arc. The extent remains constant; in other words,
+ * this rotates the arc.
+ *
+ * @param p the new start point
+ * @throws NullPointerException if p is null
+ * @see #getStartPoint()
+ * @see #getAngleStart()
+ */
+ public void setAngleStart(Point2D p)
+ {
+ // Normalize.
+ double x = p.getX() - (getX() + getWidth() / 2);
+ double y = p.getY() - (getY() + getHeight() / 2);
+ setAngleStart(Math.toDegrees(Math.atan2(-y, x)));
+ }
+
+ /**
+ * Sets the starting and extent angles to those of the given points
+ * relative to the center of the arc. The arc will be non-empty, and will
+ * extend counterclockwise.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ * @see #setAngleStart(Point2D)
+ */
+ public void setAngles(double x1, double y1, double x2, double y2)
+ {
+ // Normalize the points.
+ double mx = getX();
+ double my = getY();
+ double mw = getWidth();
+ double mh = getHeight();
+ x1 = x1 - (mx + mw / 2);
+ y1 = y1 - (my + mh / 2);
+ x2 = x2 - (mx + mw / 2);
+ y2 = y2 - (my + mh / 2);
+ double start = Math.toDegrees(Math.atan2(-y1, x1));
+ double extent = Math.toDegrees(Math.atan2(-y2, x2)) - start;
+ if (extent < 0)
+ extent += 360;
+ setAngleStart(start);
+ setAngleExtent(extent);
+ }
+
+ /**
+ * Sets the starting and extent angles to those of the given points
+ * relative to the center of the arc. The arc will be non-empty, and will
+ * extend counterclockwise.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ * @see #setAngleStart(Point2D)
+ */
+ public void setAngles(Point2D p1, Point2D p2)
+ {
+ setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+ }
+
+ /**
+ * Set the closure type of this arc.
+ *
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @see #getArcType()
+ */
+ public void setArcType(int type)
+ {
+ if (type < OPEN || type > PIE)
+ throw new IllegalArgumentException();
+ this.type = type;
+ }
+
+ /**
+ * Sets the location and bounds of the ellipse of which this arc is a part.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ * @param w the new width
+ * @param h the new height
+ * @see #getFrame()
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type);
+ }
+
+ /**
+ * Gets the bounds of the arc. This is much tighter than
+ * <code>getBounds</code>, as it takes into consideration the start and
+ * end angles, and the center point of a pie wedge, rather than just the
+ * overall ellipse.
+ *
+ * @return the bounds of the arc
+ * @see #getBounds()
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double extent = getAngleExtent();
+ if (Math.abs(extent) >= 360)
+ return makeBounds(getX(), getY(), getWidth(), getHeight());
+
+ // Find the minimal bounding box. This determined by its extrema,
+ // which are the center, the endpoints of the arc, and any local
+ // maximum contained by the arc.
+ double rX = getWidth() / 2;
+ double rY = getHeight() / 2;
+ double centerX = getX() + rX;
+ double centerY = getY() + rY;
+
+ Point2D p1 = getStartPoint();
+ Rectangle2D result = makeBounds(p1.getX(), p1.getY(), 0, 0);
+ result.add(getEndPoint());
+
+ if (type == PIE)
+ result.add(centerX, centerY);
+ if (containsAngle(0))
+ result.add(centerX + rX, centerY);
+ if (containsAngle(90))
+ result.add(centerX, centerY - rY);
+ if (containsAngle(180))
+ result.add(centerX - rX, centerY);
+ if (containsAngle(270))
+ result.add(centerX, centerY + rY);
+
+ return result;
+ }
+
+ /**
+ * Construct a bounding box in a precision appropriate for the subclass.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @return the rectangle for use in getBounds2D
+ */
+ protected abstract Rectangle2D makeBounds(double x, double y, double w,
+ double h);
+
+ /**
+ * Tests if the given angle, in degrees, is included in the arc.
+ * All angles are normalized to be between 0 and 360 degrees.
+ *
+ * @param a the angle to test
+ * @return true if it is contained
+ */
+ public boolean containsAngle(double a)
+ {
+ double start = getAngleStart();
+ double extent = getAngleExtent();
+ double end = start + extent;
+
+ if (extent == 0)
+ return false;
+
+ if (extent >= 360 || extent <= -360)
+ return true;
+
+ if (extent < 0)
+ {
+ end = start;
+ start += extent;
+ }
+
+ start %= 360;
+ while (start < 0)
+ start += 360;
+
+ end %= 360;
+ while (end < start)
+ end += 360;
+
+ a %= 360;
+ while (a < start)
+ a += 360;
+
+ return a >= start && a < end; // starting angle included, ending angle not
+ }
+
+ /**
+ * Determines if the arc contains the given point. If the bounding box
+ * is empty, then this will return false.
+ *
+ * The area considered 'inside' an arc of type OPEN is the same as the
+ * area inside an equivalent filled CHORD-type arc. The area considered
+ * 'inside' a CHORD-type arc is the same as the filled area.
+ *
+ * @param x the x coordinate to test
+ * @param y the y coordinate to test
+ * @return true if the point is inside the arc
+ */
+ public boolean contains(double x, double y)
+ {
+ double w = getWidth();
+ double h = getHeight();
+ double extent = getAngleExtent();
+ if (w <= 0 || h <= 0 || extent == 0)
+ return false;
+
+ double mx = getX() + w / 2;
+ double my = getY() + h / 2;
+ double dx = (x - mx) * 2 / w;
+ double dy = (y - my) * 2 / h;
+ if ((dx * dx + dy * dy) >= 1.0)
+ return false;
+
+ double angle = Math.toDegrees(Math.atan2(-dy, dx));
+ if (getArcType() == PIE)
+ return containsAngle(angle);
+
+ double a1 = Math.toRadians(getAngleStart());
+ double a2 = Math.toRadians(getAngleStart() + extent);
+ double x1 = mx + getWidth() * Math.cos(a1) / 2;
+ double y1 = my - getHeight() * Math.sin(a1) / 2;
+ double x2 = mx + getWidth() * Math.cos(a2) / 2;
+ double y2 = my - getHeight() * Math.sin(a2) / 2;
+ double sgn = ((x2 - x1) * (my - y1) - (mx - x1) * (y2 - y1)) * ((x2 - x1) * (y
+ - y1) - (x - x1) * (y2 - y1));
+
+ if (Math.abs(extent) > 180)
+ {
+ if (containsAngle(angle))
+ return true;
+ return sgn > 0;
+ }
+ else
+ {
+ if (! containsAngle(angle))
+ return false;
+ return sgn < 0;
+ }
+ }
+
+ /**
+ * Tests if a given rectangle intersects the area of the arc.
+ *
+ * For a definition of the 'inside' area, see the contains() method.
+ * @see #contains(double, double)
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return true if the two shapes share common points
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ double extent = getAngleExtent();
+ if (extent == 0)
+ return false;
+
+ if (contains(x, y) || contains(x, y + h) || contains(x + w, y)
+ || contains(x + w, y + h))
+ return true;
+
+ Rectangle2D rect = new Rectangle2D.Double(x, y, w, h);
+
+ double a = getWidth() / 2.0;
+ double b = getHeight() / 2.0;
+
+ double mx = getX() + a;
+ double my = getY() + b;
+ double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart()));
+ double y1 = my - b * Math.sin(Math.toRadians(getAngleStart()));
+ double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent));
+ double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent));
+
+ if (getArcType() != CHORD)
+ {
+ // check intersections against the pie radii
+ if (rect.intersectsLine(mx, my, x1, y1))
+ return true;
+ if (rect.intersectsLine(mx, my, x2, y2))
+ return true;
+ }
+ else// check the chord
+ if (rect.intersectsLine(x1, y1, x2, y2))
+ return true;
+
+ // Check the Arc segment against the four edges
+ double dx;
+
+ // Check the Arc segment against the four edges
+ double dy;
+ dy = y - my;
+ dx = a * Math.sqrt(1 - ((dy * dy) / (b * b)));
+ if (! java.lang.Double.isNaN(dx))
+ {
+ if (mx + dx >= x && mx + dx <= x + w
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
+ return true;
+ if (mx - dx >= x && mx - dx <= x + w
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx))))
+ return true;
+ }
+ dy = (y + h) - my;
+ dx = a * Math.sqrt(1 - ((dy * dy) / (b * b)));
+ if (! java.lang.Double.isNaN(dx))
+ {
+ if (mx + dx >= x && mx + dx <= x + w
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
+ return true;
+ if (mx - dx >= x && mx - dx <= x + w
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx))))
+ return true;
+ }
+ dx = x - mx;
+ dy = b * Math.sqrt(1 - ((dx * dx) / (a * a)));
+ if (! java.lang.Double.isNaN(dy))
+ {
+ if (my + dy >= y && my + dy <= y + h
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
+ return true;
+ if (my - dy >= y && my - dy <= y + h
+ && containsAngle(Math.toDegrees(Math.atan2(dy, dx))))
+ return true;
+ }
+
+ dx = (x + w) - mx;
+ dy = b * Math.sqrt(1 - ((dx * dx) / (a * a)));
+ if (! java.lang.Double.isNaN(dy))
+ {
+ if (my + dy >= y && my + dy <= y + h
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
+ return true;
+ if (my - dy >= y && my - dy <= y + h
+ && containsAngle(Math.toDegrees(Math.atan2(dy, dx))))
+ return true;
+ }
+
+ // Check whether the arc is contained within the box
+ if (rect.contains(mx, my))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Tests if a given rectangle is contained in the area of the arc.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return true if the arc contains the rectangle
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ double extent = getAngleExtent();
+ if (extent == 0)
+ return false;
+
+ if (! (contains(x, y) && contains(x, y + h) && contains(x + w, y)
+ && contains(x + w, y + h)))
+ return false;
+
+ Rectangle2D rect = new Rectangle2D.Double(x, y, w, h);
+
+ double a = getWidth() / 2.0;
+ double b = getHeight() / 2.0;
+
+ double mx = getX() + a;
+ double my = getY() + b;
+ double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart()));
+ double y1 = my - b * Math.sin(Math.toRadians(getAngleStart()));
+ double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent));
+ double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent));
+ if (getArcType() != CHORD)
+ {
+ // check intersections against the pie radii
+ if (rect.intersectsLine(mx, my, x1, y1))
+ return false;
+
+ if (rect.intersectsLine(mx, my, x2, y2))
+ return false;
+ }
+ else if (rect.intersectsLine(x1, y1, x2, y2))
+ return false;
+ return true;
+ }
+
+ /**
+ * Tests if a given rectangle is contained in the area of the arc.
+ *
+ * @param r the rectangle
+ * @return true if the arc contains the rectangle
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Returns an iterator over this arc, with an optional transformation.
+ * This iterator is threadsafe, so future modifications to the arc do not
+ * affect the iteration.
+ *
+ * @param at the transformation, or null
+ * @return a path iterator
+ */
+ public PathIterator getPathIterator(AffineTransform at)
+ {
+ return new ArcIterator(this, at);
+ }
+
+ /**
+ * This class is used to iterate over an arc. Since ellipses are a subclass
+ * of arcs, this is used by Ellipse2D as well.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ static final class ArcIterator implements PathIterator
+ {
+ /** The current iteration. */
+ private int current;
+
+ /** The last iteration. */
+ private final int limit;
+
+ /** The optional transformation. */
+ private final AffineTransform xform;
+
+ /** The x coordinate of the bounding box. */
+ private final double x;
+
+ /** The y coordinate of the bounding box. */
+ private final double y;
+
+ /** The width of the bounding box. */
+ private final double w;
+
+ /** The height of the bounding box. */
+ private final double h;
+
+ /** The start angle, in radians (not degrees). */
+ private final double start;
+
+ /** The extent angle, in radians (not degrees). */
+ private final double extent;
+
+ /** The arc closure type. */
+ private final int type;
+
+ /**
+ * Construct a new iterator over an arc.
+ *
+ * @param a the arc
+ * @param xform the transform
+ */
+ public ArcIterator(Arc2D a, AffineTransform xform)
+ {
+ this.xform = xform;
+ x = a.getX();
+ y = a.getY();
+ w = a.getWidth();
+ h = a.getHeight();
+ double start = a.getAngleStart() * (Math.PI / 180);
+ double extent = a.getAngleExtent() * (Math.PI / 180);
+
+ if (extent < 0)
+ {
+ extent = -extent;
+ start = 2 * Math.PI - extent + start;
+ }
+ this.start = start;
+ this.extent = extent;
+
+ type = a.type;
+ if (w < 0 || h < 0)
+ limit = -1;
+ else if (extent == 0)
+ limit = type;
+ else if (extent <= Math.PI / 2.0)
+ limit = type + 1;
+ else if (extent <= Math.PI)
+ limit = type + 2;
+ else if (extent <= 3.0 * (Math.PI / 2.0))
+ limit = type + 3;
+ else
+ limit = type + 4;
+ }
+
+ /**
+ * Construct a new iterator over an ellipse.
+ *
+ * @param e the ellipse
+ * @param xform the transform
+ */
+ public ArcIterator(Ellipse2D e, AffineTransform xform)
+ {
+ this.xform = xform;
+ x = e.getX();
+ y = e.getY();
+ w = e.getWidth();
+ h = e.getHeight();
+ start = 0;
+ extent = 2 * Math.PI;
+ type = CHORD;
+ limit = (w < 0 || h < 0) ? -1 : 5;
+ }
+
+ /**
+ * Return the winding rule.
+ *
+ * @return {@link PathIterator#WIND_NON_ZERO}
+ */
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ /**
+ * Test if the iteration is complete.
+ *
+ * @return true if more segments exist
+ */
+ public boolean isDone()
+ {
+ return current > limit;
+ }
+
+ /**
+ * Advance the iterator.
+ */
+ public void next()
+ {
+ current++;
+ }
+
+ /**
+ * Put the current segment into the array, and return the segment type.
+ *
+ * @param coords an array of 6 elements
+ * @return the segment type
+ * @throws NullPointerException if coords is null
+ * @throws ArrayIndexOutOfBoundsException if coords is too small
+ */
+ public int currentSegment(float[] coords)
+ {
+ double[] double_coords = new double[6];
+ int code = currentSegment(double_coords);
+ for (int i = 0; i < 6; ++i)
+ coords[i] = (float) double_coords[i];
+ return code;
+ }
+
+ /**
+ * Put the current segment into the array, and return the segment type.
+ *
+ * @param coords an array of 6 elements
+ * @return the segment type
+ * @throws NullPointerException if coords is null
+ * @throws ArrayIndexOutOfBoundsException if coords is too small
+ */
+ public int currentSegment(double[] coords)
+ {
+ double rx = w / 2;
+ double ry = h / 2;
+ double xmid = x + rx;
+ double ymid = y + ry;
+
+ if (current > limit)
+ throw new NoSuchElementException("arc iterator out of bounds");
+
+ if (current == 0)
+ {
+ coords[0] = xmid + rx * Math.cos(start);
+ coords[1] = ymid - ry * Math.sin(start);
+ if (xform != null)
+ xform.transform(coords, 0, coords, 0, 1);
+ return SEG_MOVETO;
+ }
+
+ if (type != OPEN && current == limit)
+ return SEG_CLOSE;
+
+ if ((current == limit - 1) && (type == PIE))
+ {
+ coords[0] = xmid;
+ coords[1] = ymid;
+ if (xform != null)
+ xform.transform(coords, 0, coords, 0, 1);
+ return SEG_LINETO;
+ }
+
+ // note that this produces a cubic approximation of the arc segment,
+ // not a true ellipsoid. there's no ellipsoid path segment code,
+ // unfortunately. the cubic approximation looks about right, though.
+ double kappa = (Math.sqrt(2.0) - 1.0) * (4.0 / 3.0);
+ double quad = (Math.PI / 2.0);
+
+ double curr_begin = start + (current - 1) * quad;
+ double curr_extent = Math.min((start + extent) - curr_begin, quad);
+ double portion_of_a_quadrant = curr_extent / quad;
+
+ double x0 = xmid + rx * Math.cos(curr_begin);
+ double y0 = ymid - ry * Math.sin(curr_begin);
+
+ double x1 = xmid + rx * Math.cos(curr_begin + curr_extent);
+ double y1 = ymid - ry * Math.sin(curr_begin + curr_extent);
+
+ AffineTransform trans = new AffineTransform();
+ double[] cvec = new double[2];
+ double len = kappa * portion_of_a_quadrant;
+ double angle = curr_begin;
+
+ // in a hypothetical "first quadrant" setting, our first control
+ // vector would be sticking up, from [1,0] to [1,kappa].
+ //
+ // let us recall however that in java2d, y coords are upside down
+ // from what one would consider "normal" first quadrant rules, so we
+ // will *subtract* the y value of this control vector from our first
+ // point.
+ cvec[0] = 0;
+ cvec[1] = len;
+ trans.scale(rx, ry);
+ trans.rotate(angle);
+ trans.transform(cvec, 0, cvec, 0, 1);
+ coords[0] = x0 + cvec[0];
+ coords[1] = y0 - cvec[1];
+
+ // control vector #2 would, ideally, be sticking out and to the
+ // right, in a first quadrant arc segment. again, subtraction of y.
+ cvec[0] = 0;
+ cvec[1] = -len;
+ trans.rotate(curr_extent);
+ trans.transform(cvec, 0, cvec, 0, 1);
+ coords[2] = x1 + cvec[0];
+ coords[3] = y1 - cvec[1];
+
+ // end point
+ coords[4] = x1;
+ coords[5] = y1;
+
+ if (xform != null)
+ xform.transform(coords, 0, coords, 0, 3);
+
+ return SEG_CUBICTO;
+ }
+ } // class ArcIterator
+
+ /**
+ * This class implements an arc in double precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ */
+ public static class Double extends Arc2D
+ {
+ /** The x coordinate of the box bounding the ellipse of this arc. */
+ public double x;
+
+ /** The y coordinate of the box bounding the ellipse of this arc. */
+ public double y;
+
+ /** The width of the box bounding the ellipse of this arc. */
+ public double width;
+
+ /** The height of the box bounding the ellipse of this arc. */
+ public double height;
+
+ /** The start angle of this arc, in degrees. */
+ public double start;
+
+ /** The extent angle of this arc, in degrees. */
+ public double extent;
+
+ /**
+ * Create a new, open arc at (0,0) with 0 extent.
+ */
+ public Double()
+ {
+ super(OPEN);
+ }
+
+ /**
+ * Create a new arc of the given type at (0,0) with 0 extent.
+ *
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public Double(int type)
+ {
+ super(type);
+ }
+
+ /**
+ * Create a new arc with the given dimensions.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public Double(double x, double y, double w, double h, double start,
+ double extent, int type)
+ {
+ super(type);
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ this.start = start;
+ this.extent = extent;
+ }
+
+ /**
+ * Create a new arc with the given dimensions.
+ *
+ * @param r the bounding box
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @throws NullPointerException if r is null
+ */
+ public Double(Rectangle2D r, double start, double extent, int type)
+ {
+ super(type);
+ x = r.getX();
+ y = r.getY();
+ width = r.getWidth();
+ height = r.getHeight();
+ this.start = start;
+ this.extent = extent;
+ }
+
+ /**
+ * Return the x coordinate of the bounding box.
+ *
+ * @return the value of x
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the y coordinate of the bounding box.
+ *
+ * @return the value of y
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Return the width of the bounding box.
+ *
+ * @return the value of width
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Return the height of the bounding box.
+ *
+ * @return the value of height
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Return the start angle of the arc, in degrees.
+ *
+ * @return the value of start
+ */
+ public double getAngleStart()
+ {
+ return start;
+ }
+
+ /**
+ * Return the extent of the arc, in degrees.
+ *
+ * @return the value of extent
+ */
+ public double getAngleExtent()
+ {
+ return extent;
+ }
+
+ /**
+ * Tests if the arc contains points.
+ *
+ * @return true if the arc has no interior
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Sets the arc to the given dimensions.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public void setArc(double x, double y, double w, double h, double start,
+ double extent, int type)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ this.start = start;
+ this.extent = extent;
+ setArcType(type);
+ }
+
+ /**
+ * Sets the start angle of the arc.
+ *
+ * @param start the new start angle
+ */
+ public void setAngleStart(double start)
+ {
+ this.start = start;
+ }
+
+ /**
+ * Sets the extent angle of the arc.
+ *
+ * @param extent the new extent angle
+ */
+ public void setAngleExtent(double extent)
+ {
+ this.extent = extent;
+ }
+
+ /**
+ * Creates a tight bounding box given dimensions that more precise than
+ * the bounding box of the ellipse.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ protected Rectangle2D makeBounds(double x, double y, double w, double h)
+ {
+ return new Rectangle2D.Double(x, y, w, h);
+ }
+ } // class Double
+
+ /**
+ * This class implements an arc in float precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ */
+ public static class Float extends Arc2D
+ {
+ /** The x coordinate of the box bounding the ellipse of this arc. */
+ public float x;
+
+ /** The y coordinate of the box bounding the ellipse of this arc. */
+ public float y;
+
+ /** The width of the box bounding the ellipse of this arc. */
+ public float width;
+
+ /** The height of the box bounding the ellipse of this arc. */
+ public float height;
+
+ /** The start angle of this arc, in degrees. */
+ public float start;
+
+ /** The extent angle of this arc, in degrees. */
+ public float extent;
+
+ /**
+ * Create a new, open arc at (0,0) with 0 extent.
+ */
+ public Float()
+ {
+ super(OPEN);
+ }
+
+ /**
+ * Create a new arc of the given type at (0,0) with 0 extent.
+ *
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public Float(int type)
+ {
+ super(type);
+ }
+
+ /**
+ * Create a new arc with the given dimensions.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public Float(float x, float y, float w, float h, float start,
+ float extent, int type)
+ {
+ super(type);
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ this.start = start;
+ this.extent = extent;
+ }
+
+ /**
+ * Create a new arc with the given dimensions.
+ *
+ * @param r the bounding box
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @throws NullPointerException if r is null
+ */
+ public Float(Rectangle2D r, float start, float extent, int type)
+ {
+ super(type);
+ x = (float) r.getX();
+ y = (float) r.getY();
+ width = (float) r.getWidth();
+ height = (float) r.getHeight();
+ this.start = start;
+ this.extent = (float) extent;
+ }
+
+ /**
+ * Return the x coordinate of the bounding box.
+ *
+ * @return the value of x
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the y coordinate of the bounding box.
+ *
+ * @return the value of y
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Return the width of the bounding box.
+ *
+ * @return the value of width
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Return the height of the bounding box.
+ *
+ * @return the value of height
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Return the start angle of the arc, in degrees.
+ *
+ * @return the value of start
+ */
+ public double getAngleStart()
+ {
+ return start;
+ }
+
+ /**
+ * Return the extent of the arc, in degrees.
+ *
+ * @return the value of extent
+ */
+ public double getAngleExtent()
+ {
+ return extent;
+ }
+
+ /**
+ * Tests if the arc contains points.
+ *
+ * @return true if the arc has no interior
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Sets the arc to the given dimensions.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public void setArc(double x, double y, double w, double h, double start,
+ double extent, int type)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ width = (float) w;
+ height = (float) h;
+ this.start = (float) start;
+ this.extent = (float) extent;
+ setArcType(type);
+ }
+
+ /**
+ * Sets the start angle of the arc.
+ *
+ * @param start the new start angle
+ */
+ public void setAngleStart(double start)
+ {
+ this.start = (float) start;
+ }
+
+ /**
+ * Sets the extent angle of the arc.
+ *
+ * @param extent the new extent angle
+ */
+ public void setAngleExtent(double extent)
+ {
+ this.extent = (float) extent;
+ }
+
+ /**
+ * Creates a tight bounding box given dimensions that more precise than
+ * the bounding box of the ellipse.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ protected Rectangle2D makeBounds(double x, double y, double w, double h)
+ {
+ return new Rectangle2D.Float((float) x, (float) y, (float) w, (float) h);
+ }
+ } // class Float
+} // class Arc2D
diff --git a/libjava/classpath/java/awt/geom/Area.java b/libjava/classpath/java/awt/geom/Area.java
new file mode 100644
index 00000000000..7a0fac43a34
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Area.java
@@ -0,0 +1,3312 @@
+/* Area.java -- represents a shape built by constructive area geometry
+ Copyright (C) 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.Vector;
+
+
+/**
+ * The Area class represents any area for the purpose of
+ * Constructive Area Geometry (CAG) manipulations. CAG manipulations
+ * work as an area-wise form of boolean logic, where the basic operations are:
+ * <P><li>Add (in boolean algebra: A <B>or</B> B)<BR>
+ * <li>Subtract (in boolean algebra: A <B>and</B> (<B>not</B> B) )<BR>
+ * <li>Intersect (in boolean algebra: A <B>and</B> B)<BR>
+ * <li>Exclusive Or <BR>
+ * <img src="doc-files/Area-1.png" width="342" height="302"
+ * alt="Illustration of CAG operations" /><BR>
+ * Above is an illustration of the CAG operations on two ring shapes.<P>
+ *
+ * The contains and intersects() methods are also more accurate than the
+ * specification of #Shape requires.<P>
+ *
+ * Please note that constructing an Area can be slow
+ * (Self-intersection resolving is proportional to the square of
+ * the number of segments).<P>
+ * @see #add(Area)
+ * @see #subtract(Area)
+ * @see #intersect(Area)
+ * @see #exclusiveOr(Area)
+ *
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
+ * @status Works, but could be faster and more reliable.
+ */
+public class Area implements Shape, Cloneable
+{
+ /**
+ * General numerical precision
+ */
+ private static final double EPSILON = 1E-11;
+
+ /**
+ * recursive subdivision epsilon - (see getRecursionDepth)
+ */
+ private static final double RS_EPSILON = 1E-13;
+
+ /**
+ * Snap distance - points within this distance are considered equal
+ */
+ private static final double PE_EPSILON = 1E-11;
+
+ /**
+ * Segment vectors containing solid areas and holes
+ * This is package-private to avoid an accessor method.
+ */
+ Vector solids;
+
+ /**
+ * Segment vectors containing solid areas and holes
+ * This is package-private to avoid an accessor method.
+ */
+ Vector holes;
+
+ /**
+ * Vector (temporary) storing curve-curve intersections
+ */
+ private Vector cc_intersections;
+
+ /**
+ * Winding rule WIND_NON_ZERO used, after construction,
+ * this is irrelevant.
+ */
+ private int windingRule;
+
+ /**
+ * Constructs an empty Area
+ */
+ public Area()
+ {
+ solids = new Vector();
+ holes = new Vector();
+ }
+
+ /**
+ * Constructs an Area from any given Shape. <P>
+ *
+ * If the Shape is self-intersecting, the created Area will consist
+ * of non-self-intersecting subpaths, and any inner paths which
+ * are found redundant in accordance with the Shape's winding rule
+ * will not be included.
+ *
+ * @param s the shape (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>s</code> is <code>null</code>.
+ */
+ public Area(Shape s)
+ {
+ this();
+
+ Vector p = makeSegment(s);
+
+ // empty path
+ if (p == null)
+ return;
+
+ // delete empty paths
+ for (int i = 0; i < p.size(); i++)
+ if (((Segment) p.elementAt(i)).getSignedArea() == 0.0)
+ p.remove(i--);
+
+ /*
+ * Resolve self intersecting paths into non-intersecting
+ * solids and holes.
+ * Algorithm is as follows:
+ * 1: Create nodes at all self intersections
+ * 2: Put all segments into a list
+ * 3: Grab a segment, follow it, change direction at each node,
+ * removing segments from the list in the process
+ * 4: Repeat (3) until no segments remain in the list
+ * 5: Remove redundant paths and sort into solids and holes
+ */
+ Vector paths = new Vector();
+ Segment v;
+
+ for (int i = 0; i < p.size(); i++)
+ {
+ Segment path = (Segment) p.elementAt(i);
+ createNodesSelf(path);
+ }
+
+ if (p.size() > 1)
+ {
+ for (int i = 0; i < p.size() - 1; i++)
+ for (int j = i + 1; j < p.size(); j++)
+ {
+ Segment path1 = (Segment) p.elementAt(i);
+ Segment path2 = (Segment) p.elementAt(j);
+ createNodes(path1, path2);
+ }
+ }
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ for (int i = 0; i < p.size(); i++)
+ {
+ Segment path = v = (Segment) p.elementAt(i);
+ do
+ {
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Performs an add (union) operation on this area with another Area.<BR>
+ * @param area - the area to be unioned with this one
+ */
+ public void add(Area area)
+ {
+ if (equals(area))
+ return;
+ if (area.isEmpty())
+ return;
+
+ Area B = (Area) area.clone();
+
+ Vector pathA = new Vector();
+ Vector pathB = new Vector();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+ pathB.addAll(B.solids);
+ pathB.addAll(B.holes);
+
+ int nNodes = 0;
+
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment a = (Segment) pathA.elementAt(i);
+ for (int j = 0; j < pathB.size(); j++)
+ {
+ Segment b = (Segment) pathB.elementAt(j);
+ nNodes += createNodes(a, b);
+ }
+ }
+
+ Vector paths = new Vector();
+ Segment v;
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ // In a union operation, we keep all
+ // segments of A oustide B and all B outside A
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ v = (Segment) pathA.elementAt(i);
+ Segment path = v;
+ do
+ {
+ if (v.isSegmentOutside(area))
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ for (int i = 0; i < pathB.size(); i++)
+ {
+ v = (Segment) pathB.elementAt(i);
+ Segment path = v;
+ do
+ {
+ if (v.isSegmentOutside(this))
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Performs a subtraction operation on this Area.<BR>
+ * @param area the area to be subtracted from this area.
+ * @throws NullPointerException if <code>area</code> is <code>null</code>.
+ */
+ public void subtract(Area area)
+ {
+ if (isEmpty() || area.isEmpty())
+ return;
+
+ if (equals(area))
+ {
+ reset();
+ return;
+ }
+
+ Vector pathA = new Vector();
+ Area B = (Area) area.clone();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+
+ // reverse the directions of B paths.
+ setDirection(B.holes, true);
+ setDirection(B.solids, false);
+
+ Vector pathB = new Vector();
+ pathB.addAll(B.solids);
+ pathB.addAll(B.holes);
+
+ int nNodes = 0;
+
+ // create nodes
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment a = (Segment) pathA.elementAt(i);
+ for (int j = 0; j < pathB.size(); j++)
+ {
+ Segment b = (Segment) pathB.elementAt(j);
+ nNodes += createNodes(a, b);
+ }
+ }
+
+ Vector paths = new Vector();
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ // In a subtraction operation, we keep all
+ // segments of A oustide B and all B within A
+ // We outsideness-test only one segment in each path
+ // and the segments before and after any node
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment v = (Segment) pathA.elementAt(i);
+ Segment path = v;
+ if (v.isSegmentOutside(area) && v.node == null)
+ segments.add(v);
+ boolean node = false;
+ do
+ {
+ if ((v.node != null || node))
+ {
+ node = (v.node != null);
+ if (v.isSegmentOutside(area))
+ segments.add(v);
+ }
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ for (int i = 0; i < pathB.size(); i++)
+ {
+ Segment v = (Segment) pathB.elementAt(i);
+ Segment path = v;
+ if (! v.isSegmentOutside(this) && v.node == null)
+ segments.add(v);
+ v = v.next;
+ boolean node = false;
+ do
+ {
+ if ((v.node != null || node))
+ {
+ node = (v.node != null);
+ if (! v.isSegmentOutside(this))
+ segments.add(v);
+ }
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Performs an intersection operation on this Area.<BR>
+ * @param area - the area to be intersected with this area.
+ * @throws NullPointerException if <code>area</code> is <code>null</code>.
+ */
+ public void intersect(Area area)
+ {
+ if (isEmpty() || area.isEmpty())
+ {
+ reset();
+ return;
+ }
+ if (equals(area))
+ return;
+
+ Vector pathA = new Vector();
+ Area B = (Area) area.clone();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+
+ Vector pathB = new Vector();
+ pathB.addAll(B.solids);
+ pathB.addAll(B.holes);
+
+ int nNodes = 0;
+
+ // create nodes
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment a = (Segment) pathA.elementAt(i);
+ for (int j = 0; j < pathB.size(); j++)
+ {
+ Segment b = (Segment) pathB.elementAt(j);
+ nNodes += createNodes(a, b);
+ }
+ }
+
+ Vector paths = new Vector();
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ // In an intersection operation, we keep all
+ // segments of A within B and all B within A
+ // (The rest must be redundant)
+ // We outsideness-test only one segment in each path
+ // and the segments before and after any node
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment v = (Segment) pathA.elementAt(i);
+ Segment path = v;
+ if (! v.isSegmentOutside(area) && v.node == null)
+ segments.add(v);
+ boolean node = false;
+ do
+ {
+ if ((v.node != null || node))
+ {
+ node = (v.node != null);
+ if (! v.isSegmentOutside(area))
+ segments.add(v);
+ }
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ for (int i = 0; i < pathB.size(); i++)
+ {
+ Segment v = (Segment) pathB.elementAt(i);
+ Segment path = v;
+ if (! v.isSegmentOutside(this) && v.node == null)
+ segments.add(v);
+ v = v.next;
+ boolean node = false;
+ do
+ {
+ if ((v.node != null || node))
+ {
+ node = (v.node != null);
+ if (! v.isSegmentOutside(this))
+ segments.add(v);
+ }
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Performs an exclusive-or operation on this Area.<BR>
+ * @param area - the area to be XORed with this area.
+ * @throws NullPointerException if <code>area</code> is <code>null</code>.
+ */
+ public void exclusiveOr(Area area)
+ {
+ if (area.isEmpty())
+ return;
+
+ if (isEmpty())
+ {
+ Area B = (Area) area.clone();
+ solids = B.solids;
+ holes = B.holes;
+ return;
+ }
+ if (equals(area))
+ {
+ reset();
+ return;
+ }
+
+ Vector pathA = new Vector();
+
+ Area B = (Area) area.clone();
+ Vector pathB = new Vector();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+
+ // reverse the directions of B paths.
+ setDirection(B.holes, true);
+ setDirection(B.solids, false);
+ pathB.addAll(B.solids);
+ pathB.addAll(B.holes);
+
+ int nNodes = 0;
+
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment a = (Segment) pathA.elementAt(i);
+ for (int j = 0; j < pathB.size(); j++)
+ {
+ Segment b = (Segment) pathB.elementAt(j);
+ nNodes += createNodes(a, b);
+ }
+ }
+
+ Vector paths = new Vector();
+ Segment v;
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ // In an XOR operation, we operate on all segments
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ v = (Segment) pathA.elementAt(i);
+ Segment path = v;
+ do
+ {
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ for (int i = 0; i < pathB.size(); i++)
+ {
+ v = (Segment) pathB.elementAt(i);
+ Segment path = v;
+ do
+ {
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Clears the Area object, creating an empty area.
+ */
+ public void reset()
+ {
+ solids = new Vector();
+ holes = new Vector();
+ }
+
+ /**
+ * Returns whether this area encloses any area.
+ * @return true if the object encloses any area.
+ */
+ public boolean isEmpty()
+ {
+ if (solids.size() == 0)
+ return true;
+
+ double totalArea = 0;
+ for (int i = 0; i < solids.size(); i++)
+ totalArea += Math.abs(((Segment) solids.elementAt(i)).getSignedArea());
+ for (int i = 0; i < holes.size(); i++)
+ totalArea -= Math.abs(((Segment) holes.elementAt(i)).getSignedArea());
+ if (totalArea <= EPSILON)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether the Area consists entirely of line segments
+ * @return true if the Area lines-only, false otherwise
+ */
+ public boolean isPolygonal()
+ {
+ for (int i = 0; i < holes.size(); i++)
+ if (! ((Segment) holes.elementAt(i)).isPolygonal())
+ return false;
+ for (int i = 0; i < solids.size(); i++)
+ if (! ((Segment) solids.elementAt(i)).isPolygonal())
+ return false;
+ return true;
+ }
+
+ /**
+ * Determines if the Area is rectangular.<P>
+ *
+ * This is strictly qualified. An area is considered rectangular if:<BR>
+ * <li>It consists of a single polygonal path.<BR>
+ * <li>It is oriented parallel/perpendicular to the xy axis<BR>
+ * <li>It must be exactly rectangular, i.e. small errors induced by
+ * transformations may cause a false result, although the area is
+ * visibly rectangular.<P>
+ * @return true if the above criteria are met, false otherwise
+ */
+ public boolean isRectangular()
+ {
+ if (isEmpty())
+ return true;
+
+ if (holes.size() != 0 || solids.size() != 1)
+ return false;
+
+ Segment path = (Segment) solids.elementAt(0);
+ if (! path.isPolygonal())
+ return false;
+
+ int nCorners = 0;
+ Segment s = path;
+ do
+ {
+ Segment s2 = s.next;
+ double d1 = (s.P2.getX() - s.P1.getX())*(s2.P2.getX() - s2.P1.getX())/
+ ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2)));
+ double d2 = (s.P2.getY() - s.P1.getY())*(s2.P2.getY() - s2.P1.getY())/
+ ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2)));
+ double dotproduct = d1 + d2;
+
+ // For some reason, only rectangles on the XY axis count.
+ if (d1 != 0 && d2 != 0)
+ return false;
+
+ if (Math.abs(dotproduct) == 0) // 90 degree angle
+ nCorners++;
+ else if ((Math.abs(1.0 - dotproduct) > 0)) // 0 degree angle?
+ return false; // if not, return false
+
+ s = s.next;
+ }
+ while (s != path);
+
+ return nCorners == 4;
+ }
+
+ /**
+ * Returns whether the Area consists of more than one simple
+ * (non self-intersecting) subpath.
+ *
+ * @return true if the Area consists of none or one simple subpath,
+ * false otherwise.
+ */
+ public boolean isSingular()
+ {
+ return (holes.size() == 0 && solids.size() <= 1);
+ }
+
+ /**
+ * Returns the bounding box of the Area.<P> Unlike the CubicCurve2D and
+ * QuadraticCurve2D classes, this method will return the tightest possible
+ * bounding box, evaluating the extreme points of each curved segment.<P>
+ * @return the bounding box
+ */
+ public Rectangle2D getBounds2D()
+ {
+ if (solids.size() == 0)
+ return new Rectangle2D.Double(0.0, 0.0, 0.0, 0.0);
+
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+ xmin = xmax = ((Segment) solids.elementAt(0)).P1.getX();
+ ymin = ymax = ((Segment) solids.elementAt(0)).P1.getY();
+
+ for (int path = 0; path < solids.size(); path++)
+ {
+ Rectangle2D r = ((Segment) solids.elementAt(path)).getPathBounds();
+ xmin = Math.min(r.getMinX(), xmin);
+ ymin = Math.min(r.getMinY(), ymin);
+ xmax = Math.max(r.getMaxX(), xmax);
+ ymax = Math.max(r.getMaxY(), ymax);
+ }
+
+ return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
+ }
+
+ /**
+ * Returns the bounds of this object in Rectangle format.
+ * Please note that this may lead to loss of precision.
+ *
+ * @return The bounds.
+ * @see #getBounds2D()
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ /**
+ * Create a new area of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ try
+ {
+ Area clone = new Area();
+ for (int i = 0; i < solids.size(); i++)
+ clone.solids.add(((Segment) solids.elementAt(i)).cloneSegmentList());
+ for (int i = 0; i < holes.size(); i++)
+ clone.holes.add(((Segment) holes.elementAt(i)).cloneSegmentList());
+ return clone;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Compares two Areas.
+ *
+ * @param area the area to compare against this area (<code>null</code>
+ * permitted).
+ * @return <code>true</code> if the areas are equal, and <code>false</code>
+ * otherwise.
+ */
+ public boolean equals(Area area)
+ {
+ if (area == null)
+ return false;
+
+ if (! getBounds2D().equals(area.getBounds2D()))
+ return false;
+
+ if (solids.size() != area.solids.size()
+ || holes.size() != area.holes.size())
+ return false;
+
+ Vector pathA = new Vector();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+ Vector pathB = new Vector();
+ pathB.addAll(area.solids);
+ pathB.addAll(area.holes);
+
+ int nPaths = pathA.size();
+ boolean[][] match = new boolean[2][nPaths];
+
+ for (int i = 0; i < nPaths; i++)
+ {
+ for (int j = 0; j < nPaths; j++)
+ {
+ Segment p1 = (Segment) pathA.elementAt(i);
+ Segment p2 = (Segment) pathB.elementAt(j);
+ if (! match[0][i] && ! match[1][j])
+ if (p1.pathEquals(p2))
+ match[0][i] = match[1][j] = true;
+ }
+ }
+
+ boolean result = true;
+ for (int i = 0; i < nPaths; i++)
+ result = result && match[0][i] && match[1][i];
+ return result;
+ }
+
+ /**
+ * Transforms this area by the AffineTransform at.
+ *
+ * @param at the transform.
+ */
+ public void transform(AffineTransform at)
+ {
+ for (int i = 0; i < solids.size(); i++)
+ ((Segment) solids.elementAt(i)).transformSegmentList(at);
+ for (int i = 0; i < holes.size(); i++)
+ ((Segment) holes.elementAt(i)).transformSegmentList(at);
+
+ // Note that the orientation is not invariant under inversion
+ if ((at.getType() & AffineTransform.TYPE_FLIP) != 0)
+ {
+ setDirection(holes, false);
+ setDirection(solids, true);
+ }
+ }
+
+ /**
+ * Returns a new Area equal to this one, transformed
+ * by the AffineTransform at.
+ * @param at the transform.
+ * @return the transformed area
+ * @throws NullPointerException if <code>at</code> is <code>null</code>.
+ */
+ public Area createTransformedArea(AffineTransform at)
+ {
+ Area a = (Area) clone();
+ a.transform(at);
+ return a;
+ }
+
+ /**
+ * Determines if the point (x,y) is contained within this Area.
+ *
+ * @param x the x-coordinate of the point.
+ * @param y the y-coordinate of the point.
+ * @return true if the point is contained, false otherwise.
+ */
+ public boolean contains(double x, double y)
+ {
+ int n = 0;
+ for (int i = 0; i < solids.size(); i++)
+ if (((Segment) solids.elementAt(i)).contains(x, y))
+ n++;
+
+ for (int i = 0; i < holes.size(); i++)
+ if (((Segment) holes.elementAt(i)).contains(x, y))
+ n--;
+
+ return (n != 0);
+ }
+
+ /**
+ * Determines if the Point2D p is contained within this Area.
+ *
+ * @param p the point.
+ * @return <code>true</code> if the point is contained, <code>false</code>
+ * otherwise.
+ * @throws NullPointerException if <code>p</code> is <code>null</code>.
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Determines if the rectangle specified by (x,y) as the upper-left
+ * and with width w and height h is completely contained within this Area,
+ * returns false otherwise.<P>
+ *
+ * This method should always produce the correct results, unlike for other
+ * classes in geom.
+ *
+ * @param x the x-coordinate of the rectangle.
+ * @param y the y-coordinate of the rectangle.
+ * @param w the width of the the rectangle.
+ * @param h the height of the rectangle.
+ * @return <code>true</code> if the rectangle is considered contained
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ LineSegment[] l = new LineSegment[4];
+ l[0] = new LineSegment(x, y, x + w, y);
+ l[1] = new LineSegment(x, y + h, x + w, y + h);
+ l[2] = new LineSegment(x, y, x, y + h);
+ l[3] = new LineSegment(x + w, y, x + w, y + h);
+
+ // Since every segment in the area must a contour
+ // between inside/outside segments, ANY intersection
+ // will mean the rectangle is not entirely contained.
+ for (int i = 0; i < 4; i++)
+ {
+ for (int path = 0; path < solids.size(); path++)
+ {
+ Segment v;
+ Segment start;
+ start = v = (Segment) solids.elementAt(path);
+ do
+ {
+ if (l[i].hasIntersections(v))
+ return false;
+ v = v.next;
+ }
+ while (v != start);
+ }
+ for (int path = 0; path < holes.size(); path++)
+ {
+ Segment v;
+ Segment start;
+ start = v = (Segment) holes.elementAt(path);
+ do
+ {
+ if (l[i].hasIntersections(v))
+ return false;
+ v = v.next;
+ }
+ while (v != start);
+ }
+ }
+
+ // Is any point inside?
+ if (! contains(x, y))
+ return false;
+
+ // Final hoop: Is the rectangle non-intersecting and inside,
+ // but encloses a hole?
+ Rectangle2D r = new Rectangle2D.Double(x, y, w, h);
+ for (int path = 0; path < holes.size(); path++)
+ if (! ((Segment) holes.elementAt(path)).isSegmentOutside(r))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Determines if the Rectangle2D specified by r is completely contained
+ * within this Area, returns false otherwise.<P>
+ *
+ * This method should always produce the correct results, unlike for other
+ * classes in geom.
+ *
+ * @param r the rectangle.
+ * @return <code>true</code> if the rectangle is considered contained
+ *
+ * @throws NullPointerException if <code>r</code> is <code>null</code>.
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determines if the rectangle specified by (x,y) as the upper-left
+ * and with width w and height h intersects any part of this Area.
+ *
+ * @param x the x-coordinate for the rectangle.
+ * @param y the y-coordinate for the rectangle.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @return <code>true</code> if the rectangle intersects the area,
+ * <code>false</code> otherwise.
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (solids.size() == 0)
+ return false;
+
+ LineSegment[] l = new LineSegment[4];
+ l[0] = new LineSegment(x, y, x + w, y);
+ l[1] = new LineSegment(x, y + h, x + w, y + h);
+ l[2] = new LineSegment(x, y, x, y + h);
+ l[3] = new LineSegment(x + w, y, x + w, y + h);
+
+ // Return true on any intersection
+ for (int i = 0; i < 4; i++)
+ {
+ for (int path = 0; path < solids.size(); path++)
+ {
+ Segment v;
+ Segment start;
+ start = v = (Segment) solids.elementAt(path);
+ do
+ {
+ if (l[i].hasIntersections(v))
+ return true;
+ v = v.next;
+ }
+ while (v != start);
+ }
+ for (int path = 0; path < holes.size(); path++)
+ {
+ Segment v;
+ Segment start;
+ start = v = (Segment) holes.elementAt(path);
+ do
+ {
+ if (l[i].hasIntersections(v))
+ return true;
+ v = v.next;
+ }
+ while (v != start);
+ }
+ }
+
+ // Non-intersecting, Is any point inside?
+ if (contains(x + w * 0.5, y + h * 0.5))
+ return true;
+
+ // What if the rectangle encloses the whole shape?
+ Point2D p = ((Segment) solids.elementAt(0)).getMidPoint();
+ if ((new Rectangle2D.Double(x, y, w, h)).contains(p))
+ return true;
+ return false;
+ }
+
+ /**
+ * Determines if the Rectangle2D specified by r intersects any
+ * part of this Area.
+ * @param r the rectangle to test intersection with (<code>null</code>
+ * not permitted).
+ * @return <code>true</code> if the rectangle intersects the area,
+ * <code>false</code> otherwise.
+ * @throws NullPointerException if <code>r</code> is <code>null</code>.
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Returns a PathIterator object defining the contour of this Area,
+ * transformed by at.
+ *
+ * @param at the transform.
+ * @return A path iterator.
+ */
+ public PathIterator getPathIterator(AffineTransform at)
+ {
+ return (new AreaIterator(at));
+ }
+
+ /**
+ * Returns a flattened PathIterator object defining the contour of this
+ * Area, transformed by at and with a defined flatness.
+ *
+ * @param at the transform.
+ * @param flatness the flatness.
+ * @return A path iterator.
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ //---------------------------------------------------------------------
+ // Non-public methods and classes
+
+ /**
+ * Private pathiterator object.
+ */
+ private class AreaIterator implements PathIterator
+ {
+ private Vector segments;
+ private int index;
+ private AffineTransform at;
+
+ // Simple compound type for segments
+ class IteratorSegment
+ {
+ int type;
+ double[] coords;
+
+ IteratorSegment()
+ {
+ coords = new double[6];
+ }
+ }
+
+ /**
+ * The contructor here does most of the work,
+ * creates a vector of IteratorSegments, which can
+ * readily be returned
+ */
+ public AreaIterator(AffineTransform at)
+ {
+ this.at = at;
+ index = 0;
+ segments = new Vector();
+ Vector allpaths = new Vector();
+ allpaths.addAll(solids);
+ allpaths.addAll(holes);
+
+ for (int i = 0; i < allpaths.size(); i++)
+ {
+ Segment v = (Segment) allpaths.elementAt(i);
+ Segment start = v;
+
+ IteratorSegment is = new IteratorSegment();
+ is.type = SEG_MOVETO;
+ is.coords[0] = start.P1.getX();
+ is.coords[1] = start.P1.getY();
+ segments.add(is);
+
+ do
+ {
+ is = new IteratorSegment();
+ is.type = v.pathIteratorFormat(is.coords);
+ segments.add(is);
+ v = v.next;
+ }
+ while (v != start);
+
+ is = new IteratorSegment();
+ is.type = SEG_CLOSE;
+ segments.add(is);
+ }
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ IteratorSegment s = (IteratorSegment) segments.elementAt(index);
+ if (at != null)
+ at.transform(s.coords, 0, coords, 0, 3);
+ else
+ for (int i = 0; i < 6; i++)
+ coords[i] = s.coords[i];
+ return (s.type);
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ IteratorSegment s = (IteratorSegment) segments.elementAt(index);
+ double[] d = new double[6];
+ if (at != null)
+ {
+ at.transform(s.coords, 0, d, 0, 3);
+ for (int i = 0; i < 6; i++)
+ coords[i] = (float) d[i];
+ }
+ else
+ for (int i = 0; i < 6; i++)
+ coords[i] = (float) s.coords[i];
+ return (s.type);
+ }
+
+ // Note that the winding rule should not matter here,
+ // EVEN_ODD is chosen because it renders faster.
+ public int getWindingRule()
+ {
+ return (PathIterator.WIND_EVEN_ODD);
+ }
+
+ public boolean isDone()
+ {
+ return (index >= segments.size());
+ }
+
+ public void next()
+ {
+ index++;
+ }
+ }
+
+ /**
+ * Performs the fundamental task of the Weiler-Atherton algorithm,
+ * traverse a list of segments, for each segment:
+ * Follow it, removing segments from the list and switching paths
+ * at each node. Do so until the starting segment is reached.
+ *
+ * Returns a Vector of the resulting paths.
+ */
+ private Vector weilerAtherton(Vector segments)
+ {
+ Vector paths = new Vector();
+ while (segments.size() > 0)
+ {
+ // Iterate over the path
+ Segment start = (Segment) segments.elementAt(0);
+ Segment s = start;
+ do
+ {
+ segments.remove(s);
+ if (s.node != null)
+ { // switch over
+ s.next = s.node;
+ s.node = null;
+ }
+ s = s.next; // continue
+ }
+ while (s != start);
+
+ paths.add(start);
+ }
+ return paths;
+ }
+
+ /**
+ * A small wrapper class to store intersection points
+ */
+ private class Intersection
+ {
+ Point2D p; // the 2D point of intersection
+ double ta; // the parametric value on a
+ double tb; // the parametric value on b
+ Segment seg; // segment placeholder for node setting
+
+ public Intersection(Point2D p, double ta, double tb)
+ {
+ this.p = p;
+ this.ta = ta;
+ this.tb = tb;
+ }
+ }
+
+ /**
+ * Returns the recursion depth necessary to approximate the
+ * curve by line segments within the error RS_EPSILON.
+ *
+ * This is done with Wang's formula:
+ * L0 = max{0<=i<=N-2}(|xi - 2xi+1 + xi+2|,|yi - 2yi+1 + yi+2|)
+ * r0 = log4(sqrt(2)*N*(N-1)*L0/8e)
+ * Where e is the maximum distance error (RS_EPSILON)
+ */
+ private int getRecursionDepth(CubicSegment curve)
+ {
+ double x0 = curve.P1.getX();
+ double y0 = curve.P1.getY();
+
+ double x1 = curve.cp1.getX();
+ double y1 = curve.cp1.getY();
+
+ double x2 = curve.cp2.getX();
+ double y2 = curve.cp2.getY();
+
+ double x3 = curve.P2.getX();
+ double y3 = curve.P2.getY();
+
+ double L0 = Math.max(Math.max(Math.abs(x0 - 2 * x1 + x2),
+ Math.abs(x1 - 2 * x2 + x3)),
+ Math.max(Math.abs(y0 - 2 * y1 + y2),
+ Math.abs(y1 - 2 * y2 + y3)));
+
+ double f = Math.sqrt(2) * 6.0 * L0 / (8.0 * RS_EPSILON);
+
+ int r0 = (int) Math.ceil(Math.log(f) / Math.log(4.0));
+ return (r0);
+ }
+
+ /**
+ * Performs recursive subdivision:
+ * @param c1 - curve 1
+ * @param c2 - curve 2
+ * @param depth1 - recursion depth of curve 1
+ * @param depth2 - recursion depth of curve 2
+ * @param t1 - global parametric value of the first curve's starting point
+ * @param t2 - global parametric value of the second curve's starting point
+ * @param w1 - global parametric length of curve 1
+ * @param c1 - global parametric length of curve 2
+ *
+ * The final four parameters are for keeping track of the parametric
+ * value of the curve. For a full curve t = 0, w = 1, w is halved with
+ * each subdivision.
+ */
+ private void recursiveSubdivide(CubicCurve2D c1, CubicCurve2D c2,
+ int depth1, int depth2, double t1,
+ double t2, double w1, double w2)
+ {
+ boolean flat1 = depth1 <= 0;
+ boolean flat2 = depth2 <= 0;
+
+ if (flat1 && flat2)
+ {
+ double xlk = c1.getP2().getX() - c1.getP1().getX();
+ double ylk = c1.getP2().getY() - c1.getP1().getY();
+
+ double xnm = c2.getP2().getX() - c2.getP1().getX();
+ double ynm = c2.getP2().getY() - c2.getP1().getY();
+
+ double xmk = c2.getP1().getX() - c1.getP1().getX();
+ double ymk = c2.getP1().getY() - c1.getP1().getY();
+ double det = xnm * ylk - ynm * xlk;
+
+ if (det + 1.0 == 1.0)
+ return;
+
+ double detinv = 1.0 / det;
+ double s = (xnm * ymk - ynm * xmk) * detinv;
+ double t = (xlk * ymk - ylk * xmk) * detinv;
+ if ((s < 0.0) || (s > 1.0) || (t < 0.0) || (t > 1.0))
+ return;
+
+ double[] temp = new double[2];
+ temp[0] = t1 + s * w1;
+ temp[1] = t2 + t * w1;
+ cc_intersections.add(temp);
+ return;
+ }
+
+ CubicCurve2D.Double c11 = new CubicCurve2D.Double();
+ CubicCurve2D.Double c12 = new CubicCurve2D.Double();
+ CubicCurve2D.Double c21 = new CubicCurve2D.Double();
+ CubicCurve2D.Double c22 = new CubicCurve2D.Double();
+
+ if (! flat1 && ! flat2)
+ {
+ depth1--;
+ depth2--;
+ w1 = w1 * 0.5;
+ w2 = w2 * 0.5;
+ c1.subdivide(c11, c12);
+ c2.subdivide(c21, c22);
+ if (c11.getBounds2D().intersects(c21.getBounds2D()))
+ recursiveSubdivide(c11, c21, depth1, depth2, t1, t2, w1, w2);
+ if (c11.getBounds2D().intersects(c22.getBounds2D()))
+ recursiveSubdivide(c11, c22, depth1, depth2, t1, t2 + w2, w1, w2);
+ if (c12.getBounds2D().intersects(c21.getBounds2D()))
+ recursiveSubdivide(c12, c21, depth1, depth2, t1 + w1, t2, w1, w2);
+ if (c12.getBounds2D().intersects(c22.getBounds2D()))
+ recursiveSubdivide(c12, c22, depth1, depth2, t1 + w1, t2 + w2, w1, w2);
+ return;
+ }
+
+ if (! flat1)
+ {
+ depth1--;
+ c1.subdivide(c11, c12);
+ w1 = w1 * 0.5;
+ if (c11.getBounds2D().intersects(c2.getBounds2D()))
+ recursiveSubdivide(c11, c2, depth1, depth2, t1, t2, w1, w2);
+ if (c12.getBounds2D().intersects(c2.getBounds2D()))
+ recursiveSubdivide(c12, c2, depth1, depth2, t1 + w1, t2, w1, w2);
+ return;
+ }
+
+ depth2--;
+ c2.subdivide(c21, c22);
+ w2 = w2 * 0.5;
+ if (c1.getBounds2D().intersects(c21.getBounds2D()))
+ recursiveSubdivide(c1, c21, depth1, depth2, t1, t2, w1, w2);
+ if (c1.getBounds2D().intersects(c22.getBounds2D()))
+ recursiveSubdivide(c1, c22, depth1, depth2, t1, t2 + w2, w1, w2);
+ }
+
+ /**
+ * Returns a set of interesections between two Cubic segments
+ * Or null if no intersections were found.
+ *
+ * The method used to find the intersection is recursive midpoint
+ * subdivision. Outline description:
+ *
+ * 1) Check if the bounding boxes of the curves intersect,
+ * 2) If so, divide the curves in the middle and test the bounding
+ * boxes again,
+ * 3) Repeat until a maximum recursion depth has been reached, where
+ * the intersecting curves can be approximated by line segments.
+ *
+ * This is a reasonably accurate method, although the recursion depth
+ * is typically around 20, the bounding-box tests allow for significant
+ * pruning of the subdivision tree.
+ *
+ * This is package-private to avoid an accessor method.
+ */
+ Intersection[] cubicCubicIntersect(CubicSegment curve1, CubicSegment curve2)
+ {
+ Rectangle2D r1 = curve1.getBounds();
+ Rectangle2D r2 = curve2.getBounds();
+
+ if (! r1.intersects(r2))
+ return null;
+
+ cc_intersections = new Vector();
+ recursiveSubdivide(curve1.getCubicCurve2D(), curve2.getCubicCurve2D(),
+ getRecursionDepth(curve1), getRecursionDepth(curve2),
+ 0.0, 0.0, 1.0, 1.0);
+
+ if (cc_intersections.size() == 0)
+ return null;
+
+ Intersection[] results = new Intersection[cc_intersections.size()];
+ for (int i = 0; i < cc_intersections.size(); i++)
+ {
+ double[] temp = (double[]) cc_intersections.elementAt(i);
+ results[i] = new Intersection(curve1.evaluatePoint(temp[0]), temp[0],
+ temp[1]);
+ }
+ cc_intersections = null;
+ return (results);
+ }
+
+ /**
+ * Returns the intersections between a line and a quadratic bezier
+ * Or null if no intersections are found1
+ * This is done through combining the line's equation with the
+ * parametric form of the Bezier and solving the resulting quadratic.
+ * This is package-private to avoid an accessor method.
+ */
+ Intersection[] lineQuadIntersect(LineSegment l, QuadSegment c)
+ {
+ double[] y = new double[3];
+ double[] x = new double[3];
+ double[] r = new double[3];
+ int nRoots;
+ double x0 = c.P1.getX();
+ double y0 = c.P1.getY();
+ double x1 = c.cp.getX();
+ double y1 = c.cp.getY();
+ double x2 = c.P2.getX();
+ double y2 = c.P2.getY();
+
+ double lx0 = l.P1.getX();
+ double ly0 = l.P1.getY();
+ double lx1 = l.P2.getX();
+ double ly1 = l.P2.getY();
+ double dx = lx1 - lx0;
+ double dy = ly1 - ly0;
+
+ // form r(t) = y(t) - x(t) for the bezier
+ y[0] = y0;
+ y[1] = 2 * (y1 - y0);
+ y[2] = (y2 - 2 * y1 + y0);
+
+ x[0] = x0;
+ x[1] = 2 * (x1 - x0);
+ x[2] = (x2 - 2 * x1 + x0);
+
+ // a point, not a line
+ if (dy == 0 && dx == 0)
+ return null;
+
+ // line on y axis
+ if (dx == 0 || (dy / dx) > 1.0)
+ {
+ double k = dx / dy;
+ x[0] -= lx0;
+ y[0] -= ly0;
+ y[0] *= k;
+ y[1] *= k;
+ y[2] *= k;
+ }
+ else
+ {
+ double k = dy / dx;
+ x[0] -= lx0;
+ y[0] -= ly0;
+ x[0] *= k;
+ x[1] *= k;
+ x[2] *= k;
+ }
+
+ for (int i = 0; i < 3; i++)
+ r[i] = y[i] - x[i];
+
+ if ((nRoots = QuadCurve2D.solveQuadratic(r)) > 0)
+ {
+ Intersection[] temp = new Intersection[nRoots];
+ int intersections = 0;
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ Point2D p = c.evaluatePoint(t);
+
+ // if the line is on an axis, snap the point to that axis.
+ if (dx == 0)
+ p.setLocation(lx0, p.getY());
+ if (dy == 0)
+ p.setLocation(p.getX(), ly0);
+
+ if (p.getX() <= Math.max(lx0, lx1)
+ && p.getX() >= Math.min(lx0, lx1)
+ && p.getY() <= Math.max(ly0, ly1)
+ && p.getY() >= Math.min(ly0, ly1))
+ {
+ double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1);
+ temp[i] = new Intersection(p, lineparameter, t);
+ intersections++;
+ }
+ }
+ else
+ temp[i] = null;
+ }
+ if (intersections == 0)
+ return null;
+
+ Intersection[] rValues = new Intersection[intersections];
+
+ for (int i = 0; i < nRoots; i++)
+ if (temp[i] != null)
+ rValues[--intersections] = temp[i];
+ return (rValues);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the intersections between a line and a cubic segment
+ * This is done through combining the line's equation with the
+ * parametric form of the Bezier and solving the resulting quadratic.
+ * This is package-private to avoid an accessor method.
+ */
+ Intersection[] lineCubicIntersect(LineSegment l, CubicSegment c)
+ {
+ double[] y = new double[4];
+ double[] x = new double[4];
+ double[] r = new double[4];
+ int nRoots;
+ double x0 = c.P1.getX();
+ double y0 = c.P1.getY();
+ double x1 = c.cp1.getX();
+ double y1 = c.cp1.getY();
+ double x2 = c.cp2.getX();
+ double y2 = c.cp2.getY();
+ double x3 = c.P2.getX();
+ double y3 = c.P2.getY();
+
+ double lx0 = l.P1.getX();
+ double ly0 = l.P1.getY();
+ double lx1 = l.P2.getX();
+ double ly1 = l.P2.getY();
+ double dx = lx1 - lx0;
+ double dy = ly1 - ly0;
+
+ // form r(t) = y(t) - x(t) for the bezier
+ y[0] = y0;
+ y[1] = 3 * (y1 - y0);
+ y[2] = 3 * (y2 + y0 - 2 * y1);
+ y[3] = y3 - 3 * y2 + 3 * y1 - y0;
+
+ x[0] = x0;
+ x[1] = 3 * (x1 - x0);
+ x[2] = 3 * (x2 + x0 - 2 * x1);
+ x[3] = x3 - 3 * x2 + 3 * x1 - x0;
+
+ // a point, not a line
+ if (dy == 0 && dx == 0)
+ return null;
+
+ // line on y axis
+ if (dx == 0 || (dy / dx) > 1.0)
+ {
+ double k = dx / dy;
+ x[0] -= lx0;
+ y[0] -= ly0;
+ y[0] *= k;
+ y[1] *= k;
+ y[2] *= k;
+ y[3] *= k;
+ }
+ else
+ {
+ double k = dy / dx;
+ x[0] -= lx0;
+ y[0] -= ly0;
+ x[0] *= k;
+ x[1] *= k;
+ x[2] *= k;
+ x[3] *= k;
+ }
+ for (int i = 0; i < 4; i++)
+ r[i] = y[i] - x[i];
+
+ if ((nRoots = CubicCurve2D.solveCubic(r)) > 0)
+ {
+ Intersection[] temp = new Intersection[nRoots];
+ int intersections = 0;
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ // if the line is on an axis, snap the point to that axis.
+ Point2D p = c.evaluatePoint(t);
+ if (dx == 0)
+ p.setLocation(lx0, p.getY());
+ if (dy == 0)
+ p.setLocation(p.getX(), ly0);
+
+ if (p.getX() <= Math.max(lx0, lx1)
+ && p.getX() >= Math.min(lx0, lx1)
+ && p.getY() <= Math.max(ly0, ly1)
+ && p.getY() >= Math.min(ly0, ly1))
+ {
+ double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1);
+ temp[i] = new Intersection(p, lineparameter, t);
+ intersections++;
+ }
+ }
+ else
+ temp[i] = null;
+ }
+
+ if (intersections == 0)
+ return null;
+
+ Intersection[] rValues = new Intersection[intersections];
+ for (int i = 0; i < nRoots; i++)
+ if (temp[i] != null)
+ rValues[--intersections] = temp[i];
+ return (rValues);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the intersection between two lines, or null if there is no
+ * intersection.
+ * This is package-private to avoid an accessor method.
+ */
+ Intersection linesIntersect(LineSegment a, LineSegment b)
+ {
+ Point2D P1 = a.P1;
+ Point2D P2 = a.P2;
+ Point2D P3 = b.P1;
+ Point2D P4 = b.P2;
+
+ if (! Line2D.linesIntersect(P1.getX(), P1.getY(), P2.getX(), P2.getY(),
+ P3.getX(), P3.getY(), P4.getX(), P4.getY()))
+ return null;
+
+ double x1 = P1.getX();
+ double y1 = P1.getY();
+ double rx = P2.getX() - x1;
+ double ry = P2.getY() - y1;
+
+ double x2 = P3.getX();
+ double y2 = P3.getY();
+ double sx = P4.getX() - x2;
+ double sy = P4.getY() - y2;
+
+ double determinant = sx * ry - sy * rx;
+ double nom = (sx * (y2 - y1) + sy * (x1 - x2));
+
+ // Parallel lines don't intersect. At least we pretend they don't.
+ if (Math.abs(determinant) < EPSILON)
+ return null;
+
+ nom = nom / determinant;
+
+ if (nom == 0.0)
+ return null;
+ if (nom == 1.0)
+ return null;
+
+ Point2D p = new Point2D.Double(x1 + nom * rx, y1 + nom * ry);
+
+ return new Intersection(p, p.distance(P1) / P1.distance(P2),
+ p.distance(P3) / P3.distance(P4));
+ }
+
+ /**
+ * Determines if two points are equal, within an error margin
+ * 'snap distance'
+ * This is package-private to avoid an accessor method.
+ */
+ boolean pointEquals(Point2D a, Point2D b)
+ {
+ return (a.equals(b) || a.distance(b) < PE_EPSILON);
+ }
+
+ /**
+ * Helper method
+ * Turns a shape into a Vector of Segments
+ */
+ private Vector makeSegment(Shape s)
+ {
+ Vector paths = new Vector();
+ PathIterator pi = s.getPathIterator(null);
+ double[] coords = new double[6];
+ Segment subpath = null;
+ Segment current = null;
+ double cx;
+ double cy;
+ double subpathx;
+ double subpathy;
+ cx = cy = subpathx = subpathy = 0.0;
+
+ this.windingRule = pi.getWindingRule();
+
+ while (! pi.isDone())
+ {
+ Segment v;
+ switch (pi.currentSegment(coords))
+ {
+ case PathIterator.SEG_MOVETO:
+ if (subpath != null)
+ { // close existing open path
+ current.next = new LineSegment(cx, cy, subpathx, subpathy);
+ current = current.next;
+ current.next = subpath;
+ }
+ subpath = null;
+ subpathx = cx = coords[0];
+ subpathy = cy = coords[1];
+ break;
+
+ // replace 'close' with a line-to.
+ case PathIterator.SEG_CLOSE:
+ if (subpath != null && (subpathx != cx || subpathy != cy))
+ {
+ current.next = new LineSegment(cx, cy, subpathx, subpathy);
+ current = current.next;
+ current.next = subpath;
+ cx = subpathx;
+ cy = subpathy;
+ subpath = null;
+ }
+ else if (subpath != null)
+ {
+ current.next = subpath;
+ subpath = null;
+ }
+ break;
+ case PathIterator.SEG_LINETO:
+ if (cx != coords[0] || cy != coords[1])
+ {
+ v = new LineSegment(cx, cy, coords[0], coords[1]);
+ if (subpath == null)
+ {
+ subpath = current = v;
+ paths.add(subpath);
+ }
+ else
+ {
+ current.next = v;
+ current = current.next;
+ }
+ cx = coords[0];
+ cy = coords[1];
+ }
+ break;
+ case PathIterator.SEG_QUADTO:
+ v = new QuadSegment(cx, cy, coords[0], coords[1], coords[2],
+ coords[3]);
+ if (subpath == null)
+ {
+ subpath = current = v;
+ paths.add(subpath);
+ }
+ else
+ {
+ current.next = v;
+ current = current.next;
+ }
+ cx = coords[2];
+ cy = coords[3];
+ break;
+ case PathIterator.SEG_CUBICTO:
+ v = new CubicSegment(cx, cy, coords[0], coords[1], coords[2],
+ coords[3], coords[4], coords[5]);
+ if (subpath == null)
+ {
+ subpath = current = v;
+ paths.add(subpath);
+ }
+ else
+ {
+ current.next = v;
+ current = current.next;
+ }
+
+ // check if the cubic is self-intersecting
+ double[] lpts = ((CubicSegment) v).getLoop();
+ if (lpts != null)
+ {
+ // if it is, break off the loop into its own path.
+ v.subdivideInsert(lpts[0]);
+ v.next.subdivideInsert((lpts[1] - lpts[0]) / (1.0 - lpts[0]));
+
+ CubicSegment loop = (CubicSegment) v.next;
+ v.next = loop.next;
+ loop.next = loop;
+
+ v.P2 = v.next.P1 = loop.P2 = loop.P1; // snap points
+ paths.add(loop);
+ current = v.next;
+ }
+
+ cx = coords[4];
+ cy = coords[5];
+ break;
+ }
+ pi.next();
+ }
+
+ if (subpath != null)
+ { // close any open path
+ if (subpathx != cx || subpathy != cy)
+ {
+ current.next = new LineSegment(cx, cy, subpathx, subpathy);
+ current = current.next;
+ current.next = subpath;
+ }
+ else
+ current.next = subpath;
+ }
+
+ if (paths.size() == 0)
+ return (null);
+
+ return (paths);
+ }
+
+ /**
+ * Find the intersections of two separate closed paths,
+ * A and B, split the segments at the intersection points,
+ * and create nodes pointing from one to the other
+ */
+ private int createNodes(Segment A, Segment B)
+ {
+ int nNodes = 0;
+
+ Segment a = A;
+ Segment b = B;
+
+ do
+ {
+ do
+ {
+ nNodes += a.splitIntersections(b);
+ b = b.next;
+ }
+ while (b != B);
+
+ a = a.next; // move to the next segment
+ }
+ while (a != A); // until one wrap.
+
+ return (nNodes);
+ }
+
+ /**
+ * Find the intersections of a path with itself.
+ * Splits the segments at the intersection points,
+ * and create nodes pointing from one to the other.
+ */
+ private int createNodesSelf(Segment A)
+ {
+ int nNodes = 0;
+ Segment a = A;
+
+ if (A.next == A)
+ return 0;
+
+ do
+ {
+ Segment b = a.next;
+ do
+ {
+ if (b != a) // necessary
+ nNodes += a.splitIntersections(b);
+ b = b.next;
+ }
+ while (b != A);
+ a = a.next; // move to the next segment
+ }
+ while (a != A); // until one wrap.
+
+ return (nNodes);
+ }
+
+ /**
+ * Deletes paths which are redundant from a list, (i.e. solid areas within
+ * solid areas) Clears any nodes. Sorts the remaining paths into solids
+ * and holes, sets their orientation and sets the solids and holes lists.
+ */
+ private void deleteRedundantPaths(Vector paths)
+ {
+ int npaths = paths.size();
+
+ int[][] contains = new int[npaths][npaths];
+ int[][] windingNumbers = new int[npaths][2];
+ int neg;
+ Rectangle2D[] bb = new Rectangle2D[npaths]; // path bounding boxes
+
+ neg = ((windingRule == PathIterator.WIND_NON_ZERO) ? -1 : 1);
+
+ for (int i = 0; i < npaths; i++)
+ bb[i] = ((Segment) paths.elementAt(i)).getPathBounds();
+
+ // Find which path contains which, assign winding numbers
+ for (int i = 0; i < npaths; i++)
+ {
+ Segment pathA = (Segment) paths.elementAt(i);
+ pathA.nullNodes(); // remove any now-redundant nodes, in case.
+ int windingA = pathA.hasClockwiseOrientation() ? 1 : neg;
+
+ for (int j = 0; j < npaths; j++)
+ if (i != j)
+ {
+ Segment pathB = (Segment) paths.elementAt(j);
+
+ // A contains B
+ if (bb[i].intersects(bb[j]))
+ {
+ Segment s = pathB.next;
+ while (s.P1.getY() == s.P2.getY() && s != pathB)
+ s = s.next;
+ Point2D p = s.getMidPoint();
+ if (pathA.contains(p.getX(), p.getY()))
+ contains[i][j] = windingA;
+ }
+ else
+ // A does not contain B
+ contains[i][j] = 0;
+ }
+ else
+ contains[i][j] = windingA; // i == j
+ }
+
+ for (int i = 0; i < npaths; i++)
+ {
+ windingNumbers[i][0] = 0;
+ for (int j = 0; j < npaths; j++)
+ windingNumbers[i][0] += contains[j][i];
+ windingNumbers[i][1] = contains[i][i];
+ }
+
+ Vector solids = new Vector();
+ Vector holes = new Vector();
+
+ if (windingRule == PathIterator.WIND_NON_ZERO)
+ {
+ for (int i = 0; i < npaths; i++)
+ {
+ if (windingNumbers[i][0] == 0)
+ holes.add(paths.elementAt(i));
+ else if (windingNumbers[i][0] - windingNumbers[i][1] == 0
+ && Math.abs(windingNumbers[i][0]) == 1)
+ solids.add(paths.elementAt(i));
+ }
+ }
+ else
+ {
+ windingRule = PathIterator.WIND_NON_ZERO;
+ for (int i = 0; i < npaths; i++)
+ {
+ if ((windingNumbers[i][0] & 1) == 0)
+ holes.add(paths.elementAt(i));
+ else if ((windingNumbers[i][0] & 1) == 1)
+ solids.add(paths.elementAt(i));
+ }
+ }
+
+ setDirection(holes, false);
+ setDirection(solids, true);
+ this.holes = holes;
+ this.solids = solids;
+ }
+
+ /**
+ * Sets the winding direction of a Vector of paths
+ * @param clockwise gives the direction,
+ * true = clockwise, false = counter-clockwise
+ */
+ private void setDirection(Vector paths, boolean clockwise)
+ {
+ Segment v;
+ for (int i = 0; i < paths.size(); i++)
+ {
+ v = (Segment) paths.elementAt(i);
+ if (clockwise != v.hasClockwiseOrientation())
+ v.reverseAll();
+ }
+ }
+
+ /**
+ * Class representing a linked-list of vertices forming a closed polygon,
+ * convex or concave, without holes.
+ */
+ private abstract class Segment implements Cloneable
+ {
+ // segment type, PathIterator segment types are used.
+ Point2D P1;
+ Point2D P2;
+ Segment next;
+ Segment node;
+
+ Segment()
+ {
+ P1 = P2 = null;
+ node = next = null;
+ }
+
+ /**
+ * Reverses the direction of a single segment
+ */
+ abstract void reverseCoords();
+
+ /**
+ * Returns the segment's midpoint
+ */
+ abstract Point2D getMidPoint();
+
+ /**
+ * Returns the bounding box of this segment
+ */
+ abstract Rectangle2D getBounds();
+
+ /**
+ * Transforms a single segment
+ */
+ abstract void transform(AffineTransform at);
+
+ /**
+ * Returns the PathIterator type of a segment
+ */
+ abstract int getType();
+
+ /**
+ */
+ abstract int splitIntersections(Segment b);
+
+ /**
+ * Returns the PathIterator coords of a segment
+ */
+ abstract int pathIteratorFormat(double[] coords);
+
+ /**
+ * Returns the number of intersections on the positive X axis,
+ * with the origin at (x,y), used for contains()-testing
+ *
+ * (Although that could be done by the line-intersect methods,
+ * a dedicated method is better to guarantee consitent handling
+ * of endpoint-special-cases)
+ */
+ abstract int rayCrossing(double x, double y);
+
+ /**
+ * Subdivides the segment at parametric value t, inserting
+ * the new segment into the linked list after this,
+ * such that this becomes [0,t] and this.next becomes [t,1]
+ */
+ abstract void subdivideInsert(double t);
+
+ /**
+ * Returns twice the area of a curve, relative the P1-P2 line
+ * Used for area calculations.
+ */
+ abstract double curveArea();
+
+ /**
+ * Compare two segments.
+ */
+ abstract boolean equals(Segment b);
+
+ /**
+ * Determines if this path of segments contains the point (x,y)
+ */
+ boolean contains(double x, double y)
+ {
+ Segment v = this;
+ int crossings = 0;
+ do
+ {
+ int n = v.rayCrossing(x, y);
+ crossings += n;
+ v = v.next;
+ }
+ while (v != this);
+ return ((crossings & 1) == 1);
+ }
+
+ /**
+ * Nulls all nodes of the path. Clean up any 'hairs'.
+ */
+ void nullNodes()
+ {
+ Segment v = this;
+ do
+ {
+ v.node = null;
+ v = v.next;
+ }
+ while (v != this);
+ }
+
+ /**
+ * Transforms each segment in the closed path
+ */
+ void transformSegmentList(AffineTransform at)
+ {
+ Segment v = this;
+ do
+ {
+ v.transform(at);
+ v = v.next;
+ }
+ while (v != this);
+ }
+
+ /**
+ * Determines the winding direction of the path
+ * By the sign of the area.
+ */
+ boolean hasClockwiseOrientation()
+ {
+ return (getSignedArea() > 0.0);
+ }
+
+ /**
+ * Returns the bounds of this path
+ */
+ public Rectangle2D getPathBounds()
+ {
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+ xmin = xmax = P1.getX();
+ ymin = ymax = P1.getY();
+
+ Segment v = this;
+ do
+ {
+ Rectangle2D r = v.getBounds();
+ xmin = Math.min(r.getMinX(), xmin);
+ ymin = Math.min(r.getMinY(), ymin);
+ xmax = Math.max(r.getMaxX(), xmax);
+ ymax = Math.max(r.getMaxY(), ymax);
+ v = v.next;
+ }
+ while (v != this);
+
+ return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
+ }
+
+ /**
+ * Calculates twice the signed area of the path;
+ */
+ double getSignedArea()
+ {
+ Segment s;
+ double area = 0.0;
+
+ s = this;
+ do
+ {
+ area += s.curveArea();
+
+ area += s.P1.getX() * s.next.P1.getY()
+ - s.P1.getY() * s.next.P1.getX();
+ s = s.next;
+ }
+ while (s != this);
+
+ return area;
+ }
+
+ /**
+ * Reverses the orientation of the whole polygon
+ */
+ void reverseAll()
+ {
+ reverseCoords();
+ Segment v = next;
+ Segment former = this;
+ while (v != this)
+ {
+ v.reverseCoords();
+ Segment vnext = v.next;
+ v.next = former;
+ former = v;
+ v = vnext;
+ }
+ next = former;
+ }
+
+ /**
+ * Inserts a Segment after this one
+ */
+ void insert(Segment v)
+ {
+ Segment n = next;
+ next = v;
+ v.next = n;
+ }
+
+ /**
+ * Returns if this segment path is polygonal
+ */
+ boolean isPolygonal()
+ {
+ Segment v = this;
+ do
+ {
+ if (! (v instanceof LineSegment))
+ return false;
+ v = v.next;
+ }
+ while (v != this);
+ return true;
+ }
+
+ /**
+ * Clones this path
+ */
+ Segment cloneSegmentList() throws CloneNotSupportedException
+ {
+ Vector list = new Vector();
+ Segment v = next;
+
+ while (v != this)
+ {
+ list.add(v);
+ v = v.next;
+ }
+
+ Segment clone = (Segment) this.clone();
+ v = clone;
+ for (int i = 0; i < list.size(); i++)
+ {
+ clone.next = (Segment) ((Segment) list.elementAt(i)).clone();
+ clone = clone.next;
+ }
+ clone.next = v;
+ return v;
+ }
+
+ /**
+ * Creates a node between this segment and segment b
+ * at the given intersection
+ * @return the number of nodes created (0 or 1)
+ */
+ int createNode(Segment b, Intersection i)
+ {
+ Point2D p = i.p;
+ if ((pointEquals(P1, p) || pointEquals(P2, p))
+ && (pointEquals(b.P1, p) || pointEquals(b.P2, p)))
+ return 0;
+
+ subdivideInsert(i.ta);
+ b.subdivideInsert(i.tb);
+
+ // snap points
+ b.P2 = b.next.P1 = P2 = next.P1 = i.p;
+
+ node = b.next;
+ b.node = next;
+ return 1;
+ }
+
+ /**
+ * Creates multiple nodes from a list of intersections,
+ * This must be done in the order of ascending parameters,
+ * and the parameters must be recalculated in accordance
+ * with each split.
+ * @return the number of nodes created
+ */
+ protected int createNodes(Segment b, Intersection[] x)
+ {
+ Vector v = new Vector();
+ for (int i = 0; i < x.length; i++)
+ {
+ Point2D p = x[i].p;
+ if (! ((pointEquals(P1, p) || pointEquals(P2, p))
+ && (pointEquals(b.P1, p) || pointEquals(b.P2, p))))
+ v.add(x[i]);
+ }
+
+ int nNodes = v.size();
+ Intersection[] A = new Intersection[nNodes];
+ Intersection[] B = new Intersection[nNodes];
+ for (int i = 0; i < nNodes; i++)
+ A[i] = B[i] = (Intersection) v.elementAt(i);
+
+ // Create two lists sorted by the parameter
+ // Bubble sort, OK I suppose, since the number of intersections
+ // cannot be larger than 9 (cubic-cubic worst case) anyway
+ for (int i = 0; i < nNodes - 1; i++)
+ {
+ for (int j = i + 1; j < nNodes; j++)
+ {
+ if (A[i].ta > A[j].ta)
+ {
+ Intersection swap = A[i];
+ A[i] = A[j];
+ A[j] = swap;
+ }
+ if (B[i].tb > B[j].tb)
+ {
+ Intersection swap = B[i];
+ B[i] = B[j];
+ B[j] = swap;
+ }
+ }
+ }
+ // subdivide a
+ Segment s = this;
+ for (int i = 0; i < nNodes; i++)
+ {
+ s.subdivideInsert(A[i].ta);
+
+ // renormalize the parameters
+ for (int j = i + 1; j < nNodes; j++)
+ A[j].ta = (A[j].ta - A[i].ta) / (1.0 - A[i].ta);
+
+ A[i].seg = s;
+ s = s.next;
+ }
+
+ // subdivide b, set nodes
+ s = b;
+ for (int i = 0; i < nNodes; i++)
+ {
+ s.subdivideInsert(B[i].tb);
+
+ for (int j = i + 1; j < nNodes; j++)
+ B[j].tb = (B[j].tb - B[i].tb) / (1.0 - B[i].tb);
+
+ // set nodes
+ B[i].seg.node = s.next; // node a -> b
+ s.node = B[i].seg.next; // node b -> a
+
+ // snap points
+ B[i].seg.P2 = B[i].seg.next.P1 = s.P2 = s.next.P1 = B[i].p;
+ s = s.next;
+ }
+ return nNodes;
+ }
+
+ /**
+ * Determines if two paths are equal.
+ * Colinear line segments are ignored in the comparison.
+ */
+ boolean pathEquals(Segment B)
+ {
+ if (! getPathBounds().equals(B.getPathBounds()))
+ return false;
+
+ Segment startA = getTopLeft();
+ Segment startB = B.getTopLeft();
+ Segment a = startA;
+ Segment b = startB;
+ do
+ {
+ if (! a.equals(b))
+ return false;
+
+ if (a instanceof LineSegment)
+ a = ((LineSegment) a).lastCoLinear();
+ if (b instanceof LineSegment)
+ b = ((LineSegment) b).lastCoLinear();
+
+ a = a.next;
+ b = b.next;
+ }
+ while (a != startA && b != startB);
+ return true;
+ }
+
+ /**
+ * Return the segment with the top-leftmost first point
+ */
+ Segment getTopLeft()
+ {
+ Segment v = this;
+ Segment tl = this;
+ do
+ {
+ if (v.P1.getY() < tl.P1.getY())
+ tl = v;
+ else if (v.P1.getY() == tl.P1.getY())
+ {
+ if (v.P1.getX() < tl.P1.getX())
+ tl = v;
+ }
+ v = v.next;
+ }
+ while (v != this);
+ return tl;
+ }
+
+ /**
+ * Returns if the path has a segment outside a shape
+ */
+ boolean isSegmentOutside(Shape shape)
+ {
+ return ! shape.contains(getMidPoint());
+ }
+ } // class Segment
+
+ private class LineSegment extends Segment
+ {
+ public LineSegment(double x1, double y1, double x2, double y2)
+ {
+ super();
+ P1 = new Point2D.Double(x1, y1);
+ P2 = new Point2D.Double(x2, y2);
+ }
+
+ public LineSegment(Point2D p1, Point2D p2)
+ {
+ super();
+ P1 = (Point2D) p1.clone();
+ P2 = (Point2D) p2.clone();
+ }
+
+ /**
+ * Clones this segment
+ */
+ public Object clone()
+ {
+ return new LineSegment(P1, P2);
+ }
+
+ /**
+ * Transforms the segment
+ */
+ void transform(AffineTransform at)
+ {
+ P1 = at.transform(P1, null);
+ P2 = at.transform(P2, null);
+ }
+
+ /**
+ * Swap start and end points
+ */
+ void reverseCoords()
+ {
+ Point2D p = P1;
+ P1 = P2;
+ P2 = p;
+ }
+
+ /**
+ * Returns the segment's midpoint
+ */
+ Point2D getMidPoint()
+ {
+ return (new Point2D.Double(0.5 * (P1.getX() + P2.getX()),
+ 0.5 * (P1.getY() + P2.getY())));
+ }
+
+ /**
+ * Returns twice the area of a curve, relative the P1-P2 line
+ * Obviously, a line does not enclose any area besides the line
+ */
+ double curveArea()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the PathIterator type of a segment
+ */
+ int getType()
+ {
+ return (PathIterator.SEG_LINETO);
+ }
+
+ /**
+ * Subdivides the segment at parametric value t, inserting
+ * the new segment into the linked list after this,
+ * such that this becomes [0,t] and this.next becomes [t,1]
+ */
+ void subdivideInsert(double t)
+ {
+ Point2D p = new Point2D.Double((P2.getX() - P1.getX()) * t + P1.getX(),
+ (P2.getY() - P1.getY()) * t + P1.getY());
+ insert(new LineSegment(p, P2));
+ P2 = p;
+ next.node = node;
+ node = null;
+ }
+
+ /**
+ * Determines if two line segments are strictly colinear
+ */
+ boolean isCoLinear(LineSegment b)
+ {
+ double x1 = P1.getX();
+ double y1 = P1.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+ double x3 = b.P1.getX();
+ double y3 = b.P1.getY();
+ double x4 = b.P2.getX();
+ double y4 = b.P2.getY();
+
+ if ((y1 - y3) * (x4 - x3) - (x1 - x3) * (y4 - y3) != 0.0)
+ return false;
+
+ return ((x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3) == 0.0);
+ }
+
+ /**
+ * Return the last segment colinear with this one.
+ * Used in comparing paths.
+ */
+ Segment lastCoLinear()
+ {
+ Segment prev = this;
+ Segment v = next;
+
+ while (v instanceof LineSegment)
+ {
+ if (isCoLinear((LineSegment) v))
+ {
+ prev = v;
+ v = v.next;
+ }
+ else
+ return prev;
+ }
+ return prev;
+ }
+
+ /**
+ * Compare two segments.
+ * We must take into account that the lines may be broken into colinear
+ * subsegments and ignore them.
+ */
+ boolean equals(Segment b)
+ {
+ if (! (b instanceof LineSegment))
+ return false;
+ Point2D p1 = P1;
+ Point2D p3 = b.P1;
+
+ if (! p1.equals(p3))
+ return false;
+
+ Point2D p2 = lastCoLinear().P2;
+ Point2D p4 = ((LineSegment) b).lastCoLinear().P2;
+ return (p2.equals(p4));
+ }
+
+ /**
+ * Returns a line segment
+ */
+ int pathIteratorFormat(double[] coords)
+ {
+ coords[0] = P2.getX();
+ coords[1] = P2.getY();
+ return (PathIterator.SEG_LINETO);
+ }
+
+ /**
+ * Returns if the line has intersections.
+ */
+ boolean hasIntersections(Segment b)
+ {
+ if (b instanceof LineSegment)
+ return (linesIntersect(this, (LineSegment) b) != null);
+
+ if (b instanceof QuadSegment)
+ return (lineQuadIntersect(this, (QuadSegment) b) != null);
+
+ if (b instanceof CubicSegment)
+ return (lineCubicIntersect(this, (CubicSegment) b) != null);
+
+ return false;
+ }
+
+ /**
+ * Splits intersections into nodes,
+ * This one handles line-line, line-quadratic, line-cubic
+ */
+ int splitIntersections(Segment b)
+ {
+ if (b instanceof LineSegment)
+ {
+ Intersection i = linesIntersect(this, (LineSegment) b);
+
+ if (i == null)
+ return 0;
+
+ return createNode(b, i);
+ }
+
+ Intersection[] x = null;
+
+ if (b instanceof QuadSegment)
+ x = lineQuadIntersect(this, (QuadSegment) b);
+
+ if (b instanceof CubicSegment)
+ x = lineCubicIntersect(this, (CubicSegment) b);
+
+ if (x == null)
+ return 0;
+
+ if (x.length == 1)
+ return createNode(b, (Intersection) x[0]);
+
+ return createNodes(b, x);
+ }
+
+ /**
+ * Returns the bounding box of this segment
+ */
+ Rectangle2D getBounds()
+ {
+ return (new Rectangle2D.Double(Math.min(P1.getX(), P2.getX()),
+ Math.min(P1.getY(), P2.getY()),
+ Math.abs(P1.getX() - P2.getX()),
+ Math.abs(P1.getY() - P2.getY())));
+ }
+
+ /**
+ * Returns the number of intersections on the positive X axis,
+ * with the origin at (x,y), used for contains()-testing
+ */
+ int rayCrossing(double x, double y)
+ {
+ double x0 = P1.getX() - x;
+ double y0 = P1.getY() - y;
+ double x1 = P2.getX() - x;
+ double y1 = P2.getY() - y;
+
+ if (y0 * y1 > 0)
+ return 0;
+
+ if (x0 < 0 && x1 < 0)
+ return 0;
+
+ if (y0 == 0.0)
+ y0 -= EPSILON;
+
+ if (y1 == 0.0)
+ y1 -= EPSILON;
+
+ if (Line2D.linesIntersect(x0, y0, x1, y1,
+ EPSILON, 0.0, Double.MAX_VALUE, 0.0))
+ return 1;
+ return 0;
+ }
+ } // class LineSegment
+
+ /**
+ * Quadratic Bezier curve segment
+ *
+ * Note: Most peers don't support quadratics directly, so it might make
+ * sense to represent them as cubics internally and just be done with it.
+ * I think we should be peer-agnostic, however, and stay faithful to the
+ * input geometry types as far as possible.
+ */
+ private class QuadSegment extends Segment
+ {
+ Point2D cp; // control point
+
+ /**
+ * Constructor, takes the coordinates of the start, control,
+ * and end point, respectively.
+ */
+ QuadSegment(double x1, double y1, double cx, double cy, double x2,
+ double y2)
+ {
+ super();
+ P1 = new Point2D.Double(x1, y1);
+ P2 = new Point2D.Double(x2, y2);
+ cp = new Point2D.Double(cx, cy);
+ }
+
+ /**
+ * Clones this segment
+ */
+ public Object clone()
+ {
+ return new QuadSegment(P1.getX(), P1.getY(), cp.getX(), cp.getY(),
+ P2.getX(), P2.getY());
+ }
+
+ /**
+ * Returns twice the area of a curve, relative the P1-P2 line
+ *
+ * The area formula can be derived by using Green's formula in the
+ * plane on the parametric form of the bezier.
+ */
+ double curveArea()
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp.getX();
+ double y1 = cp.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+
+ double P = (y2 - 2 * y1 + y0);
+ double Q = 2 * (y1 - y0);
+
+ double A = (x2 - 2 * x1 + x0);
+ double B = 2 * (x1 - x0);
+
+ double area = (B * P - A * Q) / 3.0;
+ return (area);
+ }
+
+ /**
+ * Compare two segments.
+ */
+ boolean equals(Segment b)
+ {
+ if (! (b instanceof QuadSegment))
+ return false;
+
+ return (P1.equals(b.P1) && cp.equals(((QuadSegment) b).cp)
+ && P2.equals(b.P2));
+ }
+
+ /**
+ * Returns a Point2D corresponding to the parametric value t
+ * of the curve
+ */
+ Point2D evaluatePoint(double t)
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp.getX();
+ double y1 = cp.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+
+ return new Point2D.Double(t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0)
+ + x0,
+ t * t * (y2 - 2 * y1 + y0) + 2 * t * (y1 - y0)
+ + y0);
+ }
+
+ /**
+ * Returns the bounding box of this segment
+ */
+ Rectangle2D getBounds()
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp.getX();
+ double y1 = cp.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+ double r0;
+ double r1;
+
+ double xmax = Math.max(x0, x2);
+ double ymax = Math.max(y0, y2);
+ double xmin = Math.min(x0, x2);
+ double ymin = Math.min(y0, y2);
+
+ r0 = 2 * (y1 - y0);
+ r1 = 2 * (y2 - 2 * y1 + y0);
+ if (r1 != 0.0)
+ {
+ double t = -r0 / r1;
+ if (t > 0.0 && t < 1.0)
+ {
+ double y = evaluatePoint(t).getY();
+ ymax = Math.max(y, ymax);
+ ymin = Math.min(y, ymin);
+ }
+ }
+ r0 = 2 * (x1 - x0);
+ r1 = 2 * (x2 - 2 * x1 + x0);
+ if (r1 != 0.0)
+ {
+ double t = -r0 / r1;
+ if (t > 0.0 && t < 1.0)
+ {
+ double x = evaluatePoint(t).getY();
+ xmax = Math.max(x, xmax);
+ xmin = Math.min(x, xmin);
+ }
+ }
+
+ return (new Rectangle2D.Double(xmin, ymin, xmax - xmin, ymax - ymin));
+ }
+
+ /**
+ * Returns a cubic segment corresponding to this curve
+ */
+ CubicSegment getCubicSegment()
+ {
+ double x1 = P1.getX() + 2.0 * (cp.getX() - P1.getX()) / 3.0;
+ double y1 = P1.getY() + 2.0 * (cp.getY() - P1.getY()) / 3.0;
+ double x2 = cp.getX() + (P2.getX() - cp.getX()) / 3.0;
+ double y2 = cp.getY() + (P2.getY() - cp.getY()) / 3.0;
+
+ return new CubicSegment(P1.getX(), P1.getY(), x1, y1, x2, y2, P2.getX(),
+ P2.getY());
+ }
+
+ /**
+ * Returns the segment's midpoint
+ */
+ Point2D getMidPoint()
+ {
+ return evaluatePoint(0.5);
+ }
+
+ /**
+ * Returns the PathIterator type of a segment
+ */
+ int getType()
+ {
+ return (PathIterator.SEG_QUADTO);
+ }
+
+ /**
+ * Returns the PathIterator coords of a segment
+ */
+ int pathIteratorFormat(double[] coords)
+ {
+ coords[0] = cp.getX();
+ coords[1] = cp.getY();
+ coords[2] = P2.getX();
+ coords[3] = P2.getY();
+ return (PathIterator.SEG_QUADTO);
+ }
+
+ /**
+ * Returns the number of intersections on the positive X axis,
+ * with the origin at (x,y), used for contains()-testing
+ */
+ int rayCrossing(double x, double y)
+ {
+ double x0 = P1.getX() - x;
+ double y0 = P1.getY() - y;
+ double x1 = cp.getX() - x;
+ double y1 = cp.getY() - y;
+ double x2 = P2.getX() - x;
+ double y2 = P2.getY() - y;
+ double[] r = new double[3];
+ int nRoots;
+ int nCrossings = 0;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0) && (y0 * y1 <= 0 || y1 * y2 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 -= EPSILON;
+ if (y2 == 0.0)
+ y2 -= EPSILON;
+
+ r[0] = y0;
+ r[1] = 2 * (y1 - y0);
+ r[2] = (y2 - 2 * y1 + y0);
+
+ nRoots = QuadCurve2D.solveQuadratic(r);
+ for (int i = 0; i < nRoots; i++)
+ if (r[i] > 0.0f && r[i] < 1.0f)
+ {
+ double t = r[i];
+ if (t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0) + x0 > 0.0)
+ nCrossings++;
+ }
+ }
+ return nCrossings;
+ }
+
+ /**
+ * Swap start and end points
+ */
+ void reverseCoords()
+ {
+ Point2D temp = P1;
+ P1 = P2;
+ P2 = temp;
+ }
+
+ /**
+ * Splits intersections into nodes,
+ * This one handles quadratic-quadratic only,
+ * Quadratic-line is passed on to the LineSegment class,
+ * Quadratic-cubic is passed on to the CubicSegment class
+ */
+ int splitIntersections(Segment b)
+ {
+ if (b instanceof LineSegment)
+ return (b.splitIntersections(this));
+
+ if (b instanceof CubicSegment)
+ return (b.splitIntersections(this));
+
+ if (b instanceof QuadSegment)
+ {
+ // Use the cubic-cubic intersection routine for quads as well,
+ // Since a quadratic can be exactly described as a cubic, this
+ // should not be a problem;
+ // The recursion depth will be the same in any case.
+ Intersection[] x = cubicCubicIntersect(getCubicSegment(),
+ ((QuadSegment) b)
+ .getCubicSegment());
+ if (x == null)
+ return 0;
+
+ if (x.length == 1)
+ return createNode(b, (Intersection) x[0]);
+
+ return createNodes(b, x);
+ }
+ return 0;
+ }
+
+ /**
+ * Subdivides the segment at parametric value t, inserting
+ * the new segment into the linked list after this,
+ * such that this becomes [0,t] and this.next becomes [t,1]
+ */
+ void subdivideInsert(double t)
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp.getX();
+ double y1 = cp.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+
+ double p10x = x0 + t * (x1 - x0);
+ double p10y = y0 + t * (y1 - y0);
+ double p11x = x1 + t * (x2 - x1);
+ double p11y = y1 + t * (y2 - y1);
+ double p20x = p10x + t * (p11x - p10x);
+ double p20y = p10y + t * (p11y - p10y);
+
+ insert(new QuadSegment(p20x, p20y, p11x, p11y, x2, y2));
+ P2 = next.P1;
+ cp.setLocation(p10x, p10y);
+
+ next.node = node;
+ node = null;
+ }
+
+ /**
+ * Transforms the segment
+ */
+ void transform(AffineTransform at)
+ {
+ P1 = at.transform(P1, null);
+ P2 = at.transform(P2, null);
+ cp = at.transform(cp, null);
+ }
+ } // class QuadSegment
+
+ /**
+ * Cubic Bezier curve segment
+ */
+ private class CubicSegment extends Segment
+ {
+ Point2D cp1; // control points
+ Point2D cp2; // control points
+
+ /**
+ * Constructor - takes coordinates of the starting point,
+ * first control point, second control point and end point,
+ * respecively.
+ */
+ public CubicSegment(double x1, double y1, double c1x, double c1y,
+ double c2x, double c2y, double x2, double y2)
+ {
+ super();
+ P1 = new Point2D.Double(x1, y1);
+ P2 = new Point2D.Double(x2, y2);
+ cp1 = new Point2D.Double(c1x, c1y);
+ cp2 = new Point2D.Double(c2x, c2y);
+ }
+
+ /**
+ * Clones this segment
+ */
+ public Object clone()
+ {
+ return new CubicSegment(P1.getX(), P1.getY(), cp1.getX(), cp1.getY(),
+ cp2.getX(), cp2.getY(), P2.getX(), P2.getY());
+ }
+
+ /**
+ * Returns twice the area of a curve, relative the P1-P2 line
+ *
+ * The area formula can be derived by using Green's formula in the
+ * plane on the parametric form of the bezier.
+ */
+ double curveArea()
+ {
+ 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 P = y3 - 3 * y2 + 3 * y1 - y0;
+ double Q = 3 * (y2 + y0 - 2 * y1);
+ double R = 3 * (y1 - y0);
+
+ double A = x3 - 3 * x2 + 3 * x1 - x0;
+ double B = 3 * (x2 + x0 - 2 * x1);
+ double C = 3 * (x1 - x0);
+
+ double area = (B * P - A * Q) / 5.0 + (C * P - A * R) / 2.0
+ + (C * Q - B * R) / 3.0;
+
+ return (area);
+ }
+
+ /**
+ * Compare two segments.
+ */
+ boolean equals(Segment b)
+ {
+ if (! (b instanceof CubicSegment))
+ return false;
+
+ return (P1.equals(b.P1) && cp1.equals(((CubicSegment) b).cp1)
+ && cp2.equals(((CubicSegment) b).cp2) && P2.equals(b.P2));
+ }
+
+ /**
+ * Returns a Point2D corresponding to the parametric value t
+ * of the curve
+ */
+ Point2D evaluatePoint(double t)
+ {
+ 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();
+
+ return new Point2D.Double(-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3)
+ + 3 * t * t * (x0 - 2 * x1 + x2)
+ + 3 * t * (x1 - x0) + x0,
+ -(t * t * t) * (y0 - 3 * y1 + 3 * y2 - y3)
+ + 3 * t * t * (y0 - 2 * y1 + y2)
+ + 3 * t * (y1 - y0) + y0);
+ }
+
+ /**
+ * Returns the bounding box of this segment
+ */
+ Rectangle2D getBounds()
+ {
+ 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[] r = new double[3];
+
+ double xmax = Math.max(x0, x3);
+ double ymax = Math.max(y0, y3);
+ double xmin = Math.min(x0, x3);
+ double ymin = Math.min(y0, y3);
+
+ r[0] = 3 * (y1 - y0);
+ r[1] = 6.0 * (y2 + y0 - 2 * y1);
+ r[2] = 3.0 * (y3 - 3 * y2 + 3 * y1 - y0);
+
+ int n = QuadCurve2D.solveQuadratic(r);
+ for (int i = 0; i < n; i++)
+ {
+ double t = r[i];
+ if (t > 0 && t < 1.0)
+ {
+ double y = evaluatePoint(t).getY();
+ ymax = Math.max(y, ymax);
+ ymin = Math.min(y, ymin);
+ }
+ }
+
+ r[0] = 3 * (x1 - x0);
+ r[1] = 6.0 * (x2 + x0 - 2 * x1);
+ r[2] = 3.0 * (x3 - 3 * x2 + 3 * x1 - x0);
+ n = QuadCurve2D.solveQuadratic(r);
+ for (int i = 0; i < n; i++)
+ {
+ double t = r[i];
+ if (t > 0 && t < 1.0)
+ {
+ double x = evaluatePoint(t).getX();
+ xmax = Math.max(x, xmax);
+ xmin = Math.min(x, xmin);
+ }
+ }
+ return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
+ }
+
+ /**
+ * Returns a CubicCurve2D object corresponding to this segment.
+ */
+ CubicCurve2D getCubicCurve2D()
+ {
+ return new CubicCurve2D.Double(P1.getX(), P1.getY(), cp1.getX(),
+ cp1.getY(), cp2.getX(), cp2.getY(),
+ P2.getX(), P2.getY());
+ }
+
+ /**
+ * Returns the parametric points of self-intersection if the cubic
+ * is self-intersecting, null otherwise.
+ */
+ double[] getLoop()
+ {
+ 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[] r = new double[4];
+ double k;
+ double R;
+ double T;
+ double A;
+ double B;
+ double[] results = new double[2];
+
+ R = x3 - 3 * x2 + 3 * x1 - x0;
+ T = y3 - 3 * y2 + 3 * y1 - y0;
+
+ // A qudratic
+ if (R == 0.0 && T == 0.0)
+ return null;
+
+ // true cubic
+ if (R != 0.0 && T != 0.0)
+ {
+ A = 3 * (x2 + x0 - 2 * x1) / R;
+ B = 3 * (x1 - x0) / R;
+
+ double P = 3 * (y2 + y0 - 2 * y1) / T;
+ double Q = 3 * (y1 - y0) / T;
+
+ if (A == P || Q == B)
+ return null;
+
+ k = (Q - B) / (A - P);
+ }
+ else
+ {
+ if (R == 0.0)
+ {
+ // quadratic in x
+ k = -(3 * (x1 - x0)) / (3 * (x2 + x0 - 2 * x1));
+ A = 3 * (y2 + y0 - 2 * y1) / T;
+ B = 3 * (y1 - y0) / T;
+ }
+ else
+ {
+ // quadratic in y
+ k = -(3 * (y1 - y0)) / (3 * (y2 + y0 - 2 * y1));
+ A = 3 * (x2 + x0 - 2 * x1) / R;
+ B = 3 * (x1 - x0) / R;
+ }
+ }
+
+ r[0] = -k * k * k - A * k * k - B * k;
+ r[1] = 3 * k * k + 2 * k * A + 2 * B;
+ r[2] = -3 * k;
+ r[3] = 2;
+
+ int n = CubicCurve2D.solveCubic(r);
+ if (n != 3)
+ return null;
+
+ // sort r
+ double t;
+ for (int i = 0; i < 2; i++)
+ for (int j = i + 1; j < 3; j++)
+ if (r[j] < r[i])
+ {
+ t = r[i];
+ r[i] = r[j];
+ r[j] = t;
+ }
+
+ if (Math.abs(r[0] + r[2] - k) < 1E-13)
+ if (r[0] >= 0.0 && r[0] <= 1.0 && r[2] >= 0.0 && r[2] <= 1.0)
+ if (evaluatePoint(r[0]).distance(evaluatePoint(r[2])) < PE_EPSILON * 10)
+ { // we snap the points anyway
+ results[0] = r[0];
+ results[1] = r[2];
+ return (results);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the segment's midpoint
+ */
+ Point2D getMidPoint()
+ {
+ return evaluatePoint(0.5);
+ }
+
+ /**
+ * Returns the PathIterator type of a segment
+ */
+ int getType()
+ {
+ return (PathIterator.SEG_CUBICTO);
+ }
+
+ /**
+ * Returns the PathIterator coords of a segment
+ */
+ int pathIteratorFormat(double[] coords)
+ {
+ coords[0] = cp1.getX();
+ coords[1] = cp1.getY();
+ coords[2] = cp2.getX();
+ coords[3] = cp2.getY();
+ coords[4] = P2.getX();
+ coords[5] = P2.getY();
+ return (PathIterator.SEG_CUBICTO);
+ }
+
+ /**
+ * Returns the number of intersections on the positive X axis,
+ * with the origin at (x,y), used for contains()-testing
+ */
+ int rayCrossing(double x, double y)
+ {
+ double x0 = P1.getX() - x;
+ double y0 = P1.getY() - y;
+ double x1 = cp1.getX() - x;
+ double y1 = cp1.getY() - y;
+ double x2 = cp2.getX() - x;
+ double y2 = cp2.getY() - y;
+ double x3 = P2.getX() - x;
+ double y3 = P2.getY() - y;
+ double[] r = new double[4];
+ int nRoots;
+ int nCrossings = 0;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0)
+ && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 -= EPSILON;
+ if (y3 == 0.0)
+ y3 -= EPSILON;
+
+ r[0] = y0;
+ r[1] = 3 * (y1 - y0);
+ r[2] = 3 * (y2 + y0 - 2 * y1);
+ r[3] = y3 - 3 * y2 + 3 * y1 - y0;
+
+ if ((nRoots = CubicCurve2D.solveCubic(r)) > 0)
+ for (int i = 0; i < nRoots; i++)
+ {
+ if (r[i] > 0.0 && r[i] < 1.0)
+ {
+ double t = r[i];
+ if (-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3)
+ + 3 * t * t * (x0 - 2 * x1 + x2) + 3 * t * (x1 - x0)
+ + x0 > 0.0)
+ nCrossings++;
+ }
+ }
+ }
+ return nCrossings;
+ }
+
+ /**
+ * Swap start and end points
+ */
+ void reverseCoords()
+ {
+ Point2D p = P1;
+ P1 = P2;
+ P2 = p;
+ p = cp1; // swap control points
+ cp1 = cp2;
+ cp2 = p;
+ }
+
+ /**
+ * Splits intersections into nodes,
+ * This one handles cubic-cubic and cubic-quadratic intersections
+ */
+ int splitIntersections(Segment b)
+ {
+ if (b instanceof LineSegment)
+ return (b.splitIntersections(this));
+
+ Intersection[] x = null;
+
+ if (b instanceof QuadSegment)
+ x = cubicCubicIntersect(this, ((QuadSegment) b).getCubicSegment());
+
+ if (b instanceof CubicSegment)
+ x = cubicCubicIntersect(this, (CubicSegment) b);
+
+ if (x == null)
+ return 0;
+
+ if (x.length == 1)
+ return createNode(b, x[0]);
+
+ return createNodes(b, x);
+ }
+
+ /**
+ * Subdivides the segment at parametric value t, inserting
+ * the new segment into the linked list after this,
+ * such that this becomes [0,t] and this.next becomes [t,1]
+ */
+ void subdivideInsert(double t)
+ {
+ CubicSegment s = (CubicSegment) clone();
+ double p1x = (s.cp1.getX() - s.P1.getX()) * t + s.P1.getX();
+ double p1y = (s.cp1.getY() - s.P1.getY()) * t + s.P1.getY();
+
+ double px = (s.cp2.getX() - s.cp1.getX()) * t + s.cp1.getX();
+ double py = (s.cp2.getY() - s.cp1.getY()) * t + s.cp1.getY();
+
+ s.cp2.setLocation((s.P2.getX() - s.cp2.getX()) * t + s.cp2.getX(),
+ (s.P2.getY() - s.cp2.getY()) * t + s.cp2.getY());
+
+ s.cp1.setLocation((s.cp2.getX() - px) * t + px,
+ (s.cp2.getY() - py) * t + py);
+
+ double p2x = (px - p1x) * t + p1x;
+ double p2y = (py - p1y) * t + p1y;
+
+ double p3x = (s.cp1.getX() - p2x) * t + p2x;
+ double p3y = (s.cp1.getY() - p2y) * t + p2y;
+ s.P1.setLocation(p3x, p3y);
+
+ // insert new curve
+ insert(s);
+
+ // set this curve
+ cp1.setLocation(p1x, p1y);
+ cp2.setLocation(p2x, p2y);
+ P2 = s.P1;
+ next.node = node;
+ node = null;
+ }
+
+ /**
+ * Transforms the segment
+ */
+ void transform(AffineTransform at)
+ {
+ P1 = at.transform(P1, null);
+ P2 = at.transform(P2, null);
+ cp1 = at.transform(cp1, null);
+ cp2 = at.transform(cp2, null);
+ }
+ } // class CubicSegment
+} // class Area
diff --git a/libjava/classpath/java/awt/geom/CubicCurve2D.java b/libjava/classpath/java/awt/geom/CubicCurve2D.java
new file mode 100644
index 00000000000..50c381194bb
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/CubicCurve2D.java
@@ -0,0 +1,1724 @@
+/* CubicCurve2D.java -- represents a parameterized cubic curve in 2-D space
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+
+/**
+ * A two-dimensional curve that is parameterized with a cubic
+ * function.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Graydon Hoare (graydon@redhat.com)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
+ */
+public abstract class CubicCurve2D implements Shape, Cloneable
+{
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+ private static final double EPSILON = 1E-10;
+
+ /**
+ * Constructs a new CubicCurve2D. Typical users will want to
+ * construct instances of a subclass, such as {@link
+ * CubicCurve2D.Float} or {@link CubicCurve2D.Double}.
+ */
+ protected CubicCurve2D()
+ {
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public abstract double getX1();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public abstract double getY1();
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public abstract Point2D getP1();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public abstract double getCtrlX1();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public abstract double getCtrlY1();
+
+ /**
+ * Returns the curve&#x2019;s first control point.
+ */
+ public abstract Point2D getCtrlP1();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public abstract double getCtrlX2();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public abstract double getCtrlY2();
+
+ /**
+ * Returns the curve&#x2019;s second control point.
+ */
+ public abstract Point2D getCtrlP2();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public abstract double getX2();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public abstract double getY2();
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public abstract Point2D getP2();
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public abstract void setCurve(double x1, double y1, double cx1, double cy1,
+ double cx2, double cy2, double x2, double y2);
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in an
+ * array.
+ *
+ * @param coords an array containing the new coordinate values. The
+ * <i>x</i> coordinate of the new start point is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * new first control point is located at <code>coords[offset +
+ * 2]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 3]</code>. The <i>x</i> coordinate of the new second control
+ * point is located at <code>coords[offset + 4]</code>, its <i>y</i>
+ * coordinate at <code>coords[offset + 5]</code>. The <i>x</i>
+ * coordinate of the new end point is located at <code>coords[offset
+ * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 7]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public void setCurve(double[] coords, int offset)
+ {
+ setCurve(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++]);
+ }
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in
+ * separate Point objects.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * <p>The curve does not keep any reference to the passed point
+ * objects. Therefore, a later change to <code>p1</code>,
+ * <code>c1</code>, <code>c2</code> or <code>p2</code> will not
+ * affect the curve geometry.
+ *
+ * @param p1 the new start point.
+ * @param c1 the new first control point.
+ * @param c2 the new second control point.
+ * @param p2 the new end point.
+ */
+ public void setCurve(Point2D p1, Point2D c1, Point2D c2, Point2D p2)
+ {
+ setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(), c2.getX(), c2.getY(),
+ p2.getX(), p2.getY());
+ }
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in an
+ * array of Point objects.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * <p>The curve does not keep references to the passed point
+ * objects. Therefore, a later change to the <code>pts</code> array
+ * or any of its elements will not affect the curve geometry.
+ *
+ * @param pts an array containing the points. The new start point
+ * is located at <code>pts[offset]</code>, the new first control
+ * point at <code>pts[offset + 1]</code>, the new second control
+ * point at <code>pts[offset + 2]</code>, and the new end point
+ * at <code>pts[offset + 3]</code>.
+ *
+ * @param offset the offset of the start point in <code>pts</code>.
+ */
+ public void setCurve(Point2D[] pts, int offset)
+ {
+ setCurve(pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(),
+ pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY(),
+ pts[offset].getX(), pts[offset++].getY());
+ }
+
+ /**
+ * Changes the curve geometry to that of another curve.
+ *
+ * @param c the curve whose coordinates will be copied.
+ */
+ public void setCurve(CubicCurve2D c)
+ {
+ setCurve(c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(),
+ c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2());
+ }
+
+ /**
+ * Calculates the squared flatness of a cubic curve, directly
+ * specifying each coordinate value. The flatness is the maximal
+ * distance of a control point to the line between start and end
+ * point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the square of the distance between C2 and the
+ * gray line, i.e. the squared length of the red line.
+ *
+ * @param x1 the <i>x</i> coordinate of the start point P1.
+ * @param y1 the <i>y</i> coordinate of the start point P1.
+ * @param cx1 the <i>x</i> coordinate of the first control point C1.
+ * @param cy1 the <i>y</i> coordinate of the first control point C1.
+ * @param cx2 the <i>x</i> coordinate of the second control point C2.
+ * @param cy2 the <i>y</i> coordinate of the second control point C2.
+ * @param x2 the <i>x</i> coordinate of the end point P2.
+ * @param y2 the <i>y</i> coordinate of the end point P2.
+ */
+ public static double getFlatnessSq(double x1, double y1, double cx1,
+ double cy1, double cx2, double cy2,
+ double x2, double y2)
+ {
+ return Math.max(Line2D.ptSegDistSq(x1, y1, x2, y2, cx1, cy1),
+ Line2D.ptSegDistSq(x1, y1, x2, y2, cx2, cy2));
+ }
+
+ /**
+ * Calculates the flatness of a cubic curve, directly specifying
+ * each coordinate value. The flatness is the maximal distance of a
+ * control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the distance between C2 and the gray line,
+ * i.e. the length of the red line.
+ *
+ * @param x1 the <i>x</i> coordinate of the start point P1.
+ * @param y1 the <i>y</i> coordinate of the start point P1.
+ * @param cx1 the <i>x</i> coordinate of the first control point C1.
+ * @param cy1 the <i>y</i> coordinate of the first control point C1.
+ * @param cx2 the <i>x</i> coordinate of the second control point C2.
+ * @param cy2 the <i>y</i> coordinate of the second control point C2.
+ * @param x2 the <i>x</i> coordinate of the end point P2.
+ * @param y2 the <i>y</i> coordinate of the end point P2.
+ */
+ public static double getFlatness(double x1, double y1, double cx1,
+ double cy1, double cx2, double cy2,
+ double x2, double y2)
+ {
+ return Math.sqrt(getFlatnessSq(x1, y1, cx1, cy1, cx2, cy2, x2, y2));
+ }
+
+ /**
+ * Calculates the squared flatness of a cubic curve, specifying the
+ * coordinate values in an array. The flatness is the maximal
+ * distance of a control point to the line between start and end
+ * point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the square of the distance between C2 and the
+ * gray line, i.e. the squared length of the red line.
+ *
+ * @param coords an array containing the coordinate values. The
+ * <i>x</i> coordinate of the start point P1 is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * first control point C1 is located at <code>coords[offset +
+ * 2]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 3]</code>. The <i>x</i> coordinate of the second control point C2
+ * is located at <code>coords[offset + 4]</code>, its <i>y</i>
+ * coordinate at <code>coords[offset + 5]</code>. The <i>x</i>
+ * coordinate of the end point P2 is located at <code>coords[offset
+ * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 7]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public static double getFlatnessSq(double[] coords, int offset)
+ {
+ return getFlatnessSq(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++]);
+ }
+
+ /**
+ * Calculates the flatness of a cubic curve, specifying the
+ * coordinate values in an array. The flatness is the maximal
+ * distance of a control point to the line between start and end
+ * point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the distance between C2 and the gray line,
+ * i.e. the length of the red line.
+ *
+ * @param coords an array containing the coordinate values. The
+ * <i>x</i> coordinate of the start point P1 is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * first control point C1 is located at <code>coords[offset +
+ * 2]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 3]</code>. The <i>x</i> coordinate of the second control point C2
+ * is located at <code>coords[offset + 4]</code>, its <i>y</i>
+ * coordinate at <code>coords[offset + 5]</code>. The <i>x</i>
+ * coordinate of the end point P2 is located at <code>coords[offset
+ * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 7]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public static double getFlatness(double[] coords, int offset)
+ {
+ return Math.sqrt(getFlatnessSq(coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++]));
+ }
+
+ /**
+ * Calculates the squared flatness of this curve. The flatness is
+ * the maximal distance of a control point to the line between start
+ * and end point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the square of the distance between C2 and the
+ * gray line, i.e. the squared length of the red line.
+ */
+ public double getFlatnessSq()
+ {
+ return getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
+ getCtrlX2(), getCtrlY2(), getX2(), getY2());
+ }
+
+ /**
+ * Calculates the flatness of this curve. The flatness is the
+ * maximal distance of a control point to the line between start and
+ * end point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the distance between C2 and the gray line,
+ * i.e. the length of the red line.
+ */
+ public double getFlatness()
+ {
+ return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
+ getCtrlX2(), getCtrlY2(), getX2(), getY2()));
+ }
+
+ /**
+ * Subdivides this curve into two halves.
+ *
+ * <p><img src="doc-files/CubicCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a CubicCurve2D" />
+ *
+ * @param left a curve whose geometry will be set to the left half
+ * of this curve, or <code>null</code> if the caller is not
+ * interested in the left half.
+ *
+ * @param right a curve whose geometry will be set to the right half
+ * of this curve, or <code>null</code> if the caller is not
+ * interested in the right half.
+ */
+ public void subdivide(CubicCurve2D left, CubicCurve2D right)
+ {
+ // Use empty slots at end to share single array.
+ double[] d = new double[]
+ {
+ getX1(), getY1(), getCtrlX1(), getCtrlY1(), getCtrlX2(),
+ getCtrlY2(), getX2(), getY2(), 0, 0, 0, 0, 0, 0
+ };
+ subdivide(d, 0, d, 0, d, 6);
+ if (left != null)
+ left.setCurve(d, 0);
+ if (right != null)
+ right.setCurve(d, 6);
+ }
+
+ /**
+ * Subdivides a cubic curve into two halves.
+ *
+ * <p><img src="doc-files/CubicCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a CubicCurve2D" />
+ *
+ * @param src the curve to be subdivided.
+ *
+ * @param left a curve whose geometry will be set to the left half
+ * of <code>src</code>, or <code>null</code> if the caller is not
+ * interested in the left half.
+ *
+ * @param right a curve whose geometry will be set to the right half
+ * of <code>src</code>, or <code>null</code> if the caller is not
+ * interested in the right half.
+ */
+ public static void subdivide(CubicCurve2D src, CubicCurve2D left,
+ CubicCurve2D right)
+ {
+ src.subdivide(left, right);
+ }
+
+ /**
+ * Subdivides a cubic curve into two halves, passing all coordinates
+ * in an array.
+ *
+ * <p><img src="doc-files/CubicCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a CubicCurve2D" />
+ *
+ * <p>The left end point and the right start point will always be
+ * identical. Memory-concious programmers thus may want to pass the
+ * same array for both <code>left</code> and <code>right</code>, and
+ * set <code>rightOff</code> to <code>leftOff + 6</code>.
+ *
+ * @param src an array containing the coordinates of the curve to be
+ * subdivided. The <i>x</i> coordinate of the start point P1 is
+ * located at <code>src[srcOff]</code>, its <i>y</i> at
+ * <code>src[srcOff + 1]</code>. The <i>x</i> coordinate of the
+ * first control point C1 is located at <code>src[srcOff +
+ * 2]</code>, its <i>y</i> at <code>src[srcOff + 3]</code>. The
+ * <i>x</i> coordinate of the second control point C2 is located at
+ * <code>src[srcOff + 4]</code>, its <i>y</i> at <code>src[srcOff +
+ * 5]</code>. The <i>x</i> coordinate of the end point is located at
+ * <code>src[srcOff + 6]</code>, its <i>y</i> at <code>src[srcOff +
+ * 7]</code>.
+ *
+ * @param srcOff an offset into <code>src</code>, specifying
+ * the index of the start point&#x2019;s <i>x</i> coordinate.
+ *
+ * @param left an array that will receive the coordinates of the
+ * left half of <code>src</code>. It is acceptable to pass
+ * <code>src</code>. A caller who is not interested in the left half
+ * can pass <code>null</code>.
+ *
+ * @param leftOff an offset into <code>left</code>, specifying the
+ * index where the start point&#x2019;s <i>x</i> coordinate will be
+ * stored.
+ *
+ * @param right an array that will receive the coordinates of the
+ * right half of <code>src</code>. It is acceptable to pass
+ * <code>src</code> or <code>left</code>. A caller who is not
+ * interested in the right half can pass <code>null</code>.
+ *
+ * @param rightOff an offset into <code>right</code>, specifying the
+ * index where the start point&#x2019;s <i>x</i> coordinate will be
+ * stored.
+ */
+ public static void subdivide(double[] src, int srcOff, double[] left,
+ int leftOff, double[] right, int rightOff)
+ {
+ // To understand this code, please have a look at the image
+ // "CubicCurve2D-3.png" in the sub-directory "doc-files".
+ double src_C1_x;
+ double src_C1_y;
+ double src_C2_x;
+ double src_C2_y;
+ double left_P1_x;
+ double left_P1_y;
+ double left_C1_x;
+ double left_C1_y;
+ double left_C2_x;
+ double left_C2_y;
+ double right_C1_x;
+ double right_C1_y;
+ double right_C2_x;
+ double right_C2_y;
+ double right_P2_x;
+ double right_P2_y;
+ double Mid_x; // Mid = left.P2 = right.P1
+ double Mid_y; // Mid = left.P2 = right.P1
+
+ left_P1_x = src[srcOff];
+ left_P1_y = src[srcOff + 1];
+ src_C1_x = src[srcOff + 2];
+ src_C1_y = src[srcOff + 3];
+ src_C2_x = src[srcOff + 4];
+ src_C2_y = src[srcOff + 5];
+ right_P2_x = src[srcOff + 6];
+ right_P2_y = src[srcOff + 7];
+
+ left_C1_x = (left_P1_x + src_C1_x) / 2;
+ left_C1_y = (left_P1_y + src_C1_y) / 2;
+ right_C2_x = (right_P2_x + src_C2_x) / 2;
+ right_C2_y = (right_P2_y + src_C2_y) / 2;
+ Mid_x = (src_C1_x + src_C2_x) / 2;
+ Mid_y = (src_C1_y + src_C2_y) / 2;
+ left_C2_x = (left_C1_x + Mid_x) / 2;
+ left_C2_y = (left_C1_y + Mid_y) / 2;
+ right_C1_x = (Mid_x + right_C2_x) / 2;
+ right_C1_y = (Mid_y + right_C2_y) / 2;
+ Mid_x = (left_C2_x + right_C1_x) / 2;
+ Mid_y = (left_C2_y + right_C1_y) / 2;
+
+ if (left != null)
+ {
+ left[leftOff] = left_P1_x;
+ left[leftOff + 1] = left_P1_y;
+ left[leftOff + 2] = left_C1_x;
+ left[leftOff + 3] = left_C1_y;
+ left[leftOff + 4] = left_C2_x;
+ left[leftOff + 5] = left_C2_y;
+ left[leftOff + 6] = Mid_x;
+ left[leftOff + 7] = Mid_y;
+ }
+
+ if (right != null)
+ {
+ right[rightOff] = Mid_x;
+ right[rightOff + 1] = Mid_y;
+ right[rightOff + 2] = right_C1_x;
+ right[rightOff + 3] = right_C1_y;
+ right[rightOff + 4] = right_C2_x;
+ right[rightOff + 5] = right_C2_y;
+ right[rightOff + 6] = right_P2_x;
+ right[rightOff + 7] = right_P2_y;
+ }
+ }
+
+ /**
+ * Finds the non-complex roots of a cubic equation, placing the
+ * results into the same array as the equation coefficients. The
+ * following equation is being solved:
+ *
+ * <blockquote><code>eqn[3]</code> &#xb7; <i>x</i><sup>3</sup>
+ * + <code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
+ * + <code>eqn[1]</code> &#xb7; <i>x</i>
+ * + <code>eqn[0]</code>
+ * = 0
+ * </blockquote>
+ *
+ * <p>For some background about solving cubic equations, see the
+ * article <a
+ * href="http://planetmath.org/encyclopedia/CubicFormula.html"
+ * >&#x201c;Cubic Formula&#x201d;</a> in <a
+ * href="http://planetmath.org/" >PlanetMath</a>. For an extensive
+ * library of numerical algorithms written in the C programming
+ * language, see the <a href= "http://www.gnu.org/software/gsl/">GNU
+ * Scientific Library</a>, from which this implementation was
+ * adapted.
+ *
+ * @param eqn an array with the coefficients of the equation. When
+ * this procedure has returned, <code>eqn</code> will contain the
+ * non-complex solutions of the equation, in no particular order.
+ *
+ * @return the number of non-complex solutions. A result of 0
+ * indicates that the equation has no non-complex solutions. A
+ * result of -1 indicates that the equation is constant (i.e.,
+ * always or never zero).
+ *
+ * @see #solveCubic(double[], double[])
+ * @see QuadCurve2D#solveQuadratic(double[],double[])
+ *
+ * @author Brian Gough (bjg@network-theory.com)
+ * (original C implementation in the <a href=
+ * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * (adaptation to Java)
+ */
+ public static int solveCubic(double[] eqn)
+ {
+ return solveCubic(eqn, eqn);
+ }
+
+ /**
+ * Finds the non-complex roots of a cubic equation. The following
+ * equation is being solved:
+ *
+ * <blockquote><code>eqn[3]</code> &#xb7; <i>x</i><sup>3</sup>
+ * + <code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
+ * + <code>eqn[1]</code> &#xb7; <i>x</i>
+ * + <code>eqn[0]</code>
+ * = 0
+ * </blockquote>
+ *
+ * <p>For some background about solving cubic equations, see the
+ * article <a
+ * href="http://planetmath.org/encyclopedia/CubicFormula.html"
+ * >&#x201c;Cubic Formula&#x201d;</a> in <a
+ * href="http://planetmath.org/" >PlanetMath</a>. For an extensive
+ * library of numerical algorithms written in the C programming
+ * language, see the <a href= "http://www.gnu.org/software/gsl/">GNU
+ * Scientific Library</a>, from which this implementation was
+ * adapted.
+ *
+ * @see QuadCurve2D#solveQuadratic(double[],double[])
+ *
+ * @param eqn an array with the coefficients of the equation.
+ *
+ * @param res an array into which the non-complex roots will be
+ * stored. The results may be in an arbitrary order. It is safe to
+ * pass the same array object reference for both <code>eqn</code>
+ * and <code>res</code>.
+ *
+ * @return the number of non-complex solutions. A result of 0
+ * indicates that the equation has no non-complex solutions. A
+ * result of -1 indicates that the equation is constant (i.e.,
+ * always or never zero).
+ *
+ * @author Brian Gough (bjg@network-theory.com)
+ * (original C implementation in the <a href=
+ * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * (adaptation to Java)
+ */
+ public static int solveCubic(double[] eqn, double[] res)
+ {
+ // Adapted from poly/solve_cubic.c in the GNU Scientific Library
+ // (GSL), revision 1.7 of 2003-07-26. For the original source, see
+ // http://www.gnu.org/software/gsl/
+ //
+ // Brian Gough, the author of that code, has granted the
+ // permission to use it in GNU Classpath under the GNU Classpath
+ // license, and has assigned the copyright to the Free Software
+ // Foundation.
+ //
+ // The Java implementation is very similar to the GSL code, but
+ // not a strict one-to-one copy. For example, GSL would sort the
+ // result.
+
+ double a;
+ double b;
+ double c;
+ double q;
+ double r;
+ double Q;
+ double R;
+ double c3;
+ double Q3;
+ double R2;
+ double CR2;
+ double CQ3;
+
+ // If the cubic coefficient is zero, we have a quadratic equation.
+ c3 = eqn[3];
+ if (c3 == 0)
+ return QuadCurve2D.solveQuadratic(eqn, res);
+
+ // Divide the equation by the cubic coefficient.
+ c = eqn[0] / c3;
+ b = eqn[1] / c3;
+ a = eqn[2] / c3;
+
+ // We now need to solve x^3 + ax^2 + bx + c = 0.
+ q = a * a - 3 * b;
+ r = 2 * a * a * a - 9 * a * b + 27 * c;
+
+ Q = q / 9;
+ R = r / 54;
+
+ Q3 = Q * Q * Q;
+ R2 = R * R;
+
+ CR2 = 729 * r * r;
+ CQ3 = 2916 * q * q * q;
+
+ if (R == 0 && Q == 0)
+ {
+ // The GNU Scientific Library would return three identical
+ // solutions in this case.
+ res[0] = -a / 3;
+ return 1;
+ }
+
+ if (CR2 == CQ3)
+ {
+ /* this test is actually R2 == Q3, written in a form suitable
+ for exact computation with integers */
+ /* Due to finite precision some double roots may be missed, and
+ considered to be a pair of complex roots z = x +/- epsilon i
+ close to the real axis. */
+ double sqrtQ = Math.sqrt(Q);
+
+ if (R > 0)
+ {
+ res[0] = -2 * sqrtQ - a / 3;
+ res[1] = sqrtQ - a / 3;
+ }
+ else
+ {
+ res[0] = -sqrtQ - a / 3;
+ res[1] = 2 * sqrtQ - a / 3;
+ }
+ return 2;
+ }
+
+ if (CR2 < CQ3) /* equivalent to R2 < Q3 */
+ {
+ double sqrtQ = Math.sqrt(Q);
+ double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
+ double theta = Math.acos(R / sqrtQ3);
+ double norm = -2 * sqrtQ;
+ res[0] = norm * Math.cos(theta / 3) - a / 3;
+ res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a / 3;
+ res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a / 3;
+
+ // The GNU Scientific Library sorts the results. We don't.
+ return 3;
+ }
+
+ double sgnR = (R >= 0 ? 1 : -1);
+ double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0);
+ double B = Q / A;
+ res[0] = A + B - a / 3;
+ return 1;
+ }
+
+ /**
+ * Determines whether a position lies inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ */
+ public boolean contains(double x, double y)
+ {
+ if (! getBounds2D().contains(x, y))
+ return false;
+
+ return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
+ }
+
+ /**
+ * Determines whether a point lies inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Determines whether any part of a rectangle is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; in a CubicCurve2D.
+ * @see #contains(double, double)
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().contains(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether any part of a Rectangle2D is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ * @see #intersects(double, double, double, double)
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determine whether a rectangle is entirely inside the area that is bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ * @see #contains(double, double)
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determine whether a Rectangle2D is entirely inside the area that is
+ * bounded by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ * @see #contains(double, double)
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control points.
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current = 0;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current >= 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getCtrlX1();
+ coords[1] = (float) getCtrlY1();
+ coords[2] = (float) getCtrlX2();
+ coords[3] = (float) getCtrlY2();
+ coords[4] = (float) getX2();
+ coords[5] = (float) getY2();
+ result = SEG_CUBICTO;
+ break;
+ default:
+ throw new NoSuchElementException("cubic iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 3);
+ return result;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getCtrlX1();
+ coords[1] = getCtrlY1();
+ coords[2] = getCtrlX2();
+ coords[3] = getCtrlY2();
+ coords[4] = getX2();
+ coords[5] = getY2();
+ result = SEG_CUBICTO;
+ break;
+ default:
+ throw new NoSuchElementException("cubic iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 3);
+ return result;
+ }
+ };
+ }
+
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ /**
+ * Create a new curve with the same contents as this one.
+ *
+ * @return the clone.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Helper method used by contains() and intersects() methods, that
+ * returns the number of curve/line intersections on a given axis
+ * extending from a certain point.
+ *
+ * @param x x coordinate of the origin point
+ * @param y y coordinate of the origin point
+ * @param useYaxis axis used, if true the positive Y axis is used,
+ * false uses the positive X axis.
+ *
+ * This is an implementation of the line-crossings algorithm,
+ * Detailed in an article on Eric Haines' page:
+ * http://www.acm.org/tog/editors/erich/ptinpoly/
+ *
+ * A special-case not adressed in this code is self-intersections
+ * of the curve, e.g. if the axis intersects the self-itersection,
+ * the degenerate roots of the polynomial will erroneously count as
+ * a single intersection of the curve, and not two.
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ int nCrossings = 0;
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double b0;
+ double b1;
+ double b2;
+ double b3;
+ double[] r = new double[4];
+ int nRoots;
+
+ a0 = a3 = 0.0;
+
+ if (useYaxis)
+ {
+ a0 = getY1() - y;
+ a1 = getCtrlY1() - y;
+ a2 = getCtrlY2() - y;
+ a3 = getY2() - y;
+ b0 = getX1() - x;
+ b1 = getCtrlX1() - x;
+ b2 = getCtrlX2() - x;
+ b3 = getX2() - x;
+ }
+ else
+ {
+ a0 = getX1() - x;
+ a1 = getCtrlX1() - x;
+ a2 = getCtrlX2() - x;
+ a3 = getX2() - x;
+ b0 = getY1() - y;
+ b1 = getCtrlY1() - y;
+ b2 = getCtrlY2() - y;
+ b3 = getY2() - y;
+ }
+
+ /* If the axis intersects a start/endpoint, shift it up by some small
+ amount to guarantee the line is 'inside'
+ If this is not done, bad behaviour may result for points on that axis.*/
+ if (a0 == 0.0 || a3 == 0.0)
+ {
+ double small = getFlatness() * EPSILON;
+ if (a0 == 0.0)
+ a0 -= small;
+ if (a3 == 0.0)
+ a3 -= small;
+ }
+
+ if (useYaxis)
+ {
+ if (Line2D.linesIntersect(b0, a0, b3, a3, EPSILON, 0.0, distance, 0.0))
+ nCrossings++;
+ }
+ else
+ {
+ if (Line2D.linesIntersect(a0, b0, a3, b3, 0.0, EPSILON, 0.0, distance))
+ nCrossings++;
+ }
+
+ r[0] = a0;
+ r[1] = 3 * (a1 - a0);
+ r[2] = 3 * (a2 + a0 - 2 * a1);
+ r[3] = a3 - 3 * a2 + 3 * a1 - a0;
+
+ if ((nRoots = solveCubic(r)) != 0)
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ double crossing = -(t * t * t) * (b0 - 3 * b1 + 3 * b2 - b3)
+ + 3 * t * t * (b0 - 2 * b1 + b2)
+ + 3 * t * (b1 - b0) + b0;
+ if (crossing > 0.0 && crossing <= distance)
+ nCrossings++;
+ }
+ }
+
+ return (nCrossings);
+ }
+
+ /**
+ * A two-dimensional curve that is parameterized with a cubic
+ * function and stores coordinate values in double-precision
+ * floating-point format.
+ *
+ * @see CubicCurve2D.Float
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ public static class Double extends CubicCurve2D
+ {
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s start point.
+ */
+ public double x1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s start point.
+ */
+ public double y1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s first control point.
+ */
+ public double ctrlx1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s first control point.
+ */
+ public double ctrly1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s second control point.
+ */
+ public double ctrlx2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s second control point.
+ */
+ public double ctrly2;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s end point.
+ */
+ public double x2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s end point.
+ */
+ public double y2;
+
+ /**
+ * Constructs a new CubicCurve2D that stores its coordinate values
+ * in double-precision floating-point format. All points are
+ * initially at position (0, 0).
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Constructs a new CubicCurve2D that stores its coordinate values
+ * in double-precision floating-point format, specifying the
+ * initial position of each point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s second
+ * control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public Double(double x1, double y1, double cx1, double cy1, double cx2,
+ double cy2, double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx1 = cx1;
+ ctrly1 = cy1;
+ ctrlx2 = cx2;
+ ctrly2 = cy2;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Double(x1, y1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public double getCtrlX1()
+ {
+ return ctrlx1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public double getCtrlY1()
+ {
+ return ctrly1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s first control point.
+ */
+ public Point2D getCtrlP1()
+ {
+ return new Point2D.Double(ctrlx1, ctrly1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public double getCtrlX2()
+ {
+ return ctrlx2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public double getCtrlY2()
+ {
+ return ctrly2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s second control point.
+ */
+ public Point2D getCtrlP2()
+ {
+ return new Point2D.Double(ctrlx2, ctrly2);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Double(x2, y2);
+ }
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public void setCurve(double x1, double y1, double cx1, double cy1,
+ double cx2, double cy2, double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx1 = cx1;
+ ctrly1 = cy1;
+ ctrlx2 = cx2;
+ ctrly2 = cy2;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control points. As the
+ * illustration below shows, the invisible control points may cause
+ * the bounds to be much larger than the area that is actually
+ * covered by the curve.
+ *
+ * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a CubicCurve2D" />
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double nx1 = Math.min(Math.min(x1, ctrlx1), Math.min(ctrlx2, x2));
+ double ny1 = Math.min(Math.min(y1, ctrly1), Math.min(ctrly2, y2));
+ double nx2 = Math.max(Math.max(x1, ctrlx1), Math.max(ctrlx2, x2));
+ double ny2 = Math.max(Math.max(y1, ctrly1), Math.max(ctrly2, y2));
+ return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1);
+ }
+ }
+
+ /**
+ * A two-dimensional curve that is parameterized with a cubic
+ * function and stores coordinate values in single-precision
+ * floating-point format.
+ *
+ * @see CubicCurve2D.Float
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ public static class Float extends CubicCurve2D
+ {
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s start point.
+ */
+ public float x1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s start point.
+ */
+ public float y1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s first control point.
+ */
+ public float ctrlx1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s first control point.
+ */
+ public float ctrly1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s second control point.
+ */
+ public float ctrlx2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s second control point.
+ */
+ public float ctrly2;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s end point.
+ */
+ public float x2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s end point.
+ */
+ public float y2;
+
+ /**
+ * Constructs a new CubicCurve2D that stores its coordinate values
+ * in single-precision floating-point format. All points are
+ * initially at position (0, 0).
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Constructs a new CubicCurve2D that stores its coordinate values
+ * in single-precision floating-point format, specifying the
+ * initial position of each point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s second
+ * control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public Float(float x1, float y1, float cx1, float cy1, float cx2,
+ float cy2, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx1 = cx1;
+ ctrly1 = cy1;
+ ctrlx2 = cx2;
+ ctrly2 = cy2;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Float(x1, y1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public double getCtrlX1()
+ {
+ return ctrlx1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public double getCtrlY1()
+ {
+ return ctrly1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s first control point.
+ */
+ public Point2D getCtrlP1()
+ {
+ return new Point2D.Float(ctrlx1, ctrly1);
+ }
+
+ /**
+ * Returns the <i>s</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public double getCtrlX2()
+ {
+ return ctrlx2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public double getCtrlY2()
+ {
+ return ctrly2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s second control point.
+ */
+ public Point2D getCtrlP2()
+ {
+ return new Point2D.Float(ctrlx2, ctrly2);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Float(x2, y2);
+ }
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value as a double-precision floating-point number.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public void setCurve(double x1, double y1, double cx1, double cy1,
+ double cx2, double cy2, double x2, double y2)
+ {
+ this.x1 = (float) x1;
+ this.y1 = (float) y1;
+ ctrlx1 = (float) cx1;
+ ctrly1 = (float) cy1;
+ ctrlx2 = (float) cx2;
+ ctrly2 = (float) cy2;
+ this.x2 = (float) x2;
+ this.y2 = (float) y2;
+ }
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value as a single-precision floating-point number.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public void setCurve(float x1, float y1, float cx1, float cy1, float cx2,
+ float cy2, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx1 = cx1;
+ ctrly1 = cy1;
+ ctrlx2 = cx2;
+ ctrly2 = cy2;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control points. As the
+ * illustration below shows, the invisible control points may cause
+ * the bounds to be much larger than the area that is actually
+ * covered by the curve.
+ *
+ * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a CubicCurve2D" />
+ */
+ public Rectangle2D getBounds2D()
+ {
+ float nx1 = (float) Math.min(Math.min(x1, ctrlx1), Math.min(ctrlx2, x2));
+ float ny1 = (float) Math.min(Math.min(y1, ctrly1), Math.min(ctrly2, y2));
+ float nx2 = (float) Math.max(Math.max(x1, ctrlx1), Math.max(ctrlx2, x2));
+ float ny2 = (float) Math.max(Math.max(y1, ctrly1), Math.max(ctrly2, y2));
+ return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/Dimension2D.java b/libjava/classpath/java/awt/geom/Dimension2D.java
new file mode 100644
index 00000000000..6b5ce8830a9
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Dimension2D.java
@@ -0,0 +1,118 @@
+/* Dimension2D.java -- abstraction of a dimension
+ Copyright (C) 1999, 2000, 2002 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.geom;
+
+/**
+ * This stores a dimension in 2-dimensional space - a width (along the x-axis)
+ * and height (along the y-axis). The storage is left to subclasses.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class Dimension2D implements Cloneable
+{
+ /**
+ * The default constructor.
+ */
+ protected Dimension2D()
+ {
+ }
+
+ /**
+ * Get the width of this dimension. A negative result, while legal, is
+ * undefined in meaning.
+ *
+ * @return the width
+ */
+ public abstract double getWidth();
+
+ /**
+ * Get the height of this dimension. A negative result, while legal, is
+ * undefined in meaning.
+ *
+ * @return the height
+ */
+ public abstract double getHeight();
+
+ /**
+ * Set the size of this dimension to the requested values. Loss of precision
+ * may occur.
+ *
+ * @param w the new width
+ * @param h the new height
+ */
+ public abstract void setSize(double w, double h);
+
+ /**
+ * Set the size of this dimension to the requested value. Loss of precision
+ * may occur.
+ *
+ * @param d the dimension containing the new values
+ *
+ * @throws NullPointerException if d is null
+ */
+ public void setSize(Dimension2D d)
+ {
+ setSize(d.getWidth(), d.getHeight());
+ }
+
+ /**
+ * Create a new dimension of the same run-time type with the same contents
+ * as this one.
+ *
+ * @return the clone
+ *
+ * @exception OutOfMemoryError If there is not enough memory available.
+ *
+ * @since 1.2
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+} // class Dimension2D
diff --git a/libjava/classpath/java/awt/geom/Ellipse2D.java b/libjava/classpath/java/awt/geom/Ellipse2D.java
new file mode 100644
index 00000000000..e8830770f60
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Ellipse2D.java
@@ -0,0 +1,413 @@
+/* Ellipse2D.java -- represents an ellipse in 2-D space
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+
+/**
+ * Ellipse2D is the shape of an ellipse.
+ * <BR>
+ * <img src="doc-files/Ellipse-1.png" width="347" height="221"
+ * alt="A drawing of an ellipse" /><BR>
+ * The ellipse is defined by it's bounding box (shown in red),
+ * and is defined by the implicit curve:<BR>
+ * <blockquote>(<i>x</i>/<i>a</i>)<sup>2</sup> +
+ * (<i>y</i>/<i>b</i>)<sup>2</sup> = 1<BR><BR></blockquote>
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.2
+ */
+public abstract class Ellipse2D extends RectangularShape
+{
+ /**
+ * Ellipse2D is defined as abstract.
+ * Implementing classes are Ellipse2D.Float and Ellipse2D.Double.
+ */
+ protected Ellipse2D()
+ {
+ }
+
+ /**
+ * Determines if a point is contained within the ellipse. <P>
+ * @param x - x coordinate of the point.
+ * @param y - y coordinate of the point.
+ * @return true if the point is within the ellipse, false otherwise.
+ */
+ public boolean contains(double x, double y)
+ {
+ double rx = getWidth() / 2;
+ double ry = getHeight() / 2;
+ double tx = (x - (getX() + rx)) / rx;
+ double ty = (y - (getY() + ry)) / ry;
+ return tx * tx + ty * ty < 1.0;
+ }
+
+ /**
+ * Determines if a rectangle is completely contained within the
+ * ellipse. <P>
+ * @param x - x coordinate of the upper-left corner of the rectangle
+ * @param y - y coordinate of the upper-left corner of the rectangle
+ * @param w - width of the rectangle
+ * @param h - height of the rectangle
+ * @return true if the rectangle is completely contained, false otherwise.
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ double x2 = x + w;
+ double y2 = y + h;
+ return (contains(x, y) && contains(x, y2) && contains(x2, y)
+ && contains(x2, y2));
+ }
+
+ /**
+ * Returns a PathIterator object corresponding to the ellipse.<P>
+ *
+ * Note: An ellipse cannot be represented exactly in PathIterator
+ * segments, the outline is thefore approximated with cubic
+ * Bezier segments.
+ *
+ * @param at an optional transform.
+ * @return A path iterator.
+ */
+ public PathIterator getPathIterator(AffineTransform at)
+ {
+ // An ellipse is just a complete arc.
+ return new Arc2D.ArcIterator(this, at);
+ }
+
+ /**
+ * Determines if a rectangle intersects any part of the ellipse.<P>
+ * @param x - x coordinate of the upper-left corner of the rectangle
+ * @param y - y coordinate of the upper-left corner of the rectangle
+ * @param w - width of the rectangle
+ * @param h - height of the rectangle
+ * @return true if the rectangle intersects the ellipse, false otherwise.
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ Rectangle2D r = new Rectangle2D.Double(x, y, w, h);
+ if (! r.intersects(getX(), getY(), getWidth(), getHeight()))
+ return false;
+
+ if (contains(x, y) || contains(x, y + h) || contains(x + w, y)
+ || contains(x + w, y + h))
+ return true;
+
+ Line2D l1 = new Line2D.Double(getX(), getY() + (getHeight() / 2),
+ getX() + getWidth(),
+ getY() + (getHeight() / 2));
+ Line2D l2 = new Line2D.Double(getX() + (getWidth() / 2), getY(),
+ getX() + (getWidth() / 2),
+ getY() + getHeight());
+
+ if (l1.intersects(r) || l2.intersects(r))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * An {@link Ellipse2D} that stores its coordinates using <code>double</code>
+ * primitives.
+ */
+ public static class Double extends Ellipse2D
+ {
+ /**
+ * The height of the ellipse.
+ */
+ public double height;
+
+ /**
+ * The width of the ellipse.
+ */
+ public double width;
+
+ /**
+ * The upper-left x coordinate of the bounding-box
+ */
+ public double x;
+
+ /**
+ * The upper-left y coordinate of the bounding-box
+ */
+ public double y;
+
+ /**
+ * Creates a new Ellipse2D with an upper-left coordinate of (0,0)
+ * and a zero size.
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Creates a new Ellipse2D within a given rectangle
+ * using double-precision coordinates.<P>
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ */
+ public Double(double x, double y, double w, double h)
+ {
+ this.x = x;
+ this.y = y;
+ height = h;
+ width = w;
+ }
+
+ /**
+ * Returns the bounding-box of the ellipse.
+ * @return The bounding box.
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle2D.Double(x, y, width, height);
+ }
+
+ /**
+ * Returns the height of the ellipse.
+ * @return The height of the ellipse.
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the width of the ellipse.
+ * @return The width of the ellipse.
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns x coordinate of the upper-left corner of
+ * the ellipse's bounding-box.
+ * @return The x coordinate.
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Returns y coordinate of the upper-left corner of
+ * the ellipse's bounding-box.
+ * @return The y coordinate.
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Returns <code>true</code> if the ellipse encloses no area, and
+ * <code>false</code> otherwise.
+ *
+ * @return A boolean.
+ */
+ public boolean isEmpty()
+ {
+ return height <= 0 || width <= 0;
+ }
+
+ /**
+ * Sets the geometry of the ellipse's bounding box.<P>
+ *
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ this.x = x;
+ this.y = y;
+ height = h;
+ width = w;
+ }
+ } // class Double
+
+ /**
+ * An {@link Ellipse2D} that stores its coordinates using <code>float</code>
+ * primitives.
+ */
+ public static class Float extends Ellipse2D
+ {
+ /**
+ * The height of the ellipse.
+ */
+ public float height;
+
+ /**
+ * The width of the ellipse.
+ */
+ public float width;
+
+ /**
+ * The upper-left x coordinate of the bounding-box
+ */
+ public float x;
+
+ /**
+ * The upper-left y coordinate of the bounding-box
+ */
+ public float y;
+
+ /**
+ * Creates a new Ellipse2D with an upper-left coordinate of (0,0)
+ * and a zero size.
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Creates a new Ellipse2D within a given rectangle
+ * using floating-point precision.<P>
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ *
+ */
+ public Float(float x, float y, float w, float h)
+ {
+ this.x = x;
+ this.y = y;
+ this.height = h;
+ this.width = w;
+ }
+
+ /**
+ * Returns the bounding-box of the ellipse.
+ * @return The bounding box.
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle2D.Float(x, y, width, height);
+ }
+
+ /**
+ * Returns the height of the ellipse.
+ * @return The height of the ellipse.
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the width of the ellipse.
+ * @return The width of the ellipse.
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns x coordinate of the upper-left corner of
+ * the ellipse's bounding-box.
+ * @return The x coordinate.
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Returns y coordinate of the upper-left corner of
+ * the ellipse's bounding-box.
+ * @return The y coordinate.
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Returns <code>true</code> if the ellipse encloses no area, and
+ * <code>false</code> otherwise.
+ *
+ * @return A boolean.
+ */
+ public boolean isEmpty()
+ {
+ return height <= 0 || width <= 0;
+ }
+
+ /**
+ * Sets the geometry of the ellipse's bounding box.<P>
+ *
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ */
+ public void setFrame(float x, float y, float w, float h)
+ {
+ this.x = x;
+ this.y = y;
+ height = h;
+ width = w;
+ }
+
+ /**
+ * Sets the geometry of the ellipse's bounding box.
+ *
+ * Note: This leads to a loss of precision.<P>
+ *
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ height = (float) h;
+ width = (float) w;
+ }
+ } // class Float
+} // class Ellipse2D
diff --git a/libjava/classpath/java/awt/geom/FlatteningPathIterator.java b/libjava/classpath/java/awt/geom/FlatteningPathIterator.java
new file mode 100644
index 00000000000..b06e6cc47b8
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/FlatteningPathIterator.java
@@ -0,0 +1,579 @@
+/* FlatteningPathIterator.java -- Approximates curves by straight lines
+ Copyright (C) 2003 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.geom;
+
+import java.util.NoSuchElementException;
+
+
+/**
+ * A PathIterator for approximating curved path segments by sequences
+ * of straight lines. Instances of this class will only return
+ * segments of type {@link PathIterator#SEG_MOVETO}, {@link
+ * PathIterator#SEG_LINETO}, and {@link PathIterator#SEG_CLOSE}.
+ *
+ * <p>The accuracy of the approximation is determined by two
+ * parameters:
+ *
+ * <ul><li>The <i>flatness</i> is a threshold value for deciding when
+ * a curved segment is consided flat enough for being approximated by
+ * a single straight line. Flatness is defined as the maximal distance
+ * of a curve control point to the straight line that connects the
+ * curve start and end. A lower flatness threshold means a closer
+ * approximation. See {@link QuadCurve2D#getFlatness()} and {@link
+ * CubicCurve2D#getFlatness()} for drawings which illustrate the
+ * meaning of flatness.</li>
+ *
+ * <li>The <i>recursion limit</i> imposes an upper bound for how often
+ * a curved segment gets subdivided. A limit of <i>n</i> means that
+ * for each individual quadratic and cubic B&#xe9;zier spline
+ * segment, at most 2<sup><small><i>n</i></small></sup> {@link
+ * PathIterator#SEG_LINETO} segments will be created.</li></ul>
+ *
+ * <p><b>Memory Efficiency:</b> The memory consumption grows linearly
+ * with the recursion limit. Neither the <i>flatness</i> parameter nor
+ * the number of segments in the flattened path will affect the memory
+ * consumption.
+ *
+ * <p><b>Thread Safety:</b> Multiple threads can safely work on
+ * separate instances of this class. However, multiple threads should
+ * not concurrently access the same instance, as no synchronization is
+ * performed.
+ *
+ * @see <a href="doc-files/FlatteningPathIterator-1.html"
+ * >Implementation Note</a>
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ *
+ * @since 1.2
+ */
+public class FlatteningPathIterator
+ implements PathIterator
+{
+ /**
+ * The PathIterator whose curved segments are being approximated.
+ */
+ private final PathIterator srcIter;
+
+
+ /**
+ * The square of the flatness threshold value, which determines when
+ * a curve segment is considered flat enough that no further
+ * subdivision is needed.
+ *
+ * <p>Calculating flatness actually produces the squared flatness
+ * value. To avoid the relatively expensive calculation of a square
+ * root for each curve segment, we perform all flatness comparisons
+ * on squared values.
+ *
+ * @see QuadCurve2D#getFlatnessSq()
+ * @see CubicCurve2D#getFlatnessSq()
+ */
+ private final double flatnessSq;
+
+
+ /**
+ * The maximal number of subdivions that are performed to
+ * approximate a quadratic or cubic curve segment.
+ */
+ private final int recursionLimit;
+
+
+ /**
+ * A stack for holding the coordinates of subdivided segments.
+ *
+ * @see <a href="doc-files/FlatteningPathIterator-1.html"
+ * >Implementation Note</a>
+ */
+ private double[] stack;
+
+
+ /**
+ * The current stack size.
+ *
+ * @see <a href="doc-files/FlatteningPathIterator-1.html"
+ * >Implementation Note</a>
+ */
+ private int stackSize;
+
+
+ /**
+ * The number of recursions that were performed to arrive at
+ * a segment on the stack.
+ *
+ * @see <a href="doc-files/FlatteningPathIterator-1.html"
+ * >Implementation Note</a>
+ */
+ private int[] recLevel;
+
+
+
+ private final double[] scratch = new double[6];
+
+
+ /**
+ * The segment type of the last segment that was returned by
+ * the source iterator.
+ */
+ private int srcSegType;
+
+
+ /**
+ * The current <i>x</i> position of the source iterator.
+ */
+ private double srcPosX;
+
+
+ /**
+ * The current <i>y</i> position of the source iterator.
+ */
+ private double srcPosY;
+
+
+ /**
+ * A flag that indicates when this path iterator has finished its
+ * iteration over path segments.
+ */
+ private boolean done;
+
+
+ /**
+ * Constructs a new PathIterator for approximating an input
+ * PathIterator with straight lines. The approximation works by
+ * recursive subdivisons, until the specified flatness threshold is
+ * not exceeded.
+ *
+ * <p>There will not be more than 10 nested recursion steps, which
+ * means that a single <code>SEG_QUADTO</code> or
+ * <code>SEG_CUBICTO</code> segment is approximated by at most
+ * 2<sup><small>10</small></sup> = 1024 straight lines.
+ */
+ public FlatteningPathIterator(PathIterator src, double flatness)
+ {
+ this(src, flatness, 10);
+ }
+
+
+ /**
+ * Constructs a new PathIterator for approximating an input
+ * PathIterator with straight lines. The approximation works by
+ * recursive subdivisons, until the specified flatness threshold is
+ * not exceeded. Additionally, the number of recursions is also
+ * bound by the specified recursion limit.
+ */
+ public FlatteningPathIterator(PathIterator src, double flatness,
+ int limit)
+ {
+ if (flatness < 0 || limit < 0)
+ throw new IllegalArgumentException();
+
+ srcIter = src;
+ flatnessSq = flatness * flatness;
+ recursionLimit = limit;
+ fetchSegment();
+ }
+
+
+ /**
+ * Returns the maximally acceptable flatness.
+ *
+ * @see QuadCurve2D#getFlatness()
+ * @see CubicCurve2D#getFlatness()
+ */
+ public double getFlatness()
+ {
+ return Math.sqrt(flatnessSq);
+ }
+
+
+ /**
+ * Returns the maximum number of recursive curve subdivisions.
+ */
+ public int getRecursionLimit()
+ {
+ return recursionLimit;
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public int getWindingRule()
+ {
+ return srcIter.getWindingRule();
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public boolean isDone()
+ {
+ return done;
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public void next()
+ {
+ if (stackSize > 0)
+ {
+ --stackSize;
+ if (stackSize > 0)
+ {
+ switch (srcSegType)
+ {
+ case PathIterator.SEG_QUADTO:
+ subdivideQuadratic();
+ return;
+
+ case PathIterator.SEG_CUBICTO:
+ subdivideCubic();
+ return;
+
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ srcIter.next();
+ fetchSegment();
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public int currentSegment(double[] coords)
+ {
+ if (done)
+ throw new NoSuchElementException();
+
+ switch (srcSegType)
+ {
+ case PathIterator.SEG_CLOSE:
+ return srcSegType;
+
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ coords[0] = srcPosX;
+ coords[1] = srcPosY;
+ return srcSegType;
+
+ case PathIterator.SEG_QUADTO:
+ if (stackSize == 0)
+ {
+ coords[0] = srcPosX;
+ coords[1] = srcPosY;
+ }
+ else
+ {
+ int sp = stack.length - 4 * stackSize;
+ coords[0] = stack[sp + 2];
+ coords[1] = stack[sp + 3];
+ }
+ return PathIterator.SEG_LINETO;
+
+ case PathIterator.SEG_CUBICTO:
+ if (stackSize == 0)
+ {
+ coords[0] = srcPosX;
+ coords[1] = srcPosY;
+ }
+ else
+ {
+ int sp = stack.length - 6 * stackSize;
+ coords[0] = stack[sp + 4];
+ coords[1] = stack[sp + 5];
+ }
+ return PathIterator.SEG_LINETO;
+ }
+
+ throw new IllegalStateException();
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public int currentSegment(float[] coords)
+ {
+ if (done)
+ throw new NoSuchElementException();
+
+ switch (srcSegType)
+ {
+ case PathIterator.SEG_CLOSE:
+ return srcSegType;
+
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ coords[0] = (float) srcPosX;
+ coords[1] = (float) srcPosY;
+ return srcSegType;
+
+ case PathIterator.SEG_QUADTO:
+ if (stackSize == 0)
+ {
+ coords[0] = (float) srcPosX;
+ coords[1] = (float) srcPosY;
+ }
+ else
+ {
+ int sp = stack.length - 4 * stackSize;
+ coords[0] = (float) stack[sp + 2];
+ coords[1] = (float) stack[sp + 3];
+ }
+ return PathIterator.SEG_LINETO;
+
+ case PathIterator.SEG_CUBICTO:
+ if (stackSize == 0)
+ {
+ coords[0] = (float) srcPosX;
+ coords[1] = (float) srcPosY;
+ }
+ else
+ {
+ int sp = stack.length - 6 * stackSize;
+ coords[0] = (float) stack[sp + 4];
+ coords[1] = (float) stack[sp + 5];
+ }
+ return PathIterator.SEG_LINETO;
+ }
+
+ throw new IllegalStateException();
+ }
+
+
+ /**
+ * Fetches the next segment from the source iterator.
+ */
+ private void fetchSegment()
+ {
+ int sp;
+
+ if (srcIter.isDone())
+ {
+ done = true;
+ return;
+ }
+
+ srcSegType = srcIter.currentSegment(scratch);
+
+ switch (srcSegType)
+ {
+ case PathIterator.SEG_CLOSE:
+ return;
+
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ srcPosX = scratch[0];
+ srcPosY = scratch[1];
+ return;
+
+ case PathIterator.SEG_QUADTO:
+ if (recursionLimit == 0)
+ {
+ srcPosX = scratch[2];
+ srcPosY = scratch[3];
+ stackSize = 0;
+ return;
+ }
+ sp = 4 * recursionLimit;
+ stackSize = 1;
+ if (stack == null)
+ {
+ stack = new double[sp + /* 4 + 2 */ 6];
+ recLevel = new int[recursionLimit + 1];
+ }
+ recLevel[0] = 0;
+ stack[sp] = srcPosX; // P1.x
+ stack[sp + 1] = srcPosY; // P1.y
+ stack[sp + 2] = scratch[0]; // C.x
+ stack[sp + 3] = scratch[1]; // C.y
+ srcPosX = stack[sp + 4] = scratch[2]; // P2.x
+ srcPosY = stack[sp + 5] = scratch[3]; // P2.y
+ subdivideQuadratic();
+ break;
+
+ case PathIterator.SEG_CUBICTO:
+ if (recursionLimit == 0)
+ {
+ srcPosX = scratch[4];
+ srcPosY = scratch[5];
+ stackSize = 0;
+ return;
+ }
+ sp = 6 * recursionLimit;
+ stackSize = 1;
+ if ((stack == null) || (stack.length < sp + 8))
+ {
+ stack = new double[sp + /* 6 + 2 */ 8];
+ recLevel = new int[recursionLimit + 1];
+ }
+ recLevel[0] = 0;
+ stack[sp] = srcPosX; // P1.x
+ stack[sp + 1] = srcPosY; // P1.y
+ stack[sp + 2] = scratch[0]; // C1.x
+ stack[sp + 3] = scratch[1]; // C1.y
+ stack[sp + 4] = scratch[2]; // C2.x
+ stack[sp + 5] = scratch[3]; // C2.y
+ srcPosX = stack[sp + 6] = scratch[4]; // P2.x
+ srcPosY = stack[sp + 7] = scratch[5]; // P2.y
+ subdivideCubic();
+ return;
+ }
+ }
+
+
+ /**
+ * Repeatedly subdivides the quadratic curve segment that is on top
+ * of the stack. The iteration terminates when the recursion limit
+ * has been reached, or when the resulting segment is flat enough.
+ */
+ private void subdivideQuadratic()
+ {
+ int sp;
+ int level;
+
+ sp = stack.length - 4 * stackSize - 2;
+ level = recLevel[stackSize - 1];
+ while ((level < recursionLimit)
+ && (QuadCurve2D.getFlatnessSq(stack, sp) >= flatnessSq))
+ {
+ recLevel[stackSize] = recLevel[stackSize - 1] = ++level;
+ QuadCurve2D.subdivide(stack, sp, stack, sp - 4, stack, sp);
+ ++stackSize;
+ sp -= 4;
+ }
+ }
+
+
+ /**
+ * Repeatedly subdivides the cubic curve segment that is on top
+ * of the stack. The iteration terminates when the recursion limit
+ * has been reached, or when the resulting segment is flat enough.
+ */
+ private void subdivideCubic()
+ {
+ int sp;
+ int level;
+
+ sp = stack.length - 6 * stackSize - 2;
+ level = recLevel[stackSize - 1];
+ while ((level < recursionLimit)
+ && (CubicCurve2D.getFlatnessSq(stack, sp) >= flatnessSq))
+ {
+ recLevel[stackSize] = recLevel[stackSize - 1] = ++level;
+
+ CubicCurve2D.subdivide(stack, sp, stack, sp - 6, stack, sp);
+ ++stackSize;
+ sp -= 6;
+ }
+ }
+
+
+ /* These routines were useful for debugging. Since they would
+ * just bloat the implementation, they are commented out.
+ *
+ *
+
+ private static String segToString(int segType, double[] d, int offset)
+ {
+ String s;
+
+ switch (segType)
+ {
+ case PathIterator.SEG_CLOSE:
+ return "SEG_CLOSE";
+
+ case PathIterator.SEG_MOVETO:
+ return "SEG_MOVETO (" + d[offset] + ", " + d[offset + 1] + ")";
+
+ case PathIterator.SEG_LINETO:
+ return "SEG_LINETO (" + d[offset] + ", " + d[offset + 1] + ")";
+
+ case PathIterator.SEG_QUADTO:
+ return "SEG_QUADTO (" + d[offset] + ", " + d[offset + 1]
+ + ") (" + d[offset + 2] + ", " + d[offset + 3] + ")";
+
+ case PathIterator.SEG_CUBICTO:
+ return "SEG_CUBICTO (" + d[offset] + ", " + d[offset + 1]
+ + ") (" + d[offset + 2] + ", " + d[offset + 3]
+ + ") (" + d[offset + 4] + ", " + d[offset + 5] + ")";
+ }
+
+ throw new IllegalStateException();
+ }
+
+
+ private void dumpQuadraticStack(String msg)
+ {
+ int sp = stack.length - 4 * stackSize - 2;
+ int i = 0;
+ System.err.print(" " + msg + ":");
+ while (sp < stack.length)
+ {
+ System.err.print(" (" + stack[sp] + ", " + stack[sp+1] + ")");
+ if (i < recLevel.length)
+ System.out.print("/" + recLevel[i++]);
+ if (sp + 3 < stack.length)
+ System.err.print(" [" + stack[sp+2] + ", " + stack[sp+3] + "]");
+ sp += 4;
+ }
+ System.err.println();
+ }
+
+
+ private void dumpCubicStack(String msg)
+ {
+ int sp = stack.length - 6 * stackSize - 2;
+ int i = 0;
+ System.err.print(" " + msg + ":");
+ while (sp < stack.length)
+ {
+ System.err.print(" (" + stack[sp] + ", " + stack[sp+1] + ")");
+ if (i < recLevel.length)
+ System.out.print("/" + recLevel[i++]);
+ if (sp + 3 < stack.length)
+ {
+ System.err.print(" [" + stack[sp+2] + ", " + stack[sp+3] + "]");
+ System.err.print(" [" + stack[sp+4] + ", " + stack[sp+5] + "]");
+ }
+ sp += 6;
+ }
+ System.err.println();
+ }
+
+ *
+ *
+ */
+}
diff --git a/libjava/classpath/java/awt/geom/GeneralPath.java b/libjava/classpath/java/awt/geom/GeneralPath.java
new file mode 100644
index 00000000000..f54855874dc
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/GeneralPath.java
@@ -0,0 +1,958 @@
+/* GeneralPath.java -- represents a shape built from subpaths
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+
+/**
+ * A general geometric path, consisting of any number of subpaths
+ * constructed out of straight lines and cubic or quadratic Bezier
+ * curves.
+ *
+ * <p>The inside of the curve is defined for drawing purposes by a winding
+ * rule. Either the WIND_EVEN_ODD or WIND_NON_ZERO winding rule can be chosen.
+ *
+ * <p><img src="doc-files/GeneralPath-1.png" width="300" height="210"
+ * alt="A drawing of a GeneralPath" />
+ * <p>The EVEN_ODD winding rule defines a point as inside a path if:
+ * A ray from the point towards infinity in an arbitrary direction
+ * intersects the path an odd number of times. Points <b>A</b> and
+ * <b>C</b> in the image are considered to be outside the path.
+ * (both intersect twice)
+ * Point <b>B</b> intersects once, and is inside.
+ *
+ * <p>The NON_ZERO winding rule defines a point as inside a path if:
+ * The path intersects the ray in an equal number of opposite directions.
+ * Point <b>A</b> in the image is outside (one intersection in the
+ * &#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;)
+ *
+ * @see Line2D
+ * @see CubicCurve2D
+ * @see QuadCurve2D
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
+ */
+public final class GeneralPath implements Shape, Cloneable
+{
+ public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
+ public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
+
+ /** Initial size if not specified. */
+ private static final int INIT_SIZE = 10;
+
+ /** A big number, but not so big it can't survive a few float operations */
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+
+ /** The winding rule.
+ * This is package-private to avoid an accessor method.
+ */
+ int rule;
+
+ /**
+ * The path type in points. Note that xpoints[index] and ypoints[index] maps
+ * to types[index]; the control points of quad and cubic paths map as
+ * well but are ignored.
+ * This is package-private to avoid an accessor method.
+ */
+ byte[] types;
+
+ /**
+ * The list of all points seen. Since you can only append floats, it makes
+ * sense for these to be float[]. I have no idea why Sun didn't choose to
+ * allow a general path of double precision points.
+ * Note: Storing x and y coords seperately makes for a slower transforms,
+ * But it speeds up and simplifies box-intersection checking a lot.
+ * These are package-private to avoid accessor methods.
+ */
+ float[] xpoints;
+ float[] ypoints;
+
+ /** The index of the most recent moveto point, or null. */
+ private int subpath = -1;
+
+ /** The next available index into points.
+ * This is package-private to avoid an accessor method.
+ */
+ int index;
+
+ /**
+ * Constructs a GeneralPath with the default (NON_ZERO)
+ * winding rule and initial capacity (20).
+ */
+ public GeneralPath()
+ {
+ this(WIND_NON_ZERO, INIT_SIZE);
+ }
+
+ /**
+ * Constructs a GeneralPath with a specific winding rule
+ * and the default initial capacity (20).
+ * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD)
+ */
+ public GeneralPath(int rule)
+ {
+ this(rule, INIT_SIZE);
+ }
+
+ /**
+ * Constructs a GeneralPath with a specific winding rule
+ * and the initial capacity. The initial capacity should be
+ * the approximate number of path segments to be used.
+ * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD)
+ * @param capacity the inital capacity, in path segments
+ */
+ public GeneralPath(int rule, int capacity)
+ {
+ if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
+ throw new IllegalArgumentException();
+ this.rule = rule;
+ if (capacity < INIT_SIZE)
+ capacity = INIT_SIZE;
+ types = new byte[capacity];
+ xpoints = new float[capacity];
+ ypoints = new float[capacity];
+ }
+
+ /**
+ * Constructs a GeneralPath from an arbitrary shape object.
+ * The Shapes PathIterator path and winding rule will be used.
+ * @param s the shape
+ */
+ public GeneralPath(Shape s)
+ {
+ types = new byte[INIT_SIZE];
+ xpoints = new float[INIT_SIZE];
+ ypoints = new float[INIT_SIZE];
+ PathIterator pi = s.getPathIterator(null);
+ setWindingRule(pi.getWindingRule());
+ append(pi, false);
+ }
+
+ /**
+ * Adds a new point to a path.
+ */
+ public void moveTo(float x, float y)
+ {
+ subpath = index;
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_MOVETO;
+ xpoints[index] = x;
+ ypoints[index++] = y;
+ }
+
+ /**
+ * Appends a straight line to the current path.
+ * @param x x coordinate of the line endpoint.
+ * @param y y coordinate of the line endpoint.
+ */
+ public void lineTo(float x, float y)
+ {
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_LINETO;
+ xpoints[index] = x;
+ ypoints[index++] = y;
+ }
+
+ /**
+ * Appends a quadratic Bezier curve to the current path.
+ * @param x1 x coordinate of the control point
+ * @param y1 y coordinate of the control point
+ * @param x2 x coordinate of the curve endpoint.
+ * @param y2 y coordinate of the curve endpoint.
+ */
+ public void quadTo(float x1, float y1, float x2, float y2)
+ {
+ ensureSize(index + 2);
+ types[index] = PathIterator.SEG_QUADTO;
+ xpoints[index] = x1;
+ ypoints[index++] = y1;
+ xpoints[index] = x2;
+ ypoints[index++] = y2;
+ }
+
+ /**
+ * Appends a cubic Bezier curve to the current path.
+ * @param x1 x coordinate of the first control point
+ * @param y1 y coordinate of the first control point
+ * @param x2 x coordinate of the second control point
+ * @param y2 y coordinate of the second control point
+ * @param x3 x coordinate of the curve endpoint.
+ * @param y3 y coordinate of the curve endpoint.
+ */
+ public void curveTo(float x1, float y1, float x2, float y2, float x3,
+ float y3)
+ {
+ ensureSize(index + 3);
+ types[index] = PathIterator.SEG_CUBICTO;
+ xpoints[index] = x1;
+ ypoints[index++] = y1;
+ xpoints[index] = x2;
+ ypoints[index++] = y2;
+ xpoints[index] = x3;
+ ypoints[index++] = y3;
+ }
+
+ /**
+ * Closes the current subpath by drawing a line
+ * back to the point of the last moveTo.
+ */
+ public void closePath()
+ {
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_CLOSE;
+ xpoints[index] = xpoints[subpath];
+ ypoints[index++] = ypoints[subpath];
+ }
+
+ /**
+ * Appends the segments of a Shape to the path. If <code>connect</code> is
+ * true, the new path segments are connected to the existing one with a line.
+ * The winding rule of the Shape is ignored.
+ */
+ public void append(Shape s, boolean connect)
+ {
+ append(s.getPathIterator(null), connect);
+ }
+
+ /**
+ * Appends the segments of a PathIterator to this GeneralPath.
+ * Optionally, the initial {@link PathIterator#SEG_MOVETO} segment
+ * of the appended path is changed into a {@link
+ * PathIterator#SEG_LINETO} segment.
+ *
+ * @param iter the PathIterator specifying which segments shall be
+ * appended.
+ *
+ * @param connect <code>true</code> for substituting the initial
+ * {@link PathIterator#SEG_MOVETO} segment by a {@link
+ * PathIterator#SEG_LINETO}, or <code>false</code> for not
+ * performing any substitution. If this GeneralPath is currently
+ * empty, <code>connect</code> is assumed to be <code>false</code>,
+ * thus leaving the initial {@link PathIterator#SEG_MOVETO}
+ * unchanged.
+ */
+ public void append(PathIterator iter, boolean connect)
+ {
+ // A bad implementation of this method had caused Classpath bug #6076.
+ float[] f = new float[6];
+ while (! iter.isDone())
+ {
+ switch (iter.currentSegment(f))
+ {
+ case PathIterator.SEG_MOVETO:
+ if (! connect || (index == 0))
+ {
+ moveTo(f[0], f[1]);
+ break;
+ }
+ if ((index >= 1) && (types[index - 1] == PathIterator.SEG_CLOSE)
+ && (f[0] == xpoints[index - 1])
+ && (f[1] == ypoints[index - 1]))
+ break;
+
+ // Fall through.
+ case PathIterator.SEG_LINETO:
+ lineTo(f[0], f[1]);
+ break;
+ case PathIterator.SEG_QUADTO:
+ quadTo(f[0], f[1], f[2], f[3]);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ curveTo(f[0], f[1], f[2], f[3], f[4], f[5]);
+ break;
+ case PathIterator.SEG_CLOSE:
+ closePath();
+ break;
+ }
+
+ connect = false;
+ iter.next();
+ }
+ }
+
+ /**
+ * Returns the path&#x2019;s current winding rule.
+ */
+ public int getWindingRule()
+ {
+ return rule;
+ }
+
+ /**
+ * Sets the path&#x2019;s winding rule, which controls which areas are
+ * considered &#x2019;inside&#x2019; or &#x2019;outside&#x2019; the path
+ * on drawing. Valid rules are WIND_EVEN_ODD for an even-odd winding rule,
+ * or WIND_NON_ZERO for a non-zero winding rule.
+ */
+ public void setWindingRule(int rule)
+ {
+ if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
+ throw new IllegalArgumentException();
+ this.rule = rule;
+ }
+
+ /**
+ * Returns the current appending point of the path.
+ */
+ public Point2D getCurrentPoint()
+ {
+ if (subpath < 0)
+ return null;
+ return new Point2D.Float(xpoints[index - 1], ypoints[index - 1]);
+ }
+
+ /**
+ * Resets the path. All points and segments are destroyed.
+ */
+ public void reset()
+ {
+ subpath = -1;
+ index = 0;
+ }
+
+ /**
+ * Applies a transform to the path.
+ */
+ public void transform(AffineTransform xform)
+ {
+ double nx;
+ double ny;
+ double[] m = new double[6];
+ xform.getMatrix(m);
+ for (int i = 0; i < index; i++)
+ {
+ nx = m[0] * xpoints[i] + m[2] * ypoints[i] + m[4];
+ ny = m[1] * xpoints[i] + m[3] * ypoints[i] + m[5];
+ xpoints[i] = (float) nx;
+ ypoints[i] = (float) ny;
+ }
+ }
+
+ /**
+ * Creates a transformed version of the path.
+ * @param xform the transform to apply
+ * @return a new transformed GeneralPath
+ */
+ public Shape createTransformedShape(AffineTransform xform)
+ {
+ GeneralPath p = new GeneralPath(this);
+ p.transform(xform);
+ return p;
+ }
+
+ /**
+ * Returns the path&#x2019;s bounding box.
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ /**
+ * Returns the path&#x2019;s bounding box, in <code>float</code> precision
+ */
+ public Rectangle2D getBounds2D()
+ {
+ float x1;
+ float y1;
+ float x2;
+ float y2;
+
+ if (index > 0)
+ {
+ x1 = x2 = xpoints[0];
+ y1 = y2 = ypoints[0];
+ }
+ else
+ x1 = x2 = y1 = y2 = 0.0f;
+
+ for (int i = 0; i < index; i++)
+ {
+ x1 = Math.min(xpoints[i], x1);
+ y1 = Math.min(ypoints[i], y1);
+ x2 = Math.max(xpoints[i], x2);
+ y2 = Math.max(ypoints[i], y2);
+ }
+ return (new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1));
+ }
+
+ /**
+ * Evaluates if a point is within the GeneralPath,
+ * The NON_ZERO winding rule is used, regardless of the
+ * set winding rule.
+ * @param x x coordinate of the point to evaluate
+ * @param y y coordinate of the point to evaluate
+ * @return true if the point is within the path, false otherwise
+ */
+ public boolean contains(double x, double y)
+ {
+ return (getWindingNumber(x, y) != 0);
+ }
+
+ /**
+ * Evaluates if a Point2D is within the GeneralPath,
+ * The NON_ZERO winding rule is used, regardless of the
+ * set winding rule.
+ * @param p The Point2D to evaluate
+ * @return true if the point is within the path, false otherwise
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Evaluates if a rectangle is completely contained within the path.
+ * This method will return false in the cases when the box
+ * intersects an inner segment of the path.
+ * (i.e.: The method is accurate for the EVEN_ODD winding rule)
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, false, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, true, h) != 0 /* right */
+ || getAxisIntersections(x, y, true, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if (getWindingNumber(x, y) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Evaluates if a rectangle is completely contained within the path.
+ * This method will return false in the cases when the box
+ * intersects an inner segment of the path.
+ * (i.e.: The method is accurate for the EVEN_ODD winding rule)
+ * @param r the rectangle
+ * @return <code>true</code> if the rectangle is completely contained
+ * within the path, <code>false</code> otherwise
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Evaluates if a rectangle intersects the path.
+ * @param x x coordinate of the rectangle
+ * @param y y coordinate of the rectangle
+ * @param w width of the rectangle
+ * @param h height of the rectangle
+ * @return <code>true</code> if the rectangle intersects the path,
+ * <code>false</code> otherwise
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, false, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, true, h) != 0 /* right */
+ || getAxisIntersections(x, y, true, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if (getWindingNumber(x, y) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Evaluates if a Rectangle2D intersects the path.
+ * @param r The rectangle
+ * @return <code>true</code> if the rectangle intersects the path,
+ * <code>false</code> otherwise
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * A PathIterator that iterates over the segments of a GeneralPath.
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ private static class GeneralPathIterator implements PathIterator
+ {
+ /**
+ * The number of coordinate values for each segment type.
+ */
+ private static final int[] NUM_COORDS = {
+ /* 0: SEG_MOVETO */ 1,
+ /* 1: SEG_LINETO */ 1,
+ /* 2: SEG_QUADTO */ 2,
+ /* 3: SEG_CUBICTO */ 3,
+ /* 4: SEG_CLOSE */ 0};
+
+ /**
+ * The GeneralPath whose segments are being iterated.
+ * This is package-private to avoid an accessor method.
+ */
+ final GeneralPath path;
+
+ /**
+ * The affine transformation used to transform coordinates.
+ */
+ private final AffineTransform transform;
+
+ /**
+ * The current position of the iterator.
+ */
+ private int pos;
+
+ /**
+ * Constructs a new iterator for enumerating the segments of a
+ * GeneralPath.
+ *
+ * @param at an affine transformation for projecting the returned
+ * points, or <code>null</code> to return the original points
+ * without any mapping.
+ */
+ GeneralPathIterator(GeneralPath path, AffineTransform transform)
+ {
+ this.path = path;
+ this.transform = transform;
+ }
+
+ /**
+ * Returns the current winding rule of the GeneralPath.
+ */
+ public int getWindingRule()
+ {
+ return path.rule;
+ }
+
+ /**
+ * Determines whether the iterator has reached the last segment in
+ * the path.
+ */
+ public boolean isDone()
+ {
+ return pos >= path.index;
+ }
+
+ /**
+ * Advances the iterator position by one segment.
+ */
+ public void next()
+ {
+ int seg;
+
+ /*
+ * Increment pos by the number of coordinate pairs.
+ */
+ seg = path.types[pos];
+ if (seg == SEG_CLOSE)
+ pos++;
+ else
+ pos += NUM_COORDS[seg];
+ }
+
+ /**
+ * Returns the current segment in float coordinates.
+ */
+ public int currentSegment(float[] coords)
+ {
+ int seg;
+ int numCoords;
+
+ seg = path.types[pos];
+ numCoords = NUM_COORDS[seg];
+ if (numCoords > 0)
+ {
+ for (int i = 0; i < numCoords; i++)
+ {
+ coords[i << 1] = path.xpoints[pos + i];
+ coords[(i << 1) + 1] = path.ypoints[pos + i];
+ }
+
+ if (transform != null)
+ transform.transform( /* src */
+ coords, /* srcOffset */
+ 0, /* dest */ coords, /* destOffset */
+ 0, /* numPoints */ numCoords);
+ }
+ return seg;
+ }
+
+ /**
+ * Returns the current segment in double coordinates.
+ */
+ public int currentSegment(double[] coords)
+ {
+ int seg;
+ int numCoords;
+
+ seg = path.types[pos];
+ numCoords = NUM_COORDS[seg];
+ if (numCoords > 0)
+ {
+ for (int i = 0; i < numCoords; i++)
+ {
+ coords[i << 1] = (double) path.xpoints[pos + i];
+ coords[(i << 1) + 1] = (double) path.ypoints[pos + i];
+ }
+ if (transform != null)
+ transform.transform( /* src */
+ coords, /* srcOffset */
+ 0, /* dest */ coords, /* destOffset */
+ 0, /* numPoints */ numCoords);
+ }
+ return seg;
+ }
+ }
+
+ /**
+ * Creates a PathIterator for iterating along the segments of the path.
+ *
+ * @param at an affine transformation for projecting the returned
+ * points, or <code>null</code> to let the created iterator return
+ * the original points without any mapping.
+ */
+ public PathIterator getPathIterator(AffineTransform at)
+ {
+ return new GeneralPathIterator(this, at);
+ }
+
+ /**
+ * Creates a new FlatteningPathIterator for the path
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ /**
+ * Creates a new shape of the same run-time type with the same contents
+ * as this one.
+ *
+ * @return the clone
+ *
+ * @exception OutOfMemoryError If there is not enough memory available.
+ *
+ * @since 1.2
+ */
+ public Object clone()
+ {
+ // This class is final; no need to use super.clone().
+ return new GeneralPath(this);
+ }
+
+ /**
+ * Helper method - ensure the size of the data arrays,
+ * otherwise, reallocate new ones twice the size
+ */
+ private void ensureSize(int size)
+ {
+ if (subpath < 0)
+ throw new IllegalPathStateException("need initial moveto");
+ if (size <= xpoints.length)
+ return;
+ byte[] b = new byte[types.length << 1];
+ System.arraycopy(types, 0, b, 0, index);
+ types = b;
+ float[] f = new float[xpoints.length << 1];
+ System.arraycopy(xpoints, 0, f, 0, index);
+ xpoints = f;
+ f = new float[ypoints.length << 1];
+ System.arraycopy(ypoints, 0, f, 0, index);
+ ypoints = f;
+ }
+
+ /**
+ * Helper method - Get the total number of intersections from (x,y) along
+ * a given axis, within a given distance.
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ return (evaluateCrossings(x, y, false, useYaxis, distance));
+ }
+
+ /**
+ * Helper method - returns the winding number of a point.
+ */
+ private int getWindingNumber(double x, double y)
+ {
+ /* Evaluate the crossings from x,y to infinity on the y axis (arbitrary
+ choice). Note that we don't actually use Double.INFINITY, since that's
+ slower, and may cause problems. */
+ return (evaluateCrossings(x, y, true, true, BIG_VALUE));
+ }
+
+ /**
+ * Helper method - evaluates the number of intersections on an axis from
+ * the point (x,y) to the point (x,y+distance) or (x+distance,y).
+ * @param x x coordinate.
+ * @param y y coordinate.
+ * @param neg True if opposite-directed intersections should cancel,
+ * false to sum all intersections.
+ * @param useYaxis Use the Y axis, false uses the X axis.
+ * @param distance Interval from (x,y) on the selected axis to find
+ * intersections.
+ */
+ private int evaluateCrossings(double x, double y, boolean neg,
+ boolean useYaxis, double distance)
+ {
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float firstx = 0.0f;
+ float firsty = 0.0f;
+
+ int negative = (neg) ? -1 : 1;
+ double x0;
+ double x1;
+ double x2;
+ double x3;
+ double y0;
+ double y1;
+ double y2;
+ double y3;
+ double[] r = new double[4];
+ int nRoots;
+ double epsilon = 0.0;
+ int pos = 0;
+ int windingNumber = 0;
+ boolean pathStarted = false;
+
+ if (index == 0)
+ return (0);
+ if (useYaxis)
+ {
+ float[] swap1;
+ swap1 = ypoints;
+ ypoints = xpoints;
+ xpoints = swap1;
+ double swap2;
+ swap2 = y;
+ y = x;
+ x = swap2;
+ }
+
+ /* Get a value which is hopefully small but not insignificant relative
+ the path. */
+ epsilon = ypoints[0] * 1E-7;
+
+ if(epsilon == 0)
+ epsilon = 1E-7;
+
+ pos = 0;
+ while (pos < index)
+ {
+ switch (types[pos])
+ {
+ case PathIterator.SEG_MOVETO:
+ if (pathStarted) // close old path
+ {
+ x0 = cx;
+ y0 = cy;
+ x1 = firstx;
+ y1 = firsty;
+
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1,
+ epsilon, 0.0, distance, 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = firstx;
+ cy = firsty;
+ }
+ cx = firstx = xpoints[pos] - (float) x;
+ cy = firsty = ypoints[pos++] - (float) y;
+ pathStarted = true;
+ break;
+ case PathIterator.SEG_CLOSE:
+ x0 = cx;
+ y0 = cy;
+ x1 = firstx;
+ y1 = firsty;
+
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1,
+ epsilon, 0.0, distance, 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = firstx;
+ cy = firsty;
+ pos++;
+ pathStarted = false;
+ break;
+ case PathIterator.SEG_LINETO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - (float) x;
+ y1 = ypoints[pos++] - (float) y;
+
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1,
+ epsilon, 0.0, distance, 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ case PathIterator.SEG_QUADTO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - x;
+ y1 = ypoints[pos++] - y;
+ x2 = xpoints[pos] - x;
+ y2 = ypoints[pos++] - y;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0)
+ && (y0 * y1 <= 0 || y1 * y2 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y2 == 0.0)
+ y2 -= epsilon;
+
+ r[0] = y0;
+ r[1] = 2 * (y1 - y0);
+ r[2] = (y2 - 2 * y1 + y0);
+
+ /* degenerate roots (=tangent points) do not
+ contribute to the winding number. */
+ if ((nRoots = QuadCurve2D.solveQuadratic(r)) == 2)
+ for (int i = 0; i < nRoots; i++)
+ {
+ float t = (float) r[i];
+ if (t > 0.0f && t < 1.0f)
+ {
+ double crossing = t * t * (x2 - 2 * x1 + x0)
+ + 2 * t * (x1 - x0) + x0;
+ if (crossing >= 0.0 && crossing <= distance)
+ windingNumber += (2 * t * (y2 - 2 * y1 + y0)
+ + 2 * (y1 - y0) < 0) ? 1 : negative;
+ }
+ }
+ }
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ case PathIterator.SEG_CUBICTO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - x;
+ y1 = ypoints[pos++] - y;
+ x2 = xpoints[pos] - x;
+ y2 = ypoints[pos++] - y;
+ x3 = xpoints[pos] - x;
+ y3 = ypoints[pos++] - y;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0)
+ && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y3 == 0.0)
+ y3 -= epsilon;
+
+ r[0] = y0;
+ r[1] = 3 * (y1 - y0);
+ r[2] = 3 * (y2 + y0 - 2 * y1);
+ r[3] = y3 - 3 * y2 + 3 * y1 - y0;
+
+ if ((nRoots = CubicCurve2D.solveCubic(r)) != 0)
+ for (int i = 0; i < nRoots; i++)
+ {
+ float t = (float) r[i];
+ if (t > 0.0 && t < 1.0)
+ {
+ double crossing = -(t * t * t) * (x0 - 3 * x1
+ + 3 * x2 - x3)
+ + 3 * t * t * (x0 - 2 * x1 + x2)
+ + 3 * t * (x1 - x0) + x0;
+ if (crossing >= 0 && crossing <= distance)
+ windingNumber += (3 * t * t * (y3 + 3 * y1
+ - 3 * y2 - y0)
+ + 6 * t * (y0 - 2 * y1 + y2)
+ + 3 * (y1 - y0) < 0) ? 1 : negative;
+ }
+ }
+ }
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ }
+ }
+
+ // swap coordinates back
+ if (useYaxis)
+ {
+ float[] swap;
+ swap = ypoints;
+ ypoints = xpoints;
+ xpoints = swap;
+ }
+ return (windingNumber);
+ }
+} // class GeneralPath
+
diff --git a/libjava/classpath/java/awt/geom/IllegalPathStateException.java b/libjava/classpath/java/awt/geom/IllegalPathStateException.java
new file mode 100644
index 00000000000..4d190c74814
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/IllegalPathStateException.java
@@ -0,0 +1,71 @@
+/* IllegalPathStateException.java -- an operation was in an illegal path state
+ Copyright (C) 2000, 2002 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.geom;
+
+/**
+ * Thrown when an operation on a path is in an illegal state, such as appending
+ * a segment to a <code>GeneralPath</code> without an initial moveto.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see GeneralPath
+ * @status updated to 1.4
+ */
+public class IllegalPathStateException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -5158084205220481094L;
+
+ /**
+ * Create an exception with no message.
+ */
+ public IllegalPathStateException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param msg the message
+ */
+ public IllegalPathStateException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/Line2D.java b/libjava/classpath/java/awt/geom/Line2D.java
new file mode 100644
index 00000000000..e15e7cfe3f5
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Line2D.java
@@ -0,0 +1,1182 @@
+/* Line2D.java -- represents a line in 2-D space, plus operations on a line
+ Copyright (C) 2000, 2001, 2002 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.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+/**
+ * Represents a directed line bewteen two points in (x,y) Cartesian space.
+ * Remember, on-screen graphics have increasing x from left-to-right, and
+ * increasing y from top-to-bottom. The storage is left to subclasses.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author David Gilbert
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class Line2D implements Shape, Cloneable
+{
+ /**
+ * The default constructor.
+ */
+ protected Line2D()
+ {
+ }
+
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the starting x coordinate
+ */
+ public abstract double getX1();
+
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the starting y coordinate
+ */
+ public abstract double getY1();
+
+ /**
+ * Return the first point.
+ *
+ * @return the starting point
+ */
+ public abstract Point2D getP1();
+
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the ending x coordinate
+ */
+ public abstract double getX2();
+
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the ending y coordinate
+ */
+ public abstract double getY2();
+
+ /**
+ * Return the second point.
+ *
+ * @return the ending point
+ */
+ public abstract Point2D getP2();
+
+ /**
+ * Set the coordinates of the line to the given coordinates. Loss of
+ * precision may occur due to rounding issues.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ */
+ public abstract void setLine(double x1, double y1, double x2, double y2);
+
+ /**
+ * Set the coordinates to the given points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public void setLine(Point2D p1, Point2D p2)
+ {
+ setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+ }
+
+ /**
+ * Set the coordinates to those of the given line.
+ *
+ * @param l the line to copy
+ * @throws NullPointerException if l is null
+ */
+ public void setLine(Line2D l)
+ {
+ setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
+ }
+
+ /**
+ * Computes the relative rotation direction needed to pivot the line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ * @param px the reference x coordinate
+ * @param py the reference y coordinate
+ * @return the relative rotation direction
+ */
+ public static int relativeCCW(double x1, double y1, double x2, double y2,
+ double px, double py)
+ {
+ if ((x1 == x2 && y1 == y2)
+ || (x1 == px && y1 == py))
+ return 0; // Coincident points.
+ // Translate to the origin.
+ x2 -= x1;
+ y2 -= y1;
+ px -= x1;
+ py -= y1;
+ double slope2 = y2 / x2;
+ double slopep = py / px;
+ if (slope2 == slopep || (x2 == 0 && px == 0))
+ return y2 > 0 // Colinear.
+ ? (py < 0 ? -1 : py > y2 ? 1 : 0)
+ : (py > 0 ? -1 : py < y2 ? 1 : 0);
+ if (x2 >= 0 && slope2 >= 0)
+ return px >= 0 // Quadrant 1.
+ ? (slope2 > slopep ? 1 : -1)
+ : (slope2 < slopep ? 1 : -1);
+ if (y2 > 0)
+ return px < 0 // Quadrant 2.
+ ? (slope2 > slopep ? 1 : -1)
+ : (slope2 < slopep ? 1 : -1);
+ if (slope2 >= 0.0)
+ return px >= 0 // Quadrant 3.
+ ? (slope2 < slopep ? 1 : -1)
+ : (slope2 > slopep ? 1 : -1);
+ return px < 0 // Quadrant 4.
+ ? (slope2 < slopep ? 1 : -1)
+ : (slope2 > slopep ? 1 : -1);
+ }
+
+ /**
+ * Computes the relative rotation direction needed to pivot this line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param px the reference x coordinate
+ * @param py the reference y coordinate
+ * @return the relative rotation direction
+ * @see #relativeCCW(double, double, double, double, double, double)
+ */
+ public int relativeCCW(double px, double py)
+ {
+ return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Computes the relative rotation direction needed to pivot this line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param p the reference point
+ * @return the relative rotation direction
+ * @throws NullPointerException if p is null
+ * @see #relativeCCW(double, double, double, double, double, double)
+ */
+ public int relativeCCW(Point2D p)
+ {
+ return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+ }
+
+ /**
+ * Computes twice the (signed) area of the triangle defined by the three
+ * points. This method is used for intersection testing.
+ *
+ * @param x1 the x-coordinate of the first point.
+ * @param y1 the y-coordinate of the first point.
+ * @param x2 the x-coordinate of the second point.
+ * @param y2 the y-coordinate of the second point.
+ * @param x3 the x-coordinate of the third point.
+ * @param y3 the y-coordinate of the third point.
+ *
+ * @return Twice the area.
+ */
+ private static double area2(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
+ }
+
+ /**
+ * Returns <code>true</code> if (x3, y3) lies between (x1, y1) and (x2, y2),
+ * and false otherwise, This test assumes that the three points are
+ * collinear, and is used for intersection testing.
+ *
+ * @param x1 the x-coordinate of the first point.
+ * @param y1 the y-coordinate of the first point.
+ * @param x2 the x-coordinate of the second point.
+ * @param y2 the y-coordinate of the second point.
+ * @param x3 the x-coordinate of the third point.
+ * @param y3 the y-coordinate of the third point.
+ *
+ * @return A boolean.
+ */
+ private static boolean between(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ if (x1 != x2) {
+ return (x1 <= x3 && x3 <= x2) || (x1 >= x3 && x3 >= x2);
+ }
+ else {
+ return (y1 <= y3 && y3 <= y2) || (y1 >= y3 && y3 >= y2);
+ }
+ }
+
+ /**
+ * Test if the line segment (x1,y1)-&gt;(x2,y2) intersects the line segment
+ * (x3,y3)-&gt;(x4,y4).
+ *
+ * @param x1 the first x coordinate of the first segment
+ * @param y1 the first y coordinate of the first segment
+ * @param x2 the second x coordinate of the first segment
+ * @param y2 the second y coordinate of the first segment
+ * @param x3 the first x coordinate of the second segment
+ * @param y3 the first y coordinate of the second segment
+ * @param x4 the second x coordinate of the second segment
+ * @param y4 the second y coordinate of the second segment
+ * @return true if the segments intersect
+ */
+ public static boolean linesIntersect(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ double a1, a2, a3, a4;
+
+ // deal with special cases
+ if ((a1 = area2(x1, y1, x2, y2, x3, y3)) == 0.0)
+ {
+ // check if p3 is between p1 and p2 OR
+ // p4 is collinear also AND either between p1 and p2 OR at opposite ends
+ if (between(x1, y1, x2, y2, x3, y3))
+ {
+ return true;
+ }
+ else
+ {
+ if (area2(x1, y1, x2, y2, x4, y4) == 0.0)
+ {
+ return between(x3, y3, x4, y4, x1, y1)
+ || between (x3, y3, x4, y4, x2, y2);
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ else if ((a2 = area2(x1, y1, x2, y2, x4, y4)) == 0.0)
+ {
+ // check if p4 is between p1 and p2 (we already know p3 is not
+ // collinear)
+ return between(x1, y1, x2, y2, x4, y4);
+ }
+
+ if ((a3 = area2(x3, y3, x4, y4, x1, y1)) == 0.0) {
+ // check if p1 is between p3 and p4 OR
+ // p2 is collinear also AND either between p1 and p2 OR at opposite ends
+ if (between(x3, y3, x4, y4, x1, y1)) {
+ return true;
+ }
+ else {
+ if (area2(x3, y3, x4, y4, x2, y2) == 0.0) {
+ return between(x1, y1, x2, y2, x3, y3)
+ || between (x1, y1, x2, y2, x4, y4);
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ else if ((a4 = area2(x3, y3, x4, y4, x2, y2)) == 0.0) {
+ // check if p2 is between p3 and p4 (we already know p1 is not
+ // collinear)
+ return between(x3, y3, x4, y4, x2, y2);
+ }
+ else { // test for regular intersection
+ return ((a1 > 0.0) ^ (a2 > 0.0)) && ((a3 > 0.0) ^ (a4 > 0.0));
+ }
+ }
+
+ /**
+ * Test if this line intersects the line given by (x1,y1)-&gt;(x2,y2).
+ *
+ * @param x1 the first x coordinate of the other segment
+ * @param y1 the first y coordinate of the other segment
+ * @param x2 the second x coordinate of the other segment
+ * @param y2 the second y coordinate of the other segment
+ * @return true if the segments intersect
+ * @see #linesIntersect(double, double, double, double,
+ * double, double, double, double)
+ */
+ public boolean intersectsLine(double x1, double y1, double x2, double y2)
+ {
+ return linesIntersect(getX1(), getY1(), getX2(), getY2(),
+ x1, y1, x2, y2);
+ }
+
+ /**
+ * Test if this line intersects the given line.
+ *
+ * @param l the other segment
+ * @return true if the segments intersect
+ * @throws NullPointerException if l is null
+ * @see #linesIntersect(double, double, double, double,
+ * double, double, double, double)
+ */
+ public boolean intersectsLine(Line2D l)
+ {
+ return linesIntersect(getX1(), getY1(), getX2(), getY2(),
+ l.getX1(), l.getY1(), l.getX2(), l.getY2());
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the segment
+ * @see #ptSegDist(double, double, double, double, double, double)
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public static double ptSegDistSq(double x1, double y1, double x2, double y2,
+ double px, double py)
+ {
+ double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
+
+ double x, y;
+ if (pd2 == 0)
+ {
+ // Points are coincident.
+ x = x1;
+ y = y2;
+ }
+ else
+ {
+ double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
+
+ if (u < 0)
+ {
+ // "Off the end"
+ x = x1;
+ y = y1;
+ }
+ else if (u > 1.0)
+ {
+ x = x2;
+ y = y2;
+ }
+ else
+ {
+ x = x1 + u * (x2 - x1);
+ y = y1 + u * (y2 - y1);
+ }
+ }
+
+ return (x - px) * (x - px) + (y - py) * (y - py);
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the segment
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public static double ptSegDist(double x1, double y1, double x2, double y2,
+ double px, double py)
+ {
+ return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on this line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the segment
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public double ptSegDistSq(double px, double py)
+ {
+ return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on this line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param p the point
+ * @return the square of the distance from the point to the segment
+ * @throws NullPointerException if p is null
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public double ptSegDistSq(Point2D p)
+ {
+ return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * this line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the segment
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public double ptSegDist(double px, double py)
+ {
+ return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * this line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param p the point
+ * @return the distance from the point to the segment
+ * @throws NullPointerException if p is null
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public double ptSegDist(Point2D p)
+ {
+ return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from the segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the extended line
+ * @see #ptLineDist(double, double, double, double, double, double)
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public static double ptLineDistSq(double x1, double y1, double x2, double y2,
+ double px, double py)
+ {
+ double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
+
+ double x, y;
+ if (pd2 == 0)
+ {
+ // Points are coincident.
+ x = x1;
+ y = y2;
+ }
+ else
+ {
+ double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
+ x = x1 + u * (x2 - x1);
+ y = y1 + u * (y2 - y1);
+ }
+
+ return (x - px) * (x - px) + (y - py) * (y - py);
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from the segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the extended line
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public static double ptLineDist(double x1, double y1,
+ double x2, double y2,
+ double px, double py)
+ {
+ return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from this segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the extended line
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public double ptLineDistSq(double px, double py)
+ {
+ return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from this segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param p the point
+ * @return the square of the distance from the point to the extended line
+ * @throws NullPointerException if p is null
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public double ptLineDistSq(Point2D p)
+ {
+ return ptLineDistSq(getX1(), getY1(), getX2(), getY2(),
+ p.getX(), p.getY());
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from this segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the extended line
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public double ptLineDist(double px, double py)
+ {
+ return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from this segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param p the point
+ * @return the distance from the point to the extended line
+ * @throws NullPointerException if p is null
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public double ptLineDist(Point2D p)
+ {
+ return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+ }
+
+ /**
+ * Test if a point is contained inside the line. Since a line has no area,
+ * this returns false.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @return false; the line does not contain points
+ */
+ public boolean contains(double x, double y)
+ {
+ return false;
+ }
+
+ /**
+ * Test if a point is contained inside the line. Since a line has no area,
+ * this returns false.
+ *
+ * @param p the point
+ * @return false; the line does not contain points
+ */
+ public boolean contains(Point2D p)
+ {
+ return false;
+ }
+
+ /**
+ * Tests if this line intersects the interior of the specified rectangle.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return true if the line intersects the rectangle
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (w <= 0 || h <= 0)
+ return false;
+ double x1 = getX1();
+ double y1 = getY1();
+ double x2 = getX2();
+ double y2 = getY2();
+
+ if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
+ return true;
+ if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
+ return true;
+
+ double x3 = x + w;
+ double y3 = y + h;
+
+ return (linesIntersect(x1, y1, x2, y2, x, y, x, y3)
+ || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
+ || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
+ || linesIntersect(x1, y1, x2, y2, x3, y, x, y));
+ }
+
+ /**
+ * Tests if this line intersects the interior of the specified rectangle.
+ *
+ * @param r the rectangle
+ * @return true if the line intersects the rectangle
+ * @throws NullPointerException if r is null
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Tests if the line contains a rectangle. Since lines have no area, this
+ * always returns false.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return false; the line does not contain points
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ return false;
+ }
+
+ /**
+ * Tests if the line contains a rectangle. Since lines have no area, this
+ * always returns false.
+ *
+ * @param r the rectangle
+ * @return false; the line does not contain points
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return false;
+ }
+
+ /**
+ * Gets a bounding box (not necessarily minimal) for this line.
+ *
+ * @return the integer bounding box
+ * @see #getBounds2D()
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ /**
+ * Return a path iterator, possibly applying a transform on the result. This
+ * iterator is not threadsafe.
+ *
+ * @param at the transform, or null
+ * @return a new path iterator
+ */
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current = 0;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current >= 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getX2();
+ coords[1] = (float) getY2();
+ result = SEG_LINETO;
+ break;
+ default:
+ throw new NoSuchElementException("line iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return result;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getX2();
+ coords[1] = getY2();
+ result = SEG_LINETO;
+ break;
+ default:
+ throw new NoSuchElementException("line iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return result;
+ }
+ };
+ }
+
+ /**
+ * Return a flat path iterator, possibly applying a transform on the result.
+ * This iterator is not threadsafe.
+ *
+ * @param at the transform, or null
+ * @param flatness ignored, since lines are already flat
+ * @return a new path iterator
+ * @see #getPathIterator(AffineTransform)
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return getPathIterator(at);
+ }
+
+ /**
+ * Create a new line of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ *
+ * @exception OutOfMemoryError If there is not enough memory available.
+ *
+ * @since 1.2
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * This class defines a point in <code>double</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Double extends Line2D
+ {
+ /** The x coordinate of the first point. */
+ public double x1;
+
+ /** The y coordinate of the first point. */
+ public double y1;
+
+ /** The x coordinate of the second point. */
+ public double x2;
+
+ /** The y coordinate of the second point. */
+ public double y2;
+
+ /**
+ * Construct the line segment (0,0)-&gt;(0,0).
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param x1 the x coordinate of the first point
+ * @param y1 the y coordinate of the first point
+ * @param x2 the x coordinate of the second point
+ * @param y2 the y coordinate of the second point
+ */
+ public Double(double x1, double y1, double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public Double(Point2D p1, Point2D p2)
+ {
+ x1 = p1.getX();
+ y1 = p1.getY();
+ x2 = p2.getX();
+ y2 = p2.getY();
+ }
+
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the value of x1
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the value of y1
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Return the first point.
+ *
+ * @return the point (x1,y1)
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Double(x1, y1);
+ }
+
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the value of x2
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the value of y2
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Return the second point.
+ *
+ * @return the point (x2,y2)
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Double(x2, y2);
+ }
+
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(double x1, double y1, double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Return the exact bounds of this line segment.
+ *
+ * @return the bounding box
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double x = Math.min(x1, x2);
+ double y = Math.min(y1, y2);
+ double w = Math.abs(x1 - x2);
+ double h = Math.abs(y1 - y2);
+ return new Rectangle2D.Double(x, y, w, h);
+ }
+ } // class Double
+
+ /**
+ * This class defines a point in <code>float</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Float extends Line2D
+ {
+ /** The x coordinate of the first point. */
+ public float x1;
+
+ /** The y coordinate of the first point. */
+ public float y1;
+
+ /** The x coordinate of the second point. */
+ public float x2;
+
+ /** The y coordinate of the second point. */
+ public float y2;
+
+ /**
+ * Construct the line segment (0,0)-&gt;(0,0).
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param x1 the x coordinate of the first point
+ * @param y1 the y coordinate of the first point
+ * @param x2 the x coordinate of the second point
+ * @param y2 the y coordinate of the second point
+ */
+ public Float(float x1, float y1, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public Float(Point2D p1, Point2D p2)
+ {
+ x1 = (float) p1.getX();
+ y1 = (float) p1.getY();
+ x2 = (float) p2.getX();
+ y2 = (float) p2.getY();
+ }
+
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the value of x1
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the value of y1
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Return the first point.
+ *
+ * @return the point (x1,y1)
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Float(x1, y1);
+ }
+
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the value of x2
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the value of y2
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Return the second point.
+ *
+ * @return the point (x2,y2)
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Float(x2, y2);
+ }
+
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(double x1, double y1, double x2, double y2)
+ {
+ this.x1 = (float) x1;
+ this.y1 = (float) y1;
+ this.x2 = (float) x2;
+ this.y2 = (float) y2;
+ }
+
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(float x1, float y1, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Return the exact bounds of this line segment.
+ *
+ * @return the bounding box
+ */
+ public Rectangle2D getBounds2D()
+ {
+ float x = Math.min(x1, x2);
+ float y = Math.min(y1, y2);
+ float w = Math.abs(x1 - x2);
+ float h = Math.abs(y1 - y2);
+ return new Rectangle2D.Float(x, y, w, h);
+ }
+ } // class Float
+} // class Line2D
diff --git a/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java b/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java
new file mode 100644
index 00000000000..7995a52eb61
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java
@@ -0,0 +1,65 @@
+/* NoninvertibleTransformException.java -- a transform can't be inverted
+ Copyright (C) 2000, 2002 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.geom;
+
+/**
+ * Thrown if an operation requires an inverse of an
+ * <code>AffineTransform</code>, but the transform is in a non-invertible
+ * state.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see AffineTransform
+ * @status updated to 1.4
+ */
+public class NoninvertibleTransformException extends Exception
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 6137225240503990466L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NoninvertibleTransformException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/PathIterator.java b/libjava/classpath/java/awt/geom/PathIterator.java
new file mode 100644
index 00000000000..2cd08b9b48b
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/PathIterator.java
@@ -0,0 +1,189 @@
+/* PathIterator.java -- describes a shape by iterating over its vertices
+ Copyright (C) 2000, 2002, 2003 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.geom;
+
+/**
+ * This interface provides a directed path over the boundary of a shape. The
+ * path can contain 1st through 3rd order Bezier curves (lines, and quadratic
+ * and cubic splines). A shape can have multiple disjoint paths via the
+ * MOVETO directive, and can close a circular path back to the previos
+ * MOVETO via the CLOSE directive.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see java.awt.Shape
+ * @see java.awt.Stroke
+ * @see FlatteningPathIterator
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface PathIterator
+{
+ /**
+ * The even-odd winding mode: a point is internal to the shape if a ray
+ * from the point to infinity (in any direction) crosses an odd number of
+ * segments.
+ */
+ int WIND_EVEN_ODD = 0;
+
+ /**
+ * The non-zero winding mode: a point is internal to the shape if a ray
+ * from the point to infinity (in any direction) crosses a different number
+ * of segments headed clockwise than those headed counterclockwise.
+ */
+ int WIND_NON_ZERO = 1;
+
+ /**
+ * Starts a new subpath. There is no segment from the previous vertex.
+ */
+ int SEG_MOVETO = 0;
+
+ /**
+ * The current segment is a line.
+ */
+ int SEG_LINETO = 1;
+
+ /**
+ * The current segment is a quadratic parametric curve. It is interpolated
+ * as t varies from 0 to 1 over the current point (CP), first control point
+ * (P1), and final interpolated control point (P2):
+ * <pre>
+ * P(t) = B(2,0)*CP + B(2,1)*P1 + B(2,2)*P2
+ * 0 &lt;= t &lt;= 1
+ * B(n,m) = mth coefficient of nth degree Bernstein polynomial
+ * = C(n,m) * t^(m) * (1 - t)^(n-m)
+ * C(n,m) = Combinations of n things, taken m at a time
+ * = n! / (m! * (n-m)!)
+ * </pre>
+ */
+ int SEG_QUADTO = 2;
+
+ /**
+ * The current segment is a cubic parametric curve (more commonly known as
+ * a Bezier curve). It is interpolated as t varies from 0 to 1 over the
+ * current point (CP), first control point (P1), the second control point
+ * (P2), and final interpolated control point (P3):
+ * <pre>
+ * P(t) = B(3,0)*CP + B(3,1)*P1 + B(3,2)*P2 + B(3,3)*P3
+ * 0 &lt;= t &lt;= 1
+ * B(n,m) = mth coefficient of nth degree Bernstein polynomial
+ * = C(n,m) * t^(m) * (1 - t)^(n-m)
+ * C(n,m) = Combinations of n things, taken m at a time
+ * = n! / (m! * (n-m)!)
+ * </pre>
+ */
+ int SEG_CUBICTO = 3;
+
+ /**
+ * The current segment closes a loop by an implicit line to the previous
+ * SEG_MOVETO coordinate.
+ */
+ int SEG_CLOSE = 4;
+
+ /**
+ * Returns the winding rule to determine which points are inside this path.
+ *
+ * @return the winding rule
+ * @see #WIND_EVEN_ODD
+ * @see #WIND_NON_ZERO
+ */
+ int getWindingRule();
+
+ /**
+ * Tests if the iterator is exhausted. If this returns true, currentSegment
+ * and next may throw a NoSuchElementException (although this is not
+ * required).
+ *
+ * @return true if the iteration is complete
+ */
+ boolean isDone();
+
+ /**
+ * Advance to the next segment in the iteration. It is not specified what
+ * this does if called when isDone() returns true.
+ *
+ * @throws java.util.NoSuchElementException optional when isDone() is true
+ */
+ void next();
+
+ /**
+ * Returns the coordinates of the next point(s), as well as the type of
+ * line segment. The input array must be at least a float[6], to accomodate
+ * up to three (x,y) point pairs (although if you know the iterator is
+ * flat, you can probably get by with a float[2]). If the returned type is
+ * SEG_MOVETO or SEG_LINETO, the first point in the array is modified; if
+ * the returned type is SEG_QUADTO, the first two points are modified; if
+ * the returned type is SEG_CUBICTO, all three points are modified; and if
+ * the returned type is SEG_CLOSE, the array is untouched.
+ *
+ * @param coords the array to place the point coordinates in
+ * @return the segment type
+ * @throws NullPointerException if coords is null
+ * @throws ArrayIndexOutOfBoundsException if coords is too small
+ * @throws java.util.NoSuchElementException optional when isDone() is true
+ * @see #SEG_MOVETO
+ * @see #SEG_LINETO
+ * @see #SEG_QUADTO
+ * @see #SEG_CUBICTO
+ * @see #SEG_CLOSE
+ */
+ int currentSegment(float[] coords);
+
+ /**
+ * Returns the coordinates of the next point(s), as well as the type of
+ * line segment. The input array must be at least a double[6], to accomodate
+ * up to three (x,y) point pairs (although if you know the iterator is
+ * flat, you can probably get by with a double[2]). If the returned type is
+ * SEG_MOVETO or SEG_LINETO, the first point in the array is modified; if
+ * the returned type is SEG_QUADTO, the first two points are modified; if
+ * the returned type is SEG_CUBICTO, all three points are modified; and if
+ * the returned type is SEG_CLOSE, the array is untouched.
+ *
+ * @param coords the array to place the point coordinates in
+ * @return the segment type
+ * @throws NullPointerException if coords is null
+ * @throws ArrayIndexOutOfBoundsException if coords is too small
+ * @throws java.util.NoSuchElementException optional when isDone() is true
+ * @see #SEG_MOVETO
+ * @see #SEG_LINETO
+ * @see #SEG_QUADTO
+ * @see #SEG_CUBICTO
+ * @see #SEG_CLOSE
+ */
+ int currentSegment(double[] coords);
+} // interface PathIterator
diff --git a/libjava/classpath/java/awt/geom/Point2D.java b/libjava/classpath/java/awt/geom/Point2D.java
new file mode 100644
index 00000000000..9f22a5a67c9
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Point2D.java
@@ -0,0 +1,396 @@
+/* Point2D.java -- generic point in 2-D space
+ Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+/**
+ * This class implements a generic point in 2D Cartesian space. The storage
+ * representation is left up to the subclass. Point includes two useful
+ * nested classes, for float and double storage respectively.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class Point2D implements Cloneable
+{
+ /**
+ * The default constructor.
+ *
+ * @see java.awt.Point
+ * @see Point2D.Float
+ * @see Point2D.Double
+ */
+ protected Point2D()
+ {
+ }
+
+ /**
+ * Get the X coordinate, in double precision.
+ *
+ * @return the x coordinate
+ */
+ public abstract double getX();
+
+ /**
+ * Get the Y coordinate, in double precision.
+ *
+ * @return the y coordinate
+ */
+ public abstract double getY();
+
+ /**
+ * Set the location of this point to the new coordinates. There may be a
+ * loss of precision.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ */
+ public abstract void setLocation(double x, double y);
+
+ /**
+ * Set the location of this point to the new coordinates. There may be a
+ * loss of precision.
+ *
+ * @param p the point to copy
+ * @throws NullPointerException if p is null
+ */
+ public void setLocation(Point2D p)
+ {
+ setLocation(p.getX(), p.getY());
+ }
+
+ /**
+ * Return the square of the distance between two points.
+ *
+ * @param x1 the x coordinate of point 1
+ * @param y1 the y coordinate of point 1
+ * @param x2 the x coordinate of point 2
+ * @param y2 the y coordinate of point 2
+ * @return (x2 - x1)^2 + (y2 - y1)^2
+ */
+ public static double distanceSq(double x1, double y1, double x2, double y2)
+ {
+ x2 -= x1;
+ y2 -= y1;
+ return x2 * x2 + y2 * y2;
+ }
+
+ /**
+ * Return the distance between two points.
+ *
+ * @param x1 the x coordinate of point 1
+ * @param y1 the y coordinate of point 1
+ * @param x2 the x coordinate of point 2
+ * @param y2 the y coordinate of point 2
+ * @return the distance from (x1,y1) to (x2,y2)
+ */
+ public static double distance(double x1, double y1, double x2, double y2)
+ {
+ return Math.sqrt(distanceSq(x1, y1, x2, y2));
+ }
+
+ /**
+ * Return the square of the distance from this point to the given one.
+ *
+ * @param x the x coordinate of the other point
+ * @param y the y coordinate of the other point
+ * @return the square of the distance
+ */
+ public double distanceSq(double x, double y)
+ {
+ return distanceSq(getX(), x, getY(), y);
+ }
+
+ /**
+ * Return the square of the distance from this point to the given one.
+ *
+ * @param p the other point
+ * @return the square of the distance
+ * @throws NullPointerException if p is null
+ */
+ public double distanceSq(Point2D p)
+ {
+ return distanceSq(getX(), p.getX(), getY(), p.getY());
+ }
+
+ /**
+ * Return the distance from this point to the given one.
+ *
+ * @param x the x coordinate of the other point
+ * @param y the y coordinate of the other point
+ * @return the distance
+ */
+ public double distance(double x, double y)
+ {
+ return distance(getX(), x, getY(), y);
+ }
+
+ /**
+ * Return the distance from this point to the given one.
+ *
+ * @param p the other point
+ * @return the distance
+ * @throws NullPointerException if p is null
+ */
+ public double distance(Point2D p)
+ {
+ return distance(getX(), p.getX(), getY(), p.getY());
+ }
+
+ /**
+ * Create a new point of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Return the hashcode for this point. The formula is not documented, but
+ * appears to be the same as:
+ * <pre>
+ * long l = Double.doubleToLongBits(getY());
+ * l = l * 31 ^ Double.doubleToLongBits(getX());
+ * return (int) ((l >> 32) ^ l);
+ * </pre>
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // Talk about a fun time reverse engineering this one!
+ long l = java.lang.Double.doubleToLongBits(getY());
+ l = l * 31 ^ java.lang.Double.doubleToLongBits(getX());
+ return (int) ((l >> 32) ^ l);
+ }
+
+ /**
+ * Compares two points for equality. This returns true if they have the
+ * same coordinates.
+ *
+ * @param o the point to compare
+ * @return true if it is equal
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof Point2D))
+ return false;
+ Point2D p = (Point2D) o;
+ return getX() == p.getX() && getY() == p.getY();
+ }
+
+ /**
+ * This class defines a point in <code>double</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Double extends Point2D
+ {
+ /** The X coordinate. */
+ public double x;
+
+ /** The Y coordinate. */
+ public double y;
+
+ /**
+ * Create a new point at (0,0).
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Create a new point at (x,y).
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public Double(double x, double y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Return the x coordinate.
+ *
+ * @return the x coordinate
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the y coordinate.
+ *
+ * @return the y coordinate
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Sets the location of this point.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ */
+ public void setLocation(double x, double y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Returns a string representation of this object. The format is:
+ * <code>"Point2D.Double[" + x + ", " + y + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return "Point2D.Double[" + x + ", " + y + ']';
+ }
+ } // class Double
+
+ /**
+ * This class defines a point in <code>float</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Float extends Point2D
+ {
+ /** The X coordinate. */
+ public float x;
+
+ /** The Y coordinate. */
+ public float y;
+
+ /**
+ * Create a new point at (0,0).
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Create a new point at (x,y).
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public Float(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Return the x coordinate.
+ *
+ * @return the x coordinate
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the y coordinate.
+ *
+ * @return the y coordinate
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Sets the location of this point.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ */
+ public void setLocation(double x, double y)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ }
+
+ /**
+ * Sets the location of this point.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ */
+ public void setLocation(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Returns a string representation of this object. The format is:
+ * <code>"Point2D.Float[" + x + ", " + y + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return "Point2D.Float[" + x + ", " + y + ']';
+ }
+ } // class Float
+} // class Point2D
diff --git a/libjava/classpath/java/awt/geom/QuadCurve2D.java b/libjava/classpath/java/awt/geom/QuadCurve2D.java
new file mode 100644
index 00000000000..41021dbc683
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/QuadCurve2D.java
@@ -0,0 +1,1467 @@
+/* QuadCurve2D.java -- represents a parameterized quadratic curve in 2-D space
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+/**
+ * A two-dimensional curve that is parameterized with a quadratic
+ * function.
+ *
+ * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a QuadCurve2D" />
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Graydon Hoare (graydon@redhat.com)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
+ */
+public abstract class QuadCurve2D implements Shape, Cloneable
+{
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+ private static final double EPSILON = 1E-10;
+
+ /**
+ * Constructs a new QuadCurve2D. Typical users will want to
+ * construct instances of a subclass, such as {@link
+ * QuadCurve2D.Float} or {@link QuadCurve2D.Double}.
+ */
+ protected QuadCurve2D()
+ {
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public abstract double getX1();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public abstract double getY1();
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public abstract Point2D getP1();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public abstract double getCtrlX();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public abstract double getCtrlY();
+
+ /**
+ * Returns the curve&#x2019;s control point.
+ */
+ public abstract Point2D getCtrlPt();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public abstract double getX2();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public abstract double getY2();
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public abstract Point2D getP2();
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public abstract void setCurve(double x1, double y1, double cx, double cy,
+ double x2, double y2);
+
+ /**
+ * Changes the curve geometry, passing coordinate values in an
+ * array.
+ *
+ * @param coords an array containing the new coordinate values. The
+ * <i>x</i> coordinate of the new start point is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * new control point is located at <code>coords[offset + 2]</code>,
+ * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
+ * <i>x</i> coordinate of the new end point is located at
+ * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 5]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public void setCurve(double[] coords, int offset)
+ {
+ setCurve(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++]);
+ }
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in
+ * separate Point objects.
+ *
+ * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a QuadCurve2D" />
+ *
+ * <p>The curve does not keep any reference to the passed point
+ * objects. Therefore, a later change to <code>p1</code>,
+ * <code>c</code> <code>p2</code> will not affect the curve
+ * geometry.
+ *
+ * @param p1 the new start point.
+ * @param c the new control point.
+ * @param p2 the new end point.
+ */
+ public void setCurve(Point2D p1, Point2D c, Point2D p2)
+ {
+ setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(), p2.getX(), p2.getY());
+ }
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in an
+ * array of Point objects.
+ *
+ * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a QuadCurve2D" />
+ *
+ * <p>The curve does not keep references to the passed point
+ * objects. Therefore, a later change to the <code>pts</code> array
+ * or any of its elements will not affect the curve geometry.
+ *
+ * @param pts an array containing the points. The new start point
+ * is located at <code>pts[offset]</code>, the new control
+ * point at <code>pts[offset + 1]</code>, and the new end point
+ * at <code>pts[offset + 2]</code>.
+ *
+ * @param offset the offset of the start point in <code>pts</code>.
+ */
+ public void setCurve(Point2D[] pts, int offset)
+ {
+ setCurve(pts[offset].getX(), pts[offset].getY(), pts[offset + 1].getX(),
+ pts[offset + 1].getY(), pts[offset + 2].getX(),
+ pts[offset + 2].getY());
+ }
+
+ /**
+ * Changes the geometry of the curve to that of another curve.
+ *
+ * @param c the curve whose coordinates will be copied.
+ */
+ public void setCurve(QuadCurve2D c)
+ {
+ setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c.getX2(),
+ c.getY2());
+ }
+
+ /**
+ * Calculates the squared flatness of a quadratic curve, directly
+ * specifying each coordinate value. The flatness is the distance of
+ * the control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the square of the distance between C and the gray line, i.e.
+ * the squared length of the red line.
+ *
+ * @param x1 the <i>x</i> coordinate of the start point P1.
+ * @param y1 the <i>y</i> coordinate of the start point P1.
+ * @param cx the <i>x</i> coordinate of the control point C.
+ * @param cy the <i>y</i> coordinate of the control point C.
+ * @param x2 the <i>x</i> coordinate of the end point P2.
+ * @param y2 the <i>y</i> coordinate of the end point P2.
+ */
+ public static double getFlatnessSq(double x1, double y1, double cx,
+ double cy, double x2, double y2)
+ {
+ return Line2D.ptSegDistSq(x1, y1, x2, y2, cx, cy);
+ }
+
+ /**
+ * Calculates the flatness of a quadratic curve, directly specifying
+ * each coordinate value. The flatness is the distance of the
+ * control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the distance between C and the gray line, i.e. the length of
+ * the red line.
+ *
+ * @param x1 the <i>x</i> coordinate of the start point P1.
+ * @param y1 the <i>y</i> coordinate of the start point P1.
+ * @param cx the <i>x</i> coordinate of the control point C.
+ * @param cy the <i>y</i> coordinate of the control point C.
+ * @param x2 the <i>x</i> coordinate of the end point P2.
+ * @param y2 the <i>y</i> coordinate of the end point P2.
+ */
+ public static double getFlatness(double x1, double y1, double cx, double cy,
+ double x2, double y2)
+ {
+ return Line2D.ptSegDist(x1, y1, x2, y2, cx, cy);
+ }
+
+ /**
+ * Calculates the squared flatness of a quadratic curve, specifying
+ * the coordinate values in an array. The flatness is the distance
+ * of the control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the square of the distance between C and the gray line, i.e.
+ * the squared length of the red line.
+ *
+ * @param coords an array containing the coordinate values. The
+ * <i>x</i> coordinate of the start point P1 is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * control point C is located at <code>coords[offset + 2]</code>,
+ * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
+ * <i>x</i> coordinate of the end point P2 is located at
+ * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 5]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public static double getFlatnessSq(double[] coords, int offset)
+ {
+ return Line2D.ptSegDistSq(coords[offset], coords[offset + 1],
+ coords[offset + 4], coords[offset + 5],
+ coords[offset + 2], coords[offset + 3]);
+ }
+
+ /**
+ * Calculates the flatness of a quadratic curve, specifying the
+ * coordinate values in an array. The flatness is the distance of
+ * the control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the the distance between C and the gray line, i.e. the length of
+ * the red line.
+ *
+ * @param coords an array containing the coordinate values. The
+ * <i>x</i> coordinate of the start point P1 is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * control point C is located at <code>coords[offset + 2]</code>,
+ * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
+ * <i>x</i> coordinate of the end point P2 is located at
+ * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 5]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public static double getFlatness(double[] coords, int offset)
+ {
+ return Line2D.ptSegDist(coords[offset], coords[offset + 1],
+ coords[offset + 4], coords[offset + 5],
+ coords[offset + 2], coords[offset + 3]);
+ }
+
+ /**
+ * Calculates the squared flatness of this curve. The flatness is
+ * the distance of the control point to the line between start and
+ * end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the square of the distance between C and the gray line, i.e. the
+ * squared length of the red line.
+ */
+ public double getFlatnessSq()
+ {
+ return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
+ getCtrlY());
+ }
+
+ /**
+ * Calculates the flatness of this curve. The flatness is the
+ * distance of the control point to the line between start and end
+ * point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the distance between C and the gray line, i.e. the length of the
+ * red line.
+ */
+ public double getFlatness()
+ {
+ return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
+ getCtrlY());
+ }
+
+ /**
+ * Subdivides this curve into two halves.
+ *
+ * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a QuadCurve2D" />
+ *
+ * @param left a curve whose geometry will be set to the left half
+ * of this curve, or <code>null</code> if the caller is not
+ * interested in the left half.
+ *
+ * @param right a curve whose geometry will be set to the right half
+ * of this curve, or <code>null</code> if the caller is not
+ * interested in the right half.
+ */
+ public void subdivide(QuadCurve2D left, QuadCurve2D right)
+ {
+ // Use empty slots at end to share single array.
+ double[] d = new double[]
+ {
+ getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2(),
+ 0, 0, 0, 0
+ };
+ subdivide(d, 0, d, 0, d, 4);
+ if (left != null)
+ left.setCurve(d, 0);
+ if (right != null)
+ right.setCurve(d, 4);
+ }
+
+ /**
+ * Subdivides a quadratic curve into two halves.
+ *
+ * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a QuadCurve2D" />
+ *
+ * @param src the curve to be subdivided.
+ *
+ * @param left a curve whose geometry will be set to the left half
+ * of <code>src</code>, or <code>null</code> if the caller is not
+ * interested in the left half.
+ *
+ * @param right a curve whose geometry will be set to the right half
+ * of <code>src</code>, or <code>null</code> if the caller is not
+ * interested in the right half.
+ */
+ public static void subdivide(QuadCurve2D src, QuadCurve2D left,
+ QuadCurve2D right)
+ {
+ src.subdivide(left, right);
+ }
+
+ /**
+ * Subdivides a quadratic curve into two halves, passing all
+ * coordinates in an array.
+ *
+ * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a QuadCurve2D" />
+ *
+ * <p>The left end point and the right start point will always be
+ * identical. Memory-concious programmers thus may want to pass the
+ * same array for both <code>left</code> and <code>right</code>, and
+ * set <code>rightOff</code> to <code>leftOff + 4</code>.
+ *
+ * @param src an array containing the coordinates of the curve to be
+ * subdivided. The <i>x</i> coordinate of the start point is
+ * located at <code>src[srcOff]</code>, its <i>y</i> at
+ * <code>src[srcOff + 1]</code>. The <i>x</i> coordinate of the
+ * control point is located at <code>src[srcOff + 2]</code>, its
+ * <i>y</i> at <code>src[srcOff + 3]</code>. The <i>x</i>
+ * coordinate of the end point is located at <code>src[srcOff +
+ * 4]</code>, its <i>y</i> at <code>src[srcOff + 5]</code>.
+ *
+ * @param srcOff an offset into <code>src</code>, specifying
+ * the index of the start point&#x2019;s <i>x</i> coordinate.
+ *
+ * @param left an array that will receive the coordinates of the
+ * left half of <code>src</code>. It is acceptable to pass
+ * <code>src</code>. A caller who is not interested in the left half
+ * can pass <code>null</code>.
+ *
+ * @param leftOff an offset into <code>left</code>, specifying the
+ * index where the start point&#x2019;s <i>x</i> coordinate will be
+ * stored.
+ *
+ * @param right an array that will receive the coordinates of the
+ * right half of <code>src</code>. It is acceptable to pass
+ * <code>src</code> or <code>left</code>. A caller who is not
+ * interested in the right half can pass <code>null</code>.
+ *
+ * @param rightOff an offset into <code>right</code>, specifying the
+ * index where the start point&#x2019;s <i>x</i> coordinate will be
+ * stored.
+ */
+ public static void subdivide(double[] src, int srcOff, double[] left,
+ int leftOff, double[] right, int rightOff)
+ {
+ double x1;
+ double y1;
+ double xc;
+ double yc;
+ double x2;
+ double y2;
+
+ x1 = src[srcOff];
+ y1 = src[srcOff + 1];
+ xc = src[srcOff + 2];
+ yc = src[srcOff + 3];
+ x2 = src[srcOff + 4];
+ y2 = src[srcOff + 5];
+
+ if (left != null)
+ {
+ left[leftOff] = x1;
+ left[leftOff + 1] = y1;
+ }
+
+ if (right != null)
+ {
+ right[rightOff + 4] = x2;
+ right[rightOff + 5] = y2;
+ }
+
+ x1 = (x1 + xc) / 2;
+ x2 = (xc + x2) / 2;
+ xc = (x1 + x2) / 2;
+ y1 = (y1 + yc) / 2;
+ y2 = (y2 + yc) / 2;
+ yc = (y1 + y2) / 2;
+
+ if (left != null)
+ {
+ left[leftOff + 2] = x1;
+ left[leftOff + 3] = y1;
+ left[leftOff + 4] = xc;
+ left[leftOff + 5] = yc;
+ }
+
+ if (right != null)
+ {
+ right[rightOff] = xc;
+ right[rightOff + 1] = yc;
+ right[rightOff + 2] = x2;
+ right[rightOff + 3] = y2;
+ }
+ }
+
+ /**
+ * Finds the non-complex roots of a quadratic equation, placing the
+ * results into the same array as the equation coefficients. The
+ * following equation is being solved:
+ *
+ * <blockquote><code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
+ * + <code>eqn[1]</code> &#xb7; <i>x</i>
+ * + <code>eqn[0]</code>
+ * = 0
+ * </blockquote>
+ *
+ * <p>For some background about solving quadratic equations, see the
+ * article <a href=
+ * "http://planetmath.org/encyclopedia/QuadraticFormula.html"
+ * >&#x201c;Quadratic Formula&#x201d;</a> in <a href=
+ * "http://planetmath.org/">PlanetMath</a>. For an extensive library
+ * of numerical algorithms written in the C programming language,
+ * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific
+ * Library</a>.
+ *
+ * @see #solveQuadratic(double[], double[])
+ * @see CubicCurve2D#solveCubic(double[], double[])
+ *
+ * @param eqn an array with the coefficients of the equation. When
+ * this procedure has returned, <code>eqn</code> will contain the
+ * non-complex solutions of the equation, in no particular order.
+ *
+ * @return the number of non-complex solutions. A result of 0
+ * indicates that the equation has no non-complex solutions. A
+ * result of -1 indicates that the equation is constant (i.e.,
+ * always or never zero).
+ *
+ * @author Brian Gough (bjg@network-theory.com)
+ * (original C implementation in the <a href=
+ * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * (adaptation to Java)
+ */
+ public static int solveQuadratic(double[] eqn)
+ {
+ return solveQuadratic(eqn, eqn);
+ }
+
+ /**
+ * Finds the non-complex roots of a quadratic equation. The
+ * following equation is being solved:
+ *
+ * <blockquote><code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
+ * + <code>eqn[1]</code> &#xb7; <i>x</i>
+ * + <code>eqn[0]</code>
+ * = 0
+ * </blockquote>
+ *
+ * <p>For some background about solving quadratic equations, see the
+ * article <a href=
+ * "http://planetmath.org/encyclopedia/QuadraticFormula.html"
+ * >&#x201c;Quadratic Formula&#x201d;</a> in <a href=
+ * "http://planetmath.org/">PlanetMath</a>. For an extensive library
+ * of numerical algorithms written in the C programming language,
+ * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific
+ * Library</a>.
+ *
+ * @see CubicCurve2D#solveCubic(double[],double[])
+ *
+ * @param eqn an array with the coefficients of the equation.
+ *
+ * @param res an array into which the non-complex roots will be
+ * stored. The results may be in an arbitrary order. It is safe to
+ * pass the same array object reference for both <code>eqn</code>
+ * and <code>res</code>.
+ *
+ * @return the number of non-complex solutions. A result of 0
+ * indicates that the equation has no non-complex solutions. A
+ * result of -1 indicates that the equation is constant (i.e.,
+ * always or never zero).
+ *
+ * @author Brian Gough (bjg@network-theory.com)
+ * (original C implementation in the <a href=
+ * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * (adaptation to Java)
+ */
+ public static int solveQuadratic(double[] eqn, double[] res)
+ {
+ // Taken from poly/solve_quadratic.c in the GNU Scientific Library
+ // (GSL), cvs revision 1.7 of 2003-07-26. For the original source,
+ // see http://www.gnu.org/software/gsl/
+ //
+ // Brian Gough, the author of that code, has granted the
+ // permission to use it in GNU Classpath under the GNU Classpath
+ // license, and has assigned the copyright to the Free Software
+ // Foundation.
+ //
+ // The Java implementation is very similar to the GSL code, but
+ // not a strict one-to-one copy. For example, GSL would sort the
+ // result.
+ double a;
+ double b;
+ double c;
+ double disc;
+
+ c = eqn[0];
+ b = eqn[1];
+ a = eqn[2];
+
+ // Check for linear or constant functions. This is not done by the
+ // GNU Scientific Library. Without this special check, we
+ // wouldn't return -1 for constant functions, and 2 instead of 1
+ // for linear functions.
+ if (a == 0)
+ {
+ if (b == 0)
+ return -1;
+
+ res[0] = -c / b;
+ return 1;
+ }
+
+ disc = b * b - 4 * a * c;
+
+ if (disc < 0)
+ return 0;
+
+ if (disc == 0)
+ {
+ // The GNU Scientific Library returns two identical results here.
+ // We just return one.
+ res[0] = -0.5 * b / a;
+ return 1;
+ }
+
+ // disc > 0
+ if (b == 0)
+ {
+ double r;
+
+ r = Math.abs(0.5 * Math.sqrt(disc) / a);
+ res[0] = -r;
+ res[1] = r;
+ }
+ else
+ {
+ double sgnb;
+ double temp;
+
+ sgnb = (b > 0 ? 1 : -1);
+ temp = -0.5 * (b + sgnb * Math.sqrt(disc));
+
+ // The GNU Scientific Library sorts the result here. We don't.
+ res[0] = temp / a;
+ res[1] = c / temp;
+ }
+ return 2;
+ }
+
+ /**
+ * Determines whether a point is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
+ */
+ public boolean contains(double x, double y)
+ {
+ if (! getBounds2D().contains(x, y))
+ return false;
+
+ return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
+ }
+
+ /**
+ * Determines whether a point is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Determines whether any part of a rectangle is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; in a CubicCurve2D.
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().contains(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether any part of a Rectangle2D is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ * @see #intersects(double, double, double, double)
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determines whether a rectangle is entirely inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
+ * @see #contains(double, double)
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether a Rectangle2D is entirely inside the area that is
+ * bounded by the curve and the straight line connecting its end points.
+ * @see #contains(double, double, double, double)
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control point. As the illustration
+ * below shows, the invisible control point may cause the bounds to
+ * be much larger than the area that is actually covered by the
+ * curve.
+ *
+ * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a QuadCurve2D" />
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current = 0;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current >= 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getCtrlX();
+ coords[1] = (float) getCtrlY();
+ coords[2] = (float) getX2();
+ coords[3] = (float) getY2();
+ result = SEG_QUADTO;
+ break;
+ default:
+ throw new NoSuchElementException("quad iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 2);
+ return result;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getCtrlX();
+ coords[1] = getCtrlY();
+ coords[2] = getX2();
+ coords[3] = getY2();
+ result = SEG_QUADTO;
+ break;
+ default:
+ throw new NoSuchElementException("quad iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 2);
+ return result;
+ }
+ };
+ }
+
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ /**
+ * Creates a new curve with the same contents as this one.
+ *
+ * @return the clone.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Helper method used by contains() and intersects() methods
+ * Return the number of curve/line intersections on a given axis
+ * extending from a certain point. useYaxis is true for using the Y axis,
+ * @param x x coordinate of the origin point
+ * @param y y coordinate of the origin point
+ * @param useYaxis axis to follow, if true the positive Y axis is used,
+ * false uses the positive X axis.
+ *
+ * This is an implementation of the line-crossings algorithm,
+ * Detailed in an article on Eric Haines' page:
+ * http://www.acm.org/tog/editors/erich/ptinpoly/
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ int nCrossings = 0;
+ double a0;
+ double a1;
+ double a2;
+ double b0;
+ double b1;
+ double b2;
+ double[] r = new double[3];
+ int nRoots;
+
+ a0 = a2 = 0.0;
+
+ if (useYaxis)
+ {
+ a0 = getY1() - y;
+ a1 = getCtrlY() - y;
+ a2 = getY2() - y;
+ b0 = getX1() - x;
+ b1 = getCtrlX() - x;
+ b2 = getX2() - x;
+ }
+ else
+ {
+ a0 = getX1() - x;
+ a1 = getCtrlX() - x;
+ a2 = getX2() - x;
+ b0 = getY1() - y;
+ b1 = getCtrlY() - y;
+ b2 = getY2() - y;
+ }
+
+ /* If the axis intersects a start/endpoint, shift it up by some small
+ amount to guarantee the line is 'inside'
+ If this is not done,bad behaviour may result for points on that axis. */
+ if (a0 == 0.0 || a2 == 0.0)
+ {
+ double small = getFlatness() * EPSILON;
+ if (a0 == 0.0)
+ a0 -= small;
+
+ if (a2 == 0.0)
+ a2 -= small;
+ }
+
+ r[0] = a0;
+ r[1] = 2 * (a1 - a0);
+ r[2] = (a2 - 2 * a1 + a0);
+
+ nRoots = solveQuadratic(r);
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ double crossing = t * t * (b2 - 2 * b1 + b0) + 2 * t * (b1 - b0)
+ + b0;
+ /* single root is always doubly degenerate in quads */
+ if (crossing > 0 && crossing < distance)
+ nCrossings += (nRoots == 1) ? 2 : 1;
+ }
+ }
+
+ if (useYaxis)
+ {
+ if (Line2D.linesIntersect(b0, a0, b2, a2, EPSILON, 0.0, distance, 0.0))
+ nCrossings++;
+ }
+ else
+ {
+ if (Line2D.linesIntersect(a0, b0, a2, b2, 0.0, EPSILON, 0.0, distance))
+ nCrossings++;
+ }
+
+ return (nCrossings);
+ }
+
+ /**
+ * A two-dimensional curve that is parameterized with a quadratic
+ * function and stores coordinate values in double-precision
+ * floating-point format.
+ *
+ * @see QuadCurve2D.Float
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ public static class Double extends QuadCurve2D
+ {
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s start point.
+ */
+ public double x1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s start point.
+ */
+ public double y1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s control point.
+ */
+ public double ctrlx;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s control point.
+ */
+ public double ctrly;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s end point.
+ */
+ public double x2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s end point.
+ */
+ public double y2;
+
+ /**
+ * Constructs a new QuadCurve2D that stores its coordinate values
+ * in double-precision floating-point format. All points are
+ * initially at position (0, 0).
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Constructs a new QuadCurve2D that stores its coordinate values
+ * in double-precision floating-point format, specifying the
+ * initial position of each point.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public Double(double x1, double y1, double cx, double cy, double x2,
+ double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx = cx;
+ ctrly = cy;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Double(x1, y1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public double getCtrlX()
+ {
+ return ctrlx;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public double getCtrlY()
+ {
+ return ctrly;
+ }
+
+ /**
+ * Returns the curve&#x2019;s control point.
+ */
+ public Point2D getCtrlPt()
+ {
+ return new Point2D.Double(ctrlx, ctrly);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Double(x2, y2);
+ }
+
+ /**
+ * Changes the geometry of the curve.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * end point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * end point.
+ */
+ public void setCurve(double x1, double y1, double cx, double cy,
+ double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx = cx;
+ ctrly = cy;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control point. As the
+ * illustration below shows, the invisible control point may cause
+ * the bounds to be much larger than the area that is actually
+ * covered by the curve.
+ *
+ * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a QuadCurve2D" />
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double nx1 = Math.min(Math.min(x1, ctrlx), x2);
+ double ny1 = Math.min(Math.min(y1, ctrly), y2);
+ double nx2 = Math.max(Math.max(x1, ctrlx), x2);
+ double ny2 = Math.max(Math.max(y1, ctrly), y2);
+ return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1);
+ }
+ }
+
+ /**
+ * A two-dimensional curve that is parameterized with a quadratic
+ * function and stores coordinate values in single-precision
+ * floating-point format.
+ *
+ * @see QuadCurve2D.Double
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ public static class Float extends QuadCurve2D
+ {
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s start point.
+ */
+ public float x1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s start point.
+ */
+ public float y1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s control point.
+ */
+ public float ctrlx;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s control point.
+ */
+ public float ctrly;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s end point.
+ */
+ public float x2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s end point.
+ */
+ public float y2;
+
+ /**
+ * Constructs a new QuadCurve2D that stores its coordinate values
+ * in single-precision floating-point format. All points are
+ * initially at position (0, 0).
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Constructs a new QuadCurve2D that stores its coordinate values
+ * in single-precision floating-point format, specifying the
+ * initial position of each point.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public Float(float x1, float y1, float cx, float cy, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx = cx;
+ ctrly = cy;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Float(x1, y1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public double getCtrlX()
+ {
+ return ctrlx;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public double getCtrlY()
+ {
+ return ctrly;
+ }
+
+ /**
+ * Returns the curve&#x2019;s control point.
+ */
+ public Point2D getCtrlPt()
+ {
+ return new Point2D.Float(ctrlx, ctrly);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Float(x2, y2);
+ }
+
+ /**
+ * Changes the geometry of the curve, specifying coordinate values
+ * as double-precision floating-point numbers.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * end point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * end point.
+ */
+ public void setCurve(double x1, double y1, double cx, double cy,
+ double x2, double y2)
+ {
+ this.x1 = (float) x1;
+ this.y1 = (float) y1;
+ ctrlx = (float) cx;
+ ctrly = (float) cy;
+ this.x2 = (float) x2;
+ this.y2 = (float) y2;
+ }
+
+ /**
+ * Changes the geometry of the curve, specifying coordinate values
+ * as single-precision floating-point numbers.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * end point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * end point.
+ */
+ public void setCurve(float x1, float y1, float cx, float cy, float x2,
+ float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx = cx;
+ ctrly = cy;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control point. As the
+ * illustration below shows, the invisible control point may cause
+ * the bounds to be much larger than the area that is actually
+ * covered by the curve.
+ *
+ * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a QuadCurve2D" />
+ */
+ public Rectangle2D getBounds2D()
+ {
+ float nx1 = (float) Math.min(Math.min(x1, ctrlx), x2);
+ float ny1 = (float) Math.min(Math.min(y1, ctrly), y2);
+ float nx2 = (float) Math.max(Math.max(x1, ctrlx), x2);
+ float ny2 = (float) Math.max(Math.max(y1, ctrly), y2);
+ return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/Rectangle2D.java b/libjava/classpath/java/awt/geom/Rectangle2D.java
new file mode 100644
index 00000000000..6a255f95391
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Rectangle2D.java
@@ -0,0 +1,992 @@
+/* Rectangle2D.java -- generic rectangles in 2-D space
+ Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+/**
+ * This class describes a rectangle by a point (x,y) and dimension (w x h).
+ * The actual storage is left up to subclasses.
+ *
+ * <p>It is valid for a rectangle to have negative width or height; but it
+ * is considered to have no area or internal points. Therefore, the behavior
+ * in methods like <code>contains</code> or <code>intersects</code> is
+ * undefined unless the rectangle has positive width and height.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class Rectangle2D extends RectangularShape
+{
+ /**
+ * The point lies left of the rectangle (p.x &lt; r.x).
+ *
+ * @see #outcode(double, double)
+ */
+ public static final int OUT_LEFT = 1;
+
+ /**
+ * The point lies above the rectangle (p.y &lt; r.y).
+ *
+ * @see #outcode(double, double)
+ */
+ public static final int OUT_TOP = 2;
+
+ /**
+ * The point lies right of the rectangle (p.x &gt; r.maxX).
+ *
+ * @see #outcode(double, double)
+ */
+ public static final int OUT_RIGHT = 4;
+
+ /**
+ * The point lies below of the rectangle (p.y &gt; r.maxY).
+ *
+ * @see #outcode(double, double)
+ */
+ public static final int OUT_BOTTOM = 8;
+
+ /**
+ * Default constructor.
+ */
+ protected Rectangle2D()
+ {
+ }
+
+ /**
+ * Set the bounding box of this rectangle.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ * @param w the new width
+ * @param h the new height
+ */
+ public abstract void setRect(double x, double y, double w, double h);
+
+ /**
+ * Set the bounding box of this rectangle from the given one.
+ *
+ * @param r rectangle to copy
+ * @throws NullPointerException if r is null
+ */
+ public void setRect(Rectangle2D r)
+ {
+ setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Tests if the specified line intersects the interior of this rectangle.
+ *
+ * @param x1 the first x coordinate of line segment
+ * @param y1 the first y coordinate of line segment
+ * @param x2 the second x coordinate of line segment
+ * @param y2 the second y coordinate of line segment
+ * @return true if the line intersects the rectangle
+ */
+ public boolean intersectsLine(double x1, double y1, double x2, double y2)
+ {
+ double x = getX();
+ double y = getY();
+ double w = getWidth();
+ double h = getHeight();
+ if (w <= 0 || h <= 0)
+ return false;
+
+ if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
+ return true;
+ if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
+ return true;
+
+ double x3 = x + w;
+ double y3 = y + h;
+
+ return (Line2D.linesIntersect(x1, y1, x2, y2, x, y, x, y3)
+ || Line2D.linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
+ || Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
+ || Line2D.linesIntersect(x1, y1, x2, y2, x3, y, x, y));
+ }
+
+ /**
+ * Tests if the specified line intersects the interior of this rectangle.
+ *
+ * @param l the line segment
+ * @return true if the line intersects the rectangle
+ * @throws NullPointerException if l is null
+ */
+ public boolean intersectsLine(Line2D l)
+ {
+ return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
+ }
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param x the x coordinate to check
+ * @param y the y coordinate to check
+ * @return the binary OR of the result
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ */
+ public abstract int outcode(double x, double y);
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param p the point to check
+ * @return the binary OR of the result
+ * @throws NullPointerException if p is null
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ */
+ public int outcode(Point2D p)
+ {
+ return outcode(p.getX(), p.getY());
+ }
+
+ /**
+ * Set the bounding box of this rectangle.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ * @param w the new width
+ * @param h the new height
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ setRect(x, y, w, h);
+ }
+
+ /**
+ * Returns the bounds of this rectangle. A pretty useless method, as this
+ * is already a rectangle.
+ *
+ * @return a copy of this rectangle
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return (Rectangle2D) clone();
+ }
+
+ /**
+ * Test if the given point is contained in the rectangle.
+ *
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ * @return true if (x,y) is in the rectangle
+ */
+ public boolean contains(double x, double y)
+ {
+ double mx = getX();
+ double my = getY();
+ double w = getWidth();
+ double h = getHeight();
+ return w > 0 && h > 0 && x >= mx && x < mx + w && y >= my && y < my + h;
+ }
+
+ /**
+ * Tests if the given rectangle intersects this one. In other words, test if
+ * the two rectangles share at least one internal point.
+ *
+ * @param x the x coordinate of the other rectangle
+ * @param y the y coordinate of the other rectangle
+ * @param w the width of the other rectangle
+ * @param h the height of the other rectangle
+ * @return true if the rectangles intersect
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ double mx = getX();
+ double my = getY();
+ double mw = getWidth();
+ double mh = getHeight();
+ return w > 0 && h > 0 && mw > 0 && mh > 0
+ && x < mx + mw && x + w > mx && y < my + mh && y + h > my;
+ }
+
+ /**
+ * Tests if this rectangle contains the given one. In other words, test if
+ * this rectangle contains all points in the given one.
+ *
+ * @param x the x coordinate of the other rectangle
+ * @param y the y coordinate of the other rectangle
+ * @param w the width of the other rectangle
+ * @param h the height of the other rectangle
+ * @return true if this rectangle contains the other
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ double mx = getX();
+ double my = getY();
+ double mw = getWidth();
+ double mh = getHeight();
+ return w > 0 && h > 0 && mw > 0 && mh > 0
+ && x >= mx && x + w <= mx + mw && y >= my && y + h <= my + mh;
+ }
+
+ /**
+ * Return a new rectangle which is the intersection of this and the given
+ * one. The result will be empty if there is no intersection.
+ *
+ * @param r the rectangle to be intersected
+ * @return the intersection
+ * @throws NullPointerException if r is null
+ */
+ public abstract Rectangle2D createIntersection(Rectangle2D r);
+
+ /**
+ * Intersects a pair of rectangles, and places the result in the
+ * destination; this can be used to avoid object creation. This method
+ * even works when the destination is also a source, although you stand
+ * to lose the original data.
+ *
+ * @param src1 the first source
+ * @param src2 the second source
+ * @param dest the destination for the intersection
+ * @throws NullPointerException if any rectangle is null
+ */
+ public static void intersect(Rectangle2D src1, Rectangle2D src2,
+ Rectangle2D dest)
+ {
+ double x = Math.max(src1.getX(), src2.getX());
+ double y = Math.max(src1.getY(), src2.getY());
+ double maxx = Math.min(src1.getMaxX(), src2.getMaxX());
+ double maxy = Math.min(src1.getMaxY(), src2.getMaxY());
+ dest.setRect(x, y, maxx - x, maxy - y);
+ }
+
+ /**
+ * Return a new rectangle which is the union of this and the given one.
+ *
+ * @param r the rectangle to be merged
+ * @return the union
+ * @throws NullPointerException if r is null
+ */
+ public abstract Rectangle2D createUnion(Rectangle2D r);
+
+ /**
+ * Joins a pair of rectangles, and places the result in the destination;
+ * this can be used to avoid object creation. This method even works when
+ * the destination is also a source, although you stand to lose the
+ * original data.
+ *
+ * @param src1 the first source
+ * @param src2 the second source
+ * @param dest the destination for the union
+ * @throws NullPointerException if any rectangle is null
+ */
+ public static void union(Rectangle2D src1, Rectangle2D src2,
+ Rectangle2D dest)
+ {
+ double x = Math.min(src1.getX(), src2.getX());
+ double y = Math.min(src1.getY(), src2.getY());
+ double maxx = Math.max(src1.getMaxX(), src2.getMaxX());
+ double maxy = Math.max(src1.getMaxY(), src2.getMaxY());
+ dest.setRect(x, y, maxx - x, maxy - y);
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified point.
+ * However, if the point falls on one of the two borders which are not
+ * inside the rectangle, a subsequent call to <code>contains</code> may
+ * return false.
+ *
+ * @param newx the X coordinate of the point to add to this rectangle
+ * @param newy the Y coordinate of the point to add to this rectangle
+ */
+ public void add(double newx, double newy)
+ {
+ double minx = Math.min(getX(), newx);
+ double maxx = Math.max(getMaxX(), newx);
+ double miny = Math.min(getY(), newy);
+ double maxy = Math.max(getMaxY(), newy);
+ setRect(minx, miny, maxx - minx, maxy - miny);
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified point.
+ * However, if the point falls on one of the two borders which are not
+ * inside the rectangle, a subsequent call to <code>contains</code> may
+ * return false.
+ *
+ * @param p the point to add to this rectangle
+ * @throws NullPointerException if p is null
+ */
+ public void add(Point2D p)
+ {
+ add(p.getX(), p.getY());
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified rectangle.
+ *
+ * @param r the rectangle to add to this rectangle
+ * @throws NullPointerException if r is null
+ * @see #union(Rectangle2D, Rectangle2D, Rectangle2D)
+ */
+ public void add(Rectangle2D r)
+ {
+ union(this, r, this);
+ }
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. Each call returns
+ * a new object, independent from others in use. This iterator is thread
+ * safe; modifications to the rectangle do not affect the results of this
+ * path instance.
+ *
+ * @param at an optional transform to apply to the iterator
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ final double minx = getX();
+ final double miny = getY();
+ final double maxx = minx + getWidth();
+ final double maxy = miny + getHeight();
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current = (maxx <= minx && maxy <= miny) ? 6 : 0;
+
+ public int getWindingRule()
+ {
+ // A test program showed that Sun J2SE 1.3.1 and 1.4.1_01
+ // return WIND_NON_ZERO paths. While this does not really
+ // make any difference for rectangles (because they are not
+ // self-intersecting), it seems appropriate to behave
+ // identically.
+
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current > 5;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ switch (current)
+ {
+ case 1:
+ coords[0] = (float) maxx;
+ coords[1] = (float) miny;
+ break;
+ case 2:
+ coords[0] = (float) maxx;
+ coords[1] = (float) maxy;
+ break;
+ case 3:
+ coords[0] = (float) minx;
+ coords[1] = (float) maxy;
+ break;
+ case 0:
+ case 4:
+ coords[0] = (float) minx;
+ coords[1] = (float) miny;
+ break;
+ case 5:
+ return SEG_CLOSE;
+ default:
+ throw new NoSuchElementException("rect iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return current == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ switch (current)
+ {
+ case 1:
+ coords[0] = maxx;
+ coords[1] = miny;
+ break;
+ case 2:
+ coords[0] = maxx;
+ coords[1] = maxy;
+ break;
+ case 3:
+ coords[0] = minx;
+ coords[1] = maxy;
+ break;
+ case 0:
+ case 4:
+ coords[0] = minx;
+ coords[1] = miny;
+ break;
+ case 5:
+ return SEG_CLOSE;
+ default:
+ throw new NoSuchElementException("rect iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return current == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+ };
+ }
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. Each call returns
+ * a new object, independent from others in use. This iterator is thread
+ * safe; modifications to the rectangle do not affect the results of this
+ * path instance. As the rectangle is already flat, the flatness parameter
+ * is ignored.
+ *
+ * @param at an optional transform to apply to the iterator
+ * @param flatness the maximum distance for deviation from the real boundary
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return getPathIterator(at);
+ }
+
+ /**
+ * Return the hashcode for this rectangle. The formula is not documented, but
+ * appears to be the same as:
+ * <pre>
+ * long l = Double.doubleToLongBits(getX())
+ * + 37 * Double.doubleToLongBits(getY())
+ * + 43 * Double.doubleToLongBits(getWidth())
+ * + 47 * Double.doubleToLongBits(getHeight());
+ * return (int) ((l &gt;&gt; 32) ^ l);
+ * </pre>
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // Talk about a fun time reverse engineering this one!
+ long l = java.lang.Double.doubleToLongBits(getX())
+ + 37 * java.lang.Double.doubleToLongBits(getY())
+ + 43 * java.lang.Double.doubleToLongBits(getWidth())
+ + 47 * java.lang.Double.doubleToLongBits(getHeight());
+ return (int) ((l >> 32) ^ l);
+ }
+
+ /**
+ * Tests this rectangle for equality against the specified object. This
+ * will be true if an only if the specified object is an instance of
+ * Rectangle2D with the same coordinates and dimensions.
+ *
+ * @param obj the object to test against for equality
+ * @return true if the specified object is equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Rectangle2D))
+ return false;
+ Rectangle2D r = (Rectangle2D) obj;
+ return r.getX() == getX() && r.getY() == getY()
+ && r.getWidth() == getWidth() && r.getHeight() == getHeight();
+ }
+
+ /**
+ * This class defines a rectangle in <code>double</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Double extends Rectangle2D
+ {
+ /** The x coordinate of the lower left corner. */
+ public double x;
+
+ /** The y coordinate of the lower left corner. */
+ public double y;
+
+ /** The width of the rectangle. */
+ public double width;
+
+ /** The height of the rectangle. */
+ public double height;
+
+ /**
+ * Create a rectangle at (0,0) with width 0 and height 0.
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Create a rectangle with the given values.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public Double(double x, double y, double w, double h)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Return the X coordinate.
+ *
+ * @return the value of x
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the Y coordinate.
+ *
+ * @return the value of y
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Return the width.
+ *
+ * @return the value of width
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Return the height.
+ *
+ * @return the value of height
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Test if the rectangle is empty.
+ *
+ * @return true if width or height is not positive
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public void setRect(double x, double y, double w, double h)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param r the rectangle to copy
+ * @throws NullPointerException if r is null
+ */
+ public void setRect(Rectangle2D r)
+ {
+ x = r.getX();
+ y = r.getY();
+ width = r.getWidth();
+ height = r.getHeight();
+ }
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param x the x coordinate to check
+ * @param y the y coordinate to check
+ * @return the binary OR of the result
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ * @since 1.2
+ */
+ public int outcode(double x, double y)
+ {
+ int result = 0;
+ if (width <= 0)
+ result |= OUT_LEFT | OUT_RIGHT;
+ else if (x < this.x)
+ result |= OUT_LEFT;
+ else if (x > this.x + width)
+ result |= OUT_RIGHT;
+ if (height <= 0)
+ result |= OUT_BOTTOM | OUT_TOP;
+ else if (y < this.y) // Remember that +y heads top-to-bottom.
+ result |= OUT_TOP;
+ else if (y > this.y + height)
+ result |= OUT_BOTTOM;
+ return result;
+ }
+
+ /**
+ * Returns the bounds of this rectangle. A pretty useless method, as this
+ * is already a rectangle.
+ *
+ * @return a copy of this rectangle
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Double(x, y, width, height);
+ }
+
+ /**
+ * Return a new rectangle which is the intersection of this and the given
+ * one. The result will be empty if there is no intersection.
+ *
+ * @param r the rectangle to be intersected
+ * @return the intersection
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle2D createIntersection(Rectangle2D r)
+ {
+ Double res = new Double();
+ intersect(this, r, res);
+ return res;
+ }
+
+ /**
+ * Return a new rectangle which is the union of this and the given one.
+ *
+ * @param r the rectangle to be merged
+ * @return the union
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle2D createUnion(Rectangle2D r)
+ {
+ Double res = new Double();
+ union(this, r, res);
+ return res;
+ }
+
+ /**
+ * Returns a string representation of this rectangle. This is in the form
+ * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
+ * + ",h=" + height + ']'</code>.
+ *
+ * @return a string representation of this rectangle
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
+ + ",h=" + height + ']';
+ }
+ }
+
+ /**
+ * This class defines a rectangle in <code>float</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Float extends Rectangle2D
+ {
+ /** The x coordinate of the lower left corner. */
+ public float x;
+
+ /** The y coordinate of the lower left corner. */
+ public float y;
+
+ /** The width of the rectangle. */
+ public float width;
+
+ /** The height of the rectangle. */
+ public float height;
+
+ /**
+ * Create a rectangle at (0,0) with width 0 and height 0.
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Create a rectangle with the given values.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public Float(float x, float y, float w, float h)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Create a rectangle with the given values.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ Float(double x, double y, double w, double h)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ width = (float) w;
+ height = (float) h;
+ }
+
+ /**
+ * Return the X coordinate.
+ *
+ * @return the value of x
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the Y coordinate.
+ *
+ * @return the value of y
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Return the width.
+ *
+ * @return the value of width
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Return the height.
+ *
+ * @return the value of height
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Test if the rectangle is empty.
+ *
+ * @return true if width or height is not positive
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public void setRect(float x, float y, float w, float h)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public void setRect(double x, double y, double w, double h)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ width = (float) w;
+ height = (float) h;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param r the rectangle to copy
+ * @throws NullPointerException if r is null
+ */
+ public void setRect(Rectangle2D r)
+ {
+ x = (float) r.getX();
+ y = (float) r.getY();
+ width = (float) r.getWidth();
+ height = (float) r.getHeight();
+ }
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param x the x coordinate to check
+ * @param y the y coordinate to check
+ * @return the binary OR of the result
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ * @since 1.2
+ */
+ public int outcode(double x, double y)
+ {
+ int result = 0;
+ if (width <= 0)
+ result |= OUT_LEFT | OUT_RIGHT;
+ else if (x < this.x)
+ result |= OUT_LEFT;
+ else if (x > this.x + width)
+ result |= OUT_RIGHT;
+ if (height <= 0)
+ result |= OUT_BOTTOM | OUT_TOP;
+ else if (y < this.y) // Remember that +y heads top-to-bottom.
+ result |= OUT_TOP;
+ else if (y > this.y + height)
+ result |= OUT_BOTTOM;
+ return result;
+ }
+
+ /**
+ * Returns the bounds of this rectangle. A pretty useless method, as this
+ * is already a rectangle.
+ *
+ * @return a copy of this rectangle
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Float(x, y, width, height);
+ }
+
+ /**
+ * Return a new rectangle which is the intersection of this and the given
+ * one. The result will be empty if there is no intersection.
+ *
+ * @param r the rectangle to be intersected
+ * @return the intersection
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle2D createIntersection(Rectangle2D r)
+ {
+ Float res = new Float();
+ intersect(this, r, res);
+ return res;
+ }
+
+ /**
+ * Return a new rectangle which is the union of this and the given one.
+ *
+ * @param r the rectangle to be merged
+ * @return the union
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle2D createUnion(Rectangle2D r)
+ {
+ Float res = new Float();
+ union(this, r, res);
+ return res;
+ }
+
+ /**
+ * Returns a string representation of this rectangle. This is in the form
+ * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
+ * + ",h=" + height + ']'</code>.
+ *
+ * @return a string representation of this rectangle
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
+ + ",h=" + height + ']';
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/RectangularShape.java b/libjava/classpath/java/awt/geom/RectangularShape.java
new file mode 100644
index 00000000000..8f66dabf2e7
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/RectangularShape.java
@@ -0,0 +1,385 @@
+/* RectangularShape.java -- a rectangular frame for several generic shapes
+ Copyright (C) 2000, 2002 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.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+/**
+ * This class provides a generic framework, and several helper methods, for
+ * subclasses which represent geometric objects inside a rectangular frame.
+ * This does not specify any geometry except for the bounding box.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @see Arc2D
+ * @see Ellipse2D
+ * @see Rectangle2D
+ * @see RoundRectangle2D
+ * @status updated to 1.4
+ */
+public abstract class RectangularShape implements Shape, Cloneable
+{
+ /**
+ * Default constructor.
+ */
+ protected RectangularShape()
+ {
+ }
+
+ /**
+ * Get the x coordinate of the upper-left corner of the framing rectangle.
+ *
+ * @return the x coordinate
+ */
+ public abstract double getX();
+
+ /**
+ * Get the y coordinate of the upper-left corner of the framing rectangle.
+ *
+ * @return the y coordinate
+ */
+ public abstract double getY();
+
+ /**
+ * Get the width of the framing rectangle.
+ *
+ * @return the width
+ */
+ public abstract double getWidth();
+
+ /**
+ * Get the height of the framing rectangle.
+ *
+ * @return the height
+ */
+ public abstract double getHeight();
+
+ /**
+ * Get the minimum x coordinate in the frame. This is misnamed, or else
+ * Sun has a bug, because the implementation returns getX() even when
+ * getWidth() is negative.
+ *
+ * @return the minimum x coordinate
+ */
+ public double getMinX()
+ {
+ return getX();
+ }
+
+ /**
+ * Get the minimum y coordinate in the frame. This is misnamed, or else
+ * Sun has a bug, because the implementation returns getY() even when
+ * getHeight() is negative.
+ *
+ * @return the minimum y coordinate
+ */
+ public double getMinY()
+ {
+ return getY();
+ }
+
+ /**
+ * Get the maximum x coordinate in the frame. This is misnamed, or else
+ * Sun has a bug, because the implementation returns getX()+getWidth() even
+ * when getWidth() is negative.
+ *
+ * @return the maximum x coordinate
+ */
+ public double getMaxX()
+ {
+ return getX() + getWidth();
+ }
+
+ /**
+ * Get the maximum y coordinate in the frame. This is misnamed, or else
+ * Sun has a bug, because the implementation returns getY()+getHeight() even
+ * when getHeight() is negative.
+ *
+ * @return the maximum y coordinate
+ */
+ public double getMaxY()
+ {
+ return getY() + getHeight();
+ }
+
+ /**
+ * Return the x coordinate of the center point of the framing rectangle.
+ *
+ * @return the central x coordinate
+ */
+ public double getCenterX()
+ {
+ return getX() + getWidth() / 2;
+ }
+
+ /**
+ * Return the y coordinate of the center point of the framing rectangle.
+ *
+ * @return the central y coordinate
+ */
+ public double getCenterY()
+ {
+ return getY() + getHeight() / 2;
+ }
+
+ /**
+ * Return the frame around this object. Note that this may be a looser
+ * bounding box than getBounds2D.
+ *
+ * @return the frame, in double precision
+ * @see #setFrame(double, double, double, double)
+ */
+ public Rectangle2D getFrame()
+ {
+ return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight());
+ }
+
+ /**
+ * Test if the shape is empty, meaning that no points are inside it.
+ *
+ * @return true if the shape is empty
+ */
+ public abstract boolean isEmpty();
+
+ /**
+ * Set the framing rectangle of this shape to the given coordinate and size.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ * @param w the new width
+ * @param h the new height
+ * @see #getFrame()
+ */
+ public abstract void setFrame(double x, double y, double w, double h);
+
+ /**
+ * Set the framing rectangle of this shape to the given coordinate and size.
+ *
+ * @param p the new point
+ * @param d the new dimension
+ * @throws NullPointerException if p or d is null
+ * @see #getFrame()
+ */
+ public void setFrame(Point2D p, Dimension2D d)
+ {
+ setFrame(p.getX(), p.getY(), d.getWidth(), d.getHeight());
+ }
+
+ /**
+ * Set the framing rectangle of this shape to the given rectangle.
+ *
+ * @param r the new framing rectangle
+ * @throws NullPointerException if r is null
+ * @see #getFrame()
+ */
+ public void setFrame(Rectangle2D r)
+ {
+ setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Set the framing rectangle of this shape using two points on a diagonal.
+ * The area will be positive.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ */
+ public void setFrameFromDiagonal(double x1, double y1, double x2, double y2)
+ {
+ if (x1 > x2)
+ {
+ double t = x2;
+ x2 = x1;
+ x1 = t;
+ }
+ if (y1 > y2)
+ {
+ double t = y2;
+ y2 = y1;
+ y1 = t;
+ }
+ setFrame(x1, y1, x2 - x1, y2 - y1);
+ }
+
+ /**
+ * Set the framing rectangle of this shape using two points on a diagonal.
+ * The area will be positive.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public void setFrameFromDiagonal(Point2D p1, Point2D p2)
+ {
+ setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+ }
+
+ /**
+ * Set the framing rectangle of this shape using the center of the frame,
+ * and one of the four corners. The area will be positive.
+ *
+ * @param centerX the x coordinate at the center
+ * @param centerY the y coordinate at the center
+ * @param cornerX the x coordinate at a corner
+ * @param cornerY the y coordinate at a corner
+ */
+ public void setFrameFromCenter(double centerX, double centerY,
+ double cornerX, double cornerY)
+ {
+ double halfw = Math.abs(cornerX - centerX);
+ double halfh = Math.abs(cornerY - centerY);
+ setFrame(centerX - halfw, centerY - halfh, halfw + halfw, halfh + halfh);
+ }
+
+ /**
+ * Set the framing rectangle of this shape using the center of the frame,
+ * and one of the four corners. The area will be positive.
+ *
+ * @param center the center point
+ * @param corner a corner point
+ * @throws NullPointerException if either point is null
+ */
+ public void setFrameFromCenter(Point2D center, Point2D corner)
+ {
+ setFrameFromCenter(center.getX(), center.getY(),
+ corner.getX(), corner.getY());
+ }
+
+ /**
+ * Tests if a point is inside the boundary of the shape.
+ *
+ * @param p the point to test
+ * @return true if the point is inside the shape
+ * @throws NullPointerException if p is null
+ * @see #contains(double, double)
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Tests if a rectangle and this shape share common internal points.
+ *
+ * @param r the rectangle to test
+ * @return true if the rectangle intersects this shpae
+ * @throws NullPointerException if r is null
+ * @see #intersects(double, double, double, double)
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Tests if the shape completely contains the given rectangle.
+ *
+ * @param r the rectangle to test
+ * @return true if r is contained in this shape
+ * @throws NullPointerException if r is null
+ * @see #contains(double, double, double, double)
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Returns a bounding box for this shape, in integer format. Notice that you
+ * may get a tighter bound with getBounds2D. If the frame is empty, the
+ * box is the default empty box at the origin.
+ *
+ * @return a bounding box
+ */
+ public Rectangle getBounds()
+ {
+ if (isEmpty())
+ return new Rectangle();
+ double x = getX();
+ double y = getY();
+ double maxx = Math.ceil(x + getWidth());
+ double maxy = Math.ceil(y + getHeight());
+ x = Math.floor(x);
+ y = Math.floor(y);
+ return new Rectangle((int) x, (int) y, (int) (maxx - x), (int) (maxy - y));
+ }
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. The path is
+ * flattened until all segments differ from the curve by at most the value
+ * of the flatness parameter, within the limits of the default interpolation
+ * recursion limit of 1024 segments between actual points. Each call
+ * returns a new object, independent from others in use. The result is
+ * threadsafe if and only if the iterator returned by
+ * {@link #getPathIterator(AffineTransform)} is as well.
+ *
+ * @param at an optional transform to apply to the iterator
+ * @param flatness the desired flatness
+ * @return a new iterator over the boundary
+ * @throws IllegalArgumentException if flatness is invalid
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ /**
+ * Create a new shape of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+} // class RectangularShape
diff --git a/libjava/classpath/java/awt/geom/RoundRectangle2D.java b/libjava/classpath/java/awt/geom/RoundRectangle2D.java
new file mode 100644
index 00000000000..ac0e6f8128a
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/RoundRectangle2D.java
@@ -0,0 +1,533 @@
+/* RoundRectangle2D.java -- represents a rectangle with rounded corners
+ Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+
+/** This class implements a rectangle with rounded corners.
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @date December 3, 2000
+ */
+public abstract class RoundRectangle2D extends RectangularShape
+{
+ /** Return the arc height of this round rectangle. */
+ public abstract double getArcHeight();
+
+ /** Return the arc width of this round rectangle. */
+ public abstract double getArcWidth();
+
+ /** Set the values of this round rectangle
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ * @param arcWidth The arc width
+ * @param arcHeight The arc height
+ */
+ public abstract void setRoundRect(double x, double y, double w, double h,
+ double arcWidth, double arcHeight);
+
+ /** Create a RoundRectangle2D. This is protected because this class
+ * is abstract and cannot be instantiated.
+ */
+ protected RoundRectangle2D()
+ {
+ }
+
+ /** Return true if this object contains the specified point.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ */
+ public boolean contains(double x, double y)
+ {
+ double mx = getX();
+ double mw = getWidth();
+ if (x < mx || x >= mx + mw)
+ return false;
+ double my = getY();
+ double mh = getHeight();
+ if (y < my || y >= my + mh)
+ return false;
+
+ // Now check to see if the point is in range of an arc.
+ double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y));
+ double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x));
+
+ // The arc dimensions are that of the corresponding ellipse
+ // thus a 90 degree segment is half of that.
+ double aw = getArcWidth() / 2.0;
+ double ah = getArcHeight() / 2.0;
+ if (dx > aw || dy > ah)
+ return true;
+
+ // At this point DX represents the distance from the nearest edge
+ // of the rectangle. But we want to transform it to represent the
+ // scaled distance from the center of the ellipse that forms the
+ // arc. Hence this code:
+ dy = (ah - dy) / ah;
+ dx = (aw - dx) / aw;
+
+ return dx * dx + dy * dy <= 1.0;
+ }
+
+ /** Return true if this object contains the specified rectangle
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ // We have to check all four points here (for ordinary rectangles
+ // we can just check opposing corners).
+ return (contains(x, y) && contains(x, y + h) && contains(x + w, y + h)
+ && contains(x + w, y));
+ }
+
+ /** Return a new path iterator which iterates over this rectangle.
+ * @param at An affine transform to apply to the object
+ */
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ final double minx = getX();
+ final double miny = getY();
+ final double maxx = minx + getWidth();
+ final double maxy = miny + getHeight();
+ final double arcwidth = getArcWidth();
+ final double archeight = getArcHeight();
+ return new PathIterator()
+ {
+ /** We iterate counterclockwise around the rectangle, starting in the
+ * upper right. This variable tracks our current point, which
+ * can be on either side of a given corner. */
+ private int current = 0;
+
+ /** Child path iterator, used for corners. */
+ private PathIterator corner;
+
+ /** This is used when rendering the corners. We re-use the arc
+ * for each corner. */
+ private Arc2D arc = new Arc2D.Double();
+
+ /** Temporary array used by getPoint. */
+ private double[] temp = new double[2];
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current > 9;
+ }
+
+ private void getPoint(int val)
+ {
+ switch (val)
+ {
+ case 0:
+ case 8:
+ temp[0] = maxx;
+ temp[1] = miny + archeight;
+ break;
+ case 7:
+ temp[0] = maxx;
+ temp[1] = maxy - archeight;
+ break;
+ case 6:
+ temp[0] = maxx - arcwidth;
+ temp[1] = maxy;
+ break;
+ case 5:
+ temp[0] = minx + arcwidth;
+ temp[1] = maxy;
+ break;
+ case 4:
+ temp[0] = minx;
+ temp[1] = maxy - archeight;
+ break;
+ case 3:
+ temp[0] = minx;
+ temp[1] = miny + archeight;
+ break;
+ case 2:
+ temp[0] = minx + arcwidth;
+ temp[1] = miny;
+ break;
+ case 1:
+ temp[0] = maxx - arcwidth;
+ temp[1] = miny;
+ break;
+ }
+ }
+
+ public void next()
+ {
+ if (current >= 8)
+ ++current;
+ else if (corner != null)
+ {
+ // We're iterating through the corner. Work on the child
+ // iterator; if it finishes, reset and move to the next
+ // point along the rectangle.
+ corner.next();
+ if (corner.isDone())
+ {
+ corner = null;
+ ++current;
+ }
+ }
+ else
+ {
+ // Make an arc between this point on the rectangle and
+ // the next one, and then iterate over this arc.
+ getPoint(current);
+ double x1 = temp[0];
+ double y1 = temp[1];
+ getPoint(current + 1);
+ Rectangle2D.Double r = new Rectangle2D.Double(Math.min(x1,
+ temp[0]),
+ Math.min(y1,
+ temp[1]),
+ Math.abs(x1
+ - temp[0]),
+ Math.abs(y1
+ - temp[1]));
+ arc.setArc(r, (current >> 1) * 90.0, 90.0, Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ if (corner != null)
+ {
+ int r = corner.currentSegment(coords);
+ if (r == SEG_MOVETO)
+ r = SEG_LINETO;
+ return r;
+ }
+
+ if (current < 9)
+ {
+ getPoint(current);
+ coords[0] = (float) temp[0];
+ coords[1] = (float) temp[1];
+ }
+ else if (current == 9)
+ return SEG_CLOSE;
+ else
+ throw new NoSuchElementException("rect iterator out of bounds");
+
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return current == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ if (corner != null)
+ {
+ int r = corner.currentSegment(coords);
+ if (r == SEG_MOVETO)
+ r = SEG_LINETO;
+ return r;
+ }
+
+ if (current < 9)
+ {
+ getPoint(current);
+ coords[0] = temp[0];
+ coords[1] = temp[1];
+ }
+ else if (current == 9)
+ return SEG_CLOSE;
+ else
+ throw new NoSuchElementException("rect iterator out of bounds");
+
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return current == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+ };
+ }
+
+ /** Return true if the given rectangle intersects this shape.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ // Check if any corner is within the rectangle
+ return (contains(x, y) || contains(x, y + h) || contains(x + w, y + h)
+ || contains(x + w, y));
+ }
+
+ /** Set the boundary of this round rectangle.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ // This is a bit lame.
+ setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
+ }
+
+ /** Set the values of this round rectangle to be the same as those
+ * of the argument.
+ * @param rr The round rectangle to copy
+ */
+ public void setRoundRect(RoundRectangle2D rr)
+ {
+ setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
+ rr.getArcWidth(), rr.getArcHeight());
+ }
+
+ /** A subclass of RoundRectangle which keeps its parameters as
+ * doubles. */
+ public static class Double extends RoundRectangle2D
+ {
+ /** The height of the corner arc. */
+ public double archeight;
+
+ /** The width of the corner arc. */
+ public double arcwidth;
+
+ /** The x coordinate of this object. */
+ public double x;
+
+ /** The y coordinate of this object. */
+ public double y;
+
+ /** The width of this object. */
+ public double width;
+
+ /** The height of this object. */
+ public double height;
+
+ /** Construct a new instance, with all parameters set to 0. */
+ public Double()
+ {
+ }
+
+ /** Construct a new instance with the given arguments.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ * @param arcWidth The arc width
+ * @param arcHeight The arc height
+ */
+ public Double(double x, double y, double w, double h, double arcWidth,
+ double arcHeight)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.arcwidth = arcWidth;
+ this.archeight = arcHeight;
+ }
+
+ public double getArcHeight()
+ {
+ return archeight;
+ }
+
+ public double getArcWidth()
+ {
+ return arcwidth;
+ }
+
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle2D.Double(x, y, width, height);
+ }
+
+ public double getX()
+ {
+ return x;
+ }
+
+ public double getY()
+ {
+ return y;
+ }
+
+ public double getWidth()
+ {
+ return width;
+ }
+
+ public double getHeight()
+ {
+ return height;
+ }
+
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ public void setRoundRect(double x, double y, double w, double h,
+ double arcWidth, double arcHeight)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.arcwidth = arcWidth;
+ this.archeight = arcHeight;
+ }
+ } // class Double
+
+ /** A subclass of RoundRectangle which keeps its parameters as
+ * floats. */
+ public static class Float extends RoundRectangle2D
+ {
+ /** The height of the corner arc. */
+ public float archeight;
+
+ /** The width of the corner arc. */
+ public float arcwidth;
+
+ /** The x coordinate of this object. */
+ public float x;
+
+ /** The y coordinate of this object. */
+ public float y;
+
+ /** The width of this object. */
+ public float width;
+
+ /** The height of this object. */
+ public float height;
+
+ /** Construct a new instance, with all parameters set to 0. */
+ public Float()
+ {
+ }
+
+ /** Construct a new instance with the given arguments.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ * @param arcWidth The arc width
+ * @param arcHeight The arc height
+ */
+ public Float(float x, float y, float w, float h, float arcWidth,
+ float arcHeight)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.arcwidth = arcWidth;
+ this.archeight = arcHeight;
+ }
+
+ public double getArcHeight()
+ {
+ return archeight;
+ }
+
+ public double getArcWidth()
+ {
+ return arcwidth;
+ }
+
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle2D.Float(x, y, width, height);
+ }
+
+ public double getX()
+ {
+ return x;
+ }
+
+ public double getY()
+ {
+ return y;
+ }
+
+ public double getWidth()
+ {
+ return width;
+ }
+
+ public double getHeight()
+ {
+ return height;
+ }
+
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ public void setRoundRect(float x, float y, float w, float h,
+ float arcWidth, float arcHeight)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.arcwidth = arcWidth;
+ this.archeight = arcHeight;
+ }
+
+ public void setRoundRect(double x, double y, double w, double h,
+ double arcWidth, double arcHeight)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ this.width = (float) w;
+ this.height = (float) h;
+ this.arcwidth = (float) arcWidth;
+ this.archeight = (float) arcHeight;
+ }
+ } // class Float
+} // class RoundRectangle2D
diff --git a/libjava/classpath/java/awt/geom/doc-files/Area-1.png b/libjava/classpath/java/awt/geom/doc-files/Area-1.png
new file mode 100644
index 00000000000..44650f2d8a1
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/Area-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png
new file mode 100644
index 00000000000..1784509be61
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png
new file mode 100644
index 00000000000..1ddae9fc84f
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png
new file mode 100644
index 00000000000..b200dad37a8
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png
new file mode 100644
index 00000000000..e57ffdc5cf0
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png
new file mode 100644
index 00000000000..701ab138f0b
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png b/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png
new file mode 100644
index 00000000000..8317db66196
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html b/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html
new file mode 100644
index 00000000000..5a52d693edd
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html
@@ -0,0 +1,481 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>The GNU Implementation of java.awt.geom.FlatteningPathIterator</title>
+ <meta name="author" content="Sascha Brawer" />
+ <style type="text/css"><!--
+ td { white-space: nowrap; }
+ li { margin: 2mm 0; }
+ --></style>
+</head>
+<body>
+
+<h1>The GNU Implementation of FlatteningPathIterator</h1>
+
+<p><i><a href="http://www.dandelis.ch/people/brawer/">Sascha
+Brawer</a>, November 2003</i></p>
+
+<p>This document describes the GNU implementation of the class
+<code>java.awt.geom.FlatteningPathIterator</code>. It does
+<em>not</em> describe how a programmer should use this class; please
+refer to the generated API documentation for this purpose. Instead, it
+is intended for maintenance programmers who want to understand the
+implementation, for example because they want to extend the class or
+fix a bug.</p>
+
+
+<h2>Data Structures</h2>
+
+<p>The algorithm uses a stack. Its allocation is delayed to the time
+when the source path iterator actually returns the first curved
+segment (either <code>SEG_QUADTO</code> or <code>SEG_CUBICTO</code>).
+If the input path does not contain any curved segments, the value of
+the <code>stack</code> variable stays <code>null</code>. In this quite
+common case, the memory consumption is minimal.</p>
+
+<dl><dt><code>stack</code></dt><dd>The variable <code>stack</code> is
+a <code>double</code> array that holds the start, control and end
+points of individual sub-segments.</dd>
+
+<dt><code>recLevel</code></dt><dd>The variable <code>recLevel</code>
+holds how many recursive sub-divisions were needed to calculate a
+segment. The original curve has recursion level 0. For each
+sub-division, the corresponding recursion level is increased by
+one.</dd>
+
+<dt><code>stackSize</code></dt><dd>Finally, the variable
+<code>stackSize</code> indicates how many sub-segments are stored on
+the stack.</dd></dl>
+
+<h2>Algorithm</h2>
+
+<p>The implementation separately processes each segment that the
+base iterator returns.</p>
+
+<p>In the case of <code>SEG_CLOSE</code>,
+<code>SEG_MOVETO</code> and <code>SEG_LINETO</code> segments, the
+implementation simply hands the segment to the consumer, without actually
+doing anything.</p>
+
+<p>Any <code>SEG_QUADTO</code> and <code>SEG_CUBICTO</code> segments
+need to be flattened. Flattening is performed with a fixed-sized
+stack, holding the coordinates of subdivided segments. When the base
+iterator returns a <code>SEG_QUADTO</code> and
+<code>SEG_CUBICTO</code> segments, it is recursively flattened as
+follows:</p>
+
+<ol><li>Intialization: Allocate memory for the stack (unless a
+sufficiently large stack has been allocated previously). Push the
+original quadratic or cubic curve onto the stack. Mark that segment as
+having a <code>recLevel</code> of zero.</li>
+
+<li>If the stack is empty, flattening the segment is complete,
+and the next segment is fetched from the base iterator.</li>
+
+<li>If the stack is not empty, pop a curve segment from the
+stack.
+
+ <ul><li>If its <code>recLevel</code> exceeds the recursion limit,
+ hand the current segment to the consumer.</li>
+
+ <li>Calculate the squared flatness of the segment. If it smaller
+ than <code>flatnessSq</code>, hand the current segment to the
+ consumer.</li>
+
+ <li>Otherwise, split the segment in two halves. Push the right
+ half onto the stack. Then, push the left half onto the stack.
+ Continue with step two.</li></ul></li>
+</ol>
+
+<p>The implementation is slightly complicated by the fact that
+consumers <em>pull</em> the flattened segments from the
+<code>FlatteningPathIterator</code>. This means that we actually
+cannot &#x201c;hand the curent segment over to the consumer.&#x201d;
+But the algorithm is easier to understand if one assumes a
+<em>push</em> paradigm.</p>
+
+
+<h2>Example</h2>
+
+<p>The following example shows how a
+<code>FlatteningPathIterator</code> processes a
+<code>SEG_QUADTO</code> segment. It is (arbitrarily) assumed that the
+recursion limit was set to 2.</p>
+
+<blockquote>
+<table border="1" cellspacing="0" cellpadding="8">
+ <tr align="center" valign="baseline">
+ <th></th><th>A</th><th>B</th><th>C</th>
+ <th>D</th><th>E</th><th>F</th><th>G</th><th>H</th>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[0]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td><i>S<sub>ll</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[1]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td><i>S<sub>ll</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[2]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td><i>C<sub>ll</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[3]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td><i>C<sub>ll</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[4]</code></th>
+ <td>&#x2014;</td>
+ <td><i>S<sub>l</sub>.x</i></td>
+ <td><i>E<sub>ll</sub>.x</i>
+ = <i>S<sub>lr</sub>.x</i></td>
+ <td><i>S<sub>lr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td><i>S<sub>rl</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[5]</code></th>
+ <td>&#x2014;</td>
+ <td><i>S<sub>l</sub>.y</i></td>
+ <td><i>E<sub>ll</sub>.x</i>
+ = <i>S<sub>lr</sub>.y</i></td>
+ <td><i>S<sub>lr</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td><i>S<sub>rl</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[6]</code></th>
+ <td>&#x2014;</td>
+ <td><i>C<sub>l</sub>.x</i></td>
+ <td><i>C<sub>lr</sub>.x</i></td>
+ <td><i>C<sub>lr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td><i>C<sub>rl</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[7]</code></th>
+ <td>&#x2014;</td>
+ <td><i>C<sub>l</sub>.y</i></td>
+ <td><i>C<sub>lr</sub>.y</i></td>
+ <td><i>C<sub>lr</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td><i>C<sub>rl</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[8]</code></th>
+ <td><i>S.x</i></td>
+ <td><i>E<sub>l</sub>.x</i>
+ = <i>S<sub>r</sub>.x</i></td>
+ <td><i>E<sub>lr</sub>.x</i>
+ = <i>S<sub>r</sub>.x</i></td>
+ <td><i>E<sub>lr</sub>.x</i>
+ = <i>S<sub>r</sub>.x</i></td>
+ <td><i>S<sub>r</sub>.x</i></td>
+ <td><i>E<sub>rl</sub>.x</i>
+ = <i>S<sub>rr</sub>.x</i></td>
+ <td><i>S<sub>rr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[9]</code></th>
+ <td><i>S.y</i></td>
+ <td><i>E<sub>l</sub>.y</i>
+ = <i>S<sub>r</sub>.y</i></td>
+ <td><i>E<sub>lr</sub>.y</i>
+ = <i>S<sub>r</sub>.y</i></td>
+ <td><i>E<sub>lr</sub>.y</i>
+ = <i>S<sub>r</sub>.y</i></td>
+ <td><i>S<sub>r</sub>.y</i></td>
+ <td><i>E<sub>rl</sub>.y</i>
+ = <i>S<sub>rr</sub>.y</i></td>
+ <td><i>S<sub>rr</sub>.y</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[10]</code></th>
+ <td><i>C.x</i></td>
+ <td><i>C<sub>r</sub>.x</i></td>
+ <td><i>C<sub>r</sub>.x</i></td>
+ <td><i>C<sub>r</sub>.x</i></td>
+ <td><i>C<sub>r</sub>.x</i></td>
+ <td><i>C<sub>rr</sub>.x</i></td>
+ <td><i>C<sub>rr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[11]</code></th>
+ <td><i>C.y</i></td>
+ <td><i>C<sub>r</sub>.y</i></td>
+ <td><i>C<sub>r</sub>.y</i></td>
+ <td><i>C<sub>r</sub>.y</i></td>
+ <td><i>C<sub>r</sub>.y</i></td>
+ <td><i>C<sub>rr</sub>.y</i></td>
+ <td><i>C<sub>rr</sub>.y</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[12]</code></th>
+ <td><i>E.x</i></td>
+ <td><i>E<sub>r</sub>.x</i></td>
+ <td><i>E<sub>r</sub>.x</i></td>
+ <td><i>E<sub>r</sub>.x</i></td>
+ <td><i>E<sub>r</sub>.x</i></td>
+ <td><i>E<sub>rr</sub>.x</i></td>
+ <td><i>E<sub>rr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[13]</code></th>
+ <td><i>E.y</i></td>
+ <td><i>E<sub>r</sub>.y</i></td>
+ <td><i>E<sub>r</sub>.y</i></td>
+ <td><i>E<sub>r</sub>.y</i></td>
+ <td><i>E<sub>r</sub>.y</i></td>
+ <td><i>E<sub>rr</sub>.y</i></td>
+ <td><i>E<sub>rr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stackSize</code></th>
+ <td>1</td>
+ <td>2</td>
+ <td>3</td>
+ <td>2</td>
+ <td>1</td>
+ <td>2</td>
+ <td>1</td>
+ <td>0</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>recLevel[2]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>2</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>recLevel[1]</code></th>
+ <td>&#x2014;</td>
+ <td>1</td>
+ <td>2</td>
+ <td>2</td>
+ <td>&#x2014;</td>
+ <td>2</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>recLevel[0]</code></th>
+ <td>0</td>
+ <td>1</td>
+ <td>1</td>
+ <td>1</td>
+ <td>1</td>
+ <td>2</td>
+ <td>2</td>
+ <td>&#x2014;</td>
+ </tr>
+ </table>
+</blockquote>
+
+<ol>
+
+<li>The data structures are initialized as follows.
+
+<ul><li>The segment&#x2019;s end point <i>E</i>, control point
+<i>C</i>, and start point <i>S</i> are pushed onto the stack.</li>
+
+ <li>Currently, the curve in the stack would be approximated by one
+ single straight line segment (<i>S</i> &#x2013; <i>E</i>).
+ Therefore, <code>stackSize</code> is set to 1.</li>
+
+ <li>This single straight line segment is approximating the original
+ curve, which can be seen as the result of zero recursive
+ splits. Therefore, <code>recLevel[0]</code> is set to
+ zero.</li></ul>
+
+Column A shows the state after the initialization step.</li>
+
+<li>The algorithm proceeds by taking the topmost curve segment
+(<i>S</i> &#x2013; <i>C</i> &#x2013; <i>E</i>) from the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[0]</code>) is zero, which is smaller than
+ the limit 2.</li>
+
+ <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code>
+ is called to calculate the squared flatness.</li>
+
+ <li>For the sake of argument, we assume that the squared flatness is
+ exceeding the threshold stored in <code>flatnessSq</code>. Thus, the
+ curve segment <i>S</i> &#x2013; <i>C</i> &#x2013; <i>E</i> gets
+ subdivided into a left and a right half, namely
+ <i>S<sub>l</sub></i> &#x2013; <i>C<sub>l</sub></i> &#x2013;
+ <i>E<sub>l</sub></i> and <i>S<sub>r</sub></i> &#x2013;
+ <i>C<sub>r</sub></i> &#x2013; <i>E<sub>r</sub></i>. Both halves are
+ pushed onto the stack, so the left half is now on top.
+
+ <br />&nbsp;<br />The left half starts at the same point
+ as the original curve, so <i>S<sub>l</sub></i> has the same
+ coordinates as <i>S</i>. Similarly, the end point of the right
+ half and of the original curve are identical
+ (<i>E<sub>r</sub></i> = <i>E</i>). More interestingly, the left
+ half ends where the right half starts. Because
+ <i>E<sub>l</sub></i> = <i>S<sub>r</sub></i>, their coordinates need
+ to be stored only once, which amounts to saving 16 bytes (two
+ <code>double</code> values) for each iteration.</li></ul>
+
+Column B shows the state after the first iteration.</li>
+
+<li>Again, the topmost curve segment (<i>S<sub>l</sub></i>
+&#x2013; <i>C<sub>l</sub></i> &#x2013; <i>E<sub>l</sub></i>) is
+taken from the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[1]</code>) is 1, which is smaller than
+ the limit 2.</li>
+
+ <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code>
+ is called to calculate the squared flatness.</li>
+
+ <li>Assuming that the segment is still not considered
+ flat enough, it gets subdivided into a left
+ (<i>S<sub>ll</sub></i> &#x2013; <i>C<sub>ll</sub></i> &#x2013;
+ <i>E<sub>ll</sub></i>) and a right (<i>S<sub>lr</sub></i>
+ &#x2013; <i>C<sub>lr</sub></i> &#x2013; <i>E<sub>lr</sub></i>)
+ half.</li></ul>
+
+Column C shows the state after the second iteration.</li>
+
+<li>The topmost curve segment (<i>S<sub>ll</sub></i> &#x2013;
+<i>C<sub>ll</sub></i> &#x2013; <i>E<sub>ll</sub></i>) is popped from
+the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than
+ the limit 2. Therefore, a <code>SEG_LINETO</code> (from
+ <i>S<sub>ll</sub></i> to <i>E<sub>ll</sub></i>) is passed to the
+ consumer.</li></ul>
+
+ The new state is shown in column D.</li>
+
+
+<li>The topmost curve segment (<i>S<sub>lr</sub></i> &#x2013;
+<i>C<sub>lr</sub></i> &#x2013; <i>E<sub>lr</sub></i>) is popped from
+the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[1]</code>) is 2, which is <em>not</em> smaller than
+ the limit 2. Therefore, a <code>SEG_LINETO</code> (from
+ <i>S<sub>lr</sub></i> to <i>E<sub>lr</sub></i>) is passed to the
+ consumer.</li></ul>
+
+ The new state is shown in column E.</li>
+
+<li>The algorithm proceeds by taking the topmost curve segment
+(<i>S<sub>r</sub></i> &#x2013; <i>C<sub>r</sub></i> &#x2013;
+<i>E<sub>r</sub></i>) from the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[0]</code>) is 1, which is smaller than
+ the limit 2.</li>
+
+ <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code>
+ is called to calculate the squared flatness.</li>
+
+ <li>For the sake of argument, we again assume that the squared
+ flatness is exceeding the threshold stored in
+ <code>flatnessSq</code>. Thus, the curve segment
+ (<i>S<sub>r</sub></i> &#x2013; <i>C<sub>r</sub></i> &#x2013;
+ <i>E<sub>r</sub></i>) is subdivided into a left and a right half,
+ namely
+ <i>S<sub>rl</sub></i> &#x2013; <i>C<sub>rl</sub></i> &#x2013;
+ <i>E<sub>rl</sub></i> and <i>S<sub>rr</sub></i> &#x2013;
+ <i>C<sub>rr</sub></i> &#x2013; <i>E<sub>rr</sub></i>. Both halves
+ are pushed onto the stack.</li></ul>
+
+ The new state is shown in column F.</li>
+
+<li>The topmost curve segment (<i>S<sub>rl</sub></i> &#x2013;
+<i>C<sub>rl</sub></i> &#x2013; <i>E<sub>rl</sub></i>) is popped from
+the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than
+ the limit 2. Therefore, a <code>SEG_LINETO</code> (from
+ <i>S<sub>rl</sub></i> to <i>E<sub>rl</sub></i>) is passed to the
+ consumer.</li></ul>
+
+ The new state is shown in column G.</li>
+
+<li>The topmost curve segment (<i>S<sub>rr</sub></i> &#x2013;
+<i>C<sub>rr</sub></i> &#x2013; <i>E<sub>rr</sub></i>) is popped from
+the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than
+ the limit 2. Therefore, a <code>SEG_LINETO</code> (from
+ <i>S<sub>rr</sub></i> to <i>E<sub>rr</sub></i>) is passed to the
+ consumer.</li></ul>
+
+ The new state is shown in column H.</li>
+
+<li>The stack is now empty. The FlatteningPathIterator will fetch the
+next segment from the base iterator, and process it.</li>
+
+</ol>
+
+<p>In order to split the most recently pushed segment, the
+<code>subdivideQuadratic()</code> method passes <code>stack</code>
+directly to
+<code>QuadCurve2D.subdivide(double[],int,double[],int,double[],int)</code>.
+Because the stack grows towards the beginning of the array, no data
+needs to be copied around: <code>subdivide</code> will directly store
+the result into the stack, which will have the contents shown to the
+right.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png b/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png
new file mode 100644
index 00000000000..d1d75d57526
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png
new file mode 100644
index 00000000000..7c2ec0ea9cb
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png
new file mode 100644
index 00000000000..496180c4474
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png
new file mode 100644
index 00000000000..a7557ba7baf
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png
new file mode 100644
index 00000000000..835c0643b29
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png
new file mode 100644
index 00000000000..72110cd5a62
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/package.html b/libjava/classpath/java/awt/geom/package.html
new file mode 100644
index 00000000000..c8ee8272f6a
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.geom package.
+ Copyright (C) 2002 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 - java.awt.geom</title></head>
+
+<body>
+<p>Classes to represent 2D objects and different path transformations.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/im/InputContext.java b/libjava/classpath/java/awt/im/InputContext.java
new file mode 100644
index 00000000000..e289677fe9c
--- /dev/null
+++ b/libjava/classpath/java/awt/im/InputContext.java
@@ -0,0 +1,434 @@
+/* InputContext.java -- provides the context for text input
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.im;
+
+import gnu.java.util.EmptyEnumeration;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.Component;
+import java.awt.im.spi.InputMethod;
+import java.awt.im.spi.InputMethodDescriptor;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * Provides a context for controlling input methods and keyboard layouts.
+ * This class provides the communication layer between the client component,
+ * and the various locale-dependent text entry input methods that can be used
+ * for the client. By default, there is one instance per Window, shared among
+ * all components, but this limits text entry to one component at a time.
+ * Thus, text components can create their own instance to allow text entry
+ * in multiple components at a time.
+ *
+ * <p>By using the interfaces of {@link java.awt.im.spi}, you can install
+ * extensions which allow additional input methods. Some of these may use
+ * platform native input methods, or keyboard layouts provided by the platform.
+ * Input methods are unavailable if none have been installed and the platform
+ * has no underlying native input methods. Extensions are installed as jar
+ * files, usually accessed in the default extension location or specified by
+ * the -extdir VM flag. The jar must contain a file named
+ * "META_INF/services/java.awt.im.spi.InputMethodDescriptor" which lists,
+ * one entry per line in UTF-8 encoding, each class in the jar that implements
+ * java.awt.im.spi.InputMethodDescriptor.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Component#getInputContext()
+ * @see Component#enableInputMethods(boolean)
+ * @since 1.2
+ * @status updated to 1.4, but unverified
+ */
+public class InputContext
+{
+ /**
+ * The list of installed input method descriptors.
+ */
+ private static final ArrayList descriptors = new ArrayList();
+ static
+ {
+ Enumeration e;
+ try
+ {
+ e = ClassLoader.getSystemResources
+ ("META_INF/services/java.awt.im.spi.InputMethodDescriptor");
+ }
+ catch (IOException ex)
+ {
+ // XXX Should we do something else?
+ e = EmptyEnumeration.getInstance();
+ }
+ while (e.hasMoreElements())
+ {
+ URL url = (URL) e.nextElement();
+ BufferedReader in;
+ String line;
+ try
+ {
+ in = new BufferedReader
+ (new InputStreamReader(url.openConnection().getInputStream(),
+ "UTF-8"));
+ line = in.readLine().trim();
+ }
+ catch (IOException ignored)
+ {
+ continue;
+ }
+ outer:
+ while (line != null)
+ {
+ try
+ {
+ if (line.charAt(0) != '#')
+ {
+ Class c = Class.forName(line);
+ descriptors.add((InputMethodDescriptor) c.newInstance());
+ }
+ line = in.readLine().trim();
+ }
+ catch (IOException ex)
+ {
+ continue outer;
+ }
+ catch (Exception ignored)
+ {
+ }
+ }
+ }
+ }
+
+ /** The current input method; null if no input methods are installed. */
+ private InputMethod im;
+
+ /** Map of locales to the most recently selected input method. */
+ private final HashMap recent = new HashMap();
+
+ /** The list of acceptable character subsets. */
+ private Character.Subset[] subsets;
+
+ /**
+ * Construct an InputContext. This is protected, so clients must use
+ * {@link #getInstance()} instead.
+ */
+ protected InputContext()
+ {
+ }
+
+ /**
+ * Returns a new InputContext.
+ *
+ * @return a new instance, initialized to the default locale if available
+ */
+ public static InputContext getInstance()
+ {
+ InputContext ic = new InputContext();
+ ic.selectInputMethod(Locale.getDefault());
+ return ic;
+ }
+
+ /**
+ * Attempts to select an input method or keyboard layout which supports the
+ * given locale. This returns true if a locale is available and was selected.
+ * The following steps are taken in choosing an input method:<ul>
+ * <li>If the currently selected input method or keyboard layout supports
+ * the requested locale, it remains selected.</li>
+ * <li>If there is no input method or keyboard layout available that
+ * supports the requested locale, the current input method or keyboard
+ * layout remains selected.</li>
+ * <li>If the user has previously selected an input method or keyboard
+ * layout for the requested locale from the user interface, then the most
+ * recently selected such input method or keyboard layout is reselected.</li>
+ * <li>Otherwise, an input method or keyboard layout that supports the
+ * requested locale is selected in an implementation dependent way. This
+ * implementation chooses the first input method which supports the requested
+ * locale based on the InputMethodDescriptors loaded from the extensions
+ * installed on the CLASSPATH.</li>
+ * </ul>
+ *
+ * <p>Before switching away from an input method, any currently uncommitted
+ * text is committed. Not all host operating systems provide API to
+ * determine the locale of the currently selected native input method or
+ * keyboard layout, and to select a native input method or keyboard layout
+ * by locale. For host operating systems that don't provide such API,
+ * selectInputMethod assumes that native input methods or keyboard layouts
+ * provided by the host operating system support only the system's default
+ * locale.
+ *
+ * <p>An example of where this may be called is in a multi-language document,
+ * when moving the insertion point between sections of different locale, so
+ * that the user may use the input method appropriate to that section of the
+ * document.
+ *
+ * @param locale the desired new locale
+ * @return true if the new locale is active
+ * @throws NullPointerException if locale is null
+ */
+ public boolean selectInputMethod(Locale locale)
+ {
+ if (im != null && im.setLocale(locale))
+ {
+ recent.put(locale, im);
+ return true;
+ }
+ InputMethod next = (InputMethod) recent.get(locale);
+ outer:
+ if (next != null)
+ for (int i = 0, limit = descriptors.size(); i < limit; i++)
+ {
+ InputMethodDescriptor d = (InputMethodDescriptor) descriptors.get(i);
+ Locale[] list;
+ try
+ {
+ list = d.getAvailableLocales();
+ }
+ catch (AWTException ignored)
+ {
+ continue;
+ }
+ for (int j = list.length; --j >= 0; )
+ if (locale.equals(list[j]))
+ {
+ try
+ {
+ next = d.createInputMethod();
+ recent.put(locale, next);
+ }
+ catch (Exception ignored)
+ {
+ continue;
+ }
+ }
+ }
+ if (next == null)
+ return false;
+ // XXX I'm not sure if this does all the necessary steps in the switch.
+ if (im != null)
+ {
+ try
+ {
+ next.setCompositionEnabled(im.isCompositionEnabled());
+ }
+ catch (UnsupportedOperationException ignored)
+ {
+ }
+ im.endComposition();
+ im.deactivate(false);
+ im.hideWindows();
+ }
+ im = next;
+ im.setLocale(locale);
+ im.setCharacterSubsets(subsets);
+ return true;
+ }
+
+ /**
+ * Returns the current locale of the current input method or keyboard
+ * layout. Returns null if the input context does not have a current input
+ * method or keyboard layout or if the current input method's
+ * {@link InputMethod#getLocale()} method returns null. Not all host
+ * operating systems provide API to determine the locale of the currently
+ * selected native input method or keyboard layout. For host operating
+ * systems that don't provide such API, getLocale assumes that the current
+ * locale of all native input methods or keyboard layouts provided by the
+ * host operating system is the system's default locale.
+ *
+ * @return the locale of the current input method, or null
+ * @since 1.3
+ */
+ public Locale getLocale()
+ {
+ return im == null ? null : im.getLocale();
+ }
+
+ /**
+ * Sets the subsets of Unicode characters allowed to be input by the current
+ * input method, as well as subsequent input methods. The value of null
+ * implies all characters are legal. Applications should not rely on this
+ * behavior, since native host input methods may not allow restrictions.
+ * If no current input method is available, this has no immediate effect.
+ *
+ * @param subsets the set of Unicode subsets to accept, or null
+ */
+ public void setCharacterSubsets(Character.Subset[] subsets)
+ {
+ this.subsets = subsets;
+ if (im != null)
+ im.setCharacterSubsets(subsets);
+ }
+
+ /**
+ * Changes the enabled status of the current input method. An input method
+ * that is enabled for composition interprets incoming events for both
+ * composition and control purposes, while a disabled input method only
+ * interprets control commands (including commands to enable itself).
+ *
+ * @param enable whether to enable the input method
+ * @throws UnsupportedOperationException if there is no current input method,
+ * or the input method does not support enabling
+ * @see #isCompositionEnabled()
+ * @since 1.3
+ */
+ public void setCompositionEnabled(boolean enable)
+ {
+ if (im == null)
+ throw new UnsupportedOperationException();
+ im.setCompositionEnabled(enable);
+ }
+
+ /**
+ * Find out if the current input method is enabled.
+ *
+ * @return true if the current input method is enabled
+ * @throws UnsupportedOperationException if there is no current input method,
+ * or the input method does not support enabling
+ * @see #setCompositionEnabled(boolean)
+ * @since 1.3
+ */
+ public boolean isCompositionEnabled()
+ {
+ if (im == null)
+ throw new UnsupportedOperationException();
+ return im.isCompositionEnabled();
+ }
+
+ /**
+ * Starts a reconversion operation in the current input method. The input
+ * method gets theh text to reconvert from the client component, using
+ * {@link InputMethodRequests#getSelectedText(Attribute[])}. Then the
+ * composed and committed text produced by the operation is sent back to
+ * the client using a sequence of InputMethodRequests.
+ *
+ * @throws UnsupportedOperationException if there is no current input method,
+ * or the input method does not support reconversion
+ * @since 1.3
+ */
+ public void reconvert()
+ {
+ if (im == null)
+ throw new UnsupportedOperationException();
+ im.reconvert();
+ }
+
+ /**
+ * Dispatches an event to the current input method. This is called
+ * automatically by AWT. If no input method is available, then the event
+ * will never be consumed.
+ *
+ * @param event the event to dispatch
+ * @throws NullPointerException if event is null
+ */
+ public void dispatchEvent(AWTEvent event)
+ {
+ if (im != null)
+ im.dispatchEvent(event);
+ }
+
+ /**
+ * Notifies the input context that a client component has been removed from
+ * its containment hierarchy, or that input method support has been disabled
+ * for the component. This method is usually called from the client
+ * component's {@link Component#removeNotify()} method. Potentially pending
+ * input from input methods for this component is discarded. If no input
+ * methods are available, then this method has no effect.
+ *
+ * @param client the client component
+ * @throws NullPointerException if client is null
+ */
+ public void removeNotify(Component client)
+ {
+ // XXX What to do with client information?
+ if (im != null)
+ {
+ im.deactivate(false);
+ im.removeNotify();
+ }
+ }
+
+ /**
+ * Ends any input composition that may currently be going on in this
+ * context. Depending on the platform and possibly user preferences, this
+ * may commit or delete uncommitted text. Any changes to the text are
+ * communicated to the active component using an input method event. If no
+ * input methods are available, then this method has no effect. This may
+ * be called for a variety of reasons, such as when the user moves the
+ * insertion point in the client text outside the range of the composed text,
+ * or when text is saved to file.
+ */
+ public void endComposition()
+ {
+ if (im != null)
+ im.endComposition();
+ }
+
+ /**
+ * Disposes of the input context and release the resources used by it.
+ * Called automatically by AWT for the default input context of each
+ * Window. If no input methods are available, then this method has no
+ * effect.
+ */
+ public void dispose()
+ {
+ if (im != null)
+ {
+ im.deactivate(false);
+ im.dispose();
+ }
+ }
+
+ /**
+ * Returns a control object from the current input method, or null. A
+ * control object provides implementation-dependent methods that control
+ * the behavior of the input method or obtain information from the input
+ * method. Clients have to compare the result against known input method
+ * control object types. If no input methods are available or the current
+ * input method does not provide an input method control object, then null
+ * is returned.
+ *
+ * @return the control object, or null
+ */
+ public Object getInputMethodControlObject()
+ {
+ return im == null ? null : im.getControlObject();
+ }
+} // class InputContext
diff --git a/libjava/classpath/java/awt/im/InputMethodHighlight.java b/libjava/classpath/java/awt/im/InputMethodHighlight.java
new file mode 100644
index 00000000000..0d664b19366
--- /dev/null
+++ b/libjava/classpath/java/awt/im/InputMethodHighlight.java
@@ -0,0 +1,185 @@
+/* InputMethodHighlight.java -- highlights the current text selection
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im;
+
+import java.util.Map;
+
+/**
+ * This describes the highlight attributes of text composed in an input method.
+ * The description includes an abstract level (whether text has been converted
+ * yet, and whether it is selected), and a concrete level (which style
+ * attributes are used in rendering). If no concrete level is defined, the
+ * renderer should use
+ * {@link Toolkit#mapInputMethodHighlight(InputMethodHighlight)}. An example
+ * of conversion state is kana -&gt; kanji.
+ *
+ * <p>Instances of this class are typically used in
+ * AttributedCharacterIterators, and may be wrapped in Annotations to separate
+ * text segments.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see AttributedCharacterIterators
+ * @see Annotation
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InputMethodHighlight
+{
+ /** Raw text state (before conversion). */
+ public static final int RAW_TEXT = 0;
+
+ /** Converted text state (after conversion). */
+ public static final int CONVERTED_TEXT = 1;
+
+ /** Default do-nothing highlighting for unselected raw text. */
+ public static final InputMethodHighlight UNSELECTED_RAW_TEXT_HIGHLIGHT
+ = new InputMethodHighlight(false, RAW_TEXT);
+
+ /** Default do-nothing highlighting for selected raw text. */
+ public static final InputMethodHighlight SELECTED_RAW_TEXT_HIGHLIGHT
+ = new InputMethodHighlight(true, RAW_TEXT);
+
+ /** Default do-nothing highlighting for unselected converted text. */
+ public static final InputMethodHighlight UNSELECTED_CONVERTED_TEXT_HIGHLIGHT
+ = new InputMethodHighlight(false, CONVERTED_TEXT);
+
+ /** Default do-nothing highlighting for selected converted text. */
+ public static final InputMethodHighlight SELECTED_CONVERTED_TEXT_HIGHLIGHT
+ = new InputMethodHighlight(true, CONVERTED_TEXT);
+
+ /** Whether the highlighting applies to selected text. */
+ private final boolean selected;
+
+ /** The state of highlighted text. */
+ private final int state;
+
+ /** Any variation on the highlighting style. */
+ private final int variation;
+
+ /** The unmodifiable map of rendering styles. */
+ private final Map style;
+
+ /**
+ * Create an input method highlight style, with variation 0 and null style
+ * mapping.
+ *
+ * @param selected whether the text range is selected
+ * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT}
+ * @throws IllegalArgumentException if state is invalid
+ */
+ public InputMethodHighlight(boolean selected, int state)
+ {
+ this(selected, state, 0, null);
+ }
+
+ /**
+ * Create an input method highlight style, with null style mapping.
+ *
+ * @param selected whether the text range is selected
+ * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT}
+ * @param variation the style variation
+ * @throws IllegalArgumentException if state is invalid
+ */
+ public InputMethodHighlight(boolean selected, int state, int variation)
+ {
+ this(selected, state, variation, null);
+ }
+
+ /**
+ * Create an input method highlight style.
+ *
+ * @param selected whether the text range is selected
+ * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT}
+ * @param variation the style variation
+ * @param style an unmodifiable map of rendering styles, or null
+ * @throws IllegalArgumentException if state is invalid
+ * @since 1.3
+ */
+ public InputMethodHighlight(boolean selected, int state, int variation,
+ Map style)
+ {
+ if (state != RAW_TEXT && state != CONVERTED_TEXT)
+ throw new IllegalArgumentException();
+ this.selected = selected;
+ this.state = state;
+ this.variation = variation;
+ this.style = style;
+ }
+
+ /**
+ * Return whether the highlighting applies to selected text.
+ *
+ * @return the selection status
+ */
+ public boolean isSelected()
+ {
+ return selected;
+ }
+
+ /**
+ * Return the conversion state of the highlighted text.
+ *
+ * @return one of {@link #RAW_TEXT} or {@link #CONVERTED_TEXT}
+ */
+ public int getState()
+ {
+ return state;
+ }
+
+ /**
+ * Return the highlighting style variation.
+ *
+ * @return the variation
+ */
+ public int getVariation()
+ {
+ return variation;
+ }
+
+ /**
+ * Return the rendering style attributes map, or null if it should be the
+ * default mapping.
+ *
+ * @return the style map
+ * @since 1.3
+ */
+ public Map getStyle()
+ {
+ return style;
+ }
+} // class InputMethodHighlight
diff --git a/libjava/classpath/java/awt/im/InputMethodRequests.java b/libjava/classpath/java/awt/im/InputMethodRequests.java
new file mode 100644
index 00000000000..d50ec33c5c8
--- /dev/null
+++ b/libjava/classpath/java/awt/im/InputMethodRequests.java
@@ -0,0 +1,153 @@
+/* InputMethodRequests.java -- handles text insertion via input methods
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im;
+
+import java.awt.Rectangle;
+import java.awt.font.TextHitInfo;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+
+/**
+ * This interface handles requests made by input methods on text editing
+ * components. A component must specify a handler for input methods that
+ * implements this interface, and which supports one of two user interfaces:
+ * <ul><li><em>on-the-spot</em>: composed text is shown in place</li>
+ * <li><em>below-the-spot</em>: composed text is in a separate window,
+ * usually below the main text window, until it is committed into place at
+ * the insertion point, overwriting any selected text</li></ul>
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Component#getInputMethodRequests()
+ * @see InputMethodListener
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface InputMethodRequests
+{
+ /**
+ * Gets the location of a given offset of the text. This can be used to
+ * position a composition window near the location of where the composed
+ * text will be inserted.
+ *
+ * <p>If the component has composed text (from the most recent
+ * InputMethodEvent), then offset 0 indicates the location of the first
+ * character of this composed text. Otherwise, the offset is ignored, and
+ * the location should be the beginning of the final line of selected
+ * text (in horizontal left-to-right text, like English, this would be the
+ * lower left corner of the selction; in vertical top-to-bottom text, like
+ * Chinese, this would be the top right corner of the selection).
+ *
+ * <p>The location returned is a 0-thickness caret (either horizontal or
+ * vertical, depending on text flow), mapped to absolute screen coordinates.
+ *
+ * @param offset offset within composed text, or null
+ * @return the screen location of the caret at the offset
+ */
+ Rectangle getTextLocation(TextHitInfo offset);
+
+ /**
+ * Get the text offset for the given screen coordinate. The offset is
+ * relative to the composed text, and the return is null if it is outside
+ * the range of composed text. For example, this can be used to find
+ * where a mouse click should pop up a text composition window.
+ *
+ * @param x the x screen coordinate
+ * @param y the y screen coordinate
+ * @return a text hit info describing the composed text offset
+ */
+ TextHitInfo getLocationOffset(int x, int y);
+
+ /**
+ * Gets the offset where the committed text exists in the text editing
+ * component. This can be used to examine the text surrounding the insert
+ * position.
+ *
+ * @return the offset of the insert position
+ */
+ int getInsertPositionOffset();
+
+ /**
+ * Gets an interator which provides access to the text and its attributes,
+ * except for the uncommitted text. The input method may provide a list of
+ * attributes it is interested in; and the iterator need not provide
+ * information on the remaining attributes. If the attribute list is null,
+ * the iterator must list all attributes.
+ *
+ * @param beginIndex the index of the first character in the iteration
+ * @param endIndex the index of the last character in the iteration
+ * @param attributes a list of attributes interested in, or null
+ * @return an iterator over the region of text with its attributes
+ */
+ AttributedCharacterIterator getCommittedText(int beginIndex, int endIndex,
+ Attribute[] attributes);
+
+ /**
+ * Gets the length of committed text.
+ *
+ * @return the number of committed characters
+ */
+ int getCommittedTextLength();
+
+ /**
+ * Gets the latest committed text, and removes it from the component's text
+ * body. This allows an input method to provide an "Undo" command. In
+ * general, this should only be supported immediately after a commit, and
+ * not when other actions intervene; if not supported, simply return null.
+ * The input method may provide a list of attributes it is interested in;
+ * and the iterator need not provide information on the remaining attributes.
+ * If the attribute list is null, the iterator must list all attributes.
+ *
+ * @param attributes a list of attributes interested in, or null
+ * @return the latest committed text, or null
+ */
+ AttributedCharacterIterator cancelLatestCommittedText
+ (Attribute[] attributes);
+
+ /**
+ * Gets the currently selected text. One use of this is to implement a
+ * "Reconvert" feature in an input method, which modifies the selection
+ * based on the text in the composition window. The input method may
+ * provide a list of attributes it is interested in; and the iterator need
+ * not provide information on the remaining attributes. If the attribute
+ * list is null, the iterator must list all attributes.
+ *
+ * @param attributes a list of attributes interested in, or null
+ * @return the current selection
+ */
+ AttributedCharacterIterator getSelectedText(Attribute[] attributes);
+} // interface InputMethodRequests
diff --git a/libjava/classpath/java/awt/im/InputSubset.java b/libjava/classpath/java/awt/im/InputSubset.java
new file mode 100644
index 00000000000..5e7d58e7f42
--- /dev/null
+++ b/libjava/classpath/java/awt/im/InputSubset.java
@@ -0,0 +1,129 @@
+/* InputSubset.java -- subsets of Unicode important in text input
+ Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im;
+
+/**
+ * Defines additional Unicode character blocks for use by input methods.
+ * These constants encompass several Unicode blocks, or portions thereof, for
+ * simplification over {@link Character.UnicodeBlock}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class InputSubset extends Character.Subset
+{
+ /**
+ * Constant for all Latin characters, including the characters in the
+ * BASIC_LATIN, LATIN_1_SUPPLEMENT, LATIN_EXTENDED_A, LATIN_EXTENDED_B
+ * Unicode character blocks.
+ */
+ public static final InputSubset LATIN = new InputSubset("LATIN");
+
+ /**
+ * Constant for the digits included in the BASIC_LATIN Unicode character
+ * block.
+ */
+ public static final InputSubset LATIN_DIGITS
+ = new InputSubset("LATIN_DIGITS");
+
+ /**
+ * Constant for all Han characters used in writing Traditional Chinese,
+ * including a subset of the CJK unified ideographs as well as Traditional
+ * Chinese Han characters that may be defined as surrogate characters.
+ */
+ public static final InputSubset TRADITIONAL_HANZI
+ = new InputSubset("TRADITIONAL_HANZI");
+
+ /**
+ * Constant for all Han characters used in writing Simplified Chinese,
+ * including a subset of the CJK unified ideographs as well as Simplified
+ * Chinese Han characters that may be defined as surrogate characters.
+ */
+ public static final InputSubset SIMPLIFIED_HANZI
+ = new InputSubset("SIMPLIFIED_HANZI");
+
+ /**
+ * Constant for all Han characters used in writing Japanese, including a
+ * subset of the CJK unified ideographs as well as Japanese Han characters
+ * that may be defined as surrogate characters.
+ */
+ public static final InputSubset KANJI = new InputSubset("KANJI");
+
+ /**
+ * Constant for all Han characters used in writing Korean, including a
+ * subset of the CJK unified ideographs as well as Korean Han characters
+ * that may be defined as surrogate characters.
+ */
+ public static final InputSubset HANJA = new InputSubset("HANJA");
+
+ /**
+ * Constant for the halfwidth katakana subset of the Unicode halfwidth and
+ * fullwidth forms character block.
+ */
+ public static final InputSubset HALFWIDTH_KATAKANA
+ = new InputSubset("HALFWIDTH_KATAKANA");
+
+ /**
+ * Constant for the fullwidth ASCII variants subset of the Unicode
+ * halfwidth and fullwidth forms character block.
+ *
+ * @since 1.3
+ */
+ public static final InputSubset FULLWIDTH_LATIN
+ = new InputSubset("FULLWIDTH_LATIN");
+
+ /**
+ * Constant for the fullwidth digits included in the Unicode halfwidth and
+ * fullwidth forms character block.
+ *
+ * @since 1.3
+ */
+ public static final InputSubset FULLWIDTH_DIGITS
+ = new InputSubset("FULLWIDTH_DIGITS");
+
+ /**
+ * Construct a subset.
+ *
+ * @param name the subset name
+ */
+ private InputSubset(String name)
+ {
+ super(name);
+ }
+} // class InputSubset
diff --git a/libjava/classpath/java/awt/im/package.html b/libjava/classpath/java/awt/im/package.html
new file mode 100644
index 00000000000..895da66d5d9
--- /dev/null
+++ b/libjava/classpath/java/awt/im/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.im package.
+ Copyright (C) 2002 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 - java.awt.im</title></head>
+
+<body>
+<p>Support for text input methods.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/im/spi/InputMethod.java b/libjava/classpath/java/awt/im/spi/InputMethod.java
new file mode 100644
index 00000000000..840d193a8d8
--- /dev/null
+++ b/libjava/classpath/java/awt/im/spi/InputMethod.java
@@ -0,0 +1,240 @@
+/* InputMethod.java -- defines an interface for complex text input
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im.spi;
+
+import java.awt.AWTEvent;
+import java.awt.Rectangle;
+import java.util.Locale;
+
+/**
+ * This interface supports complex text input, often for situations where
+ * the text is more complex than a keyboard will accomodate. For example,
+ * this can be used for Chinese, Japanese, and Korean, where multiple
+ * keystrokes are necessary to compose text. This could also support things
+ * like phonetic English, or reordering Thai.
+ *
+ * <p>These contexts can be loaded by the input method framework, using
+ * {@link InputContext#selectInputMethod(Locale)}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface InputMethod
+{
+ /**
+ * Set the input method context, which ties the input method to a client
+ * component. This is called once automatically when creating the input
+ * method.
+ *
+ * @param context the context for this input method
+ * @throws NullPointerException if context is null
+ */
+ void setInputMethodContext(InputMethodContext context);
+
+ /**
+ * Sets the input locale. If the input method supports that locale, it
+ * changes its behavior to be consistent with the locale and returns true.
+ * Otherwise, it returns false. This is called by
+ * {@link InputContext#selectInputMethod(Locale)} when the user specifies
+ * a locale, or when the previously selected input method had a locale.
+ *
+ * @param locale the locale to use for input
+ * @return true if the change is successful
+ * @throws NullPointerException if locale is null
+ */
+ boolean setLocale(Locale locale);
+
+ /**
+ * Returns the current input locale, or null if none is defined. This is
+ * called by {@link InputContext#getLocale()}, or before switching input
+ * methods.
+ *
+ * @return the current input locale, or null
+ */
+ Locale getLocale();
+
+ /**
+ * Sets the allowed Unicode subsets that this input method can use. Null
+ * indicates that all characters are allowed. This is called after creation,
+ * or when switching to this input method, by
+ * {@link InputContext#setCharacterSubsets(Character.Subset[])}.
+ *
+ * @param subsets the accepted subsets for this input method, or null for all
+ */
+ void setCharacterSubsets(Character.Subset[] subsets);
+
+ /**
+ * Changes the enabled status of this input method. An enabled input method
+ * accepts incoming events for composition and control purposes, while a
+ * disabled input method ignores events (except for control purposes). This
+ * is called by {@link InputContext#setCompositionEnabled(boolean)} or when
+ * switching from an input method if the previous input method returned
+ * without exception on {@link #isCompositionEnabled()}.
+ *
+ * @param enable whether to enable this input method
+ * @throws UnsupportedOperationException if enabling/disabling is unsupported
+ * @see #isCompositionEnabled()
+ */
+ void setCompositionEnabled(boolean enable);
+
+ /**
+ * Find out if this input method is enabled. This is called by
+ * {@link InputContext#isCompositionEnabled()}, or when switching input
+ * methods via {@link InputContext#selectInputMethod(Locale)}.
+ *
+ * @return true if this input method is enabled
+ * @throws UnsupportedOperationException if enabling/disabling is unsupported
+ * @see #setCompositionEnabled(boolean)
+ */
+ boolean isCompositionEnabled();
+
+ /**
+ * Starts a reconversion operation. The input method gets its text from the
+ * client, using {@link InputMethodRequests#getSelectedText(Attribute[])}.
+ * Then the composed and committed text produced by the operation is sent
+ * back to the client using a sequence of InputMethodEvents. This is called
+ * by {@link InputContext#reconvert()}.
+ *
+ * @throws UnsupportedOperationException if reconversion is unsupported
+ */
+ void reconvert();
+
+ /**
+ * Dispatch an event to the input method. If input method support is enabled,
+ * certain events are dispatched to the input method before the client
+ * component or event listeners. The input method must either consume the
+ * event or pass it on to the component. Instances of InputEvent, including
+ * KeyEvent and MouseEvent, are given to this input method. This method is
+ * called by {@link InputContext#dispatchEvent(AWTEvent)}.
+ *
+ * @param event the event to dispatch
+ * @throws NullPointerException if event is null
+ */
+ void dispatchEvent(AWTEvent event);
+
+ /**
+ * Notify this input method of changes in the client window. This is called
+ * when notifications are enabled (see {@link
+ * InputMethodContext#enableClientWindowNotification(InputMethod, boolean)},
+ * if {@link #removeNotify(Component)} has not been called. The following
+ * situations trigger a notification:<ul>
+ * <li>The client window changes in location, size, visibility,
+ * iconification, or is closed.</li>
+ * <li>When enabling client notification (or on the first activation after
+ * enabling if no client existed at the time).</li>
+ * <li>When activating a new client after <code>removeNotify</code> was
+ * called on a previous client.</li>
+ * </ul>
+ *
+ * @param bounds the client window's current bounds, or null
+ */
+ void notifyClientWindowChange(Rectangle bounds);
+
+ /**
+ * Activate this input method for input processing. If the input method
+ * provides its own windows, it should make them open and visible at this
+ * time. This method is called when a client component receives a
+ * FOCUS_GAINED event, or when switching to this input method from another
+ * one. It is only called when the input method is inactive, assuming that
+ * new instances begin in an inactive state.
+ */
+ void activate();
+
+ /**
+ * Deactivate this input method, either temporarily or permanently for the
+ * given client. If the input method provides its own windows, it should
+ * only close those related to the current composition (such as a lookup
+ * choice panel), while leaving more persistant windows (like a control
+ * panel) open to avoid screen flicker. Before control is given to another
+ * input method, {@link #hideWindows()} will be called on this instance.
+ * This method is called when a client component receives a
+ * FOCUS_LOST event, when switching to another input method, or before
+ * {@link #removeNotify()} when the client is removed.
+ *
+ * @param isTemporary true if the focus change is temporary
+ */
+ void deactivate(boolean isTemporary);
+
+ /**
+ * Close or hide all windows opened by this input method. This is called
+ * before activating a different input method, and before calling
+ * {@link #dispose()} on this instance. It is only called when the input
+ * method is inactive.
+ */
+ void hideWindows();
+
+ /**
+ * Notify the input method that a client component has been removed from its
+ * hierarchy, or that input method support has been disabled. This is
+ * called by {@link InputContext#removeNotify()}, and only when the input
+ * method is inactive.
+ */
+ void removeNotify();
+
+ /**
+ * End any input composition currently taking place. Depending on the
+ * platform and user preferences, this may commit or delete uncommitted text,
+ * using input method events. This may be called for a variety of reasons,
+ * such as when the user moves the insertion point in the client text outside
+ * the range of the composed text, or when text is saved to file. This is
+ * called by {@link InputContext#endComposition()}, when switching to a
+ * new input method, or by {@link InputContext#selectInputMethod(Locale)}.
+ */
+ void endComposition();
+
+ /**
+ * Disposes the input method and release any resources it is using. In
+ * particular, the input method should dispose windows and close files. This
+ * is called by {@link InputContext#dispose()}, when the input method is
+ * inactive; and nothing will be called on this instance afterwards.
+ */
+ void dispose();
+
+ /**
+ * Returns a control object from this input method, or null. A control object
+ * provides method to control the behavior of this input method, as well as
+ * query information about it. The object is implementation dependent, so
+ * clients must compare the result against known input method control
+ * object types. This is called by
+ * {@link InputContext#getInputMethodControlObject()}.
+ *
+ * @return the control object, or null
+ */
+ Object getControlObject();
+} // interface InputMethod
diff --git a/libjava/classpath/java/awt/im/spi/InputMethodContext.java b/libjava/classpath/java/awt/im/spi/InputMethodContext.java
new file mode 100644
index 00000000000..43bee8d8617
--- /dev/null
+++ b/libjava/classpath/java/awt/im/spi/InputMethodContext.java
@@ -0,0 +1,123 @@
+/* InputMethodContext.java -- communication between an input method and client
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.im.spi;
+
+import java.awt.Window;
+import java.awt.font.TextHitInfo;
+import java.awt.im.InputMethodRequests;
+import java.text.AttributedCharacterIterator;
+
+import javax.swing.JFrame;
+
+/**
+ * Provides methods for the communication context between an input method
+ * and the client component. This should be passed to
+ * {@link InputMethod#setInputMethodContext(InputMethodContext)}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface InputMethodContext extends InputMethodRequests
+{
+ /**
+ * Create an input method event and dispatch it to the client.
+ *
+ * @param id the event type
+ * @param text an iterator over the text to be committed
+ * @param count the count of characters to be committed
+ * @param caret the insertion point of the commit, or null
+ * @param visiblePosition the best location to make visible, or null
+ */
+ void dispatchInputMethodEvent(int id, AttributedCharacterIterator text,
+ int count, TextHitInfo caret,
+ TextHitInfo visiblePosition);
+
+ /**
+ * Creates a top-level window for use by the input method. This window should
+ * float above all document windows and dialogs, not receive focus, and have
+ * lightweight decorations (such as no title, reduced drag regions). But
+ * this behavior may be modified to meet the platform style. The title may
+ * or may not be displayed, depending on the platform.
+ *
+ * <p>If attachToInputContext is true, the new window will share the input
+ * context of the input method, so that events in the new window are
+ * dispatched to the input method. Also, this supresses deactivate and
+ * activate calls to the input method caused by setVisible.
+ *
+ * @param title the window title, if one is displayed; null becomes ""
+ * @param attachToInputContext true for the window to share context with
+ * the input method
+ * @return the new window for use by the input method
+ * @throws HeadlessException if GraphicsEnvironment.isHeadless is true
+ */
+ Window createInputMethodWindow(String title, boolean attachToInputContext);
+
+ /**
+ * Creates a top-level Swing JFrame for use by the input method. This frame
+ * should float above all document windows and dialogs, not receive focus,
+ * and have lightweight decorations (such as no title, reduced drag
+ * regions). But this behavior may be modified to meet the platform style.
+ * The title may or may not be displayed, depending on the platform.
+ *
+ * <p>If attachToInputContext is true, the new window will share the input
+ * context of the input method, so that events in the new window are
+ * dispatched to the input method. Also, this supresses deactivate and
+ * activate calls to the input method caused by setVisible.
+ *
+ * @param title the window title, if one is displayed; null becomes ""
+ * @param attachToInputContext true for the window to share context with
+ * the input method
+ * @return the new window for use by the input method
+ * @throws HeadlessException if GraphicsEnvironment.isHeadless is true
+ * @since 1.4
+ */
+ JFrame createInputMethodJFrame(String title, boolean attachToInputContext);
+
+ /**
+ * Sets whether notification of the client window's location and state should
+ * be enabled for the input method. When enabled, the input method's
+ * {@link #notifyClientWindowChange(Rectangle)} method is called.
+ * Notification is automatically disabled when the input method is disposed.
+ *
+ * @param inputMethod the method to change status of
+ * @param enable true to enable notification
+ */
+ void enableClientWindowNotification(InputMethod inputMethod, boolean enable);
+} // interface InputMethodContext
diff --git a/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java b/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java
new file mode 100644
index 00000000000..093d7319217
--- /dev/null
+++ b/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java
@@ -0,0 +1,113 @@
+/* InputMethodDescriptor.java -- enables loading and use of an input method
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im.spi;
+
+import java.awt.AWTException;
+import java.awt.Image;
+import java.util.Locale;
+
+/**
+ * This interface provides information about an InputMethod before it is
+ * loaded.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface InputMethodDescriptor
+{
+ /**
+ * Returns the locales supported by the input method this describes. This
+ * allows the selection of input methods by locale (by language only, or
+ * also by country and variant), via
+ * {@link InputContext#selectInputMethod(Locale)}. The returned list should
+ * ignore pass-through locales, so it is usually a subset of locales for
+ * which {@link InputMethod#setContext(Locale)} returns true. If
+ * {@link #hasDynamicLocaleList()} returns true, this is called each time
+ * information is needed, allowing dynamic addition or removal of supported
+ * locales.
+ *
+ * @return the list of supported locales
+ * @throws AWTException if the input method is not available
+ */
+ Locale[] getAvailableLocales() throws AWTException;
+
+ /**
+ * Test whether the input method this describes has a static or dynamic
+ * locale list. For example, this would return true if the list of supported
+ * locales depends on adapters currently loaded over a network.
+ *
+ * @return true if the locale list is dynamic
+ */
+ boolean hasDynamicLocaleList();
+
+ /**
+ * Returns a user visible name of the input locale, displayed in the
+ * specified locale. The inputLocale parameter must be one obtained from
+ * the list in {@link #getAvailableLocales()}, or null for a
+ * locale-independent description of the input method. If a translation to
+ * the desired display language is not available, another language may be
+ * used.
+ *
+ * @param inputLocale the locale of the input method, or null
+ * @param displayLanguage the language of the result
+ * @return the name of the input method when using the given inputLocale
+ */
+ String getInputMethodDisplayName(Locale inputLocale,
+ Locale displayLanguage);
+
+ /**
+ * Returns a 16x16 icon for the input locale. The inputLocale parameter
+ * must be one obtained from the list in {@link #getAvailableLocales()}, or
+ * null for a locale-independent icon for the input method.
+ *
+ * @param inputLocale the locale of the input method, or null
+ * @return a 16x16 icon for the input method when using the given inputLocale
+ */
+ Image getInputMethodIcon(Locale inputLocale);
+
+ /**
+ * Creates a new instance of the input method.
+ *
+ * @return the newly created input method
+ * @throws Exception if anything goes wrong
+ */
+ InputMethod createInputMethod() throws Exception;
+
+} // interface InputMethodDescriptor
+
diff --git a/libjava/classpath/java/awt/im/spi/package.html b/libjava/classpath/java/awt/im/spi/package.html
new file mode 100644
index 00000000000..c526ee1590d
--- /dev/null
+++ b/libjava/classpath/java/awt/im/spi/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.im.spi package.
+ Copyright (C) 2002 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 - java.awt.im.spi</title></head>
+
+<body>
+<p>Interfaces for implementation of text input methods.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/image/AffineTransformOp.java b/libjava/classpath/java/awt/image/AffineTransformOp.java
new file mode 100644
index 00000000000..f11066e4e3d
--- /dev/null
+++ b/libjava/classpath/java/awt/image/AffineTransformOp.java
@@ -0,0 +1,375 @@
+/* AffineTransformOp.java -- This class performs affine
+ transformation between two images or rasters in 2 dimensions.
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+/**
+ * This class performs affine transformation between two images or
+ * rasters in 2 dimensions.
+ *
+ * @author Olga Rodimina (rodimina@redhat.com)
+ */
+public class AffineTransformOp implements BufferedImageOp, RasterOp
+{
+ public static final int TYPE_NEAREST_NEIGHBOR = 1;
+
+ public static final int TYPE_BILINEAR = 2;
+
+ /**
+ * @since 1.5.0
+ */
+ public static final int TYPE_BICUBIC = 3;
+
+ private AffineTransform transform;
+ private RenderingHints hints;
+
+ /**
+ * Construct AffineTransformOp with the given xform and interpolationType.
+ * Interpolation type can be TYPE_BILINEAR, TYPE_BICUBIC or
+ * TYPE_NEAREST_NEIGHBOR.
+ *
+ * @param xform AffineTransform that will applied to the source image
+ * @param interpolationType type of interpolation used
+ */
+ public AffineTransformOp (AffineTransform xform, int interpolationType)
+ {
+ this.transform = xform;
+ if (xform.getDeterminant() == 0)
+ throw new ImagingOpException(null);
+
+ switch (interpolationType)
+ {
+ case TYPE_BILINEAR:
+ hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ break;
+ case TYPE_BICUBIC:
+ hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ break;
+ default:
+ hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+ }
+ }
+
+ /**
+ * Construct AffineTransformOp with the given xform and rendering hints.
+ *
+ * @param xform AffineTransform that will applied to the source image
+ * @param hints rendering hints that will be used during transformation
+ */
+ public AffineTransformOp (AffineTransform xform, RenderingHints hints)
+ {
+ this.transform = xform;
+ this.hints = hints;
+ if (xform.getDeterminant() == 0)
+ throw new ImagingOpException(null);
+ }
+
+ /**
+ * Creates empty BufferedImage with the size equal to that of the
+ * transformed image and correct number of bands. The newly created
+ * image is created with the specified ColorModel.
+ * If the ColorModel is equal to null, then image is created
+ * with the ColorModel of the source image.
+ *
+ * @param src source image
+ * @param destCM color model for the destination image
+ * @return new compatible destination image
+ */
+ public BufferedImage createCompatibleDestImage (BufferedImage src,
+ ColorModel destCM)
+ {
+
+ // if destCm is not specified, use color model of the source image
+
+ if (destCM == null)
+ destCM = src.getColorModel ();
+
+ return new BufferedImage (destCM,
+ createCompatibleDestRaster (src.getRaster ()),
+ src.isAlphaPremultiplied (),
+ null);
+
+ }
+
+ /**
+ * Creates empty WritableRaster with the size equal to the transformed
+ * source raster and correct number of bands
+ *
+ * @param src source raster
+ * @throws RasterFormatException if resulting width or height of raster is 0
+ * @return new compatible raster
+ */
+ public WritableRaster createCompatibleDestRaster (Raster src)
+ {
+ Rectangle rect = (Rectangle) getBounds2D (src);
+
+ // throw RasterFormatException if resulting width or height of the
+ // transformed raster is 0
+
+ if (rect.getWidth () == 0 || rect.getHeight () == 0)
+ throw new RasterFormatException("width or height is 0");
+
+ return src.createCompatibleWritableRaster ((int) rect.getWidth (),
+ (int) rect.getHeight ());
+ }
+
+ /**
+ * Transforms source image using transform specified at the constructor.
+ * The resulting transformed image is stored in the destination image.
+ *
+ * @param src source image
+ * @param dst destination image
+ * @return transformed source image
+ */
+ public final BufferedImage filter (BufferedImage src, BufferedImage dst)
+ {
+
+ if (dst == src)
+ throw new IllegalArgumentException ("src image cannot be the same as the dst image");
+
+ // If the destination image is null, then BufferedImage is
+ // created with ColorModel of the source image
+
+ if (dst == null)
+ dst = createCompatibleDestImage(src, src.getColorModel ());
+
+ // FIXME: Must check if color models of src and dst images are the same.
+ // If it is not, then source image should be converted to color model
+ // of the destination image
+
+ Graphics2D gr = (Graphics2D) dst.createGraphics ();
+ gr.setRenderingHints (hints);
+ gr.drawImage (src, transform, null);
+ return dst;
+
+ }
+
+ /**
+ * Transforms source raster using transform specified at the constructor.
+ * The resulting raster is stored in the destination raster.
+ *
+ * @param src source raster
+ * @param dst destination raster
+ * @return transformed raster
+ */
+ public final WritableRaster filter (Raster src, WritableRaster dst)
+ {
+ if (dst == src)
+ throw new IllegalArgumentException("src image cannot be the same as"
+ + " the dst image");
+
+ if (dst == null)
+ dst = createCompatibleDestRaster(src);
+
+ if (src.getNumBands() != dst.getNumBands())
+ throw new IllegalArgumentException("src and dst must have same number"
+ + " of bands");
+
+ double[] dpts = new double[dst.getWidth() * 2];
+ double[] pts = new double[dst.getWidth() * 2];
+ for (int x = 0; x < dst.getWidth(); x++)
+ {
+ dpts[2 * x] = x + dst.getMinX();
+ dpts[2 * x + 1] = x;
+ }
+ Rectangle srcbounds = src.getBounds();
+ if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
+ {
+ for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++)
+ {
+ try {
+ transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2);
+ } catch (NoninvertibleTransformException e) {
+ // Can't happen since the constructor traps this
+ e.printStackTrace();
+ }
+
+ for (int x = 0; x < dst.getWidth(); x++)
+ {
+ if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1]))
+ continue;
+ dst.setDataElements(x + dst.getMinX(), y,
+ src.getDataElements((int)pts[2 * x],
+ (int)pts[2 * x + 1],
+ null));
+ }
+ }
+ }
+ else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ {
+ double[] tmp = new double[4 * src.getNumBands()];
+ for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++)
+ {
+ try {
+ transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2);
+ } catch (NoninvertibleTransformException e) {
+ // Can't happen since the constructor traps this
+ e.printStackTrace();
+ }
+
+ for (int x = 0; x < dst.getWidth(); x++)
+ {
+ if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1]))
+ continue;
+ int xx = (int)pts[2 * x];
+ int yy = (int)pts[2 * x + 1];
+ double dx = (pts[2 * x] - xx);
+ double dy = (pts[2 * x + 1] - yy);
+
+ // TODO write this more intelligently
+ if (xx == src.getMinX() + src.getWidth() - 1 ||
+ yy == src.getMinY() + src.getHeight() - 1)
+ {
+ // bottom or right edge
+ Arrays.fill(tmp, 0);
+ src.getPixel(xx, yy, tmp);
+ }
+ else
+ {
+ // Normal case
+ src.getPixels(xx, yy, 2, 2, tmp);
+ for (int b = 0; b < src.getNumBands(); b++)
+ tmp[b] = dx * dy * tmp[b]
+ + (1 - dx) * dy * tmp[b + src.getNumBands()]
+ + dx * (1 - dy) * tmp[b + 2 * src.getNumBands()]
+ + (1 - dx) * (1 - dy) * tmp[b + 3 * src.getNumBands()];
+ }
+ dst.setPixel(x, y, tmp);
+ }
+ }
+ }
+ else
+ {
+ // Bicubic
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+ return dst;
+ }
+
+ /**
+ * Transforms source image using transform specified at the constructor and
+ * returns bounds of the transformed image.
+ *
+ * @param src image to be transformed
+ * @return bounds of the transformed image.
+ */
+ public final Rectangle2D getBounds2D (BufferedImage src)
+ {
+ return getBounds2D (src.getRaster());
+ }
+
+ /**
+ * Returns bounds of the transformed raster.
+ *
+ * @param src raster to be transformed
+ * @return bounds of the transformed raster.
+ */
+ public final Rectangle2D getBounds2D (Raster src)
+ {
+ // determine new size for the transformed raster.
+ // Need to calculate transformed coordinates of the lower right
+ // corner of the raster. The upper left corner is always (0,0)
+
+ double x2 = (double) src.getWidth () + src.getMinX ();
+ double y2 = (double) src.getHeight () + src.getMinY ();
+ Point2D p2 = getPoint2D (new Point2D.Double (x2,y2), null);
+
+ Rectangle2D rect = new Rectangle (0, 0, (int) p2.getX (), (int) p2.getY ());
+ return rect.getBounds ();
+ }
+
+ /**
+ * Returns interpolation type used during transformations
+ *
+ * @return interpolation type
+ */
+ public final int getInterpolationType ()
+ {
+ if(hints.containsValue (RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ return TYPE_BILINEAR;
+ else
+ return TYPE_NEAREST_NEIGHBOR;
+ }
+
+ /**
+ * Returns location of the transformed source point. The resulting point
+ * is stored in the dstPt if one is specified.
+ *
+ * @param srcPt point to be transformed
+ * @param dstPt destination point
+ * @return the location of the transformed source point.
+ */
+ public Point2D getPoint2D (Point2D srcPt, Point2D dstPt)
+ {
+ return transform.transform (srcPt, dstPt);
+ }
+
+ /**
+ * Returns rendering hints that are used during transformation.
+ *
+ * @return rendering hints
+ */
+ public final RenderingHints getRenderingHints ()
+ {
+ return hints;
+ }
+
+ /**
+ * Returns transform used in transformation between source and destination
+ * image.
+ *
+ * @return transform
+ */
+ public final AffineTransform getTransform ()
+ {
+ return transform;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java b/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java
new file mode 100644
index 00000000000..b9ca1b70758
--- /dev/null
+++ b/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java
@@ -0,0 +1,127 @@
+/* AreaAveragingScaleFilter.java -- Java class for filtering images
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * This filter should produce images which do not have image artifacts
+ * like broken lines which were originally unbroken. The cost is of
+ * course speed. Using bi-linear interpolation here against 4 pixel
+ * points should give the desired results although Sun does not
+ * specify what the exact algorithm should be.
+ * <br>
+ * Currently this filter does nothing and needs to be implemented.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class AreaAveragingScaleFilter extends ReplicateScaleFilter
+{
+ /**
+ * Construct an instance of <code>AreaAveragingScaleFilter</code> which
+ * should be used in conjunction with a <code>FilteredImageSource</code>
+ * object.
+ *
+ * @param width the width of the destination image
+ * @param height the height of the destination image
+ */
+ public AreaAveragingScaleFilter(int width, int height) {
+ super(width, height);
+ }
+
+ /**
+ * The <code>ImageProducer</code> should call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the
+ * <code>ImageConsumer</code> interface.
+ * <br>
+ * FIXME - more than likely Sun's implementation desires
+ * <code>TOPDOWNLEFTRIGHT</code> order and this method is overloaded here
+ * in order to assure that mask is part of the hints added to
+ * the consumer.
+ *
+ * @param flags a bit mask of hints
+ * @see ImageConsumer
+ */
+ public void setHints(int flags)
+ {
+ consumer.setHints(flags);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize)
+ {
+ consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize)
+ {
+ consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
+ }
+
+}
+
diff --git a/libjava/classpath/java/awt/image/BandCombineOp.java b/libjava/classpath/java/awt/image/BandCombineOp.java
new file mode 100644
index 00000000000..79efb02e713
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BandCombineOp.java
@@ -0,0 +1,168 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * Filter Raster pixels by applying a matrix.
+ *
+ * BandCombineOp applies a matrix to each pixel to produce new pixel values.
+ * The width of the matrix must be the same or one more than the number of
+ * bands in the source Raster. If one more, the pixels in the source are
+ * assumed to contain an implicit 1.0 at the end.
+ *
+ * The rows of the matrix are multiplied by the pixel to produce the values
+ * for the destination. Therefore the destination Raster must contain the
+ * same number of bands as the number of rows in the filter matrix.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public class BandCombineOp implements RasterOp
+{
+ private RenderingHints hints;
+ private float[][] matrix;
+
+ /**
+ * Construct a BandCombineOp.
+ *
+ * @param matrix The matrix to filter pixels with.
+ * @param hints Rendering hints to apply. Ignored.
+ */
+ public BandCombineOp(float[][] matrix, RenderingHints hints)
+ {
+ this.matrix = matrix;
+ this.hints = hints;
+ }
+
+ /**
+ * Filter Raster pixels through a matrix.
+ *
+ * Applies the Op matrix to source pixes to produce dest pixels. Each row
+ * of the matrix is multiplied by the src pixel components to produce the
+ * dest pixel. If matrix is one more than the number of bands in the src,
+ * the last element is implicitly multiplied by 1, i.e. added to the sum
+ * for that dest component.
+ *
+ * If dest is null, a suitable Raster is created. This implementation uses
+ * createCompatibleDestRaster.
+ *
+ * @param src The source Raster.
+ * @param dest The destination Raster, or null.
+ * @returns The destination Raster or an allocated Raster.
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
+ *java.awt.image.WritableRaster)
+ */
+ public WritableRaster filter(Raster src, WritableRaster dest) {
+ if (dest == null)
+ dest = createCompatibleDestRaster(src);
+
+ // Filter the pixels
+ float[] spix = new float[matrix[0].length];
+ float[] dpix = new float[matrix.length];
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ {
+ // In case matrix rows have implicit translation
+ spix[spix.length - 1] = 1.0f;
+ src.getPixel(x, y, spix);
+ for (int i = 0; i < matrix.length; i++)
+ {
+ dpix[i] = 0;
+ for (int j = 0; j < matrix[0].length; j++)
+ dpix[i] += spix[j] * matrix[i][j];
+ }
+ dest.setPixel(x, y, dpix);
+ }
+
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /**
+ * Creates a new WritableRaster that can be used as the destination for this
+ * Op. This implementation creates a Banded Raster with data type FLOAT.
+ * @see
+ *java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return Raster.createBandedRaster(DataBuffer.TYPE_FLOAT, src.getWidth(),
+ src.getHeight(), matrix.length,
+ new Point(src.getMinX(), src.getMinY()));
+ }
+
+ /** Return corresponding destination point for source point.
+ *
+ * LookupOp will return the value of src unchanged.
+ * @param src The source point.
+ * @param dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D,
+ *java.awt.geom.Point2D)
+ */
+ public Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null) return (Point2D)src.clone();
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /** Return the matrix for this Op. */
+ public float[][] getMatrix()
+ {
+ return matrix;
+ }
+
+}
diff --git a/libjava/classpath/java/awt/image/BandedSampleModel.java b/libjava/classpath/java/awt/image/BandedSampleModel.java
new file mode 100644
index 00000000000..24d315a1c35
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BandedSampleModel.java
@@ -0,0 +1,548 @@
+/* Copyright (C) 2004, 2005, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/**
+ * 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.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public final class BandedSampleModel extends ComponentSampleModel
+{
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;
+ private int dataBitOffset;
+ private int elemBits;
+ private int numberOfBits;
+ private int numElems;
+
+ private static int[] createBankArray(int size)
+ {
+ int[] result = new int[size];
+ for (int i = 0; i < size; i++)
+ result[i] = i;
+ return result;
+ }
+
+ public BandedSampleModel(int dataType, int w, int h, int numBands)
+ {
+ this(dataType, w, h, w, createBankArray(numBands), new int[numBands]);
+ }
+
+ public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
+ int[] bankIndices, int[] bandOffsets)
+ {
+ super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ // NOTE: blackdown 1.4.1 sets all offsets to 0. Sun's 1.4.2 docs
+ // disagree.
+
+ // 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++)
+ 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;
+ }
+ int bank = 0;
+ int offset = 0;
+ 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;
+ }
+
+ return new BandedSampleModel(dataType, w, h, scanlineStride, bankIndices, newoffsets);
+ }
+
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ if (bands.length > bankIndices.length)
+ throw new
+ RasterFormatException("BandedSampleModel createSubsetSampleModel too"
+ +" many bands");
+ int[] newoff = new int[bands.length];
+ int[] newbanks = new int[bands.length];
+ for (int i=0; i < bands.length; i++)
+ {
+ int b = bands[i];
+ newoff[i] = bandOffsets[b];
+ newbanks[i] = bankIndices[b];
+ }
+
+ return new BandedSampleModel(dataType, width, height, scanlineStride,
+ newbanks, newoff);
+ }
+
+ /**
+ * Extract all samples of one pixel and return in an array of transfer type.
+ *
+ * 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 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)
+ */
+ public Object getDataElements(int x, int y, Object obj,
+ DataBuffer data)
+ {
+ int pixel = getSample(x, y, 0, data);
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ byte[] b = (byte[])obj;
+ if (b == null) b = new byte[numBands];
+ 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;
+ if (b == null) b = new short[numBands];
+ 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;
+ if (b == null) b = new int[numBands];
+ for (int i=0; i < numBands; i++)
+ b[i] = getSample(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ {
+ float[] b = (float[])obj;
+ if (b == null) b = new float[numBands];
+ 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++)
+ b[i] = getSample(x, y, i, data);
+ return b;
+ }
+
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ }
+
+ 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++)
+ iArray[i] = getSample(x, y, i, data);
+
+ return iArray;
+ }
+
+ /**
+ * Copy pixels from a region into an array.
+ *
+ * Copies the samples of the pixels in the rectangle starting at x, y that
+ * is w pixels wide and h scanlines high. When there is more than one band,
+ * the samples stored in order before the next pixel. This ordering isn't
+ * well specified in Sun's docs as of 1.4.2.
+ *
+ * If iArray is null, a new array is allocated, filled, and returned.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param w The width in pixels of the rectangle.
+ * @param h The height in pixels of the rectangle.
+ * @param iArray The int 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.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ if (iArray == null) iArray = new int[w*h*numBands];
+ int outOffset = 0;
+ int maxX = x + w;
+ int maxY = y + h;
+ for (int yy = x; yy < maxY; yy++)
+ {
+ for (int xx = x; xx < maxX; xx++)
+ {
+ for (int b = 0; b < numBands; b++)
+ {
+ int offset = bandOffsets[b] + yy * scanlineStride + xx;
+ iArray[outOffset++] =
+ data.getElem(bankIndices[b], offset);
+ }
+ }
+ }
+ return iArray;
+ }
+
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElem(bankIndices[b], offset);
+ }
+
+ public float getSampleFloat(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElemFloat(bankIndices[b], offset);
+ }
+
+ public double getSampleDouble(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElemDouble(bankIndices[b], offset);
+ }
+
+ /**
+ * Copy one band's samples from a region into an array.
+ *
+ * Copies from one band the samples of the pixels in the rectangle starting
+ * at x, y that is w pixels wide and h scanlines high.
+ *
+ * If iArray is null, a new array is allocated, filled, and returned.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param w The width in pixels of the rectangle.
+ * @param h The height in pixels of the rectangle.
+ * @param b The band to retrieve.
+ * @param iArray The int 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.
+ */
+ 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];
+ int outOffset = 0;
+ int maxX = x + w;
+ int maxY = y + h;
+ for (int yy = y; yy < maxY; yy++)
+ {
+ for (int xx = x; xx < maxX; xx++)
+ {
+ int offset = bandOffsets[b] + yy * scanlineStride + xx;
+ iArray[outOffset++] =
+ data.getElem(bankIndices[b], offset);
+ }
+ }
+ return iArray;
+ }
+
+
+ /**
+ * Set the pixel at x, y to the value in the first element of the primitive
+ * array obj.
+ *
+ * @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 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 = y * scanlineStride + x;
+
+ try
+ {
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] in = (byte[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_SHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] in = (short[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferUShort out = (DataBufferUShort) data;
+ short[] in = (short[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] in = (int[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ {
+ DataBufferFloat out = (DataBufferFloat) data;
+ float[] in = (float[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_DOUBLE:
+ {
+ DataBufferDouble out = (DataBufferDouble) data;
+ double[] in = (double[]) obj;
+ for (int i=0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ 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);
+ }
+ }
+
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ for (int b=0; b < numBands; b++)
+ data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
+ iArray[b]);
+ }
+
+ public void setPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = y * scanlineStride + (x + ww);
+ for (int b=0; b < numBands; b++)
+ data.setElem(bankIndices[b], bandOffsets[b] + offset,
+ iArray[inOffset++]);
+ }
+ y++;
+ }
+ }
+
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ }
+
+ public void setSample(int x, int y, int b, float s, DataBuffer data)
+ {
+ data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ }
+
+ public void setSample(int x, int y, int b, double s, DataBuffer data)
+ {
+ data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (byte)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_SHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (short)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (short)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ case DataBuffer.TYPE_DOUBLE:
+ break;
+ default:
+ throw new ClassCastException("Unsupported data type");
+ }
+
+ // Default implementation probably slower for float and double
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ data.setElem(bankIndices[b], offset, iArray[inOffset++]);
+ }
+ y++;
+ }
+ }
+
+ /**
+ * Creates a String with some information about this SampleModel.
+ * @return A String describing this SampleModel.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+ result.append(getClass().getName());
+ result.append("[");
+ result.append("scanlineStride=").append(scanlineStride);
+ for(int i=0; i < bitMasks.length; i+=1)
+ {
+ result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
+ }
+
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/BufferStrategy.java b/libjava/classpath/java/awt/image/BufferStrategy.java
new file mode 100644
index 00000000000..e86aad60fe9
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BufferStrategy.java
@@ -0,0 +1,124 @@
+/* BufferStrategy.java -- describes image buffering resources
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.BufferCapabilities;
+import java.awt.Graphics;
+
+/**
+ * This class describes a strategy for managing image buffering
+ * resources on a Canvas or Window. A given buffer strategy may make
+ * use of hardware acceleration or take advantage of features of the
+ * native graphics system. Examples of buffering strategies are
+ * double or triple buffering using either flipping or blitting. For
+ * the details of these algorithms see BufferCapabilities.
+ *
+ * To use a buffer strategy, you retrieve it from either the current
+ * GraphicsConfiguration or from the Component on which you'd like to
+ * draw. Then you can query the strategy's capabilities to make sure
+ * they're suitable.
+ *
+ * If the strategy's capabilities are suitable, you can obtain a
+ * graphics object and use it to draw with this strategy. Drawing
+ * with a buffer strategy requires extra care, however. You'll need
+ * to manually cause the next buffer to be shown on the output device.
+ * And since buffer strategies are usually implemented with a
+ * VolatileImage, you must frequently check that the contents of the
+ * buffer are valid and that the buffer still exists.
+ *
+ * A buffer strategy is usually implemented using a VolatileImage.
+ *
+ * @see VolatileImage
+ * @since 1.4
+ */
+public abstract class BufferStrategy
+{
+ /**
+ * Creates a new buffer strategy.
+ */
+ public BufferStrategy()
+ {
+ }
+
+ /**
+ * Retrieves the capabilities of this buffer strategy.
+ *
+ * @return this buffer strategy's capabilities
+ */
+ public abstract BufferCapabilities getCapabilities();
+
+ /**
+ * Retrieves a graphics object that can be used to draw using this
+ * buffer strategy. This method may not be synchronized so be
+ * careful when calling it from multiple threads. You also must
+ * manually dispose of this graphics object.
+ *
+ * @return a graphics object that can be used to draw using this
+ * buffer strategy
+ */
+ public abstract Graphics getDrawGraphics();
+
+ /**
+ * Returns whether or not the buffer's resources have been reclaimed
+ * by the native graphics system. If the buffer resources have been
+ * lost then you'll need to obtain new resources before drawing
+ * again. For details, see the documentation for VolatileImage.
+ *
+ * @return true if the contents were lost, false otherwise
+ */
+ public abstract boolean contentsLost();
+
+ /**
+ * Returns whether or not the buffer's resources were re-created and
+ * cleared to the default background color. If the buffer's
+ * resources have recently been re-created and initialized then the
+ * buffer's image may need to be re-rendered. For details, see the
+ * documentation for VolatileImage.
+ *
+ * @return true if the contents were restored, false otherwise
+ */
+ public abstract boolean contentsRestored();
+
+ /**
+ * Applies this buffer strategy. In other words, this method brings
+ * the contents of the back or intermediate buffers to the front
+ * buffer.
+ */
+ public abstract void show();
+}
diff --git a/libjava/classpath/java/awt/image/BufferedImage.java b/libjava/classpath/java/awt/image/BufferedImage.java
new file mode 100644
index 00000000000..124b81368e2
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BufferedImage.java
@@ -0,0 +1,693 @@
+/* BufferedImage.java --
+ Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.ComponentDataBlitOp;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+/**
+ * A buffered image always starts at coordinates (0, 0).
+ *
+ * The buffered image is not subdivided into multiple tiles. Instead,
+ * the image consists of one large tile (0,0) with the width and
+ * height of the image. This tile is always considered to be checked
+ * out.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class BufferedImage extends Image
+ implements WritableRenderedImage
+{
+ public static final int TYPE_CUSTOM = 0,
+ TYPE_INT_RGB = 1,
+ TYPE_INT_ARGB = 2,
+ TYPE_INT_ARGB_PRE = 3,
+ TYPE_INT_BGR = 4,
+ TYPE_3BYTE_BGR = 5,
+ TYPE_4BYTE_ABGR = 6,
+ TYPE_4BYTE_ABGR_PRE = 7,
+ TYPE_USHORT_565_RGB = 8,
+ TYPE_USHORT_555_RGB = 9,
+ TYPE_BYTE_GRAY = 10,
+ TYPE_USHORT_GRAY = 11,
+ TYPE_BYTE_BINARY = 12,
+ TYPE_BYTE_INDEXED = 13;
+
+ static final int[] bits3 = { 8, 8, 8 };
+ static final int[] bits4 = { 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;
+
+ public BufferedImage(int w, int h, int type)
+ {
+ 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)
+ {
+ 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
+ );
+ 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);
+ break;
+ case TYPE_BYTE_BINARY:
+ byte[] vals = { 0, (byte) 0xff };
+ cm = new IndexColorModel(8, 2, vals, vals, vals);
+ break;
+ case TYPE_BYTE_INDEXED:
+ String msg2 = "type not implemented yet";
+ throw new UnsupportedOperationException(msg2);
+ // FIXME: build color-cube and create color model
+ }
+
+ init(cm,
+ cm.createCompatibleWritableRaster(w, h),
+ 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");
+
+ init(indexcolormodel,
+ indexcolormodel.createCompatibleWritableRaster(w, h),
+ false, // not premultiplied (guess)
+ null, // no properties
+ type);
+ }
+
+ public BufferedImage(ColorModel colormodel,
+ WritableRaster writableraster,
+ boolean premultiplied,
+ Hashtable properties)
+ {
+ init(colormodel, writableraster, premultiplied, properties,
+ TYPE_CUSTOM);
+ // TODO: perhaps try to identify type?
+ }
+
+ WritableRaster raster;
+ ColorModel colorModel;
+ Hashtable properties;
+ boolean isPremultiplied;
+ int type;
+
+ private void init(ColorModel cm,
+ WritableRaster writableraster,
+ boolean premultiplied,
+ Hashtable properties,
+ int type)
+ {
+ raster = writableraster;
+ colorModel = cm;
+ this.properties = properties;
+ isPremultiplied = premultiplied;
+ this.type = type;
+ }
+
+ //public void addTileObserver(TileObserver tileobserver) {}
+
+ public void coerceData(boolean premultiplied)
+ {
+ colorModel = colorModel.coerceData(raster, premultiplied);
+ }
+
+ public WritableRaster copyData(WritableRaster dest)
+ {
+ if (dest == null)
+ dest = raster.createCompatibleWritableRaster(getMinX(), getMinY(),
+ getWidth(),getHeight());
+
+ int x = dest.getMinX();
+ int y = dest.getMinY();
+ int w = dest.getWidth();
+ int h = dest.getHeight();
+
+ // create a src child that has the right bounds...
+ WritableRaster src =
+ raster.createWritableChild(x, y, w, h, x, y,
+ null // same bands
+ );
+ if (src.getSampleModel () instanceof ComponentSampleModel
+ && dest.getSampleModel () instanceof ComponentSampleModel)
+ // Refer to ComponentDataBlitOp for optimized data blitting:
+ ComponentDataBlitOp.INSTANCE.filter(src, dest);
+ else
+ {
+ // slower path
+ int samples[] = src.getPixels (x, y, w, h, (int [])null);
+ dest.setPixels (x, y, w, h, samples);
+ }
+ return dest;
+ }
+
+ public Graphics2D createGraphics()
+ {
+ GraphicsEnvironment env;
+ env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
+ return env.createGraphics (this);
+ }
+
+ public void flush() {
+ }
+
+ public WritableRaster getAlphaRaster()
+ {
+ return colorModel.getAlphaRaster(raster);
+ }
+
+ public ColorModel getColorModel()
+ {
+ return colorModel;
+ }
+
+ public Raster getData()
+ {
+ return copyData(null);
+ /* TODO: this might be optimized by returning the same
+ raster (not writable) as long as image data doesn't change. */
+ }
+
+ public Raster getData(Rectangle rectangle)
+ {
+ WritableRaster dest =
+ raster.createCompatibleWritableRaster(rectangle);
+ return copyData(dest);
+ }
+
+ public Graphics getGraphics()
+ {
+ return createGraphics();
+ }
+
+ public int getHeight()
+ {
+ return raster.getHeight();
+ }
+
+ public int getHeight(ImageObserver imageobserver)
+ {
+ return getHeight();
+ }
+
+ public int getMinTileX()
+ {
+ return 0;
+ }
+
+ public int getMinTileY()
+ {
+ return 0;
+ }
+
+ public int getMinX()
+ {
+ return 0;
+ }
+
+ public int getMinY()
+ {
+ return 0;
+ }
+
+ public int getNumXTiles()
+ {
+ return 1;
+ }
+
+ public int getNumYTiles()
+ {
+ return 1;
+ }
+
+ public Object getProperty(String string)
+ {
+ if (properties == null)
+ return null;
+ return properties.get(string);
+ }
+
+ public Object getProperty(String string, ImageObserver imageobserver)
+ {
+ return getProperty(string);
+ }
+
+
+ public String[] getPropertyNames()
+ {
+ // FIXME: implement
+ return null;
+ }
+
+ public int getRGB(int x, int y)
+ {
+ Object rgbElem = raster.getDataElements(x, y,
+ null // create as needed
+ );
+ return colorModel.getRGB(rgbElem);
+ }
+
+ public int[] getRGB(int startX, int startY, int w, int h,
+ int[] rgbArray,
+ int offset, int scanlineStride)
+ {
+ if (rgbArray == null)
+ {
+ /*
+ 000000000000000000
+ 00000[#######----- [ = start
+ -----########----- ] = end
+ -----#######]00000
+ 000000000000000000 */
+ int size = (h-1)*scanlineStride + w;
+ rgbArray = new int[size];
+ }
+
+ int endX = startX + w;
+ int endY = startY + h;
+
+ /* *TODO*:
+ Opportunity for optimization by examining color models...
+
+ Perhaps wrap the rgbArray up in a WritableRaster with packed
+ sRGB color model and perform optimized rendering into the
+ array. */
+
+ Object rgbElem = null;
+ for (int y=startY; y<endY; y++)
+ {
+ int xoffset = offset;
+ for (int x=startX; x<endX; x++)
+ {
+ int rgb;
+ rgbElem = raster.getDataElements(x, y, rgbElem);
+ rgb = colorModel.getRGB(rgbElem);
+ rgbArray[xoffset++] = rgb;
+ }
+ offset += scanlineStride;
+ }
+ return rgbArray;
+ }
+
+ public WritableRaster getRaster()
+ {
+ return raster;
+ }
+
+ public SampleModel getSampleModel()
+ {
+ return raster.getSampleModel();
+ }
+
+ public ImageProducer getSource()
+ {
+ return new ImageProducer() {
+
+ Vector consumers = new Vector();
+
+ public void addConsumer(ImageConsumer ic)
+ {
+ if(!consumers.contains(ic))
+ consumers.add(ic);
+ }
+
+ public boolean isConsumer(ImageConsumer ic)
+ {
+ return consumers.contains(ic);
+ }
+
+ public void removeConsumer(ImageConsumer ic)
+ {
+ consumers.remove(ic);
+ }
+
+ public void startProduction(ImageConsumer ic)
+ {
+ int x = 0;
+ int y = 0;
+ int width = getWidth();
+ int height = getHeight();
+ int stride = width;
+ int offset = 0;
+ int[] pixels = getRGB(x, y,
+ width, height,
+ (int[])null, offset, stride);
+ ColorModel model = getColorModel();
+
+ consumers.add(ic);
+
+ for(int i=0;i<consumers.size();i++)
+ {
+ ImageConsumer c = (ImageConsumer) consumers.elementAt(i);
+ c.setHints(ImageConsumer.SINGLEPASS);
+ c.setDimensions(getWidth(), getHeight());
+ c.setPixels(x, y, width, height, model, pixels, offset, stride);
+ c.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer ic)
+ {
+ startProduction(ic);
+ }
+
+ };
+ }
+
+ public Vector getSources()
+ {
+ return null;
+ }
+
+ public BufferedImage getSubimage(int x, int y, int w, int h)
+ {
+ WritableRaster subRaster =
+ getRaster().createWritableChild(x, y, w, h, 0, 0, null);
+
+ return new BufferedImage(getColorModel(),
+ subRaster,
+ isPremultiplied,
+ properties);
+ }
+
+ public Raster getTile(int tileX, int tileY)
+ {
+ return getWritableTile(tileX, tileY);
+ }
+
+ public int getTileGridXOffset()
+ {
+ return 0; // according to javadocs
+ }
+
+ public int getTileGridYOffset()
+ {
+ return 0; // according to javadocs
+ }
+
+ public int getTileHeight()
+ {
+ return getHeight(); // image is one big tile
+ }
+
+ public int getTileWidth()
+ {
+ return getWidth(); // image is one big tile
+ }
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public int getWidth()
+ {
+ return raster.getWidth();
+ }
+
+ public int getWidth(ImageObserver imageobserver)
+ {
+ return getWidth();
+ }
+
+ public WritableRaster getWritableTile(int tileX, int tileY)
+ {
+ isTileWritable(tileX, tileY); // for exception
+ return raster;
+ }
+
+ private static final Point[] tileIndices = { new Point() };
+
+ public Point[] getWritableTileIndices()
+ {
+ return tileIndices;
+ }
+
+ public boolean hasTileWriters()
+ {
+ return true;
+ }
+
+ public boolean isAlphaPremultiplied()
+ {
+ return isPremultiplied;
+ }
+
+ public boolean isTileWritable(int tileX, int tileY)
+ {
+ if ((tileX != 0) || (tileY != 0))
+ throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
+ return true;
+ }
+
+ public void releaseWritableTile(int tileX, int tileY)
+ {
+ isTileWritable(tileX, tileY); // for exception
+ }
+
+ //public void removeTileObserver(TileObserver tileobserver) {}
+
+ public void setData(Raster src)
+ {
+ int x = src.getMinX();
+ int y = src.getMinY();
+ int w = src.getWidth();
+ int h = src.getHeight();
+
+ // create a dest child that has the right bounds...
+ WritableRaster dest =
+ raster.createWritableChild(x, y, w, h, x, y,
+ null // same bands
+ );
+
+ if (src.getSampleModel () instanceof ComponentSampleModel
+ && dest.getSampleModel () instanceof ComponentSampleModel)
+
+ // Refer to ComponentDataBlitOp for optimized data blitting:
+ ComponentDataBlitOp.INSTANCE.filter(src, dest);
+ else
+ {
+ // slower path
+ int samples[] = src.getPixels (x, y, w, h, (int [])null);
+ dest.setPixels (x, y, w, h, samples);
+ }
+ }
+
+ public void setRGB(int x, int y, int argb)
+ {
+ Object rgbElem = colorModel.getDataElements(argb, null);
+ raster.setDataElements(x, y, rgbElem);
+ }
+
+ public void setRGB(int startX, int startY, int w, int h,
+ int[] argbArray, int offset, int scanlineStride)
+ {
+ int endX = startX + w;
+ int endY = startY + h;
+
+ Object rgbElem = null;
+ for (int y=startY; y<endY; y++)
+ {
+ int xoffset = offset;
+ for (int x=startX; x<endX; x++)
+ {
+ int argb = argbArray[xoffset++];
+ rgbElem = colorModel.getDataElements(argb, rgbElem);
+ raster.setDataElements(x, y, rgbElem);
+ }
+ offset += scanlineStride;
+ }
+ }
+
+ public String toString()
+ {
+ StringBuffer buf;
+
+ buf = new StringBuffer(/* estimated length */ 120);
+ buf.append("BufferedImage@");
+ buf.append(Integer.toHexString(hashCode()));
+ buf.append(": type=");
+ buf.append(type);
+ buf.append(' ');
+ buf.append(colorModel);
+ buf.append(' ');
+ buf.append(raster);
+
+ return buf.toString();
+ }
+
+
+ /**
+ * Adds a tile observer. If the observer is already present, it receives
+ * multiple notifications.
+ *
+ * @param to The TileObserver to add.
+ */
+ public void addTileObserver (TileObserver to)
+ {
+ if (observers == null)
+ observers = new Vector ();
+
+ observers.add (to);
+ }
+
+ /**
+ * Removes a tile observer. If the observer was not registered,
+ * nothing happens. If the observer was registered for multiple
+ * notifications, it is now registered for one fewer notification.
+ *
+ * @param to The TileObserver to remove.
+ */
+ public void removeTileObserver (TileObserver to)
+ {
+ if (observers == null)
+ return;
+
+ observers.remove (to);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/BufferedImageFilter.java b/libjava/classpath/java/awt/image/BufferedImageFilter.java
new file mode 100644
index 00000000000..50d627d66a3
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BufferedImageFilter.java
@@ -0,0 +1,110 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.awt.Point;
+
+/**
+ * The BufferedImageFilter class wraps BufferedImageOp objects in a Filter.
+ *
+ * When pixels are pushed through the filter, we create a BufferedImage,
+ * apply the BufferedImageOp, and pass the filtered pixels to the base class.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class BufferedImageFilter extends ImageFilter implements Cloneable
+{
+ private BufferedImageOp op;
+
+ /**
+ *
+ */
+ public BufferedImageFilter(BufferedImageOp op)
+ {
+ super();
+ if (op == null)
+ throw new NullPointerException("BufferedImageFilter null"
+ + " op in constructor");
+ this.op = op;
+ }
+
+ /**
+ * @return Returns the contained BufferedImageOp.
+ */
+ public BufferedImageOp getBufferedImageOp()
+ {
+ return op;
+ }
+
+ // FIXME: Definitely not sure this is the right thing. I'm not sure how to
+ // create a compatible sample model that incorporates scansize != w. I
+ // asume off is handled by the db itself.
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int off, int scansize)
+ {
+ // Create an input BufferedImage
+ DataBufferByte db = new DataBufferByte(pixels, scansize * h + off, off);
+ SampleModel sm = model.createCompatibleSampleModel(scansize, h);
+ WritableRaster wr = new WritableRaster(sm, db, new Point(0, 0));
+ BufferedImage in =
+ new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
+ BufferedImage out = op.createCompatibleDestImage(in, model);
+ op.filter(in, out);
+ DataBuffer dbout = out.getRaster().getDataBuffer();
+ super.setPixels(0, 0, w, h, model, ((DataBufferByte)dbout).getData(), 0,
+ scansize);
+ }
+
+ // FIXME: Definitely not sure this is the right thing. I'm not sure how
+ // to create a compatible sample model that incorporates
+ // scansize != w. I asume off is handled by the db itself.
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int off, int scansize)
+ {
+ // Create an input BufferedImage
+ DataBufferInt db = new DataBufferInt(pixels, scansize * h + off, off);
+ SampleModel sm = model.createCompatibleSampleModel(scansize, h);
+ WritableRaster wr = new WritableRaster(sm, db, new Point(0, 0));
+ BufferedImage in =
+ new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
+ BufferedImage out = op.createCompatibleDestImage(in, model);
+ op.filter(in, out);
+ DataBuffer dbout = out.getRaster().getDataBuffer();
+ super.setPixels(0, 0, w, h, model, ((DataBufferInt)dbout).getData(), 0,
+ scansize);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/BufferedImageOp.java b/libjava/classpath/java/awt/image/BufferedImageOp.java
new file mode 100644
index 00000000000..2ecbec056a0
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BufferedImageOp.java
@@ -0,0 +1,55 @@
+/* BufferedImageOp.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * NEEDS DOCUMENTATION
+ */
+public interface BufferedImageOp
+{
+ BufferedImage filter(BufferedImage src, BufferedImage dst);
+ Rectangle2D getBounds2D(BufferedImage src);
+ BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM);
+ Point2D getPoint2D(Point2D src, Point2D dst);
+ RenderingHints getRenderingHints();
+} // interface BufferedImageOp
diff --git a/libjava/classpath/java/awt/image/ByteLookupTable.java b/libjava/classpath/java/awt/image/ByteLookupTable.java
new file mode 100644
index 00000000000..df02d0a1bf7
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ByteLookupTable.java
@@ -0,0 +1,166 @@
+/* ByteLookupTable.java -- Java class for a pixel translation table.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * ByteLookupTable represents translation arrays for pixel values. It wraps
+ * one or more data arrays for each layer (or component) in an image, such as
+ * Alpha, R, G, and B. When doing translation, the offset is subtracted from
+ * the pixel values to allow a subset of an array to be used.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @version 1.0
+ */
+public class ByteLookupTable extends LookupTable
+{
+ // Array of translation tables.
+ private byte data[][];
+
+ /**
+ * Creates a new <code>ByteLookupTable</code> instance.
+ *
+ * Offset is subtracted from pixel values when looking up in the translation
+ * tables. If data.length is one, the same table is applied to all pixel
+ * components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param data Array of lookup tables.
+ * @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;
+ }
+
+ /**
+ * Creates a new <code>ByteLookupTable</code> instance.
+ *
+ * Offset is subtracted from pixel values when looking up in the translation
+ * table. The same table is applied to all pixel components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param data Lookup table for all components.
+ * @exception IllegalArgumentException if offset &lt; 0.
+ */
+ public ByteLookupTable(int offset, byte[] data)
+ throws IllegalArgumentException
+ {
+ super(offset, 1);
+ this.data = new byte[][] {data};
+ }
+
+ /**
+ * Return the lookup tables.
+ *
+ * @return the tables
+ */
+ public final byte[][] getTable()
+ {
+ return data;
+ }
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dst Destination array for values, or null.
+ * @return Translated values for the pixel.
+ */
+ public int[] lookupPixel(int[] src, int[] dst)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if (dst == null)
+ dst = new int[src.length];
+
+ if (data.length == 1)
+ 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];
+
+ return dst;
+ }
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dst Destination array for values, or null.
+ * @return Translated values for the pixel.
+ */
+ public byte[] lookupPixel(byte[] src, byte[] dst)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if (dst == null)
+ dst = new byte[src.length];
+
+ if (data.length == 1)
+ 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];
+
+ return dst;
+
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ColorConvertOp.java b/libjava/classpath/java/awt/image/ColorConvertOp.java
new file mode 100644
index 00000000000..18609e0c4b0
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ColorConvertOp.java
@@ -0,0 +1,319 @@
+/* ColorModel.java --
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * ColorConvertOp is a filter for converting an image from one colorspace to
+ * another colorspace. The filter can convert the image through a sequence
+ * of colorspaces or just from source to destination.
+ *
+ * Color conversion is done on the color components without alpha. Thus
+ * if a BufferedImage has alpha premultiplied, this is divided out before
+ * color conversion, and premultiplication applied if the destination
+ * requires it.
+ *
+ * Color rendering and dithering hints may be applied if specified. This is
+ * likely platform-dependent.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class ColorConvertOp implements BufferedImageOp, RasterOp
+{
+ private ColorSpace srccs;
+ private ColorSpace dstcs;
+ private RenderingHints hints;
+ private ICC_Profile[] profiles;
+ private ColorSpace[] spaces;
+ private boolean rasterValid;
+
+
+ /**
+ * Convert BufferedImage through a ColorSpace.
+ *
+ * This filter version is only valid for BufferedImages. The source image
+ * is converted to cspace. If the destination is not null, it is then
+ * converted to the destination colorspace. Normally this filter will only
+ * be used with a null destination.
+ *
+ * @param cspace The target color space.
+ * @param hints Rendering hints to use in conversion, or null.
+ */
+ public ColorConvertOp(ColorSpace cspace, RenderingHints hints)
+ {
+ if (cspace == null)
+ throw new NullPointerException();
+ spaces = new ColorSpace[]{cspace};
+ this.hints = hints;
+ rasterValid = false;
+ }
+
+ public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace,
+ RenderingHints hints)
+ {
+ if (srcCspace == null || dstCspace == null)
+ throw new NullPointerException();
+ spaces = new ColorSpace[]{srcCspace, dstCspace};
+ this.hints = hints;
+ }
+
+ /**
+ * Convert from a source image destination image color space.
+ *
+ * This constructor builds a ColorConvertOp from an array of ICC_Profiles.
+ * The source image will be converted through the sequence of color spaces
+ * defined by the profiles. If the sequence of profiles doesn't give a
+ * well-defined conversion, throws IllegalArgumentException.
+ *
+ * NOTE: Sun's docs don't clearly define what a well-defined conversion is
+ * - or perhaps someone smarter can come along and sort it out.
+ *
+ * For BufferedImages, when the first and last profiles match the
+ * requirements of the source and destination color space respectively, the
+ * corresponding conversion is unnecessary. TODO: code this up. I don't
+ * yet understand how you determine this.
+ *
+ * For Rasters, the first and last profiles must have the same number of
+ * bands as the source and destination Rasters, respectively. If this is
+ * not the case, or there fewer than 2 profiles, an IllegalArgumentException
+ * will be thrown.
+ *
+ * @param profiles
+ * @param hints
+ */
+ public ColorConvertOp(ICC_Profile[] profiles, RenderingHints hints)
+ {
+ if (profiles == null)
+ throw new NullPointerException();
+ this.hints = hints;
+ this.profiles = profiles;
+ // TODO: Determine if this is well-defined.
+ // Create colorspace array with space for src and dest colorspace
+ spaces = new ColorSpace[profiles.length];
+ for (int i = 0; i < profiles.length; i++)
+ spaces[i] = new ICC_ColorSpace(profiles[i]);
+ }
+
+ /** Convert from source image color space to destination image color space.
+ *
+ * Only valid for BufferedImage objects, this Op converts from the source
+ * color space to the destination color space. The destination can't be
+ * null for this operation.
+ *
+ * @param hints Rendering hints to use during conversion, or null.
+ */
+ public ColorConvertOp(RenderingHints hints)
+ {
+ this.hints = hints;
+ srccs = null;
+ dstcs = null;
+ rasterValid = false;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage,
+ java.awt.image.BufferedImage)
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ // TODO: The plan is to create a scanline buffer for intermediate buffers.
+ // For now we just suck it up and create intermediate buffers.
+
+ if (dst == null && spaces.length == 0)
+ throw new IllegalArgumentException();
+
+ // Make sure input isn't premultiplied by alpha
+ if (src.isAlphaPremultiplied())
+ {
+ BufferedImage tmp = createCompatibleDestImage(src, src.getColorModel());
+ copyimage(src, tmp);
+ tmp.coerceData(false);
+ src = tmp;
+ }
+
+ ColorModel scm = src.getColorModel();
+ for (int i = 0; i < spaces.length; i++)
+ {
+ ColorModel cm = scm.cloneColorModel(spaces[i]);
+ BufferedImage tmp = createCompatibleDestImage(src, cm);
+ copyimage(src, tmp);
+ src = tmp;
+ }
+
+ // Intermediate conversions leave result in src
+ if (dst == null)
+ return src;
+
+ // Apply final conversion
+ copyimage(src, dst);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ // FIXME: set properties to those in src
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isPremultiplied,
+ null);
+ }
+
+ public final ICC_Profile[] getICC_Profiles()
+ {
+ return profiles;
+ }
+
+ /** Return the rendering hints for this op. */
+ public final RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ if (!rasterValid)
+ throw new IllegalArgumentException();
+
+ // Need to iterate through each color space - there must be at least 2
+ for (int i = 1; i < spaces.length - 1; i++)
+ {
+ // FIXME: this is wrong. tmp needs to have the same number of bands as
+ // spaces[i] has.
+ WritableRaster tmp = createCompatibleDestRaster(src);
+ copyraster(src, spaces[i - 1], tmp, spaces[i]);
+ src = tmp;
+ }
+
+ // FIXME: this is wrong. dst needs to have the same number of bands as
+ // spaces[i] has.
+ if (dest == null)
+ dest = createCompatibleDestRaster(src);
+ copyraster(src, spaces[spaces.length - 2],
+ dest, spaces[spaces.length - 1]);
+
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+ /** Return corresponding destination point for source point.
+ *
+ * LookupOp will return the value of src unchanged.
+ * @param src The source point.
+ * @param dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null) return (Point2D)src.clone();
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public final Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ // According to Sven de Marothy, we need to copy the src into the dest
+ // using Graphics2D, in order to use the rendering hints.
+ private void copyimage(BufferedImage src, BufferedImage dst)
+ {
+ Graphics2D gg = dst.createGraphics();
+ gg.setRenderingHints(hints);
+ gg.drawImage(src, 0, 0, null);
+ gg.dispose();
+ }
+
+ private void copyraster(Raster src, ColorSpace scs, WritableRaster dst,
+ ColorSpace dcs)
+ {
+ float[] sbuf = new float[src.getNumBands()];
+
+ if (hints.get(RenderingHints.KEY_COLOR_RENDERING) ==
+ RenderingHints.VALUE_COLOR_RENDER_QUALITY)
+ {
+ // use cie for accuracy
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dst.setPixel(x, y,
+ dcs.fromCIEXYZ(scs.toCIEXYZ(src.getPixel(x, y, sbuf))));
+ }
+ else
+ {
+ // use rgb - it's probably faster
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dst.setPixel(x, y,
+ dcs.fromRGB(scs.toRGB(src.getPixel(x, y, sbuf))));
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/awt/image/ColorModel.java b/libjava/classpath/java/awt/image/ColorModel.java
new file mode 100644
index 00000000000..1ebcb98a76b
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ColorModel.java
@@ -0,0 +1,758 @@
+/* ColorModel.java --
+ Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+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;
+
+/**
+ * A color model operates with colors in several formats:
+ *
+ * <ul>
+ * <li>normalized: component samples are in range [0.0, 1.0].</li>
+ *
+ * <li>color model pixel value: all the color component samples for a
+ * sigle pixel packed/encoded in a way natural for the color
+ * model.</li>
+ *
+ * <li>color model pixel int value: only makes sense if the natural
+ * encoding of a single pixel can fit in a single int value.</li>
+ *
+ * <li>array of transferType containing a single pixel: the pixel is
+ * encoded in the natural way of the color model, taking up as many
+ * array elements as needed.</li>
+ *
+ * <li>sRGB pixel int value: a pixel in sRGB color space, encoded in
+ * default 0xAARRGGBB format, assumed not alpha premultiplied.</li>
+ *
+ * <li>single [0, 255] scaled int samples from default sRGB color
+ * space. These are always assumed to be alpha non-premultiplied.</li>
+ *
+ * <li>arrays of unnormalized component samples of single pixel: these
+ * samples are scaled and multiplied according to the color model, but
+ * is otherwise not packed or encoded. Each element of the array is one
+ * separate component sample. The color model only operate on the
+ * components from one pixel at a time, but using offsets, allows
+ * manipulation of arrays that contain the components of more than one
+ * pixel.</li>
+ *
+ * </ul>
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public abstract class ColorModel implements Transparency
+{
+ protected int pixel_bits;
+ protected int transferType;
+
+ int[] bits;
+ ColorSpace cspace;
+ int transparency;
+ boolean hasAlpha;
+ boolean isAlphaPremultiplied;
+
+ static int[] nArray(int value, int times)
+ {
+ int[] array = new int[times];
+ java.util.Arrays.fill(array, value);
+ return array;
+ }
+
+ static byte[] nArray(byte value, int times)
+ {
+ byte[] array = new byte[times];
+ java.util.Arrays.fill(array, value);
+ return array;
+ }
+
+ /**
+ * Constructs the default color model. The default color model
+ * can be obtained by calling <code>getRGBdefault</code> of this
+ * class.
+ * @param bits the number of bits wide used for bit size of pixel values
+ */
+ public ColorModel(int bits)
+ {
+ this(bits * 4, // total bits, sRGB, four channels
+ nArray(bits, 4), // bits for each channel
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT,
+ Buffers.smallestAppropriateTransferType(bits * 4));
+ }
+
+ /**
+ * Constructs a ColorModel that translates pixel values to
+ * color/alpha components.
+ *
+ * @exception IllegalArgumentException If the length of the bit array is less
+ * than the number of color or alpha components in this ColorModel, or if the
+ * transparency is not a valid value, or if the sum of the number of bits in
+ * bits is less than 1 or if any of the elements in bits is less than 0.
+ */
+ protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
+ boolean hasAlpha, boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ int bits_sum = 0;
+ for (int i = 0; i < bits.length; i++)
+ {
+ if (bits [i] < 0)
+ throw new IllegalArgumentException ();
+
+ bits_sum |= bits [i];
+ }
+
+ if ((bits.length < cspace.getNumComponents())
+ || (bits_sum < 1))
+ throw new IllegalArgumentException ();
+
+ this.pixel_bits = pixel_bits;
+ this.bits = bits;
+ this.cspace = cspace;
+ this.hasAlpha = hasAlpha;
+ this.isAlphaPremultiplied = isAlphaPremultiplied;
+ 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()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Returns the default color model which in Sun's case is an instance
+ * of <code>DirectColorModel</code>.
+ */
+ public static ColorModel getRGBdefault()
+ {
+ return new DirectColorModel(32, 0xff0000, 0xff00, 0xff, 0xff000000);
+ }
+
+ public final boolean hasAlpha()
+ {
+ return hasAlpha;
+ }
+
+ public final boolean isAlphaPremultiplied()
+ {
+ return isAlphaPremultiplied;
+ }
+
+ /**
+ * Get get number of bits wide used for the bit size of pixel values
+ */
+ public int getPixelSize()
+ {
+ return pixel_bits;
+ }
+
+ public int getComponentSize(int componentIdx)
+ {
+ return bits[componentIdx];
+ }
+
+ public int[] getComponentSize()
+ {
+ return bits;
+ }
+
+ public int getTransparency()
+ {
+ return transparency;
+ }
+
+ public int getNumComponents()
+ {
+ return getNumColorComponents() + (hasAlpha ? 1 : 0);
+ }
+
+ public int getNumColorComponents()
+ {
+ return cspace.getNumComponents();
+ }
+
+ /**
+ * Converts pixel value to sRGB and extract red int sample scaled
+ * to range [0, 255].
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model, (assumed alpha premultiplied if color model says
+ * so.)
+ *
+ * @return red sample scaled to range [0, 255], from default color
+ * space sRGB, alpha non-premultiplied.
+ */
+ public abstract int getRed(int pixel);
+
+ /**
+ * Converts pixel value to sRGB and extract green int sample
+ * scaled to range [0, 255].
+ *
+ * @see #getRed(int)
+ */
+ public abstract int getGreen(int pixel);
+
+ /**
+ * Converts pixel value to sRGB and extract blue int sample
+ * scaled to range [0, 255].
+ *
+ * @see #getRed(int)
+ */
+ public abstract int getBlue(int pixel);
+
+ /**
+ * Extract alpha int sample from pixel value, scaled to [0, 255].
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model.
+ *
+ * @return alpha sample, scaled to range [0, 255].
+ */
+ public abstract int getAlpha(int pixel);
+
+ /**
+ * Converts a pixel int value of the color space of the color
+ * model to a sRGB pixel int value.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model.
+ *
+ * @return a pixel in sRGB color space, encoded in default
+ * 0xAARRGGBB format. */
+ public int getRGB(int pixel)
+ {
+ return
+ ((getAlpha(pixel) & 0xff) << 24) |
+ (( getRed(pixel) & 0xff) << 16) |
+ ((getGreen(pixel) & 0xff) << 8) |
+ (( getBlue(pixel) & 0xff) << 0);
+ }
+
+
+ /**
+ * In this color model we know that the whole pixel value will
+ * always be contained within the first element of the pixel
+ * array.
+ */
+ final int getPixelFromArray(Object inData) {
+ DataBuffer data =
+ Buffers.createBufferFromData(transferType, inData, 1);
+ Object da = Buffers.getData(data);
+
+ return data.getElem(0);
+ }
+
+ /**
+ * Converts pixel in the given array to sRGB and extract blue int
+ * sample scaled to range [0-255].
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param inData array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ */
+ public int getRed(Object inData)
+ {
+ return getRed(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getGreen(Object inData)
+ {
+ return getGreen(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getBlue(Object inData) {
+ return getBlue(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getAlpha(Object inData) {
+ return getAlpha(getPixelFromArray(inData));
+ }
+
+ /**
+ * Converts a pixel in the given array of the color space of the
+ * color model to an sRGB pixel int value.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getDataElements(int rgb, Object pixel)</code>.
+ * I.e. <code>(rgb == cm.getRGB(cm.getDataElements(rgb,
+ * null)))</code>.
+ *
+ * @param inData array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ *
+ * @return a pixel in sRGB color space, encoded in default
+ * 0xAARRGGBB format.
+ *
+ * @see #getDataElements(int, Object)
+ */
+ public int getRGB(Object inData)
+ {
+ return
+ ((getAlpha(inData) & 0xff) << 24) |
+ (( getRed(inData) & 0xff) << 16) |
+ ((getGreen(inData) & 0xff) << 8) |
+ (( getBlue(inData) & 0xff) << 0);
+ }
+
+ /**
+ * Converts an sRGB pixel int value to an array containing a
+ * single pixel of the color space of the color model.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getRGB(Object inData)</code>.
+ *
+ * Outline of conversion process:
+ *
+ * <ol>
+ *
+ * <li>Convert rgb to normalized [0.0, 1.0] sRGB values.</li>
+ *
+ * <li>Convert to color space components using fromRGB in
+ * ColorSpace.</li>
+ *
+ * <li>If color model has alpha and should be premultiplied,
+ * multiply color space components with alpha value</li>
+ *
+ * <li>Scale the components to the correct number of bits.</li>
+ *
+ * <li>Arrange the components in the output array</li>
+ *
+ * </ol>
+ *
+ * @param rgb The color to be converted to dataElements. A pixel
+ * in sRGB color space, encoded in default 0xAARRGGBB format,
+ * assumed not alpha premultiplied.
+ *
+ * @param pixel to avoid needless creation of arrays, an array to
+ * use to return the pixel can be given. If null, a suitable array
+ * will be created.
+ *
+ * @return An array of transferType values representing the color,
+ * in the color model format. The color model defines whether the
+ *
+ * @see #getRGB(Object)
+ */
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // subclasses has to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from a
+ * pixel value. I.e. decompose the pixel, but not perform any
+ * color conversion.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param pixel pixel value encoded according to the color model.
+ *
+ * @return arrays of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are
+ * according to the color model. Each component sample is stored
+ * as a separate element in the array.
+ */
+ public int[] getComponents(int pixel, int[] components, int offset)
+ {
+ // subclasses has to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from an
+ * array of transferType containing a single pixel. I.e. decompose
+ * the pixel, but not perform any color conversion.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ *
+ * @return arrays of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are
+ * according to the color model. Each component sample is stored
+ * as a separate element in the array.
+ */
+ public int[] getComponents(Object pixel, int[] components, int offset)
+ {
+ // subclasses has to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Convert normalized components to unnormalized components.
+ */
+ public int[] getUnnormalizedComponents(float[] normComponents,
+ int normOffset,
+ int[] components,
+ int offset)
+ {
+ int numComponents = getNumComponents();
+ if (components == null)
+ {
+ components = new int[offset + numComponents];
+ }
+
+ for (int i=0; i<numComponents; i++)
+ {
+ float in = normComponents[normOffset++];
+ int out = (int) (in * ((1<<getComponentSize(i)) - 1));
+ components[offset++] = out;
+ }
+ return components;
+ }
+
+ /**
+ * Convert unnormalized components to normalized components.
+ */
+ public float[] getNormalizedComponents(int[] components,
+ int offset,
+ float[] normComponents,
+ int normOffset)
+ {
+ int numComponents = getNumComponents();
+ if (normComponents == null)
+ {
+ normComponents = new float[normOffset + numComponents];
+ }
+
+ for (int i=0; i<numComponents; i++)
+ {
+ float in = components[offset++];
+ float out = in / ((1<<getComponentSize(i)) - 1);
+ normComponents[normOffset++] = out;
+ }
+ return normComponents;
+ }
+
+ /**
+ * Convert unnormalized components to normalized components.
+ *
+ * @since 1.4
+ */
+ public float[] getNormalizedComponents (Object pixel,
+ float[] normComponents,
+ int normOffset)
+ {
+ // subclasses has to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Converts the unnormalized component samples from an array to a
+ * pixel value. I.e. composes the pixel from component samples, but
+ * does not perform any color conversion or scaling of the samples.
+ *
+ * This method performs the inverse function of
+ * <code>getComponents(int pixel, int[] components,
+ * int offset)</code>. I.e.
+ *
+ * <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null,
+ * 0), 0))</code>.
+ *
+ * This method is overriden in subclasses since this abstract class throws
+ * UnsupportedOperationException().
+ *
+ * @param components Array of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are according
+ * to the color model. Each component sample is stored as a separate element
+ * in the array.
+ * @param offset Position of the first value of the pixel in components.
+ *
+ * @return pixel value encoded according to the color model.
+ */
+ public int getDataElement(int[] components, int offset)
+ {
+ // subclasses have to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Converts the normalized component samples from an array to a pixel
+ * value. I.e. composes the pixel from component samples, but does not
+ * perform any color conversion or scaling of the samples.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation. The method provided by this abstract
+ * class converts the components to unnormalized form and returns
+ * getDataElement(int[], int).
+ *
+ * @param components Array of normalized component samples of single pixel.
+ * The scale and multiplication state of the samples are according to the
+ * color model. Each component sample is stored as a separate element in the
+ * array.
+ * @param offset Position of the first value of the pixel in components.
+ *
+ * @return pixel value encoded according to the color model.
+ * @since 1.4
+ */
+ public int getDataElement (float[] components, int offset)
+ {
+ return
+ getDataElement(getUnnormalizedComponents(components, offset, null, 0),
+ 0);
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ // subclasses have to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Converts the normalized component samples from an array to an array of
+ * TransferType values. I.e. composes the pixel from component samples, but
+ * does not perform any color conversion or scaling of the samples.
+ *
+ * If obj is null, a new array of TransferType is allocated and returned.
+ * Otherwise the results are stored in obj and obj is returned. If obj is
+ * not long enough, ArrayIndexOutOfBounds is thrown. If obj is not an array
+ * of primitives, ClassCastException is thrown.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation. The method provided by this abstract
+ * class converts the components to unnormalized form and returns
+ * getDataElement(int[], int, Object).
+ *
+ * @param components Array of normalized component samples of single pixel.
+ * The scale and multiplication state of the samples are according to the
+ * color model. Each component sample is stored as a separate element in the
+ * array.
+ * @param offset Position of the first value of the pixel in components.
+ * @param obj Array of TransferType or null.
+ *
+ * @return pixel value encoded according to the color model.
+ * @throws ArrayIndexOutOfBounds
+ * @throws ClassCastException
+ * @since 1.4
+ */
+ public Object getDataElements(float[] components, int offset, Object obj)
+ {
+ return
+ getDataElements(getUnnormalizedComponents(components, offset, null, 0),
+ 0, obj);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ColorModel)) return false;
+
+ ColorModel o = (ColorModel) obj;
+ return
+ (pixel_bits == o.pixel_bits) &&
+ (transferType == o.transferType) &&
+ (transparency == o.transparency) &&
+ (hasAlpha == o.hasAlpha) &&
+ (isAlphaPremultiplied == o.isAlphaPremultiplied) &&
+ Arrays.equals(bits, o.bits) &&
+ (cspace.equals(o.cspace));
+ }
+
+ public final ColorSpace getColorSpace()
+ {
+ return cspace;
+ }
+
+ // Typically overridden
+ public ColorModel coerceData(WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied)
+ return this;
+
+ int w = raster.getWidth();
+ int h = raster.getHeight();
+ int x = raster.getMinX();
+ int y = raster.getMinY();
+ int size = w*h;
+ int numColors = getNumColorComponents();
+ int numComponents = getNumComponents();
+ int alphaScale = (1<<getComponentSize(numColors)) - 1;
+ double[] pixels = raster.getPixels(x, y, w, h, (double[]) null);
+
+ for (int i=0; i<size; i++)
+ {
+ double alpha = pixels[i*numComponents+numColors]*alphaScale;
+ for (int c=0; c<numColors; c++)
+ {
+ int offset = i*numComponents+c;
+ if (isAlphaPremultiplied)
+ pixels[offset] = pixels[offset]/alpha;
+ else
+ pixels[offset] = pixels[offset]*alpha;
+ }
+ }
+
+ raster.setPixels(0, 0, w, h, pixels);
+
+ // FIXME: what can we return?
+ return null;
+ }
+
+ /**
+ * Checks if the given raster has a compatible data-layout (SampleModel).
+ * @param raster The Raster to test.
+ * @return true if raster is compatible.
+ */
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ SampleModel sampleModel = raster.getSampleModel();
+ return isCompatibleSampleModel(sampleModel);
+ }
+
+ // Typically overridden
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ return new WritableRaster(createCompatibleSampleModel(w, h),
+ new Point(0, 0));
+ }
+
+ // Typically overridden
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ // Typically overridden
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return sm.getTransferType() == transferType;
+ }
+
+ public final int getTransferType ()
+ {
+ return transferType;
+ }
+
+ /**
+ * Subclasses must override this method if it is possible for the
+ * color model to have an alpha channel.
+ *
+ * @return null, as per JDK 1.3 doc. Subclasses will only return
+ * null if no alpha raster exists.
+ */
+ public WritableRaster getAlphaRaster(WritableRaster raster)
+ {
+ return null;
+
+ /* It is a mystery to me why we couldn't use the following code...
+
+
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+
+
+ ...here, and avoided overriding the method in subclasses,
+ but the Sun docs state that this method always will return
+ null, and that overriding is required. Oh, well.
+ */
+ }
+
+ String stringParam()
+ {
+ return "pixel_bits=" + pixel_bits +
+ ", cspace=" + cspace +
+ ", transferType=" + transferType +
+ ", transparency=" + transparency +
+ ", hasAlpha=" + hasAlpha +
+ ", isAlphaPremultiplied=" + isAlphaPremultiplied;
+ }
+
+ public String toString()
+ {
+ return getClass().getName() + "[" + stringParam() + "]";
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ComponentColorModel.java b/libjava/classpath/java/awt/image/ComponentColorModel.java
new file mode 100644
index 00000000000..f56688f9362
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ComponentColorModel.java
@@ -0,0 +1,391 @@
+/* ComponentColorModel.java --
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.Point;
+import java.awt.color.ColorSpace;
+
+public class ComponentColorModel extends ColorModel
+{
+ private static int sum(int[] values)
+ {
+ int sum = 0;
+ for (int i=0; i<values.length; i++)
+ sum += values[i];
+ return sum;
+ }
+
+ public ComponentColorModel(ColorSpace colorSpace, int[] bits,
+ boolean hasAlpha,
+ boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ super(sum(bits), bits, colorSpace, hasAlpha, isAlphaPremultiplied,
+ transparency, transferType);
+ }
+
+ /**
+ * Construct a new ComponentColorModel.
+ *
+ * This constructor makes all bits of each sample significant, so for a
+ * transferType of DataBuffer.BYTE, the bits per sample is 8, etc. If
+ * both hasAlpha and isAlphaPremultiplied are true, color samples are
+ * assumed to be premultiplied by the alpha component. Transparency may be
+ * one of OPAQUE, BITMASK, or TRANSLUCENT.
+ *
+ * @param colorSpace The colorspace for this color model.
+ * @param hasAlpha True if there is an alpha component.
+ * @param isAlphaPremultiplied True if colors are already multiplied by
+ * alpha.
+ * @param transparency The type of alpha values.
+ * @param transferType Data type of pixel sample values.
+ * @since 1.4
+ */
+ public ComponentColorModel(ColorSpace colorSpace,
+ boolean hasAlpha,
+ boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
+ transparency, transferType);
+ }
+
+ public int getRed(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getGreen(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getBlue(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getAlpha(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ int shift = 8 - getComponentSize(getNumColorComponents());
+ if (shift >= 0) return pixel << shift;
+ return pixel >> (-shift);
+ }
+
+ public int getRGB(int pixel)
+ {
+ float[] rgb = getRGBFloat(pixel);
+ int ret = getRGB(rgb);
+ if (hasAlpha()) ret |= getAlpha(pixel) << 24;
+ return ret;
+ }
+
+
+ /* Note, it's OK to pass a to large array to toRGB(). Extra
+ elements are ignored. */
+
+ private float[] getRGBFloat(int pixel)
+ {
+ float[] data = { pixel };
+ return cspace.toRGB(data);
+ }
+
+ private float[] getRGBFloat(Object inData)
+ {
+ DataBuffer buffer =
+ Buffers.createBufferFromData(transferType, inData,
+ getNumComponents());
+ int colors = getNumColorComponents();
+ float[] data = new float[colors];
+
+ // FIXME: unpremultiply data that is premultiplied
+ for (int i=0; i<colors; i++)
+ {
+ float maxValue = (1<<getComponentSize(i))-1;
+ data[i] = buffer.getElemFloat(i)/maxValue;
+ }
+ float[] rgb = cspace.toRGB(data);
+ return rgb;
+ }
+
+ public int getRed(Object inData)
+ {
+ return (int) getRGBFloat(inData)[0]*255;
+ }
+
+ public int getGreen(Object inData)
+ {
+ return (int) getRGBFloat(inData)[1]*255;
+ }
+
+ public int getBlue(Object inData)
+ {
+ return (int) getRGBFloat(inData)[2]*255;
+ }
+
+ public int getAlpha(Object inData)
+ {
+ DataBuffer buffer =
+ Buffers.createBufferFromData(transferType, inData,
+ getNumComponents());
+ int shift = 8 - getComponentSize(getNumColorComponents());
+ int alpha = buffer.getElem(getNumColorComponents());
+ if (shift >= 0) return alpha << shift;
+ return alpha >> (-shift);
+ }
+
+ private int getRGB(float[] rgb)
+ {
+ /* NOTE: We could cast to byte instead of int here. This would
+ avoid bits spilling over from one bit field to
+ another. But, if we assume that floats are in the [0.0,
+ 1.0] range, this will never happen anyway. */
+
+ /* Remember to multiply BEFORE casting to int, otherwise, decimal
+ point data will be lost. */
+ int ret =
+ (((int) (rgb[0]*255F)) << 16) |
+ (((int) (rgb[1]*255F)) << 8) |
+ (((int) (rgb[2]*255F)) << 0);
+ return ret;
+ }
+
+ /**
+ * @param inData pixel data of transferType, as returned by the
+ * getDataElements method in SampleModel.
+ */
+ public int getRGB(Object inData)
+ {
+ float[] rgb = getRGBFloat(inData);
+ int ret = getRGB(rgb);
+ if (hasAlpha()) ret |= getAlpha(inData) << 24;
+ return ret;
+ }
+
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // Convert rgb to [0.0, 1.0] sRGB values.
+ float[] rgbFloats = {
+ ((rgb >> 16)&0xff)/255.0F,
+ ((rgb >> 8)&0xff)/255.0F,
+ ((rgb >> 0)&0xff)/255.0F
+ };
+
+ // Convert from rgb to color space components.
+ float[] data = cspace.fromRGB(rgbFloats);
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
+ getNumComponents());
+ int numColors = getNumColorComponents();
+
+ if (hasAlpha())
+ {
+ float alpha = ((rgb >> 24)&0xff)/255.0F;
+
+ /* If color model has alpha and should be premultiplied, multiply
+ color space components with alpha value. */
+ if (isAlphaPremultiplied()) {
+ for (int i=0; i<numColors; i++)
+ data[i] *= alpha;
+ }
+ // Scale the alpha sample to the correct number of bits.
+ alpha *= (1<<(bits[numColors]-1));
+ // Arrange the alpha sample in the output array.
+ buffer.setElemFloat(numColors, alpha);
+ }
+ for (int i=0; i<numColors; i++)
+ {
+ // Scale the color samples to the correct number of bits.
+ float value = data[i]*(1<<(bits[i]-1));
+ // Arrange the color samples in the output array.
+ buffer.setElemFloat(i, value);
+ }
+ return Buffers.getData(buffer);
+ }
+
+ public int[] getComponents(int pixel, int[] components, int offset)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ if (components == null)
+ components = new int[getNumComponents() + offset];
+ components[offset] = pixel;
+ return components;
+ }
+
+ public int[] getComponents(Object pixel, int[] components, int offset)
+ {
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
+ getNumComponents());
+ int numComponents = getNumComponents();
+
+ if (components == null)
+ components = new int[numComponents + offset];
+
+ for (int i=0; i<numComponents; i++)
+ components[offset++] = buffer.getElem(i);
+
+ return components;
+ }
+
+ public int getDataElement(int[] components, int offset)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return components[offset];
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ DataBuffer buffer = Buffers.createBuffer(transferType, obj,
+ getNumComponents());
+ int numComponents = getNumComponents();
+
+ for (int i=0; i<numComponents; i++)
+ buffer.setElem(i, components[offset++]);
+
+ return Buffers.getData(buffer);
+ }
+
+ public ColorModel coerceData(WritableRaster raster,
+ boolean isAlphaPremultiplied) {
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied)
+ return this;
+
+ /* TODO: provide better implementation based on the
+ assumptions we can make due to the specific type of the
+ color model. */
+ super.coerceData(raster, isAlphaPremultiplied);
+
+ return new ComponentColorModel(cspace, bits, hasAlpha(),
+ isAlphaPremultiplied, // argument
+ transparency, transferType);
+ }
+
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ return super.isCompatibleRaster(raster);
+ // FIXME: Should we test something more here? (Why override?)
+ }
+
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ SampleModel sm = createCompatibleSampleModel(w, h);
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(sm, origin);
+ }
+
+
+ /**
+ * Creates a <code>SampleModel</code> whose arrangement of pixel
+ * data is compatible to this <code>ColorModel</code>.
+ *
+ * @param w the number of pixels in the horizontal direction.
+ * @param h the number of pixels in the vertical direction.
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ int pixelStride, scanlineStride;
+ int[] bandOffsets;
+
+ pixelStride = getNumComponents();
+ scanlineStride = pixelStride * w;
+
+ /* We might be able to re-use the same bandOffsets array among
+ * multiple calls to this method. However, this optimization does
+ * not seem worthwile because setting up descriptive data
+ * structures (such as SampleModels) is neglectible in comparision
+ * to shuffling around masses of pixel data.
+ */
+ bandOffsets = new int[pixelStride];
+ for (int i = 0; i < pixelStride; i++)
+ bandOffsets[i] = i;
+
+ /* FIXME: Think about whether it would make sense to return the
+ * possibly more efficient PixelInterleavedSampleModel for other
+ * transferTypes as well. It seems unlikely that this would break
+ * any user applications, so the Mauve tests on this method
+ * might be too restrictive.
+ */
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_USHORT:
+ return new PixelInterleavedSampleModel(transferType, w, h,
+ pixelStride,
+ scanlineStride,
+ bandOffsets);
+
+ default:
+ return new ComponentSampleModel(transferType, w, h,
+ pixelStride,
+ scanlineStride,
+ bandOffsets);
+ }
+ }
+
+
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return
+ (sm instanceof ComponentSampleModel) &&
+ super.isCompatibleSampleModel(sm);
+ }
+
+ public WritableRaster getAlphaRaster(WritableRaster raster)
+ {
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ComponentColorModel)) return false;
+ return super.equals(obj);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ComponentSampleModel.java b/libjava/classpath/java/awt/image/ComponentSampleModel.java
new file mode 100644
index 00000000000..953f63c1ea1
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ComponentSampleModel.java
@@ -0,0 +1,544 @@
+/* Copyright (C) 2000, 2002 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.image;
+
+import gnu.java.awt.Buffers;
+
+/* FIXME: This class does not yet support data type TYPE_SHORT */
+
+/**
+ * ComponentSampleModel supports a flexible organization of pixel samples in
+ * memory, permitting pixel samples to be interleaved by band, by scanline,
+ * and by pixel.
+ *
+ * A DataBuffer for this sample model has K banks of data. Pixels have N
+ * samples, so there are N bands in the DataBuffer. Each band is completely
+ * contained in one bank of data, but a bank may contain more than one band.
+ * Each pixel sample is stored in a single data element.
+ *
+ * Within a bank, each band begins at an offset stored in bandOffsets. The
+ * banks containing the band is given by bankIndices. Within the bank, there
+ * are three dimensions - band, pixel, and scanline. The dimension ordering
+ * is controlled by bandOffset, pixelStride, and scanlineStride, which means
+ * that any combination of interleavings is supported.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class ComponentSampleModel extends SampleModel
+{
+ protected int[] bandOffsets;
+ protected int[] bankIndices;
+
+ // FIXME: Should we really shadow the numBands in the superclass?
+ //protected int numBands;
+
+ /** Used when creating data buffers. */
+ protected int numBanks;
+
+ protected int scanlineStride;
+
+ protected int pixelStride;
+
+ private boolean tightPixelPacking = false;
+
+ public ComponentSampleModel(int dataType,
+ int w, int h,
+ int pixelStride,
+ int scanlineStride,
+ int[] bandOffsets)
+ {
+ this(dataType, w, h, pixelStride, scanlineStride,
+ new int[bandOffsets.length], bandOffsets);
+ }
+
+ public ComponentSampleModel(int dataType,
+ int w, int h,
+ int pixelStride,
+ int scanlineStride,
+ int[] bankIndices,
+ int[] bandOffsets)
+ {
+ super(dataType, w, h, bandOffsets.length);
+ if ((pixelStride<0) || (scanlineStride<0) ||
+ (bandOffsets.length<1) ||
+ (bandOffsets.length != bankIndices.length))
+ throw new IllegalArgumentException();
+
+ this.bandOffsets = bandOffsets;
+ this.bankIndices = bankIndices;
+
+ this.numBanks = 0;
+ for (int b=0; b<bankIndices.length; b++)
+ this.numBanks = Math.max(this.numBanks, bankIndices[b]+1);
+
+ this.scanlineStride = scanlineStride;
+ this.pixelStride = pixelStride;
+
+ // See if we can use some speedups
+
+ /* FIXME: May these checks should be reserved for the
+ PixelInterleavedSampleModel? */
+
+ if (pixelStride == numBands)
+ {
+ tightPixelPacking = true;
+ for (int b=0; b<numBands; b++) {
+ if ((bandOffsets[b] != b) || (bankIndices[b] !=0))
+ {
+ tightPixelPacking = false;
+ break;
+ }
+ }
+ }
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ return new ComponentSampleModel(dataType, w, h, pixelStride,
+ scanlineStride, bankIndices,
+ bandOffsets);
+ }
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ int numBands = bands.length;
+
+ int[] bankIndices = new int[numBands];
+ int[] bandOffsets = new int[numBands];
+ for (int b=0; b<numBands; b++)
+ {
+ bankIndices[b] = this.bankIndices[bands[b]];
+ bandOffsets[b] = this.bandOffsets[bands[b]];
+ }
+
+ return new ComponentSampleModel(dataType, width, height, pixelStride,
+ scanlineStride, bankIndices,
+ bandOffsets);
+ }
+
+ public DataBuffer createDataBuffer()
+ {
+ // 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]);
+ }
+ int size = pixelStride*(width-1) + scanlineStride*(height-1) +
+ highestOffset + 1;
+
+ return Buffers.createBuffer(getDataType(), size, numBanks);
+ }
+
+ public int getOffset(int x, int y)
+ {
+ return getOffset(x, y, 0);
+ }
+
+ public int getOffset(int x, int y, int b)
+ {
+ return bandOffsets[b] + pixelStride*x + scanlineStride*y;
+ }
+
+ public final int[] getSampleSize()
+ {
+ int size = DataBuffer.getDataTypeSize(getDataType());
+ int[] sizes = new int[numBands];
+
+ java.util.Arrays.fill(sizes, size);
+ return sizes;
+ }
+
+ public final int getSampleSize(int band)
+ {
+ return DataBuffer.getDataTypeSize(getDataType());
+ }
+
+ public final int[] getBankIndices()
+ {
+ return bankIndices;
+ }
+
+ public final int[] getBandOffsets()
+ {
+ return bandOffsets;
+ }
+
+ public final int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ public final int getPixelStride()
+ {
+ return pixelStride;
+ }
+
+ public final int getNumDataElements()
+ {
+ return numBands;
+ }
+
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int xyOffset = pixelStride*x + scanlineStride*y;
+
+ int[] totalBandDataOffsets = new int[numBands];
+
+ /* Notice that band and bank offsets are different. Band offsets
+ are managed by the sample model, and bank offsets are managed
+ by the data buffer. Both must be accounted for. */
+
+ /* FIXME: For single pixels, it is probably easier to simple
+ call getElem instead of calculating the bank offset ourself.
+
+ On the other hand, then we need to push the value through
+ the int type returned by the getElem method. */
+
+ int[] bankOffsets = data.getOffsets();
+
+ for (int b=0; b<numBands; b++)
+ {
+ totalBandDataOffsets[b] =
+ bandOffsets[b]+bankOffsets[bankIndices[b]] + xyOffset;
+ }
+
+ try
+ {
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ DataBufferByte inByte = (DataBufferByte) data;
+ byte[] outByte = (byte[]) obj;
+ if (outByte == null) outByte = new byte[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outByte[b] = inByte.getData(bankIndices[b])[dOffset];
+ }
+ return outByte;
+
+ case DataBuffer.TYPE_USHORT:
+ DataBufferUShort inUShort = (DataBufferUShort) data;
+ short[] outUShort = (short[]) obj;
+ if (outUShort == null) outUShort = new short[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outUShort[b] = inUShort.getData(bankIndices[b])[dOffset];
+ }
+ return outUShort;
+
+ case DataBuffer.TYPE_SHORT:
+ DataBufferShort inShort = (DataBufferShort) data;
+ short[] outShort = (short[]) obj;
+ if (outShort == null) outShort = new short[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outShort[b] = inShort.getData(bankIndices[b])[dOffset];
+ }
+ return outShort;
+
+ case DataBuffer.TYPE_INT:
+ DataBufferInt inInt = (DataBufferInt) data;
+ int[] outInt = (int[]) obj;
+ if (outInt == null) outInt = new int[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outInt[b] = inInt.getData(bankIndices[b])[dOffset];
+ }
+ return outInt;
+
+ case DataBuffer.TYPE_FLOAT:
+ DataBufferFloat inFloat = (DataBufferFloat) data;
+ float[] outFloat = (float[]) obj;
+ if (outFloat == null) outFloat = new float[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outFloat[b] = inFloat.getData(bankIndices[b])[dOffset];
+ }
+ return outFloat;
+
+ case DataBuffer.TYPE_DOUBLE:
+ DataBufferDouble inDouble = (DataBufferDouble) data;
+ double[] outDouble = (double[]) obj;
+ if (outDouble == null) outDouble = new double[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outDouble[b] = inDouble.getData(bankIndices[b])[dOffset];
+ }
+ return outDouble;
+
+ default:
+ throw new IllegalStateException("unknown transfer type " +
+ getTransferType());
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe)
+ {
+ String msg = "While reading data elements, " +
+ "x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset +
+ ", data.getSize()=" + data.getSize() + ": " + aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
+ }
+ }
+
+ public Object getDataElements(int x, int y, int w, int h, Object obj,
+ DataBuffer data)
+ {
+ if (!tightPixelPacking)
+ {
+ return super.getDataElements(x, y, w, h, obj, data);
+ }
+
+ // using get speedup
+
+ // We can copy whole rows
+ int rowSize = w*numBands;
+ int dataSize = rowSize*h;
+
+ DataBuffer transferBuffer =
+ Buffers.createBuffer(getTransferType(), obj, dataSize);
+ obj = Buffers.getData(transferBuffer);
+
+ int inOffset =
+ pixelStride*x +
+ scanlineStride*y +
+ data.getOffset(); // Assumes only one band is used
+
+ /* We don't add band offsets since we assume that bands have
+ offsets 0, 1, 2, ... */
+
+ // See if we can copy everything in one go
+ if (scanlineStride == rowSize)
+ {
+ // Collapse scan lines:
+ rowSize *= h;
+ // We ignore scanlineStride since it won't be of any use
+ h = 1;
+ }
+
+ int outOffset = 0;
+ Object inArray = Buffers.getData(data);
+ for (int yd = 0; yd<h; yd++)
+ {
+ System.arraycopy(inArray, inOffset, obj, outOffset, rowSize);
+ inOffset += scanlineStride;
+ outOffset += rowSize;
+ }
+ return obj;
+ }
+
+ public void setDataElements(int x, int y, int w, int h,
+ Object obj, DataBuffer data)
+ {
+ if (!tightPixelPacking)
+ {
+ super.setDataElements(x, y, w, h, obj, data);
+ return;
+ }
+
+ // using set speedup, we can copy whole rows
+ int rowSize = w*numBands;
+ int dataSize = rowSize*h;
+
+ DataBuffer transferBuffer =
+ Buffers.createBufferFromData(getTransferType(), obj, dataSize);
+
+ int[] bankOffsets = data.getOffsets();
+
+ int outOffset =
+ pixelStride*x +
+ scanlineStride*y +
+ bankOffsets[0]; // same assuptions as in get...
+
+ // See if we can copy everything in one go
+ if (scanlineStride == rowSize)
+ {
+ // Collapse scan lines:
+ rowSize *= h;
+ h = 1;
+ }
+
+ int inOffset = 0;
+ Object outArray = Buffers.getData(data);
+ for (int yd = 0; yd<h; yd++)
+ {
+ System.arraycopy(obj, inOffset, outArray, outOffset, rowSize);
+ outOffset += scanlineStride;
+ inOffset += rowSize;
+ }
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = pixelStride*x + scanlineStride*y;
+ if (iArray == null) iArray = new int[numBands];
+ for (int b=0; b<numBands; b++)
+ {
+ iArray[b] = data.getElem(bankIndices[b], offset+bandOffsets[b]);
+ }
+ return iArray;
+ }
+
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int offset = pixelStride*x + scanlineStride*y;
+ if (iArray == null) iArray = new int[numBands*w*h];
+ int outOffset = 0;
+ for (y=0; y<h; y++)
+ {
+ int lineOffset = offset;
+ for (x=0; x<w; x++)
+ {
+ for (int b=0; b<numBands; b++)
+ {
+ iArray[outOffset++] =
+ data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
+ }
+ lineOffset += pixelStride;
+ }
+ offset += scanlineStride;
+ }
+ return iArray;
+ }
+
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ return data.getElem(bankIndices[b], getOffset(x, y, b));
+ }
+
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int offset = pixelStride*x + scanlineStride*y;
+ int[] totalBandDataOffsets = new int[numBands];
+ int[] bankOffsets = data.getOffsets();
+ for (int b=0; b<numBands; b++)
+ totalBandDataOffsets[b] =
+ bandOffsets[b]+bankOffsets[bankIndices[b]] + offset;
+
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] in = (byte[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferUShort out = (DataBufferUShort) data;
+ short[] in = (short[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ case DataBuffer.TYPE_SHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] in = (short[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] in = (int[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ {
+ DataBufferFloat out = (DataBufferFloat) data;
+ float[] in = (float[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ case DataBuffer.TYPE_DOUBLE:
+ {
+ DataBufferDouble out = (DataBufferDouble) data;
+ double[] in = (double[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ default:
+ throw new UnsupportedOperationException("transfer type not " +
+ "implemented");
+ }
+ }
+
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = pixelStride*x + scanlineStride*y;
+ for (int b=0; b<numBands; b++)
+ data.setElem(bankIndices[b], offset+bandOffsets[b], iArray[b]);
+ }
+
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ data.setElem(bankIndices[b], getOffset(x, y, b), s);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ConvolveOp.java b/libjava/classpath/java/awt/image/ConvolveOp.java
new file mode 100644
index 00000000000..f841c13557f
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ConvolveOp.java
@@ -0,0 +1,337 @@
+/* ConvolveOp.java --
+ Copyright (C) 2004 Free Software Foundation -- ConvolveOp
+
+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.image;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+/**
+ * Convolution filter.
+ *
+ * ConvolveOp convolves the source image with a Kernel to generate a
+ * destination image. This involves multiplying each pixel and its neighbors
+ * with elements in the kernel to compute a new pixel.
+ *
+ * Each band in a Raster is convolved and copied to the destination Raster.
+ *
+ * For BufferedImages, convolution is applied to all components. If the
+ * source is not premultiplied, the data will be premultiplied before
+ * convolving. Premultiplication will be undone if the destination is not
+ * premultiplied. Color conversion will be applied if needed.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class ConvolveOp implements BufferedImageOp, RasterOp
+{
+ /** Edge pixels are set to 0. */
+ public static final int EDGE_ZERO_FILL = 0;
+
+ /** Edge pixels are copied from the source. */
+ public static final int EDGE_NO_OP = 1;
+
+ private Kernel kernel;
+ private int edge;
+ private RenderingHints hints;
+
+ /**
+ * Construct a ConvolveOp.
+ *
+ * The edge condition specifies that pixels outside the area that can be
+ * filtered are either set to 0 or copied from the source image.
+ *
+ * @param kernel The kernel to convolve with.
+ * @param edgeCondition Either EDGE_ZERO_FILL or EDGE_NO_OP.
+ * @param hints Rendering hints for color conversion, or null.
+ */
+ public ConvolveOp(Kernel kernel,
+ int edgeCondition,
+ RenderingHints hints)
+ {
+ this.kernel = kernel;
+ edge = edgeCondition;
+ this.hints = hints;
+ }
+
+ /**
+ * Construct a ConvolveOp.
+ *
+ * The edge condition defaults to EDGE_ZERO_FILL.
+ *
+ * @param kernel The kernel to convolve with.
+ */
+ public ConvolveOp(Kernel kernel)
+ {
+ this.kernel = kernel;
+ edge = EDGE_ZERO_FILL;
+ hints = null;
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage,
+ * java.awt.image.BufferedImage)
+ */
+ public BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ if (src == dst)
+ throw new IllegalArgumentException();
+
+ if (dst == null)
+ dst = createCompatibleDestImage(src, src.getColorModel());
+
+ // Make sure source image is premultiplied
+ BufferedImage src1 = src;
+ if (!src.isPremultiplied)
+ {
+ src1 = createCompatibleDestImage(src, src.getColorModel());
+ src.copyData(src1.getRaster());
+ src1.coerceData(true);
+ }
+
+ BufferedImage dst1 = dst;
+ if (!src.getColorModel().equals(dst.getColorModel()))
+ dst1 = createCompatibleDestImage(src, src.getColorModel());
+
+ filter(src1.getRaster(), dst1.getRaster());
+
+ if (dst1 != dst)
+ {
+ // Convert between color models.
+ // TODO Check that premultiplied alpha is handled correctly here.
+ Graphics2D gg = dst.createGraphics();
+ gg.setRenderingHints(hints);
+ gg.drawImage(dst1, 0, 0, null);
+ gg.dispose();
+ }
+
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see
+ * java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage,
+ * java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ // FIXME: set properties to those in src
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isPremultiplied, null);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /**
+ * @return The edge condition.
+ */
+ public int getEdgeCondition()
+ {
+ return edge;
+ }
+
+ /**
+ * @return The convolution kernel.
+ */
+ public Kernel getKernel()
+ {
+ return kernel;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
+ * java.awt.image.WritableRaster)
+ */
+ public WritableRaster filter(Raster src, WritableRaster dest) {
+ if (src.numBands != dest.numBands)
+ throw new ImagingOpException(null);
+ if (src == dest)
+ throw new IllegalArgumentException();
+ if (src.getWidth() < kernel.getWidth() ||
+ src.getHeight() < kernel.getHeight())
+ throw new ImagingOpException(null);
+
+ if (dest == null)
+ dest = createCompatibleDestRaster(src);
+
+ // 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);
+ }
+
+ // Handle main section
+ float[] kvals = kernel.getKernelData(null);
+
+ 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++)
+ {
+ // 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);
+ }
+ }
+
+ // 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++)
+ {
+
+ }
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
+ {
+
+ }
+
+ // 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)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /** Return corresponding destination point for source point.
+ *
+ * ConvolveOp will return the value of src unchanged.
+ * @param src The source point.
+ * @param dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D,
+ * java.awt.geom.Point2D)
+ */
+ public Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null) return (Point2D)src.clone();
+ dst.setLocation(src);
+ return dst;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/CropImageFilter.java b/libjava/classpath/java/awt/image/CropImageFilter.java
new file mode 100644
index 00000000000..490f43cd728
--- /dev/null
+++ b/libjava/classpath/java/awt/image/CropImageFilter.java
@@ -0,0 +1,180 @@
+/* CropImageFilter.java -- Java class for cropping image filter
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Rectangle;
+import java.util.Hashtable;
+
+/**
+ * Currently this filter does almost nothing and needs to be implemented.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class CropImageFilter extends ImageFilter
+{
+ int x;
+ int y;
+ int width;
+ int height;
+
+ /**
+ * Construct a new <code>CropImageFilter</code> instance.
+ *
+ * @param x the x-coordinate location of the top-left of the cropped rectangle
+ * @param y the y-coordinate location of the top-left of the cropped rectangle
+ * @param width the width of the cropped rectangle
+ * @param height the height of the cropped rectangle
+ */
+ public CropImageFilter(int x, int y, int width, int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method. This filter overrides this
+ * method in order to set the dimentions to the size of the
+ * cropped rectangle instead of the size of the image.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void setDimensions(int width, int height)
+ {
+ consumer.setDimensions(this.width, this.height);
+ }
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ * <br>
+ * FIXME - What property is set for this class?
+ *
+ * @param props the list of properties associated with this image
+ */
+ public void setProperties(Hashtable props)
+ {
+ props.put("filters", "CropImageFilter");
+ consumer.setProperties(props);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize)
+ {
+ Rectangle filterBounds = new Rectangle(this.x, this.y,
+ this.width, this.height);
+ Rectangle pixelBounds = new Rectangle(x, y, w, h);
+
+ if (filterBounds.intersects(pixelBounds))
+ {
+ Rectangle bounds = filterBounds.intersection(pixelBounds);
+
+ byte[] cropped = new byte[bounds.width * bounds.height];
+ for (int i = 0; i < bounds.height; i++)
+ {
+ int start = (bounds.y - pixelBounds.y + i) * scansize + offset;
+
+ for (int j = 0; j < bounds.width; j++)
+ cropped[i * bounds.width + j] = pixels[start + bounds.x + j];
+ }
+
+ consumer.setPixels(bounds.x, bounds.y,
+ bounds.width, bounds.height,
+ model, cropped, 0, bounds.width);
+ }
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize)
+ {
+ Rectangle filterBounds = new Rectangle(this.x, this.y,
+ this.width, this.height);
+ Rectangle pixelBounds = new Rectangle(x, y, w, h);
+
+ if (filterBounds.intersects(pixelBounds))
+ {
+ Rectangle bounds = filterBounds.intersection(pixelBounds);
+
+ int[] cropped = new int[bounds.width * bounds.height];
+ for (int i = 0; i < bounds.height; i++)
+ {
+ int start = (bounds.y - pixelBounds.y + i) * scansize + offset;
+
+ for (int j = 0; j < bounds.width; j++)
+ cropped[i * bounds.width + j] = pixels[start + bounds.x + j];
+ }
+
+ consumer.setPixels(bounds.x, bounds.y,
+ bounds.width, bounds.height,
+ model, cropped, 0, bounds.width);
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/java/awt/image/DataBuffer.java b/libjava/classpath/java/awt/image/DataBuffer.java
new file mode 100644
index 00000000000..9e4f714180a
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBuffer.java
@@ -0,0 +1,436 @@
+/* Copyright (C) 2000, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/**
+ * Class that manages arrays of data elements. A data buffer consists
+ * of one or more banks. A bank is a continuous region of data
+ * elements.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public abstract class DataBuffer
+{
+ /**
+ * A constant representing a data type that uses <code>byte</code> primitives
+ * as the storage unit.
+ */
+ public static final int TYPE_BYTE = 0;
+
+ /**
+ * A constant representing a data type that uses <code>short</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_USHORT = 1;
+
+ /**
+ * A constant representing a data type that uses <code>short</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_SHORT = 2;
+
+ /**
+ * A constant representing a data type that uses <code>int</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_INT = 3;
+
+ /**
+ * A constant representing a data type that uses <code>float</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_FLOAT = 4;
+
+ /**
+ * A constant representing a data type that uses <code>double</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_DOUBLE = 5;
+
+ /**
+ * A constant representing an undefined data type.
+ */
+ public static final int TYPE_UNDEFINED = 32;
+
+ /** The type of the data elements stored in the data buffer. */
+ protected int dataType;
+
+ /** The number of banks in this buffer. */
+ protected int banks = 1;
+
+ /** Offset into the default (0'th) bank). */
+ protected int offset; // FIXME: Is offsets[0] always mirrored in offset?
+
+ /** The size of the banks. */
+ protected int size;
+
+ /** Offset into each bank. */
+ protected int[] offsets;
+
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type and
+ * size. The <code>dataType</code> should be one of the constants
+ * {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, {@link #TYPE_USHORT},
+ * {@link #TYPE_INT}, {@link #TYPE_FLOAT} and {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ */
+ protected DataBuffer(int dataType, int size)
+ {
+ this.dataType = dataType;
+ this.size = size;
+ }
+
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ */
+ protected DataBuffer(int dataType, int size, int numBanks) {
+ this(dataType, size);
+ banks = numBanks;
+ offsets = new int[numBanks];
+ }
+
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. An offset (which applies to all banks) is
+ * also specified. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ * @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);
+
+ this.offset = offset;
+ }
+
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. An offset (which applies to all banks) is
+ * also specified. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ * @param offsets the offsets to the first element for all banks.
+ *
+ * @throws ArrayIndexOutOfBoundsException if
+ * <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();
+
+ banks = numBanks;
+ this.offsets = offsets;
+
+ offset = offsets[0];
+ }
+
+ /**
+ * Returns the size (number of bits) of the specified data type. Valid types
+ * are defined by the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ *
+ * @param dataType the data type.
+ * @return The number of bits for the specified data type.
+ * @throws IllegalArgumentException if <code>dataType < 0</code> or
+ * <code>dataType > TYPE_DOUBLE</code>.
+ */
+ public static int getDataTypeSize(int dataType) {
+ // Maybe this should be a lookup table instead.
+ switch (dataType)
+ {
+ case TYPE_BYTE:
+ return 8;
+ case TYPE_USHORT:
+ case TYPE_SHORT:
+ return 16;
+ case TYPE_INT:
+ case TYPE_FLOAT:
+ return 32;
+ case TYPE_DOUBLE:
+ return 64;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Returns the type of the data elements in the data buffer. Valid types
+ * are defined by the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ *
+ * @return The type.
+ */
+ public int getDataType()
+ {
+ return dataType;
+ }
+
+ /**
+ * Returns the size of the data buffer.
+ *
+ * @return The size.
+ */
+ public int getSize()
+ {
+ return size;
+ }
+
+ /**
+ * Returns the element offset for the first data bank.
+ *
+ * @return The element offset.
+ */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the offsets for all the data banks used by this
+ * <code>DataBuffer</code>.
+ *
+ * @return The offsets.
+ */
+ public int[] getOffsets()
+ {
+ if (offsets == null)
+ {
+ // is this necessary?
+ offsets = new int[1];
+ offsets[0] = offset;
+ }
+ return offsets;
+ }
+
+ /**
+ * Returns the number of data banks for this <code>DataBuffer</code>.
+ * @return The number of data banks.
+ */
+ public int getNumBanks()
+ {
+ return banks;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return getElem(0, i);
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public abstract int getElem(int bank, int i);
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ setElem(0, i, val);
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public abstract void setElem(int bank, int i, int val);
+
+ /**
+ * Returns an element from the first data bank, converted to a
+ * <code>float</code>. The offset (specified in the constructor) is added
+ * to <code>i</code> before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public float getElemFloat(int i)
+ {
+ return getElem(i);
+ }
+
+ /**
+ * Returns an element from a particular data bank, converted to a
+ * <code>float</code>. The offset (specified in the constructor) is
+ * added to <code>i</code> before accessing the underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public float getElemFloat(int bank, int i)
+ {
+ return getElem(bank, i);
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElemFloat(int i, float val)
+ {
+ setElem(i, (int) val);
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElemFloat(int bank, int i, float val)
+ {
+ setElem(bank, i, (int) val);
+ }
+
+ /**
+ * Returns an element from the first data bank, converted to a
+ * <code>double</code>. The offset (specified in the constructor) is added
+ * to <code>i</code> before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public double getElemDouble(int i)
+ {
+ return getElem(i);
+ }
+
+ /**
+ * Returns an element from a particular data bank, converted to a
+ * <code>double</code>. The offset (specified in the constructor) is
+ * added to <code>i</code> before accessing the underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public double getElemDouble(int bank, int i)
+ {
+ return getElem(bank, i);
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElemDouble(int i, double val)
+ {
+ setElem(i, (int) val);
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElemDouble(int bank, int i, double val)
+ {
+ setElem(bank, i, (int) val);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferByte.java b/libjava/classpath/java/awt/image/DataBufferByte.java
new file mode 100644
index 00000000000..1113ebb7843
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferByte.java
@@ -0,0 +1,245 @@
+/* Copyright (C) 2000, 2002 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.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>byte</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public final class DataBufferByte extends DataBuffer
+{
+ private byte[] data;
+ private byte[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>byte</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferByte(int size)
+ {
+ super(TYPE_BYTE, size, 1, 0);
+ bankData = new byte[1][];
+ data = new byte[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>byte</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferByte(int size, int numBanks)
+ {
+ super(TYPE_BYTE, size, numBanks);
+ bankData = new byte[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferByte(byte[] dataArray, int size)
+ {
+ super(TYPE_BYTE, size, 1, 0);
+ bankData = new byte[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferByte(byte[] dataArray, int size, int offset)
+ {
+ super(TYPE_BYTE, size, 1, offset);
+ bankData = new byte[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferByte(byte[][] dataArray, int size)
+ {
+ super(TYPE_BYTE, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferByte(byte[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_BYTE, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public byte[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public byte[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return data[i+offset] & 0xff; // get unsigned byte as int
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ // get unsigned byte as int
+ return bankData[bank][i+offsets[bank]] & 0xff;
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (byte) val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (byte) val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferDouble.java b/libjava/classpath/java/awt/image/DataBufferDouble.java
new file mode 100644
index 00000000000..a8c4b9d0558
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferDouble.java
@@ -0,0 +1,288 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>double</code> primitives
+ * to represent each of its banks.
+ *
+ * @since 1.4
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+public final class DataBufferDouble
+ extends DataBuffer
+{
+ private double[] data;
+ private double[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>double</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferDouble(int size)
+ {
+ super(TYPE_DOUBLE, size, 1, 0);
+ bankData = new double[1][];
+ data = new double[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>double</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferDouble(int size, int numBanks)
+ {
+ super(TYPE_DOUBLE, size, numBanks);
+ bankData = new double[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferDouble(double[] dataArray, int size)
+ {
+ super(TYPE_DOUBLE, size, 1, 0);
+ bankData = new double[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferDouble(double[] dataArray, int size, int offset)
+ {
+ super(TYPE_DOUBLE, size, 1, offset);
+ bankData = new double[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferDouble(double[][] dataArray, int size)
+ {
+ super(TYPE_DOUBLE, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferDouble(double[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_DOUBLE, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public double[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public double[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public double[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return (int) data[i+offset];
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ return (int) bankData[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+
+ public float getElemFloat(int i)
+ {
+ return (float) data[i+offset];
+ }
+
+ public float getElemFloat(int bank, int i)
+ {
+ return (float) bankData[bank][i+offsets[bank]];
+ }
+
+ public void setElemFloat(int i, float val)
+ {
+ data[i+offset] = val;
+ }
+
+ public void setElemFloat(int bank, int i, float val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+
+ public double getElemDouble(int i)
+ {
+ return data[i + offset];
+ }
+
+ public double getElemDouble(int bank, int i)
+ {
+ return bankData[bank][i + offsets[bank]];
+ }
+
+ public void setElemDouble(int i, double val)
+ {
+ data[i + offset] = val;
+ }
+
+ public void setElemDouble(int bank, int i, double val)
+ {
+ bankData[bank][i + offsets[bank]] = val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferFloat.java b/libjava/classpath/java/awt/image/DataBufferFloat.java
new file mode 100644
index 00000000000..9cf8784d78c
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferFloat.java
@@ -0,0 +1,286 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>float</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+public final class DataBufferFloat
+ extends DataBuffer
+{
+ private float[] data;
+ private float[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>float</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferFloat(int size)
+ {
+ super(TYPE_FLOAT, size, 1, 0);
+ bankData = new float[1][];
+ data = new float[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>float</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferFloat(int size, int numBanks)
+ {
+ super(TYPE_FLOAT, size, numBanks);
+ bankData = new float[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferFloat(float[] dataArray, int size)
+ {
+ super(TYPE_FLOAT, size, 1, 0);
+ bankData = new float[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferFloat(float[] dataArray, int size, int offset)
+ {
+ super(TYPE_FLOAT, size, 1, offset);
+ bankData = new float[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferFloat(float[][] dataArray, int size)
+ {
+ super(TYPE_FLOAT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferFloat(float[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_FLOAT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public float[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public float[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public float[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return (int) data[i+offset];
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ return (int) bankData[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+
+ public float getElemFloat(int i)
+ {
+ return data[i+offset];
+ }
+
+ public float getElemFloat(int bank, int i)
+ {
+ return bankData[bank][i+offsets[bank]];
+ }
+
+ public void setElemFloat(int i, float val)
+ {
+ data[i+offset] = val;
+ }
+
+ public void setElemFloat(int bank, int i, float val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+
+ public double getElemDouble(int i)
+ {
+ return getElemFloat(i);
+ }
+
+ public double getElemDouble(int bank, int i)
+ {
+ return getElemFloat(bank, i);
+ }
+
+ public void setElemDouble(int i, double val)
+ {
+ setElemFloat(i, (float) val);
+ }
+
+ public void setElemDouble(int bank, int i, double val)
+ {
+ setElemFloat(bank, i, (float) val);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferInt.java b/libjava/classpath/java/awt/image/DataBufferInt.java
new file mode 100644
index 00000000000..0aac9404067
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferInt.java
@@ -0,0 +1,244 @@
+/* Copyright (C) 2000, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>int</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public final class DataBufferInt extends DataBuffer
+{
+ private int[] data;
+ private int[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>int</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferInt(int size)
+ {
+ super(TYPE_INT, size, 1, 0);
+ bankData = new int[1][];
+ data = new int[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>int</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferInt(int size, int numBanks)
+ {
+ super(TYPE_INT, size, numBanks);
+ bankData = new int[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferInt(int[] dataArray, int size)
+ {
+ super(TYPE_INT, size, 1, 0);
+ bankData = new int[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferInt(int[] dataArray, int size, int offset)
+ {
+ super(TYPE_INT, size, 1, offset);
+ bankData = new int[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferInt(int[][] dataArray, int size)
+ {
+ super(TYPE_INT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferInt(int[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_INT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public int[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public int[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public int[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The <code>offset</code> is
+ * added to the specified index before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return data[i+offset];
+ }
+
+ /**
+ * Returns an element from a particular data bank. The <code>offset</code>
+ * is added to the specified index before accessing the underlying data
+ * array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ // get unsigned int as int
+ return bankData[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferShort.java b/libjava/classpath/java/awt/image/DataBufferShort.java
new file mode 100644
index 00000000000..5c67a8d3c3f
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferShort.java
@@ -0,0 +1,245 @@
+/* DataBufferShort.java --
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>short</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public final class DataBufferShort extends DataBuffer
+{
+ private short[] data;
+ private short[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferShort(int size)
+ {
+ super(TYPE_SHORT, size, 1, 0);
+ bankData = new short[1][];
+ data = new short[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferShort(int size, int numBanks)
+ {
+ super(TYPE_SHORT, size, numBanks);
+ bankData = new short[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferShort(short[] dataArray, int size)
+ {
+ super(TYPE_SHORT, size, 1, 0);
+ bankData = new short[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferShort(short[] dataArray, int size, int offset)
+ {
+ super(TYPE_SHORT, size, 1, offset);
+ bankData = new short[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferShort(short[][] dataArray, int size)
+ {
+ super(TYPE_SHORT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferShort(short[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_SHORT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public short[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public short[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public short[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return data[i+offset];
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ return bankData[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (short) val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (short) val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferUShort.java b/libjava/classpath/java/awt/image/DataBufferUShort.java
new file mode 100644
index 00000000000..981e9e9d2fd
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferUShort.java
@@ -0,0 +1,246 @@
+/* DataBufferUShort.java --
+ Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>short</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public final class DataBufferUShort extends DataBuffer
+{
+ private short[] data;
+ private short[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferUShort(int size)
+ {
+ super(TYPE_USHORT, size, 1, 0);
+ bankData = new short[1][];
+ data = new short[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferUShort(int size, int numBanks)
+ {
+ super(TYPE_USHORT, size, numBanks);
+ bankData = new short[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if dataArray is null
+ */
+ public DataBufferUShort(short[] dataArray, int size)
+ {
+ super(TYPE_USHORT, size, 1, 0);
+ if (dataArray == null)
+ throw new NullPointerException();
+ bankData = new short[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ *
+ * @throws NullPointerException if dataArray is null
+ */
+ public DataBufferUShort(short[] dataArray, int size, int offset)
+ {
+ super(TYPE_USHORT, size, 1, offset);
+ if (dataArray == null)
+ throw new NullPointerException();
+ bankData = new short[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferUShort(short[][] dataArray, int size)
+ {
+ super(TYPE_USHORT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferUShort(short[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_USHORT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public short[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public short[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public short[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return data[i+offset] & 0xffff; // get unsigned short as int
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ // get unsigned short as int
+ return bankData[bank][i+offsets[bank]] & 0xffff;
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (short) val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (short) val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DirectColorModel.java b/libjava/classpath/java/awt/image/DirectColorModel.java
new file mode 100644
index 00000000000..c98c3f8ea70
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DirectColorModel.java
@@ -0,0 +1,420 @@
+/* DirectColorModel.java --
+ Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.Point;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author C. Brian Jones (cbj@gnu.org)
+ * @author Mark Benvenuto (mcb54@columbia.edu)
+ */
+public class DirectColorModel extends PackedColorModel
+{
+ /**
+ * For the color model created with this constructor the pixels
+ * will have fully opaque alpha components with a value of 255.
+ * Each mask should describe a fully contiguous set of bits in the
+ * most likely order of alpha, red, green, blue from the most significant
+ * byte to the least significant byte.
+ *
+ * @param pixelBits the number of bits wide used for bit size of pixel values
+ * @param rmask the bits describing the red component of a pixel
+ * @param gmask the bits describing the green component of a pixel
+ * @param bmask the bits describing the blue component of a pixel
+ */
+ public DirectColorModel(int pixelBits, int rmask, int gmask, int bmask)
+ {
+ this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
+ rmask, gmask, bmask, 0,
+ false, // not alpha premultiplied
+ Buffers.smallestAppropriateTransferType(pixelBits) // find type
+ );
+ }
+
+ /**
+ * For the color model created with this constructor the pixels
+ * will have fully opaque alpha components with a value of 255.
+ * Each mask should describe a fully contiguous set of bits in the
+ * most likely order of red, green, blue from the most significant
+ * byte to the least significant byte.
+ *
+ * @param pixelBits the number of bits wide used for bit size of pixel values
+ * @param rmask the bits describing the red component of a pixel
+ * @param gmask the bits describing the green component of a pixel
+ * @param bmask the bits describing the blue component of a pixel
+ * @param amask the bits describing the alpha component of a pixel
+ */
+ public DirectColorModel(int pixelBits,
+ int rmask, int gmask, int bmask, int amask)
+ {
+ this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
+ rmask, gmask, bmask, amask,
+ false, // not alpha premultiplied
+ Buffers.smallestAppropriateTransferType(pixelBits) // find type
+ );
+ }
+
+ public DirectColorModel(ColorSpace cspace, int pixelBits,
+ int rmask, int gmask, int bmask, int amask,
+ boolean isAlphaPremultiplied,
+ int transferType)
+ {
+ super(cspace, pixelBits,
+ rmask, gmask, bmask, amask, isAlphaPremultiplied,
+ ((amask == 0) ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
+ transferType);
+ }
+
+ public final int getRedMask()
+ {
+ return getMask(0);
+ }
+
+ public final int getGreenMask()
+ {
+ return getMask(1);
+ }
+
+ public final int getBlueMask()
+ {
+ return getMask(2);
+ }
+
+ public final int getAlphaMask()
+ {
+ return hasAlpha() ? getMask(3) : 0;
+ }
+
+ /**
+ * Get the red component of the given pixel.
+ * <br>
+ */
+ public final int getRed(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 0);
+ }
+
+ /**
+ * Get the green component of the given pixel.
+ * <br>
+ */
+ public final int getGreen(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 1);
+ }
+
+ /**
+ * Get the blue component of the given pixel.
+ * <br>
+ */
+ public final int getBlue(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 2);
+ }
+
+ /**
+ * Get the alpha component of the given pixel.
+ * <br>
+ */
+ public final int getAlpha(int pixel)
+ {
+ if (!hasAlpha())
+ return 255;
+ return extractAndScaleSample(pixel, 3);
+ }
+
+ private int extractAndNormalizeSample(int pixel, int component)
+ {
+ int value = extractAndScaleSample(pixel, component);
+ if (hasAlpha() && isAlphaPremultiplied())
+ value = value*255/getAlpha(pixel);
+ return value;
+ }
+
+ private int extractAndScaleSample(int pixel, int component)
+ {
+ int field = pixel & getMask(component);
+ int to8BitShift =
+ 8 - shifts[component] - getComponentSize(component);
+ return (to8BitShift>0) ?
+ (field << to8BitShift) :
+ (field >>> (-to8BitShift));
+ }
+
+ /**
+ * Get the RGB color value of the given pixel using the default
+ * RGB color model.
+ * <br>
+ *
+ * @param pixel a pixel value
+ */
+ public final int getRGB(int pixel)
+ {
+ /* FIXME: The Sun docs show that this method is overridden, but I
+ don't see any way to improve on the superclass
+ implementation. */
+ return super.getRGB(pixel);
+ }
+
+ public int getRed(Object inData)
+ {
+ return getRed(getPixelFromArray(inData));
+ }
+
+ public int getGreen(Object inData)
+ {
+ return getGreen(getPixelFromArray(inData));
+ }
+
+ public int getBlue(Object inData)
+ {
+ return getBlue(getPixelFromArray(inData));
+ }
+
+ public int getAlpha(Object inData)
+ {
+ return getAlpha(getPixelFromArray(inData));
+ }
+
+ public int getRGB(Object inData)
+ {
+ return getRGB(getPixelFromArray(inData));
+ }
+
+ /**
+ * Converts a normalized pixel int value in the sRGB color
+ * space to an array containing a single pixel of the color space
+ * of the color model.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getRGB(Object inData)</code>.
+ *
+ * @param rgb pixel as a normalized sRGB, 0xAARRGGBB value.
+ *
+ * @param pixel to avoid needless creation of arrays, an array to
+ * use to return the pixel can be given. If null, a suitable array
+ * will be created.
+ *
+ * @return array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ *
+ * @see #getRGB(Object)
+ */
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // FIXME: handle alpha multiply
+
+ int pixelValue = 0;
+ int a = 0;
+ if (hasAlpha()) {
+ a = (rgb >>> 24) & 0xff;
+ pixelValue = valueToField(a, 3, 8);
+ }
+
+ if (hasAlpha() && isAlphaPremultiplied())
+ {
+ int r, g, b;
+ /* if r=0xff and a=0xff, then resulting
+ value will be (r*a)>>>8 == 0xfe... This seems wrong.
+ We should divide by 255 rather than shifting >>>8 after
+ multiplying.
+
+ Too bad, shifting is probably less expensive.
+ r = ((rgb >>> 16) & 0xff)*a;
+ g = ((rgb >>> 8) & 0xff)*a;
+ b = ((rgb >>> 0) & 0xff)*a; */
+ /* The r, g, b values we calculate are 16 bit. This allows
+ us to avoid discarding the lower 8 bits obtained if
+ multiplying with the alpha band. */
+
+ // using 16 bit values
+ r = ((rgb >>> 8) & 0xff00)*a/255;
+ g = ((rgb >>> 0) & 0xff00)*a/255;
+ b = ((rgb << 8) & 0xff00)*a/255;
+ pixelValue |=
+ valueToField(r, 0, 16) | // Red
+ valueToField(g, 1, 16) | // Green
+ valueToField(b, 2, 16); // Blue
+ }
+ else
+ {
+ int r, g, b;
+ // using 8 bit values
+ r = (rgb >>> 16) & 0xff;
+ g = (rgb >>> 8) & 0xff;
+ b = (rgb >>> 0) & 0xff;
+
+ pixelValue |=
+ valueToField(r, 0, 8) | // Red
+ valueToField(g, 1, 8) | // Green
+ valueToField(b, 2, 8); // Blue
+ }
+
+ /* In this color model, the whole pixel fits in the first element
+ of the array. */
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
+ buffer.setElem(0, pixelValue);
+ return Buffers.getData(buffer);
+ }
+
+ /**
+ * Converts a value to the correct field bits based on the
+ * information derived from the field masks.
+ *
+ * @param highBit the position of the most significant bit in the
+ * val parameter.
+ */
+ private int valueToField(int val, int component, int highBit)
+ {
+ int toFieldShift =
+ getComponentSize(component) + shifts[component] - highBit;
+ int ret = (toFieldShift>0) ?
+ (val << toFieldShift) :
+ (val >>> (-toFieldShift));
+ return ret & getMask(component);
+ }
+
+ /**
+ * Converts a 16 bit value to the correct field bits based on the
+ * information derived from the field masks.
+ */
+ private int value16ToField(int val, int component)
+ {
+ int toFieldShift = getComponentSize(component) + shifts[component] - 16;
+ return (toFieldShift>0) ?
+ (val << toFieldShift) :
+ (val >>> (-toFieldShift));
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from a
+ * pixel value. I.e. decompose the pixel, but not perform any
+ * color conversion.
+ */
+ public final int[] getComponents(int pixel, int[] components, int offset)
+ {
+ int numComponents = getNumComponents();
+ if (components == null) components = new int[offset + numComponents];
+
+ for (int b=0; b<numComponents; b++)
+ components[offset++] = (pixel&getMask(b)) >>> shifts[b];
+
+ return components;
+ }
+
+ public final int[] getComponents(Object pixel, int[] components,
+ int offset)
+ {
+ return getComponents(getPixelFromArray(pixel), components, offset);
+ }
+
+ public final WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ SampleModel sm = createCompatibleSampleModel(w, h);
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(sm, origin);
+ }
+
+ public int getDataElement(int[] components, int offset)
+ {
+ int numComponents = getNumComponents();
+ int pixelValue = 0;
+
+ for (int c=0; c<numComponents; c++)
+ pixelValue |= (components[offset++] << shifts[c]) & getMask(c);
+
+ return pixelValue;
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ /* In this color model, the whole pixel fits in the first element
+ of the array. */
+ int pixelValue = getDataElement(components, offset);
+
+ DataBuffer buffer = Buffers.createBuffer(transferType, obj, 1);
+ buffer.setElem(0, pixelValue);
+ return Buffers.getData(buffer);
+ }
+
+ public final ColorModel coerceData (WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied)
+ return this;
+
+ /* TODO: provide better implementation based on the
+ assumptions we can make due to the specific type of the
+ color model. */
+ super.coerceData(raster, isAlphaPremultiplied);
+
+ return new ComponentColorModel(cspace, bits, hasAlpha(),
+ isAlphaPremultiplied, // argument
+ transparency, transferType);
+ }
+
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ /* FIXME: the Sun docs say this method is overridden here,
+ but I don't see any way to improve upon the implementation
+ in ColorModel. */
+ return super.isCompatibleRaster(raster);
+ }
+
+ String stringParam()
+ {
+ return super.stringParam() +
+ ", redMask=" + Integer.toHexString(getRedMask()) +
+ ", greenMask=" + Integer.toHexString(getGreenMask()) +
+ ", blueMask=" + Integer.toHexString(getBlueMask()) +
+ ", alphaMask=" + Integer.toHexString(getAlphaMask());
+ }
+
+ public String toString()
+ {
+ /* FIXME: Again, docs say override, but how do we improve upon the
+ superclass implementation? */
+ return super.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/FilteredImageSource.java b/libjava/classpath/java/awt/image/FilteredImageSource.java
new file mode 100644
index 00000000000..8893e86a625
--- /dev/null
+++ b/libjava/classpath/java/awt/image/FilteredImageSource.java
@@ -0,0 +1,125 @@
+/* FilteredImageSource.java -- Java class for providing image data
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ *
+ * @see ImageConsumer
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class FilteredImageSource implements ImageProducer
+{
+ ImageProducer ip;
+ ImageFilter filter;
+ Hashtable consumers = new Hashtable();
+
+ /**
+ * The given filter is applied to the given image producer
+ * to create a new image producer.
+ */
+ public FilteredImageSource(ImageProducer ip, ImageFilter filter) {
+ this.ip = ip;
+ this.filter = filter;
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code>.
+ */
+ public synchronized void addConsumer(ImageConsumer ic) {
+ if (consumers.containsKey(ic))
+ return;
+
+ ImageFilter f = filter.getFilterInstance(ic);
+ consumers.put(ic, f);
+ ip.addConsumer(f);
+ }
+
+ /**
+ * Used to determine if the given <code>ImageConsumer</code> is
+ * already registered with this <code>ImageProducer</code>.
+ */
+ public synchronized boolean isConsumer(ImageConsumer ic) {
+ ImageFilter f = (ImageFilter)consumers.get(ic);
+ if (f != null)
+ return ip.isConsumer(f);
+ return false;
+ }
+
+ /**
+ * Used to remove an <code>ImageConsumer</code> from the list of
+ * registered consumers for this <code>ImageProducer</code>.
+ */
+ public synchronized void removeConsumer(ImageConsumer ic) {
+ ImageFilter f = (ImageFilter)consumers.remove(ic);
+ if (f != null)
+ ip.removeConsumer(f);
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then immediately start
+ * reconstruction of the image data to be delivered to all
+ * registered consumers.
+ */
+ public void startProduction(ImageConsumer ic) {
+ ImageFilter f;
+ if (!(consumers.containsKey(ic))) {
+ f = filter.getFilterInstance(ic);
+ consumers.put(ic, f);
+ ip.addConsumer(f);
+ } else {
+ f = (ImageFilter)consumers.get( ic );
+ }
+ ip.startProduction(f);
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then request that this producer
+ * resend the image data in the order top-down, left-right.
+ */
+ public void requestTopDownLeftRightResend(ImageConsumer ic) {
+ ImageFilter f = (ImageFilter)consumers.get(ic);
+ ip.requestTopDownLeftRightResend(f);
+ }
+}
+
diff --git a/libjava/classpath/java/awt/image/ImageConsumer.java b/libjava/classpath/java/awt/image/ImageConsumer.java
new file mode 100644
index 00000000000..e1834c3978f
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImageConsumer.java
@@ -0,0 +1,216 @@
+/* ImageConsumer.java -- Java interface for image consumption
+ Copyright (C) 1999, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * An object implementing the <code>ImageProducer</code> interface can
+ * use objects implementing this interface to deliver the image data.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public interface ImageConsumer
+{
+ /**
+ * The pixel order may be random. This should be
+ * the default assumption of the <code>ImageConsumer</code>.
+ *
+ * @see #setHints
+ */
+ int RANDOMPIXELORDER = 1;
+
+ /**
+ * The pixel order is top-down, left-right.
+ *
+ * @see #setHints
+ */
+ int TOPDOWNLEFTRIGHT = 2;
+
+ /**
+ * The pixel order is in multiples of complete scanlines.
+ *
+ * @see #setHints
+ */
+ int COMPLETESCANLINES = 4;
+
+ /**
+ * The pixels will be delivered in a single pass. There is at
+ * most one call to <code>setPixels</code> for any single pixel.
+ *
+ * @see #setHints
+ * @see #setPixels
+ */
+ int SINGLEPASS = 8;
+
+ /**
+ * The pixels will be delivered with multiple calls to
+ * <code>setPixels</code>. The image contains a single frame
+ * which ends when <code>imageComplete</code> is called with the
+ * <code>STATICIMAGEDONE</code> flag. If the image is constantly
+ * changing such as with video then the end of each frame is
+ * marked by a similar call to <code>imageComplete</code> with the
+ * <code>SINGLEFRAMEDONE</code> flag.
+ *
+ * @see #setHints
+ * @see #imageComplete
+ */
+ int SINGLEFRAME = 16;
+
+ /**
+ * Indicates an error occurred while producing an image.
+ *
+ * @see #imageComplete
+ */
+ int IMAGEERROR = 1;
+
+ /**
+ * A single frame is complete but more will follow.
+ *
+ * @see #imageComplete
+ */
+ int SINGLEFRAMEDONE = 2;
+
+ /**
+ * The image is complete and no more pixels or frames will follow.
+ *
+ * @see #imageComplete
+ */
+ int STATICIMAGEDONE = 3;
+
+ /**
+ * Production of the image has been aborted.
+ *
+ * @see #imageComplete
+ */
+ int IMAGEABORTED = 4;
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ void setDimensions(int width, int height);
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ *
+ * @param props the list of properties associated with this image
+ */
+ void setProperties(Hashtable props);
+
+ /**
+ * This <code>ColorModel</code> should indicate the model used by
+ * the majority of calls to <code>setPixels</code>. Each call to
+ * <code>setPixels</code> could however indicate a different
+ * <code>ColorModel</code>.
+ *
+ * @param model the color model to be used most often by setPixels
+ * @see ColorModel
+ */
+ void setColorModel(ColorModel model);
+
+ /**
+ * The <code>ImageProducer</code> should call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
+ *
+ * @param flags a bit mask of hints
+ */
+ void setHints(int flags);
+
+ /**
+ * Deliver a subset of an ImageProducer's pixels to this ImageConsumer.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the block of
+ * pixels being delivered to this ImageConsumer. They are
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel block's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize);
+
+ /**
+ * Deliver a subset of an ImageProducer's pixels to this ImageConsumer.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize);
+
+ /**
+ * The <code>ImageProducer</code> calls this method to indicate a
+ * single frame or the entire image is complete. The method is
+ * also used to indicate an error in loading or producing the
+ * image.
+ *
+ * @param status the status of image production, represented by a
+ * bitwise OR of ImageConsumer flags
+ */
+ void imageComplete(int status);
+}
diff --git a/libjava/classpath/java/awt/image/ImageFilter.java b/libjava/classpath/java/awt/image/ImageFilter.java
new file mode 100644
index 00000000000..9940a2b1b91
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImageFilter.java
@@ -0,0 +1,221 @@
+/* ImageFilter.java -- Java class for filtering images
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * The <code>ImageFilter</code> class is a base class which can be
+ * extended to provide different types of filters for an image. By
+ * default this class does nothing to an image passing through it.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class ImageFilter implements ImageConsumer, Cloneable
+{
+ /**
+ * The consumer this filter is filtering an image data stream for.
+ * It is initialized in the method <code>getFilterInstance</code>.
+ */
+ protected ImageConsumer consumer = null;
+
+ /**
+ * The <code>ImageConsumer</code> can use this method to request
+ * the pixels be delivered in top-down, left-right order.
+ * <br>
+ * The filter can respond in three different ways.
+ * <ul>
+ * <li>The default behavior is to forward the request to the
+ * <code>ImageProducer</code>
+ * using the method <code>requestTopDownLeftRightResend</code>
+ * and using the filter as the consumer.</li>
+ * <li>The filter has the pixels and can retransmit them in the
+ * top-down, left-right order.</li>
+ * <li>The filter can do nothing when this method is called.</li>
+ * </ul>
+ */
+ public void resendTopDownLeftRight(ImageProducer ip)
+ {
+ ip.requestTopDownLeftRightResend(this);
+ }
+
+ /**
+ * By default, returns a shallow copy of the object created by
+ * <code>Object.clone()</code>
+ *
+ * @see java.lang.Object#clone ()
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // This should never happen as this class implements the
+ // Cloneable interface.
+ throw new InternalError ();
+ }
+ }
+
+ /**
+ * This is the only method which can set the
+ * <code>ImageConsumer</code> for this filter. By default a clone
+ * of this filter with the appropriate consumer set is returned.
+ *
+ * @see #clone ()
+ */
+ public ImageFilter getFilterInstance(ImageConsumer ic)
+ {
+ if ( ic == null )
+ throw new IllegalArgumentException("null argument for ImageFilter.getFilterInstance(ImageConsumer)");
+
+ consumer = ic;
+ ImageFilter f = (ImageFilter)clone();
+ consumer = null;
+ return f;
+ }
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method. A filter can override this
+ * method to intercept these calls from the producer in order to
+ * change either the width or the height before in turn calling
+ * the consumer's <code>setDimensions</code> method.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void setDimensions(int width, int height)
+ {
+ consumer.setDimensions(width, height);
+ }
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ *
+ * @param props the list of properties associated with this image
+ */
+ public void setProperties(Hashtable props)
+ {
+ props.put("filters", "ImageFilter");
+ consumer.setProperties(props);
+ }
+
+ /**
+ * Override this method to process calls to this method from the
+ * <code>ImageProducer</code>. By default the <code>setColorModel</code>
+ * method of the consumer is called with the specified <code>model</code>.
+ *
+ * @param model the color model to be used most often by setPixels
+ * @see ColorModel */
+ public void setColorModel(ColorModel model)
+ {
+ consumer.setColorModel(model);
+ }
+
+ /**
+ * The <code>ImageProducer</code> should call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the
+ * <code>ImageConsumer</code> interface.
+ *
+ * @param flags a bit mask of hints
+ * @see ImageConsumer
+ */
+ public void setHints(int flags)
+ {
+ consumer.setHints(flags);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize)
+ {
+ consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize)
+ {
+ consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
+ }
+
+ /**
+ * The <code>ImageProducer</code> calls this method to indicate a
+ * single frame or the entire image is complete. The method is
+ * also used to indicate an error in loading or producing the
+ * image.
+ */
+ public void imageComplete(int status)
+ {
+ consumer.imageComplete(status);
+ }
+}
+
diff --git a/libjava/classpath/java/awt/image/ImageObserver.java b/libjava/classpath/java/awt/image/ImageObserver.java
new file mode 100644
index 00000000000..36dd013f4e9
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImageObserver.java
@@ -0,0 +1,129 @@
+/* ImageObserver.java -- Java interface for asynchronous updates to an image
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Image;
+
+/**
+ * An object implementing the <code>ImageObserver</code> interface can
+ * receive updates on image construction from an
+ * <code>ImageProducer</code> asynchronously.
+ *
+ * @see ImageProducer
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public interface ImageObserver
+{
+ /**
+ * The width of the image has been provided as the
+ * <code>width</code> argument to <code>imageUpdate</code>.
+ *
+ * @see #imageUpdate
+ */
+ int WIDTH = 1;
+
+ /**
+ * The height of the image has been provided as the
+ * <code>height</code> argument to <code>imageUpdate</code>.
+ *
+ * @see #imageUpdate
+ */
+ int HEIGHT = 2;
+
+ /**
+ * The properties of the image have been provided.
+ *
+ * @see #imageUpdate
+ * @see java.awt.Image#getProperty (java.lang.String, java.awt.image.ImageObserver)
+ */
+ int PROPERTIES = 4;
+
+ /**
+ * More pixels are now available for drawing a scaled variation of
+ * the image.
+ *
+ * @see #imageUpdate
+ */
+ int SOMEBITS = 8;
+
+ /**
+ * All the pixels needed to draw a complete frame of a multi-frame
+ * image are available.
+ *
+ * @see #imageUpdate
+ */
+ int FRAMEBITS = 16;
+
+ /**
+ * An image with a single frame, a static image, is complete.
+ *
+ * @see #imageUpdate
+ */
+ int ALLBITS = 32;
+
+ /**
+ * An error was encountered while producing the image.
+ *
+ * @see #imageUpdate
+ */
+ int ERROR = 64;
+
+ /**
+ * Production of the image was aborted.
+ *
+ * @see #imageUpdate
+ */
+ int ABORT = 128;
+
+ /**
+ * This is a callback method for an asynchronous image producer to
+ * provide updates on the production of the image as it happens.
+ *
+ * @param image the image the update refers to
+ * @param flags a bit mask indicating what is provided with this update
+ * @param x the x coordinate of the image
+ * @param y the y coordinate of the image
+ * @param width the width of the image
+ * @param height the height of the image
+ *
+ * @see java.awt.Image
+ */
+ boolean imageUpdate(Image image, int flags, int x,
+ int y, int width, int height);
+}
diff --git a/libjava/classpath/java/awt/image/ImageProducer.java b/libjava/classpath/java/awt/image/ImageProducer.java
new file mode 100644
index 00000000000..49846685a3e
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImageProducer.java
@@ -0,0 +1,85 @@
+/* ImageProducer.java -- Java interface for image production
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * An object implementing the <code>ImageProducer</code> interface can
+ * produce data for images. Each image has a corresponding
+ * <code>ImageProducer</code> which is needed for things such as
+ * resizing the image.
+ *
+ * @see ImageConsumer
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public interface ImageProducer
+{
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code>.
+ */
+ void addConsumer(ImageConsumer ic);
+
+ /**
+ * Used to determine if the given <code>ImageConsumer</code> is
+ * already registered with this <code>ImageProducer</code>.
+ */
+ boolean isConsumer(ImageConsumer ic);
+
+ /**
+ * Used to remove an <code>ImageConsumer</code> from the list of
+ * registered consumers for this <code>ImageProducer</code>.
+ */
+ void removeConsumer(ImageConsumer ic);
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then immediately start
+ * reconstruction of the image data to be delivered to all
+ * registered consumers.
+ */
+ void startProduction(ImageConsumer ic);
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then request that this producer
+ * resend the image data in the order top-down, left-right.
+ */
+ void requestTopDownLeftRightResend(ImageConsumer ic);
+}
+
diff --git a/libjava/classpath/java/awt/image/ImagingOpException.java b/libjava/classpath/java/awt/image/ImagingOpException.java
new file mode 100644
index 00000000000..ca40e9ed365
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImagingOpException.java
@@ -0,0 +1,66 @@
+/* ImagingOpException.java -- indicates an imaging filter failure
+ Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * This exception is thrown when <code>BufferedImageOp</code> or
+ * <code>RasterOp</code> filters cannot process an image.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see BufferedImageOp
+ * @see RasterOp
+ * @status updated to 1.4
+ */
+public class ImagingOpException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 8026288481846276658L;
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public ImagingOpException(String message)
+ {
+ super(message);
+ }
+} // class ImagingOpException
diff --git a/libjava/classpath/java/awt/image/IndexColorModel.java b/libjava/classpath/java/awt/image/IndexColorModel.java
new file mode 100644
index 00000000000..299b4dc0d86
--- /dev/null
+++ b/libjava/classpath/java/awt/image/IndexColorModel.java
@@ -0,0 +1,697 @@
+/* IndexColorModel.java -- Java class for interpreting Pixel objects
+ Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.color.ColorSpace;
+import java.math.BigInteger;
+
+/**
+ * Color model similar to pseudo visual in X11.
+ * <br><br>
+ * This color model maps linear pixel values to actual RGB and alpha colors.
+ * Thus, pixel values are indexes into the color map. Each color component is
+ * an 8-bit unsigned value.
+ * <br><br>
+ * The <code>IndexColorModel</code> supports a map of valid pixels, allowing
+ * the representation of holes in the the color map. The valid map is
+ * represented as a {@link BigInteger} where each bit indicates the validity
+ * of the map entry with the same index.
+ * <br><br>
+ * Colors can have alpha components for transparency support. If alpha
+ * component values aren't given, color values are opaque. The model also
+ * supports a reserved pixel value to represent completely transparent colors,
+ * no matter what the actual color component values are.
+ * <br><br>
+ * <code>IndexColorModel</code> supports anywhere from 1 to 16 bit index
+ * values. The allowed transfer types are {@link DataBuffer#TYPE_BYTE} and
+ * {@link DataBuffer#TYPE_USHORT}.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class IndexColorModel extends ColorModel
+{
+ private int map_size;
+ private boolean opaque; // no alpha, but doesn't account for trans
+ private int trans = -1;
+ private int[] rgb;
+ private BigInteger validBits = BigInteger.ZERO;
+
+ /**
+ * Creates a new indexed color model for <code>size</code> color elements
+ * with no alpha component. Each array must contain at least
+ * <code>size</code> elements. For each array, the i-th color is described
+ * by reds[i], greens[i] and blues[i].
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors.
+ * @param size the number of colors in the color map.
+ * @param reds the red component of all colors.
+ * @param greens the green component of all colors.
+ * @param blues the blue component of all colors.
+ *
+ * @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
+ * <code>bits</code> &gt; 16.
+ * @throws NullPointerException if any of the arrays is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
+ * than the length of the component arrays.
+ */
+ public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
+ byte[] blues)
+ {
+ this(bits, size, reds, greens, blues, (byte[]) null);
+ }
+
+ /**
+ * Creates a new indexed color model for <code>size</code> color elements.
+ * Each array must contain at least <code>size</code> elements. For each
+ * array, the i-th color is described by reds[i], greens[i] and blues[i].
+ * All the colors are opaque except for the transparent color.
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors
+ * @param size the number of colors in the color map
+ * @param reds the red component of all colors
+ * @param greens the green component of all colors
+ * @param blues the blue component of all colors
+ * @param trans the index of the transparent color (use -1 for no
+ * transparent color).
+ *
+ * @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
+ * <code>bits</code> &gt; 16.
+ * @throws NullPointerException if any of the arrays is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
+ * than the length of the component arrays.
+ */
+ public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
+ byte[] blues, int trans)
+ {
+ super(bits, nArray(8, (0 <= trans && trans < size) ? 4 : 3),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ (0 <= trans && trans < size), // hasAlpha
+ false, OPAQUE,
+ Buffers.smallestAppropriateTransferType(bits));
+ if (bits < 1)
+ throw new IllegalArgumentException("bits < 1");
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ if (0 <= trans && trans < size) {
+ this.trans = trans;
+ transparency = BITMASK;
+ }
+ rgb = new int[size];
+ for (int i = 0; i < size; i++)
+ {
+ rgb[i] = (0xff000000
+ | ((reds[i] & 0xff) << 16)
+ | ((greens[i] & 0xff) << 8)
+ | (blues[i] & 0xff));
+ }
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Creates a new indexed color model for <code>size</code> color elements
+ * including alpha. Each array must contain at least <code>size</code>
+ * elements. For each array, the i-th color is described
+ * by reds[i], greens[i], blues[i] and alphas[i].
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors.
+ * @param size the number of colors in the color map.
+ * @param reds the red component of all colors.
+ * @param greens the green component of all colors.
+ * @param blues the blue component of all colors.
+ * @param alphas the alpha component of all colors (<code>null</code>
+ * permitted).
+ *
+ * @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
+ * <code>bits</code> &gt; 16.
+ * @throws NullPointerException if <code>reds</code>, <code>greens</code> or
+ * <code>blues</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
+ * than the length of the component arrays.
+ */
+ public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
+ byte[] blues, byte[] alphas)
+ {
+ super(bits, nArray(8, (alphas == null ? 3 : 4)),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ (alphas != null), false, TRANSLUCENT,
+ Buffers.smallestAppropriateTransferType(bits));
+ if (bits < 1)
+ throw new IllegalArgumentException("bits < 1");
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = (alphas == null);
+
+ rgb = new int[size];
+ if (alphas == null)
+ {
+ for (int i = 0; i < size; i++)
+ {
+ rgb[i] = (0xff000000
+ | ((reds[i] & 0xff) << 16)
+ | ((greens[i] & 0xff) << 8)
+ | (blues[i] & 0xff));
+ }
+ transparency = OPAQUE;
+ }
+ else
+ {
+ byte alphaZero = (byte) 0x00;
+ byte alphaOne = (byte) 0xFF;
+ for (int i = 0; i < size; i++)
+ {
+ alphaZero = (byte) (alphaZero | alphas[i]);
+ alphaOne = (byte) (alphaOne & alphas[i]);
+ rgb[i] = ((alphas[i] & 0xff) << 24
+ | ((reds[i] & 0xff) << 16)
+ | ((greens[i] & 0xff) << 8)
+ | (blues[i] & 0xff));
+ }
+ if ((alphaZero == (byte) 0x00) || (alphaOne == (byte) 0xFF))
+ transparency = BITMASK;
+ else
+ transparency = TRANSLUCENT;
+ }
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Creates a new indexed color model using the color components in
+ * <code>cmap</code>. If <code>hasAlpha</code> is <code>true</code> then
+ * <code>cmap</code> contains an alpha component after each of the red, green
+ * and blue components.
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors
+ * @param size the number of colors in the color map
+ * @param cmap packed color components
+ * @param start the offset of the first color component in <code>cmap</code>
+ * @param hasAlpha <code>cmap</code> has alpha values
+ * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
+ * &lt; 1.
+ * @throws NullPointerException if <code>cmap</code> is <code>null</code>.
+ */
+ public IndexColorModel(int bits, int size, byte[] cmap, int start,
+ boolean hasAlpha)
+ {
+ this(bits, size, cmap, start, hasAlpha, -1);
+ }
+
+ /**
+ * Construct an IndexColorModel from an array of red, green, blue, and
+ * optional alpha components. The component values are interleaved as RGB(A).
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors
+ * @param size the number of colors in the color map
+ * @param cmap interleaved color components
+ * @param start the offset of the first color component in <code>cmap</code>
+ * @param hasAlpha <code>cmap</code> has alpha values
+ * @param trans the index of the transparent color
+ * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
+ * &lt; 1.
+ * @throws NullPointerException if <code>cmap</code> is <code>null</code>.
+ */
+ public IndexColorModel(int bits, int size, byte[] cmap, int start,
+ boolean hasAlpha, int trans)
+ {
+ super(bits, nArray(8, hasAlpha || (0 <= trans && trans < size) ? 4 : 3),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ hasAlpha || (0 <= trans && trans < size), false, OPAQUE,
+ Buffers.smallestAppropriateTransferType(bits));
+ if (bits < 1)
+ throw new IllegalArgumentException("bits < 1");
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = !hasAlpha;
+ if (0 <= trans && trans < size)
+ this.trans = trans;
+
+ rgb = new int[size];
+ if (hasAlpha)
+ {
+ int alpha;
+ int alphaZero = 0x00; // use to detect all zeros
+ int alphaOne = 0xff; // use to detect all ones
+ for (int i = 0; i < size; i++) {
+ alpha = cmap[4 * i + 3 + start] & 0xff;
+ alphaZero = alphaZero | alpha;
+ alphaOne = alphaOne & alpha;
+ rgb[i] =
+ ( alpha << 24
+ // red
+ | ((cmap[4 * i + start] & 0xff) << 16)
+ // green
+ | ((cmap[4 * i + 1 + start] & 0xff) << 8)
+ // blue
+ | (cmap[4 * i + 2 + start] & 0xff));
+ }
+ if (alphaZero == 0)
+ transparency = BITMASK;
+ else if (alphaOne == 255)
+ transparency = (trans != -1 ? BITMASK : OPAQUE);
+ else
+ transparency = TRANSLUCENT;
+ }
+ else
+ {
+ for (int i = 0; i < size; i++)
+ rgb[i] = (0xff000000
+ // red
+ | ((cmap[3 * i + start] & 0xff) << 16)
+ // green
+ | ((cmap[3 * i + 1 + start] & 0xff) << 8)
+ // blue
+ | (cmap[3 * i + 2 + start] & 0xff));
+ if (trans != -1)
+ transparency = BITMASK;
+ }
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Construct an IndexColorModel from an array of <code>size</code> packed
+ * colors. Each int element contains 8-bit red, green, blue, and optional
+ * alpha values packed in order. If hasAlpha is false, then all the colors
+ * are opaque except for the transparent color.
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors
+ * @param size the number of colors in the color map
+ * @param cmap packed color components
+ * @param start the offset of the first color component in <code>cmap</code>
+ * @param hasAlpha <code>cmap</code> has alpha values
+ * @param trans the index of the transparent color
+ * @param transferType {@link DataBuffer#TYPE_BYTE} or
+ {@link DataBuffer#TYPE_USHORT}.
+ * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
+ * &lt; 1.
+ * @throws IllegalArgumentException if <code>transferType</code> is something
+ * other than {@link DataBuffer#TYPE_BYTE} or
+ * {@link DataBuffer#TYPE_USHORT}.
+ */
+ public IndexColorModel(int bits, int size, int[] cmap, int start,
+ boolean hasAlpha, int trans, int transferType)
+ {
+ super(bits,
+ nArray(8, 4), // bits for each channel
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT, transferType);
+ if (transferType != DataBuffer.TYPE_BYTE
+ && transferType != DataBuffer.TYPE_USHORT)
+ throw new IllegalArgumentException();
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = !hasAlpha;
+ if (0 <= trans && trans < size)
+ this.trans = trans;
+
+ rgb = new int[size];
+ if (!hasAlpha)
+ for (int i = 0; i < size; i++)
+ rgb[i] = cmap[i + start] | 0xff000000;
+ else
+ System.arraycopy(cmap, start, rgb, 0, size);
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Construct an IndexColorModel using a colormap with holes.
+ * <br><br>
+ * The IndexColorModel is built from the array of ints defining the
+ * colormap. Each element contains red, green, blue, and alpha
+ * components. The ColorSpace is sRGB. The transparency value is
+ * automatically determined.
+ * <br><br>
+ * This constructor permits indicating which colormap entries are valid,
+ * using the validBits argument. Each entry in cmap is valid if the
+ * corresponding bit in validBits is set.
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors.
+ * @param size the number of colors in the color map.
+ * @param cmap packed color components.
+ * @param start the offset of the first color component in <code>cmap</code>.
+ * @param transferType {@link DataBuffer#TYPE_BYTE} or
+ * {@link DataBuffer#TYPE_USHORT}.
+ * @param validBits a map of the valid entries in <code>cmap</code>.
+ * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
+ * &lt; 1.
+ * @throws IllegalArgumentException if transferType is something other than
+ * {@link DataBuffer#TYPE_BYTE} or {@link DataBuffer#TYPE_USHORT}.
+ */
+ public IndexColorModel(int bits, int size, int[] cmap, int start,
+ int transferType, BigInteger validBits)
+ {
+ super(bits, // total bits, sRGB, four channels
+ nArray(8, 4), // bits for each channel
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT, transferType);
+ if (transferType != DataBuffer.TYPE_BYTE
+ && transferType != DataBuffer.TYPE_USHORT)
+ throw new IllegalArgumentException();
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = false;
+ this.trans = -1;
+ this.validBits = validBits;
+
+ rgb = new int[size];
+ if (!hasAlpha)
+ for (int i = 0; i < size; i++)
+ rgb[i] = cmap[i + start] | 0xff000000;
+ else
+ System.arraycopy(cmap, start, rgb, 0, size);
+ }
+
+ /**
+ * Returns the size of the color lookup table.
+ *
+ * @return The size of the color lookup table.
+ */
+ public final int getMapSize()
+ {
+ return map_size;
+ }
+
+ /**
+ * Get the index of the transparent color in this color model.
+ *
+ * @return The index of the color that is considered transparent, or -1 if
+ * there is no transparent color.
+ */
+ public final int getTransparentPixel()
+ {
+ return trans;
+ }
+
+ /**
+ * Fills the supplied array with the red component of each color in the
+ * lookup table.
+ *
+ * @param r an array that is at least as large as {@link #getMapSize()}.
+ * @throws NullPointerException if <code>r</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>r</code> has less
+ * than {@link #getMapSize()} elements.
+ */
+ public final void getReds(byte[] r)
+ {
+ int i;
+ for (i = 0; i < map_size; i++)
+ r[i] = (byte) ((0x00FF0000 & rgb[i]) >> 16);
+ }
+
+ /**
+ * Fills the supplied array with the green component of each color in the
+ * lookup table.
+ *
+ * @param g an array that is at least as large as {@link #getMapSize()}.
+ * @throws NullPointerException if <code>g</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>g</code> has less
+ * than {@link #getMapSize()} elements.
+ */
+ public final void getGreens(byte[] g)
+ {
+ int i;
+ for (i = 0; i < map_size; i++)
+ g[i] = (byte) ((0x0000FF00 & rgb[i]) >> 8);
+ }
+
+ /**
+ * Fills the supplied array with the blue component of each color in the
+ * lookup table.
+ *
+ * @param b an array that is at least as large as {@link #getMapSize()}.
+ * @throws NullPointerException if <code>b</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>b</code> has less
+ * than {@link #getMapSize()} elements.
+ */
+ public final void getBlues(byte[] b)
+ {
+ int i;
+ for (i = 0; i < map_size; i++)
+ b[i] = (byte) (0x000000FF & rgb[i]);
+ }
+
+ /**
+ * Fills the supplied array with the alpha component of each color in the
+ * lookup table. If the model has a transparent pixel specified, the alpha
+ * for that pixel will be 0.
+ *
+ * @param a an array that is at least as large as {@link #getMapSize()}.
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>a</code> has less
+ * than {@link #getMapSize()} elements.
+ */
+ public final void getAlphas(byte[] a)
+ {
+ int i;
+ for (i = 0; i < map_size; i++)
+ if (i == trans)
+ a[i] = (byte) 0;
+ else
+ a[i] = (byte) ((0xFF000000 & rgb[i]) >> 24);
+ }
+
+ /**
+ * Returns the red component of the color in the lookup table for the
+ * given pixel value.
+ *
+ * @param pixel the pixel lookup value.
+ *
+ * @return The red component of the color in the lookup table.
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getRed(int pixel)
+ {
+ if (pixel < map_size)
+ return (0x00FF0000 & rgb[pixel]) >> 16;
+
+ return 0;
+ }
+
+ /**
+ * Returns the green component of the color in the lookup table for the
+ * given pixel value.
+ *
+ * @param pixel the pixel lookup value.
+ *
+ * @return The green component of the color in the lookup table.
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getGreen(int pixel)
+ {
+ if (pixel < map_size)
+ return (0x0000FF00 & rgb[pixel]) >> 8;
+
+ return 0;
+ }
+
+ /**
+ * Returns the blue component of the color in the lookup table for the
+ * given pixel value.
+ *
+ * @param pixel the pixel lookup value.
+ *
+ * @return The blue component of the color in the lookup table.
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getBlue(int pixel)
+ {
+ if (pixel < map_size)
+ return 0x000000FF & rgb[pixel];
+
+ return 0;
+ }
+
+ /**
+ * Returns the alpha component of the color in the lookup table for the
+ * given pixel value. If no alpha channel was specified when the color model
+ * was created, then 255 is returned for all pixels except the transparent
+ * pixel (if one is defined - see {@link #getTransparentPixel()}) which
+ * returns an alpha of 0.
+ *
+ * @param pixel the pixel lookup value.
+ *
+ * @return The alpha component of the color in the lookup table (in the
+ * range 0 to 255).
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getAlpha(int pixel)
+ {
+ if (opaque && pixel != trans)
+ return 255;
+ if ((pixel == trans && trans != -1) || pixel >= map_size)
+ return 0;
+
+ return (0xFF000000 & rgb[pixel]) >> 24;
+ }
+
+ /**
+ * Get the RGB color value of the given pixel using the default
+ * RGB color model.
+ *
+ * @param pixel the pixel lookup value.
+ * @return The RGB color value.
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getRGB(int pixel)
+ {
+ if (pixel >= 0 && pixel < map_size)
+ return rgb[pixel];
+
+ return 0;
+ }
+
+ /**
+ * Get the RGB color values of all pixels in the map using the default
+ * RGB color model.
+ *
+ * @param rgb The destination array.
+ */
+ public final void getRGBs(int[] rgb)
+ {
+ System.arraycopy(this.rgb, 0, rgb, 0, map_size);
+ }
+
+ /**
+ * Return <code>true</code> if the lookup table contains valid data for
+ * <code>pixel</code>, and <code>false</code> otherwise.
+ *
+ * @param pixel the pixel value used to index the color lookup table.
+ * @return <code>true</code> if <code>pixel</code> is valid,
+ * <code>false</code> otherwise.
+ */
+ public boolean isValid(int pixel)
+ {
+ if (pixel >= 0)
+ return validBits.testBit(pixel);
+ return false;
+ }
+
+ /**
+ * Return <code>true</code> if all pixels are valid, <code>false</code>
+ * otherwise.
+ *
+ * @return <code>true</code> if all pixels are valid, <code>false</code>
+ * otherwise.
+ */
+ public boolean isValid()
+ {
+ // Generate a bigint with 1's for every pixel
+ BigInteger allbits = new BigInteger("0");
+ allbits = allbits.setBit(map_size);
+ allbits = allbits.subtract(new BigInteger("1"));
+ return allbits.equals(validBits);
+ }
+
+ /**
+ * Returns a binary value ({@link BigInteger}) where each bit represents an
+ * entry in the color lookup table. If the bit is on, the entry is valid.
+ *
+ * @return The binary value.
+ */
+ public BigInteger getValidPixels()
+ {
+ return validBits;
+ }
+
+ /**
+ * Construct a {@link BufferedImage} with rgb pixel values from a
+ * {@link Raster}.
+ *
+ * Constructs a new BufferedImage in which each pixel is an RGBA int from
+ * a Raster with index-valued pixels. If this model has no alpha component
+ * or transparent pixel, the type of the new BufferedImage is TYPE_INT_RGB.
+ * Otherwise the type is TYPE_INT_ARGB. If forceARGB is true, the type is
+ * forced to be TYPE_INT_ARGB no matter what.
+ *
+ * @param raster The source of pixel values.
+ * @param forceARGB True if type must be TYPE_INT_ARGB.
+ * @return New BufferedImage with RBGA int pixel values.
+ */
+ public BufferedImage convertToIntDiscrete(Raster raster, boolean forceARGB)
+ {
+ int type = forceARGB ? BufferedImage.TYPE_INT_ARGB
+ : ((opaque && trans == -1) ? BufferedImage.TYPE_INT_RGB :
+ BufferedImage.TYPE_INT_ARGB);
+
+ // FIXME: assuming that raster has only 1 band since pixels are supposed
+ // to be int indexes.
+ // FIXME: it would likely be more efficient to fetch a complete array,
+ // but it would take much more memory.
+ // FIXME: I'm not sure if transparent pixels or alpha values need special
+ // handling here.
+ BufferedImage im = new BufferedImage(raster.width, raster.height, type);
+ for (int x = raster.minX; x < raster.width + raster.minX; x++)
+ for (int y = raster.minY; y < raster.height + raster.minY; y++)
+ im.setRGB(x, y, rgb[raster.getSample(x, y, 0)]);
+
+ return im;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/Kernel.java b/libjava/classpath/java/awt/image/Kernel.java
new file mode 100644
index 00000000000..f7c29c3cde9
--- /dev/null
+++ b/libjava/classpath/java/awt/image/Kernel.java
@@ -0,0 +1,143 @@
+/* Kernel.java -- Java class for an image processing kernel
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * Kernel represents an image processing kernel. It gets used to hold
+ * convolution filters among other purposes. It stores an array of float
+ * values representing a 2-dimensional array in row-major order.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @version 1.0
+ */
+public class Kernel implements Cloneable
+{
+ private final int width;
+ private final int height;
+ private final float[] data;
+
+ /**
+ * Creates a new <code>Kernel</code> instance.
+ *
+ * @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.
+ */
+ public Kernel(int width, int height, float[] data)
+ throws IllegalArgumentException
+ {
+ this.width = width;
+ this.height = height;
+ if (data.length < width * height || width < 0 || height < 0)
+ throw new IllegalArgumentException();
+ this.data = new float[width * height];
+ System.arraycopy(data, 0, this.data, 0, width * height);
+ }
+
+ /**
+ * Return the X origin: (width - 1) / 2
+ */
+ public final int getXOrigin()
+ {
+ return (width - 1) / 2;
+ }
+
+ /**
+ * Return the Y origin: (height - 1) / 2
+ */
+ public final int getYOrigin()
+ {
+ return (height - 1) / 2;
+ }
+
+ /**
+ * @return The kernel width.
+ */
+ public final int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * @return The kernel height.
+ */
+ public final int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Return the kernel data.
+ *
+ * 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.
+ * @return The array with copied values.
+ * @exception IllegalArgumentException if data != null and too small.
+ */
+ public final float[] getKernelData(float[] data)
+ throws IllegalArgumentException
+ {
+ if (data == null)
+ return (float[])this.data.clone();
+
+ if (data.length < this.data.length)
+ throw new IllegalArgumentException();
+
+ System.arraycopy(this.data, 0, data, 0, this.data.length);
+ return data;
+ }
+
+ /**
+ * @return a clone of this Kernel.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/image/LookupOp.java b/libjava/classpath/java/awt/image/LookupOp.java
new file mode 100644
index 00000000000..f131daabae3
--- /dev/null
+++ b/libjava/classpath/java/awt/image/LookupOp.java
@@ -0,0 +1,252 @@
+/* LookupOp.java -- Filter that converts each pixel using a lookup table.
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * LookupOp is a filter that converts each pixel using a lookup table.
+ *
+ * For filtering Rasters, the lookup table must have either one component
+ * that is applied to all bands, or one component for every band in the
+ * Rasters.
+ *
+ * For BufferedImages, the lookup table may apply to both color and alpha
+ * components. If the lookup table contains one component, or if there are
+ * the same number of components as color components in the source, the table
+ * applies to all color components. Otherwise the table applies to all
+ * components including alpha. Alpha premultiplication is ignored during the
+ * lookup filtering.
+ *
+ * After filtering, if color conversion is necessary, the conversion happens,
+ * taking alpha premultiplication into account.
+ *
+ * @author jlquinn
+ */
+public class LookupOp implements BufferedImageOp, RasterOp
+{
+ private LookupTable lut;
+ private RenderingHints hints;
+
+ /** Construct a new LookupOp.
+ *
+ * @param lookup LookupTable to use.
+ * @param hints Rendering hints (can be null).
+ */
+ public LookupOp(LookupTable lookup, RenderingHints hints)
+ {
+ lut = lookup;
+ this.hints = hints;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage)
+ */
+ public BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ if (src.getColorModel() instanceof IndexColorModel)
+ throw new IllegalArgumentException("LookupOp.filter: IndexColorModel "
+ + "not allowed");
+ if (dst == null)
+ dst = createCompatibleDestImage(src, src.getColorModel());
+
+ // Set up for potential colormodel mismatch
+ BufferedImage tgt;
+ if (dst.getColorModel().equals(src.getColorModel()))
+ tgt = dst;
+ else
+ tgt = createCompatibleDestImage(src, src.getColorModel());
+
+ Raster sr = src.getRaster();
+ WritableRaster dr = tgt.getRaster();
+
+ if (src.getColorModel().hasAlpha() &&
+ (lut.getNumComponents() == 1 ||
+ lut.getNumComponents() == src.getColorModel().getNumColorComponents()))
+ {
+ // Need to ignore alpha for lookup
+ int[] dbuf = new int[src.getColorModel().getNumComponents()];
+ int tmpBands = src.getColorModel().getNumColorComponents();
+ int[] tmp = new int[tmpBands];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ {
+ // Filter only color components, but also copy alpha
+ sr.getPixel(x, y, dbuf);
+ System.arraycopy(dbuf, 0, tmp, 0, tmpBands);
+ dr.setPixel(x, y, lut.lookupPixel(tmp, dbuf));
+ }
+ }
+ else if (lut.getNumComponents() != 1
+ &&
+ lut.getNumComponents() != src.getColorModel().getNumComponents())
+ throw new IllegalArgumentException("LookupOp.filter: "
+ + "Incompatible lookup "
+ + "table and source image");
+
+ // No alpha to ignore
+ int[] dbuf = new int[src.getColorModel().getNumComponents()];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dr.setPixel(x, y, lut.lookupPixel(sr.getPixel(x, y, dbuf), dbuf));
+
+ if (tgt != dst)
+ {
+ // Convert between color models.
+ // TODO Check that premultiplied alpha is handled correctly here.
+ Graphics2D gg = dst.createGraphics();
+ gg.setRenderingHints(hints);
+ gg.drawImage(tgt, 0, 0, null);
+ gg.dispose();
+ }
+
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ // FIXME: set properties to those in src
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isPremultiplied, null);
+ }
+
+ /** Return corresponding destination point for source point.
+ *
+ * LookupOp will return the value of src unchanged.
+ * @param src The source point.
+ * @param dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
+ */
+ public Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ return (Point2D) src.clone();
+
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /** Return the LookupTable for this op. */
+ public LookupTable getTable()
+ {
+ return lut;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /** Filter a raster through a lookup table.
+ *
+ * Applies the lookup table for this Rasterop to each pixel of src and
+ * puts the results in dest. If dest is null, a new Raster is created and
+ * returned.
+ *
+ * @param src The source raster.
+ * @param dest The destination raster.
+ * @return The WritableRaster with the filtered pixels.
+ * @throws IllegalArgumentException if lookup table has more than one
+ * component but not the same as src and dest.
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ */
+ public WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ if (dest == null)
+ // Allocate a raster if needed
+ dest = createCompatibleDestRaster(src);
+ else
+ if (src.getNumBands() != dest.getNumBands())
+ throw new IllegalArgumentException();
+
+ if (lut.getNumComponents() != 1
+ && lut.getNumComponents() != src.getNumBands())
+ throw new IllegalArgumentException();
+
+
+ // Allocate pixel storage.
+ int[] tmp = new int[src.getNumBands()];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dest.setPixel(x, y, lut.lookupPixel(src.getPixel(x, y, tmp), tmp));
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+}
diff --git a/libjava/classpath/java/awt/image/LookupTable.java b/libjava/classpath/java/awt/image/LookupTable.java
new file mode 100644
index 00000000000..f814b8e090b
--- /dev/null
+++ b/libjava/classpath/java/awt/image/LookupTable.java
@@ -0,0 +1,109 @@
+/* LookupTable.java -- Java class for a pixel translation table.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * LookupTable represents translation arrays for pixel values. It wraps one
+ * or more data arrays for each layer (or component) in an image, such as
+ * Alpha, R, G, and B. When doing translation, the offset is subtracted from
+ * the pixel values to allow a subset of an array to be used.
+ *
+ * @see ByteLookupTable
+ * @see ShortLookupTable
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @version 1.0
+ */
+public abstract class LookupTable
+{
+ // Not protected since that's part of the public API.
+ int offset;
+ int numComponents;
+
+ /**
+ * Creates a new <code>LookupTable</code> instance.
+ *
+ * If numComponents is 1, the same translation table is used for all pixel
+ * components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param numComponents Number of image components.
+ * @exception IllegalArgumentException if offset < 0 or numComponents < 1.
+ */
+ protected LookupTable(int offset, int numComponents)
+ throws IllegalArgumentException
+ {
+ if (offset < 0 || numComponents < 1)
+ throw new IllegalArgumentException();
+ this.offset = offset;
+ this.numComponents = numComponents;
+ }
+
+ /** Return the number of components. */
+ public int getNumComponents()
+ {
+ return numComponents;
+ }
+
+ /** Return the offset. */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dest Destination array for values, or null.
+ * @return Translated values for the pixel.
+ */
+ public abstract int[] lookupPixel(int[] src, int[] dest);
+}
diff --git a/libjava/classpath/java/awt/image/MemoryImageSource.java b/libjava/classpath/java/awt/image/MemoryImageSource.java
new file mode 100644
index 00000000000..c27e0bf7317
--- /dev/null
+++ b/libjava/classpath/java/awt/image/MemoryImageSource.java
@@ -0,0 +1,373 @@
+/* MemoryImageSource.java -- Java class for providing image data
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class MemoryImageSource implements ImageProducer
+{
+ private boolean animated = false;
+ private boolean fullbuffers = false;
+ private int[] pixeli;
+ private int width;
+ private int height;
+ private int offset;
+ private int scansize;
+ private byte[] pixelb;
+ private ColorModel cm;
+ private Hashtable props = new Hashtable();
+ private Vector consumers = new Vector();
+
+ /**
+ * Construct an image producer that reads image data from a byte
+ * array.
+ *
+ * @param w width of image
+ * @param h height of image
+ * @param cm the color model used to represent pixel values
+ * @param pix a byte array of pixel values
+ * @param off the offset into the array at which the first pixel is stored
+ * @param scan the number of array elements that represents a single pixel row
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
+ int scan)
+ {
+ this(w, h, cm, pix, off, scan, null);
+ }
+
+ /**
+ * Constructs an ImageProducer from memory
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
+ int scan, Hashtable props)
+ {
+ width = w;
+ height = h;
+ this.cm = cm;
+ offset = off;
+ scansize = scan;
+ this.props = props;
+ int max = ((scansize > width) ? scansize : width);
+ pixelb = pix;
+ }
+
+ /**
+ * Construct an image producer that reads image data from an
+ * integer array.
+ *
+ * @param w width of image
+ * @param h height of image
+ * @param cm the color model used to represent pixel values
+ * @param pix an integer array of pixel values
+ * @param off the offset into the array at which the first pixel is stored
+ * @param scan the number of array elements that represents a single pixel row
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off,
+ int scan)
+ {
+ this(w, h, cm, pix, off, scan, null);
+ }
+
+ /**
+ Constructs an ImageProducer from memory
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off,
+ int scan, Hashtable props)
+ {
+ width = w;
+ height = h;
+ this.cm = cm;
+ offset = off;
+ scansize = scan;
+ this.props = props;
+ int max = ((scansize > width) ? scansize : width);
+ pixeli = pix;
+ }
+
+ /**
+ * Constructs an ImageProducer from memory using the default RGB ColorModel
+ */
+ public MemoryImageSource(int w, int h, int[] pix, int off, int scan,
+ Hashtable props)
+ {
+ this(w, h, ColorModel.getRGBdefault(), pix, off, scan, props);
+ }
+
+ /**
+ * Constructs an ImageProducer from memory using the default RGB ColorModel
+ */
+ public MemoryImageSource(int w, int h, int[] pix, int off, int scan)
+ {
+ this(w, h, ColorModel.getRGBdefault(), pix, off, scan, null);
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code>.
+ */
+ public synchronized void addConsumer(ImageConsumer ic)
+ {
+ if (consumers.contains(ic))
+ return;
+
+ consumers.addElement(ic);
+ }
+
+ /**
+ * Used to determine if the given <code>ImageConsumer</code> is
+ * already registered with this <code>ImageProducer</code>.
+ */
+ public synchronized boolean isConsumer(ImageConsumer ic)
+ {
+ if (consumers.contains(ic))
+ return true;
+ return false;
+ }
+
+ /**
+ * Used to remove an <code>ImageConsumer</code> from the list of
+ * registered consumers for this <code>ImageProducer</code>.
+ */
+ public synchronized void removeConsumer(ImageConsumer ic)
+ {
+ consumers.removeElement(ic);
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then immediately start
+ * reconstruction of the image data to be delivered to all
+ * registered consumers.
+ */
+ public void startProduction(ImageConsumer ic)
+ {
+ if (! (consumers.contains(ic)))
+ consumers.addElement(ic);
+
+ Vector list = (Vector) consumers.clone();
+ for (int i = 0; i < list.size(); i++)
+ {
+ ic = (ImageConsumer) list.elementAt(i);
+ sendPicture(ic);
+ if (animated)
+ ic.imageComplete(ImageConsumer.SINGLEFRAME);
+ else
+ ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then request that this producer
+ * resend the image data in the order top-down, left-right.
+ */
+ public void requestTopDownLeftRightResend(ImageConsumer ic)
+ {
+ startProduction(ic);
+ }
+
+ /**
+ * Changes a flag to indicate whether this MemoryImageSource supports
+ * animations.
+ *
+ * @param animated A flag indicating whether this class supports animations
+ */
+ public synchronized void setAnimated(boolean animated)
+ {
+ this.animated = animated;
+ }
+
+ /**
+ * A flag to indicate whether or not to send full buffer updates when
+ * sending animation. If this flag is set then full buffers are sent
+ * in the newPixels methods instead of just regions.
+ *
+ * @param fullbuffers - a flag indicating whether to send the full buffers
+ */
+ public synchronized void setFullBufferUpdates(boolean fullbuffers)
+ {
+ this.fullbuffers = fullbuffers;
+ }
+
+ /**
+ * Send an animation frame to the image consumers.
+ */
+ public void newPixels()
+ {
+ if (animated == true)
+ {
+ ImageConsumer ic;
+ Vector list = (Vector) consumers.clone();
+ for (int i = 0; i < list.size(); i++)
+ {
+ ic = (ImageConsumer) list.elementAt(i);
+ sendPicture(ic);
+ ic.imageComplete(ImageConsumer.SINGLEFRAME);
+ }
+ }
+ }
+
+ private void sendPicture(ImageConsumer ic)
+ {
+ ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
+ if (props != null)
+ ic.setProperties(props);
+ ic.setDimensions(width, height);
+ ic.setColorModel(cm);
+ if (pixeli != null)
+ ic.setPixels(0, 0, width, height, cm, pixeli, offset, scansize);
+ else
+ ic.setPixels(0, 0, width, height, cm, pixelb, offset, scansize);
+ }
+
+ /**
+ * Send an animation frame to the image consumers containing the specified
+ * pixels unless setFullBufferUpdates is set.
+ */
+ public synchronized void newPixels(int x, int y, int w, int h)
+ {
+ if (animated == true)
+ {
+ if (fullbuffers)
+ newPixels();
+ else
+ {
+ ImageConsumer ic;
+ Vector list = (Vector) consumers.clone();
+ for (int i = 0; i < list.size(); i++)
+ {
+ ic = (ImageConsumer) list.elementAt(i);
+ ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
+ if (props != null)
+ ic.setProperties(props);
+ if (pixeli != null)
+ {
+ int[] pixelbuf = new int[w * h];
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixeli, row * scansize + x + offset,
+ pixelbuf, 0, w * h);
+ ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
+ }
+ else
+ {
+ byte[] pixelbuf = new byte[w * h];
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixelb, row * scansize + x + offset,
+ pixelbuf, 0, w * h);
+
+ ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
+ }
+ ic.imageComplete(ImageConsumer.SINGLEFRAME);
+ }
+ }
+ }
+ }
+
+ /**
+ * Send an animation frame to the image consumers containing the specified
+ * pixels unless setFullBufferUpdates is set.
+ *
+ * If framenotify is set then a notification is sent when the frame
+ * is sent otherwise no status is sent.
+ */
+ public synchronized void newPixels(int x, int y, int w, int h,
+ boolean framenotify)
+ {
+ if (animated == true)
+ {
+ if (fullbuffers)
+ newPixels();
+ else
+ {
+ ImageConsumer ic;
+ Vector list = (Vector) consumers.clone();
+ for (int i = 0; i < list.size(); i++)
+ {
+ ic = (ImageConsumer) list.elementAt(i);
+ ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
+ if (props != null)
+ ic.setProperties(props);
+ if (pixeli != null)
+ {
+ int[] pixelbuf = new int[w * h];
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixeli, row * scansize + x + offset,
+ pixelbuf, 0, w * h);
+ ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
+ }
+ else
+ {
+ byte[] pixelbuf = new byte[w * h];
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixelb, row * scansize + x + offset,
+ pixelbuf, 0, w * h);
+ ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
+ }
+ if (framenotify == true)
+ ic.imageComplete(ImageConsumer.SINGLEFRAME);
+ }
+ }
+ }
+ }
+
+ public synchronized void newPixels(byte[] newpix, ColorModel newmodel,
+ int offset, int scansize)
+ {
+ pixeli = null;
+ pixelb = newpix;
+ cm = newmodel;
+ this.offset = offset;
+ this.scansize = scansize;
+ if (animated == true)
+ newPixels();
+ }
+
+ public synchronized void newPixels(int[] newpix, ColorModel newmodel,
+ int offset, int scansize)
+ {
+ pixelb = null;
+ pixeli = newpix;
+ cm = newmodel;
+ this.offset = offset;
+ this.scansize = scansize;
+ if (animated == true)
+ newPixels();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java b/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java
new file mode 100644
index 00000000000..18a6e555205
--- /dev/null
+++ b/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java
@@ -0,0 +1,388 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.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.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public class MultiPixelPackedSampleModel extends SampleModel
+{
+ private int scanlineStride;
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;
+ private int dataBitOffset;
+ private int elemBits;
+ private int numberOfBits;
+ private int numElems;
+
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits)
+ {
+ this(dataType, w, h, numberOfBits, 0, 0);
+ }
+
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits, int scanlineStride,
+ int dataBitOffset)
+ {
+ super(dataType, w, h, 1);
+
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ elemBits = 8;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ elemBits = 16;
+ break;
+ case DataBuffer.TYPE_INT:
+ elemBits = 32;
+ break;
+ default:
+ throw new IllegalArgumentException("MultiPixelPackedSampleModel"
+ + " unsupported dataType");
+ }
+
+ this.dataBitOffset = dataBitOffset;
+
+ this.numberOfBits = numberOfBits;
+ if (numberOfBits > elemBits)
+ throw new RasterFormatException("MultiPixelPackedSampleModel pixel size"
+ + " larger than dataType");
+ switch (numberOfBits)
+ {
+ case 1: case 2: case 4: case 8: case 16: case 32: break;
+ default:
+ throw new RasterFormatException("MultiPixelPackedSampleModel pixel"
+ + " size not 2^n bits");
+ }
+ numElems = elemBits / numberOfBits;
+
+ // Compute scan line large enough for w pixels.
+ if (scanlineStride == 0)
+ scanlineStride = ((dataBitOffset + w * numberOfBits) / elemBits);
+ this.scanlineStride = scanlineStride;
+
+
+ sampleSize = new int[1];
+ sampleSize[0] = numberOfBits;
+
+ bitMasks = new int[numElems];
+ bitOffsets = new int[numElems];
+ for (int i=0; i < numElems; i++)
+ {
+ bitOffsets[numElems - i- 1] = numberOfBits * i;
+ bitMasks[numElems - i - 1] = ((1 << numberOfBits) - 1) <<
+ bitOffsets[numElems - i - 1];
+ }
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ /* FIXME: We can avoid recalculation of bit offsets and sample
+ sizes here by passing these from the current instance to a
+ special private constructor. */
+ 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.
+ */
+ 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;
+
+ return Buffers.createBuffer(getDataType(), size);
+ }
+
+
+ public int getNumDataElements()
+ {
+ return 1;
+ }
+
+ public int[] getSampleSize()
+ {
+ return sampleSize;
+ }
+
+ public int getSampleSize(int band)
+ {
+ return sampleSize[0];
+ }
+
+ public int getOffset(int x, int y)
+ {
+ return scanlineStride * y + ((dataBitOffset + x*numberOfBits) / elemBits);
+ }
+
+ public int getBitOffset(int x)
+ {
+ return (dataBitOffset + x*numberOfBits) % elemBits;
+ }
+
+ public int getDataBitOffset()
+ {
+ return dataBitOffset;
+ }
+
+ public int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ public int getPixelBitStride()
+ {
+ return numberOfBits;
+ }
+
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ int numBands = bands.length;
+ if (numBands != 1)
+ throw new RasterFormatException("MultiPixelPackedSampleModel only"
+ + " supports one band");
+
+ return new MultiPixelPackedSampleModel(dataType, width, height,
+ numberOfBits, scanlineStride,
+ dataBitOffset);
+ }
+
+ /**
+ * Extract one pixel and return in an array of transfer type.
+ *
+ * Extracts the pixel at x, y from data and stores into the 0th index of the
+ * 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 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)
+ */
+ 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();
+ }
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ 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;
+ }
+
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int pos =
+ ((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits;
+ int offset = getOffset(x, y);
+ int samples = data.getElem(offset);
+ return (samples & bitMasks[pos]) >>> bitOffsets[pos];
+ }
+
+ /**
+ * Set the pixel at x, y to the value in the first element of the primitive
+ * array obj.
+ *
+ * @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 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");
+ }
+ }
+ 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);
+ }
+ }
+
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ setSample(x, y, 0, iArray[0], data);
+ }
+
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ int bitpos =
+ ((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits;
+ int offset = getOffset(x, y);
+
+ s = s << bitOffsets[bitpos];
+ s = s & bitMasks[bitpos];
+
+ int sample = data.getElem(offset);
+ sample |= s;
+ data.setElem(offset, sample);
+ }
+
+ /**
+ * Creates a String with some information about this SampleModel.
+ * @return A String describing this SampleModel.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+ result.append(getClass().getName());
+ result.append("[");
+ result.append("scanlineStride=").append(scanlineStride);
+ for(int i=0; i < bitMasks.length; i+=1)
+ {
+ result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
+ }
+
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/PackedColorModel.java b/libjava/classpath/java/awt/image/PackedColorModel.java
new file mode 100644
index 00000000000..894e6e66fda
--- /dev/null
+++ b/libjava/classpath/java/awt/image/PackedColorModel.java
@@ -0,0 +1,192 @@
+/* Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.BitMaskExtent;
+
+import java.awt.Point;
+import java.awt.color.ColorSpace;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public abstract class PackedColorModel extends ColorModel
+{
+ private int masks[];
+
+ /* Package accessibility, the DirectColorModel needs this array */
+ int shifts[];
+
+ public PackedColorModel(ColorSpace cspace, int pixelBits,
+ int[] colorMaskArray, int alphaMask,
+ boolean isAlphaPremultiplied,
+ int transparency,
+ int transferType)
+ {
+ super(pixelBits, calcBitsPerComponent(colorMaskArray, alphaMask),
+ cspace, (alphaMask != 0), isAlphaPremultiplied, transparency,
+ transferType);
+ initMasks(colorMaskArray, alphaMask);
+ if ((pixelBits<1) || (pixelBits>32)) {
+ throw new IllegalArgumentException("pixels per bits must be " +
+ "in the range [1, 32]");
+ }
+ }
+
+ private static int[] calcBitsPerComponent(int[] colorMaskArray,
+ int alphaMask)
+ {
+ int numComponents = colorMaskArray.length;
+ if (alphaMask != 0) numComponents++;
+
+ int[] bitsPerComponent = new int[numComponents];
+
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b=0; b<colorMaskArray.length; b++)
+ {
+ extent.setMask(colorMaskArray[b]);
+ bitsPerComponent[b] = extent.bitWidth;
+ }
+ if (alphaMask != 0)
+ {
+ extent.setMask(alphaMask);
+ bitsPerComponent[numComponents-1] = extent.bitWidth;
+ }
+ return bitsPerComponent;
+ }
+
+ /** Initializes the masks.
+ *
+ * @return an array containing the number of bits per color
+ * component.
+ */
+ private void initMasks(int[] colorMaskArray, int alphaMask)
+ {
+ int numComponents = colorMaskArray.length;
+ if (alphaMask == 0)
+ {
+ masks = colorMaskArray;
+ }
+ else
+ {
+ masks = new int[numComponents+1];
+ System.arraycopy(colorMaskArray, 0,
+ masks, 0,
+ numComponents);
+ masks[numComponents++] = alphaMask;
+ }
+
+ shifts = new int[numComponents];
+
+ // Bit field handling have been moved to a utility class
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b=0; b<numComponents; b++)
+ {
+ extent.setMask(masks[b]);
+ shifts[b] = extent.leastSignificantBit;
+ }
+ }
+
+ public PackedColorModel(ColorSpace cspace, int pixelBits,
+ int rmask, int gmask, int bmask,
+ int amask, boolean isAlphaPremultiplied,
+ int transparency,
+ int transferType)
+ {
+ this(cspace, pixelBits, makeColorMaskArray(rmask, gmask, bmask),
+ amask, isAlphaPremultiplied, transparency, transferType);
+ }
+
+ /* TODO: If there is a alpha mask, it is inefficient to create a
+ color mask array that will be discarded when the alpha mask is
+ appended. We should probably create a private constructor that
+ takes a complete array of masks (color+alpha) as an
+ argument. */
+
+ private static int[] makeColorMaskArray(int rmask, int gmask, int bmask)
+ {
+ int[] colorMaskArray = { rmask, gmask, bmask };
+ return colorMaskArray;
+ }
+
+ public final int getMask(int index)
+ {
+ return masks[index];
+ }
+
+ public final int[] getMasks()
+ {
+ return masks;
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ return new SinglePixelPackedSampleModel(transferType, w, h, masks);
+ }
+
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ if (!super.isCompatibleSampleModel(sm)) return false;
+ if (!(sm instanceof SinglePixelPackedSampleModel)) return false;
+
+ SinglePixelPackedSampleModel sppsm =
+ (SinglePixelPackedSampleModel) sm;
+ return java.util.Arrays.equals(sppsm.getBitMasks(), masks);
+ }
+
+ public WritableRaster getAlphaRaster(WritableRaster raster) {
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!super.equals(obj)) return false;
+ if (!(obj instanceof PackedColorModel)) return false;
+
+ PackedColorModel other = (PackedColorModel) obj;
+
+ return java.util.Arrays.equals(masks, other.masks);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/PixelGrabber.java b/libjava/classpath/java/awt/image/PixelGrabber.java
new file mode 100644
index 00000000000..b576dbfad98
--- /dev/null
+++ b/libjava/classpath/java/awt/image/PixelGrabber.java
@@ -0,0 +1,618 @@
+/* PixelGrabber.java -- retrieve a subset of an image's data
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Image;
+import java.util.Hashtable;
+
+/**
+ * PixelGrabber is an ImageConsumer that extracts a rectangular region
+ * of pixels from an Image.
+ */
+public class PixelGrabber implements ImageConsumer
+{
+ int x, y, offset;
+ int width = -1;
+ int height = -1;
+ int scansize = -1;
+ boolean forceRGB = true;
+
+ ColorModel model = ColorModel.getRGBdefault();
+ int hints;
+ Hashtable props;
+
+ int int_pixel_buffer[];
+ boolean ints_delivered = false;
+ byte byte_pixel_buffer[];
+ boolean bytes_delivered = false;
+
+ ImageProducer ip;
+ int observerStatus;
+ int consumerStatus;
+
+ private Thread grabberThread;
+ boolean grabbing = false;
+
+ /**
+ * Construct a PixelGrabber that will retrieve RGB data from a given
+ * Image.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image. The data will be
+ * stored in the provided <code>pix</code> array, which must have
+ * been initialized to a size of at least <code>w * h</code>. The
+ * data for a pixel (m, n) in the grab rectangle will be stored at
+ * <code>pix[(n - y) * scansize + (m - x) + off]</code>.
+ *
+ * @param img the Image from which to grab pixels
+ * @param x the x coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param y the y coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param pix the array in which to store grabbed RGB pixel data
+ * @param off the offset into the <code>pix</code> array at which to
+ * start storing RGB data
+ * @param scansize a set of <code>scansize</code> consecutive
+ * elements in the <code>pix</code> array represents one row of
+ * pixels in the grab rectangle
+ */
+ public PixelGrabber(Image img, int x, int y, int w, int h,
+ int pix[], int off, int scansize)
+ {
+ this (img.getSource(), x, y, w, h, pix, off, scansize);
+ }
+
+ /**
+ * Construct a PixelGrabber that will retrieve RGB data from a given
+ * ImageProducer.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image produced by
+ * <code>ip</code>. The data will be stored in the provided
+ * <code>pix</code> array, which must have been initialized to a
+ * size of at least <code>w * h</code>. The data for a pixel (m, n)
+ * in the grab rectangle will be stored at
+ * <code>pix[(n - y) * scansize + (m - x) + off]</code>.
+ *
+ * @param ip the ImageProducer from which to grab pixels
+ * @param x the x coordinate of the grab rectangle's top-left pixel,
+ * specified relative to the top-left corner of the image produced
+ * by <code>ip</code>
+ * @param y the y coordinate of the grab rectangle's top-left pixel,
+ * specified relative to the top-left corner of the image produced
+ * by <code>ip</code>
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param pix the array in which to store grabbed RGB pixel data
+ * @param off the offset into the <code>pix</code> array at which to
+ * start storing RGB data
+ * @param scansize a set of <code>scansize</code> consecutive
+ * elements in the <code>pix</code> array represents one row of
+ * pixels in the grab rectangle
+ */
+ public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
+ int pix[], int off, int scansize)
+ {
+ this.ip = ip;
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.offset = off;
+ this.scansize = scansize;
+
+ int_pixel_buffer = pix;
+ // Initialize the byte array in case ip sends us byte-formatted
+ // pixel data.
+ byte_pixel_buffer = new byte[pix.length * 4];
+ }
+
+ /**
+ * Construct a PixelGrabber that will retrieve data from a given
+ * Image.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image. The data will be
+ * stored in an internal array which can be accessed by calling
+ * <code>getPixels</code>. The data for a pixel (m, n) in the grab
+ * rectangle will be stored in the returned array at index
+ * <code>(n - y) * scansize + (m - x) + off</code>.
+ * If forceRGB is false, then the returned data will be not be
+ * converted to RGB from its format in <code>img</code>.
+ *
+ * If <code>w</code> is negative, the width of the grab region will
+ * be from x to the right edge of the image. Likewise, if
+ * <code>h</code> is negative, the height of the grab region will be
+ * from y to the bottom edge of the image.
+ *
+ * @param img the Image from which to grab pixels
+ * @param x the x coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param y the y coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param forceRGB true to force conversion of the rectangular
+ * region's pixel data to RGB
+ */
+ public PixelGrabber(Image img,
+ int x, int y,
+ int w, int h,
+ boolean forceRGB)
+ {
+ this.ip = img.getSource();
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ // If width or height is negative, postpone pixel buffer
+ // initialization until setDimensions is called back by ip.
+ if (width >= 0 && height >= 0)
+ {
+ int_pixel_buffer = new int[width * height];
+ byte_pixel_buffer = new byte[width * height];
+ }
+ this.forceRGB = forceRGB;
+ }
+
+ /**
+ * Start grabbing pixels.
+ *
+ * Spawns an image production thread that calls back to this
+ * PixelGrabber's ImageConsumer methods.
+ */
+ public synchronized void startGrabbing()
+ {
+ // Make sure we're not already grabbing.
+ if (grabbing == false)
+ {
+ grabbing = true;
+ grabberThread = new Thread ()
+ {
+ public void run ()
+ {
+ ip.startProduction (PixelGrabber.this);
+ }
+ };
+ grabberThread.start ();
+ }
+ }
+
+ /**
+ * Abort pixel grabbing.
+ */
+ public synchronized void abortGrabbing()
+ {
+ if (grabbing)
+ {
+ // Interrupt the grabbing thread.
+ Thread moribund = grabberThread;
+ grabberThread = null;
+ moribund.interrupt();
+
+ imageComplete (ImageConsumer.IMAGEABORTED);
+ }
+ }
+
+ /**
+ * Have our Image or ImageProducer start sending us pixels via our
+ * ImageConsumer methods and wait for all pixels in the grab
+ * rectangle to be delivered.
+ *
+ * @return true if successful, false on abort or error
+ *
+ * @throws InterruptedException if interrupted by another thread.
+ */
+ public synchronized boolean grabPixels() throws InterruptedException
+ {
+ return grabPixels(0);
+ }
+
+ /**
+ * grabPixels's behavior depends on the value of <code>ms</code>.
+ *
+ * If ms < 0, return true if all pixels from the source image have
+ * been delivered, false otherwise. Do not wait.
+ *
+ * If ms >= 0 then we request that our Image or ImageProducer start
+ * delivering pixels to us via our ImageConsumer methods.
+ *
+ * If ms > 0, wait at most <code>ms</code> milliseconds for
+ * delivery of all pixels within the grab rectangle.
+ *
+ * If ms == 0, wait until all pixels have been delivered.
+ *
+ * @return true if all pixels from the source image have been
+ * delivered, false otherwise
+ *
+ * @throws InterruptedException if this thread is interrupted while
+ * we are waiting for pixels to be delivered
+ */
+ public synchronized boolean grabPixels(long ms) throws InterruptedException
+ {
+ if (ms < 0)
+ return ((observerStatus & (ImageObserver.FRAMEBITS
+ | ImageObserver.ALLBITS)) != 0);
+
+ // Spawn a new ImageProducer thread to send us the image data via
+ // our ImageConsumer methods.
+ startGrabbing();
+
+ if (ms > 0)
+ {
+ long stop_time = System.currentTimeMillis() + ms;
+ long time_remaining;
+ while (grabbing)
+ {
+ time_remaining = stop_time - System.currentTimeMillis();
+ if (time_remaining <= 0)
+ break;
+ wait (time_remaining);
+ }
+ abortGrabbing ();
+ }
+ else
+ wait ();
+
+ // If consumerStatus is non-zero then the image is done loading or
+ // an error has occurred.
+ if (consumerStatus != 0)
+ return setObserverStatus ();
+
+ return ((observerStatus & (ImageObserver.FRAMEBITS
+ | ImageObserver.ALLBITS)) != 0);
+ }
+
+ // Set observer status flags based on the current consumer status
+ // flags. Return true if the consumer flags indicate that the
+ // image was loaded successfully, or false otherwise.
+ private synchronized boolean setObserverStatus ()
+ {
+ boolean retval = false;
+
+ if ((consumerStatus & IMAGEERROR) != 0)
+ observerStatus |= ImageObserver.ERROR;
+
+ if ((consumerStatus & IMAGEABORTED) != 0)
+ observerStatus |= ImageObserver.ABORT;
+
+ if ((consumerStatus & STATICIMAGEDONE) != 0)
+ {
+ observerStatus |= ImageObserver.ALLBITS;
+ retval = true;
+ }
+
+ if ((consumerStatus & SINGLEFRAMEDONE) != 0)
+ {
+ observerStatus |= ImageObserver.FRAMEBITS;
+ retval = true;
+ }
+
+ return retval;
+ }
+
+ /**
+ * @return the status of the pixel grabbing thread, represented by a
+ * bitwise OR of ImageObserver flags
+ */
+ public synchronized int getStatus()
+ {
+ return observerStatus;
+ }
+
+ /**
+ * @return the width of the grab rectangle in pixels, or a negative
+ * number if the ImageProducer has not yet called our setDimensions
+ * method
+ */
+ public synchronized int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * @return the height of the grab rectangle in pixels, or a negative
+ * number if the ImageProducer has not yet called our setDimensions
+ * method
+ */
+ public synchronized int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * @return a byte array of pixel data if ImageProducer delivered
+ * pixel data using the byte[] variant of setPixels, or an int array
+ * otherwise
+ */
+ public synchronized Object getPixels()
+ {
+ if (ints_delivered)
+ return int_pixel_buffer;
+ else if (bytes_delivered)
+ return byte_pixel_buffer;
+ else
+ return null;
+ }
+
+ /**
+ * @return the ColorModel currently being used for the majority of
+ * pixel data conversions
+ */
+ public synchronized ColorModel getColorModel()
+ {
+ return model;
+ }
+
+ /**
+ * Our <code>ImageProducer</code> calls this method to indicate the
+ * size of the image being produced.
+ *
+ * setDimensions is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public synchronized void setDimensions(int width, int height)
+ {
+ // Our width wasn't set when we were constructed. Set our width
+ // so that the grab region includes all pixels from x to the right
+ // edge of the source image.
+ if (this.width < 0)
+ this.width = width - x;
+
+ // Our height wasn't set when we were constructed. Set our height
+ // so that the grab region includes all pixels from y to the
+ // bottom edge of the source image.
+ if (this.height < 0)
+ this.height = height - y;
+
+ if (scansize < 0)
+ scansize = this.width;
+
+ if (int_pixel_buffer == null)
+ int_pixel_buffer = new int[this.width * this.height];
+
+ if (byte_pixel_buffer == null)
+ byte_pixel_buffer = new byte[this.width * this.height];
+ }
+
+ /**
+ * Our <code>ImageProducer</code> may call this method to send us a
+ * list of its image's properties.
+ *
+ * setProperties is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param props a list of properties associated with the image being
+ * produced
+ */
+ public synchronized void setProperties(Hashtable props)
+ {
+ this.props = props;
+ }
+
+ /**
+ * Our ImageProducer will call <code>setColorModel</code> to
+ * indicate the model used by the majority of calls to
+ * <code>setPixels</code>. Each call to <code>setPixels</code>
+ * could however indicate a different <code>ColorModel</code>.
+ *
+ * setColorModel is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param model the color model to be used most often by setPixels
+ *
+ * @see ColorModel
+ */
+ public synchronized void setColorModel(ColorModel model)
+ {
+ this.model = model;
+ }
+
+ /**
+ * Our <code>ImageProducer</code> may call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
+ *
+ * setHints is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param flags a bit mask of hints
+ */
+ public synchronized void setHints(int flags)
+ {
+ hints = flags;
+ }
+
+ /**
+ * Our ImageProducer calls setPixels to deliver a subset of its
+ * pixels.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ public synchronized void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels,
+ int offset, int scansize)
+ {
+ ColorModel currentModel;
+ if (model != null)
+ currentModel = model;
+ else
+ currentModel = this.model;
+
+ for(int yp = y; yp < (y + h); yp++)
+ {
+ for(int xp = x; xp < (x + w); xp++)
+ {
+ // Check if the coordinates (xp, yp) are within the
+ // pixel block that we are grabbing.
+ if(xp >= this.x
+ && yp >= this.y
+ && xp < (this.x + this.width)
+ && yp < (this.y + this.height))
+ {
+ int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
+ int p = (yp - y) * scansize + (xp - x) + offset;
+ if (forceRGB)
+ {
+ ints_delivered = true;
+
+ int_pixel_buffer[i] = currentModel.getRGB (pixels[p] & 0xFF);
+ }
+ else
+ {
+ bytes_delivered = true;
+
+ byte_pixel_buffer[i] = pixels[p];
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Our ImageProducer calls setPixels to deliver a subset of its
+ * pixels.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ public synchronized void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels,
+ int offset, int scansize)
+ {
+ ColorModel currentModel;
+ if (model != null)
+ currentModel = model;
+ else
+ currentModel = this.model;
+
+ ints_delivered = true;
+
+ for(int yp = y; yp < (y + h); yp++)
+ {
+ for(int xp = x; xp < (x + w); xp++)
+ {
+ // Check if the coordinates (xp, yp) are within the
+ // pixel block that we are grabbing.
+ if(xp >= this.x
+ && yp >= this.y
+ && xp < (this.x + this.width)
+ && yp < (this.y + this.height))
+ {
+ int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
+ int p = (yp - y) * scansize + (xp - x) + offset;
+ if (forceRGB)
+ int_pixel_buffer[i] = currentModel.getRGB (pixels[p]);
+ else
+ int_pixel_buffer[i] = pixels[p];
+ }
+ }
+ }
+ }
+
+ /**
+ * Our <code>ImageProducer</code> calls this method to inform us
+ * that a single frame or the entire image is complete. The method
+ * is also used to inform us of an error in loading or producing the
+ * image.
+ *
+ * @param status the status of image production, represented by a
+ * bitwise OR of ImageConsumer flags
+ */
+ public synchronized void imageComplete(int status)
+ {
+ consumerStatus = status;
+ setObserverStatus ();
+ grabbing = false;
+ ip.removeConsumer (this);
+
+ notifyAll ();
+ }
+
+ /**
+ * @return the return value of getStatus
+ *
+ * @specnote The newer getStatus should be used in place of status.
+ */
+ public synchronized int status()
+ {
+ return getStatus();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java b/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java
new file mode 100644
index 00000000000..4c5c436edfc
--- /dev/null
+++ b/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java
@@ -0,0 +1,98 @@
+/* PixelInterleavedSampleModel.java
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+
+/**
+ * A <code>SampleModel</code> that uses exactly one element of the
+ * raster&#x2019;s {@link DataBuffer} per pixel, holds all bands in a
+ * single bank, and stores band data in pixel-interleaved manner.
+ *
+ * @since 1.2
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+public class PixelInterleavedSampleModel
+ extends ComponentSampleModel
+{
+ public PixelInterleavedSampleModel(int dataType, int width, int height,
+ int pixelStride, int scanlineStride,
+ int[] bandOffsets)
+ {
+ super(dataType, width, height, pixelStride, scanlineStride,
+ bandOffsets);
+ }
+
+
+ /**
+ * Creates a new <code>SampleModel</code> that is like this one, but
+ * uses the specified width and height.
+ *
+ * @param width the number of pixels in the horizontal direction.
+ *
+ * @param height the number of pixels in the vertical direction.
+ */
+ public SampleModel createCompatibleSampleModel(int width, int height)
+ {
+ return new PixelInterleavedSampleModel(dataType, width, height,
+ pixelStride, scanlineStride,
+ bandOffsets);
+ }
+
+
+ /**
+ * Creates a new <code>SampleModel</code> that is like this one, but
+ * uses only a subset of its bands.
+ *
+ * @param bands an array whose elements indicate which bands shall
+ * be part of the subset. For example, <code>[0, 2, 3]</code> would
+ * create a SampleModel containing bands #0, #2 and #3.
+ */
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ int[] subOffsets;
+
+ subOffsets = new int[bands.length];
+ for (int i = 0; i < bands.length; i++)
+ subOffsets[i] = bandOffsets[bands[i]];
+
+ return new PixelInterleavedSampleModel(dataType, width, height,
+ pixelStride, scanlineStride,
+ subOffsets);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/RGBImageFilter.java b/libjava/classpath/java/awt/image/RGBImageFilter.java
new file mode 100644
index 00000000000..f7b39b97b28
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RGBImageFilter.java
@@ -0,0 +1,267 @@
+/* RGBImageFilter.java -- Java class for filtering Pixels by RGB values
+ Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * A filter designed to filter images in the default RGBColorModel regardless of
+ * the ImageProducer's ColorModel.
+ *
+ * @author Mark Benvenuto (mcb54@columbia.edu)
+ */
+public abstract class RGBImageFilter extends ImageFilter
+{
+ protected ColorModel origmodel;
+
+ protected ColorModel newmodel;
+
+ /**
+ Specifies whether to apply the filter to the index entries of the
+ IndexColorModel. Subclasses should set this to true if the filter
+ does not depend on the pixel's coordinate.
+ */
+ protected boolean canFilterIndexColorModel = false;
+
+ /**
+ Construct new RGBImageFilter.
+ */
+ public RGBImageFilter()
+ {
+ }
+
+ /**
+ * Sets the ColorModel used to filter with. If the specified ColorModel is IndexColorModel
+ * and canFilterIndexColorModel is true, we subsitute the ColorModel for a filtered one
+ * here and in setPixels whenever the original one appears. Otherwise overrides the default
+ * ColorModel of ImageProducer and specifies the default RGBColorModel
+ *
+ * @param model the color model to be used most often by setPixels
+ * @see ColorModel */
+ public void setColorModel(ColorModel model)
+ {
+ origmodel = model;
+ newmodel = model;
+
+ if( ( model instanceof IndexColorModel) && canFilterIndexColorModel ) {
+ newmodel = filterIndexColorModel( (IndexColorModel) model );
+ consumer.setColorModel(newmodel);
+ }
+ else {
+ consumer.setColorModel(ColorModel.getRGBdefault());
+ }
+ }
+
+ /**
+ Registers a new ColorModel to subsitute for the old ColorModel when
+ setPixels encounters the a pixel with the old ColorModel. The pixel
+ remains unchanged except for a new ColorModel.
+
+ @param oldcm the old ColorModel
+ @param newcm the new ColorModel
+ */
+ public void substituteColorModel(ColorModel oldcm,
+ ColorModel newcm)
+ {
+ origmodel = oldcm;
+ newmodel = newcm;
+ }
+
+ /**
+ Filters an IndexColorModel through the filterRGB function. Uses
+ coordinates of -1 to indicate its filtering an index and not a pixel.
+
+ @param icm an IndexColorModel to filter
+ */
+ public IndexColorModel filterIndexColorModel(IndexColorModel icm)
+ {
+ int len = icm.getMapSize(), rgb;
+ byte reds[] = new byte[len], greens[] = new byte[len], blues[] = new byte[len], alphas[] = new byte[len];
+
+ icm.getAlphas( alphas );
+ icm.getReds( reds );
+ icm.getGreens( greens );
+ icm.getBlues( blues );
+
+ for( int i = 0; i < len; i++ )
+ {
+ rgb = filterRGB( -1, -1, makeColor ( alphas[i], reds[i], greens[i], blues[i] ) );
+ alphas[i] = (byte)(( 0xff000000 & rgb ) >> 24);
+ reds[i] = (byte)(( 0xff0000 & rgb ) >> 16);
+ greens[i] = (byte)(( 0xff00 & rgb ) >> 8);
+ blues[i] = (byte)(0xff & rgb);
+ }
+ return new IndexColorModel( icm.getPixelSize(), len, reds, greens, blues, alphas );
+ }
+
+ private int makeColor( byte a, byte r, byte g, byte b )
+ {
+ return ( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b );
+ }
+
+ /**
+ This functions filters a set of RGB pixels through filterRGB.
+
+ @param x the x coordinate of the rectangle
+ @param y the y coordinate of the rectangle
+ @param w the width of the rectangle
+ @param h the height of the rectangle
+ @param pixels the array of pixel values
+ @param offset the index of the first pixels in the <code>pixels</code> array
+ @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void filterRGBPixels(int x, int y, int w, int h, int[] pixels,
+ int offset, int scansize)
+ {
+ for (int yp = 0; yp < h; yp++)
+ {
+ for (int xp = 0; xp < w; xp++)
+ {
+ pixels[offset + xp] = filterRGB(xp + x, yp + y, pixels[offset + xp]);
+ }
+ offset += scansize;
+ }
+ }
+
+
+ /**
+ * If the ColorModel is the same ColorModel which as already converted
+ * then it converts it the converted ColorModel. Otherwise it passes the
+ * array of pixels through filterRGBpixels.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels,
+ int offset, int scansize)
+ {
+ if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
+ {
+ consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
+ }
+ else
+ {
+ int intPixels[] =
+ convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize );
+ filterRGBPixels( x, y, w, h, intPixels, offset, scansize );
+ consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), intPixels, offset, scansize);
+ }
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels,
+ int offset, int scansize)
+ {
+ if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
+ {
+ consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
+ }
+ else
+ {
+ //FIXME: Store the filtered pixels in a separate temporary buffer?
+ convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize );
+ filterRGBPixels( x, y, w, h, pixels, offset, scansize );
+ consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), pixels, offset, scansize);
+ }
+ }
+
+ private int[] convertColorModelToDefault(int x, int y, int w, int h,
+ ColorModel model, byte pixels[],
+ int offset, int scansize)
+ {
+ int intPixels[] = new int[pixels.length];
+ for (int i = 0; i < pixels.length; i++)
+ intPixels[i] = makeColorbyDefaultCM(model, pixels[i]);
+ return intPixels;
+ }
+
+ private void convertColorModelToDefault(int x, int y, int w, int h,
+ ColorModel model, int pixels[],
+ int offset, int scansize)
+ {
+ for (int i = 0; i < pixels.length; i++)
+ pixels[i] = makeColorbyDefaultCM(model, pixels[i]);
+ }
+
+ private int makeColorbyDefaultCM(ColorModel model, byte rgb)
+ {
+ return makeColor( model.getAlpha( rgb ) * 4, model.getRed( rgb ) * 4, model.getGreen( rgb ) * 4, model.getBlue( rgb ) * 4 );
+ }
+
+ private int makeColorbyDefaultCM(ColorModel model, int rgb)
+ {
+ return makeColor( model.getAlpha( rgb ), model.getRed( rgb ), model.getGreen( rgb ), model.getBlue( rgb ) );
+ }
+
+ private int makeColor( int a, int r, int g, int b )
+ {
+ return (int)( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b );
+ }
+
+
+ /**
+ Filters a single pixel from the default ColorModel.
+
+ @param x x-coordinate
+ @param y y-coordinate
+ @param rgb color
+ */
+ public abstract int filterRGB(int x,
+ int y,
+ int rgb);
+}
diff --git a/libjava/classpath/java/awt/image/Raster.java b/libjava/classpath/java/awt/image/Raster.java
new file mode 100644
index 00000000000..4af958a17c7
--- /dev/null
+++ b/libjava/classpath/java/awt/image/Raster.java
@@ -0,0 +1,546 @@
+/* Copyright (C) 2000, 2002, 2003 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.image;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class Raster
+{
+ protected SampleModel sampleModel;
+ protected DataBuffer dataBuffer;
+ protected int minX;
+ protected int minY;
+ protected int width;
+ protected int height;
+ protected int sampleModelTranslateX;
+ protected int sampleModelTranslateY;
+ protected int numBands;
+ protected int numDataElements;
+ protected Raster parent;
+
+ protected Raster(SampleModel sampleModel, Point origin)
+ {
+ this(sampleModel, sampleModel.createDataBuffer(), origin);
+ }
+
+ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Point origin)
+ {
+ this(sampleModel, dataBuffer,
+ new Rectangle(origin.x, origin.y,
+ sampleModel.getWidth(), sampleModel.getHeight()),
+ origin, null);
+ }
+
+ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Rectangle aRegion,
+ Point sampleModelTranslate, Raster parent)
+ {
+ this.sampleModel = sampleModel;
+ this.dataBuffer = dataBuffer;
+ this.minX = aRegion.x;
+ this.minY = aRegion.y;
+ this.width = aRegion.width;
+ this.height = aRegion.height;
+
+ // If sampleModelTranslate is null, use (0,0). Methods such as
+ // Raster.createRaster are specified to allow for a null argument.
+ if (sampleModelTranslate != null)
+ {
+ this.sampleModelTranslateX = sampleModelTranslate.x;
+ this.sampleModelTranslateY = sampleModelTranslate.y;
+ }
+
+ this.numBands = sampleModel.getNumBands();
+ this.numDataElements = sampleModel.getNumDataElements();
+ this.parent = parent;
+ }
+
+ public static WritableRaster createInterleavedRaster(int dataType,
+ 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;
+
+ int scanlineStride = bands*w;
+ return createInterleavedRaster(dataType, w, h, scanlineStride, bands,
+ 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);
+ return createWritableRaster(sm, location);
+ }
+
+ 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)
+ {
+ SampleModel sm = new BandedSampleModel(dataType, w, h, scanlineStride,
+ bankIndices, bandOffsets);
+ return createWritableRaster(sm, location);
+ }
+
+ public static WritableRaster createPackedRaster(int dataType,
+ int w, int h,
+ int[] bandMasks,
+ Point location)
+ {
+ SampleModel sm = new SinglePixelPackedSampleModel(dataType,
+ w, h,
+ bandMasks);
+ return createWritableRaster(sm, location);
+ }
+
+ public static WritableRaster createPackedRaster(int dataType,
+ int w, int h,
+ int bands, int bitsPerBand,
+ Point location)
+ {
+ if (bands <= 0 || (bands * bitsPerBand > getTypeBits(dataType)))
+ throw new IllegalArgumentException();
+
+ SampleModel sm;
+
+ if (bands == 1)
+ 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);
+ }
+ return createWritableRaster(sm, location);
+ }
+
+ 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);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ 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);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ 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);
+ 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);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ public static Raster createRaster(SampleModel sm, DataBuffer db,
+ Point location)
+ {
+ return new Raster(sm, db, location);
+ }
+
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ Point location)
+ {
+ return new WritableRaster(sm, location);
+ }
+
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ DataBuffer db,
+ Point location)
+ {
+ return new WritableRaster(sm, db, location);
+ }
+
+ public Raster getParent()
+ {
+ return parent;
+ }
+
+ public final int getSampleModelTranslateX()
+ {
+ return sampleModelTranslateX;
+ }
+
+ public final int getSampleModelTranslateY()
+ {
+ return sampleModelTranslateY;
+ }
+
+ public WritableRaster createCompatibleWritableRaster()
+ {
+ return new WritableRaster(getSampleModel(), new Point(minX, minY));
+ }
+
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ return createCompatibleWritableRaster(minX, minY, w, h);
+ }
+
+ public WritableRaster createCompatibleWritableRaster(Rectangle rect)
+ {
+ return createCompatibleWritableRaster(rect.x, rect.y,
+ rect.width, rect.height);
+ }
+
+ public WritableRaster createCompatibleWritableRaster(int x, int y,
+ int w, int h)
+ {
+ SampleModel sm = getSampleModel().createCompatibleSampleModel(w, h);
+ return new WritableRaster(sm, sm.createDataBuffer(),
+ new Point(x, y));
+ }
+
+ public Raster createTranslatedChild(int childMinX, int childMinY) {
+ int tcx = sampleModelTranslateX - minX + childMinX;
+ int tcy = sampleModelTranslateY - minY + childMinY;
+
+ return new Raster(sampleModel, dataBuffer,
+ 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)
+ {
+ /* FIXME: Throw RasterFormatException if child bounds extends
+ beyond the bounds of this raster. */
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ /*
+ data origin
+ /
+ +-------------------------
+ |\. __ parent trans
+ | \`.
+ | \ `. parent origin
+ | \ `. /
+ | /\ +-------- - -
+ |trans\ /<\-- deltaTrans
+ |child +-+-\---- - -
+ | /|`| \__ parent [x, y]
+ |child | |`. \
+ |origin| : `.\
+ | | / `\
+ | : / +
+ | child [x, y]
+
+ parent_xy - parent_trans = child_xy - child_trans
+
+ child_trans = parent_trans + child_xy - parent_xy
+ */
+
+ return new Raster(sm, dataBuffer,
+ new Rectangle(childMinX, childMinY,
+ width, height),
+ new Point(sampleModelTranslateX+childMinX-parentX,
+ sampleModelTranslateY+childMinY-parentY),
+ this);
+ }
+
+ public Rectangle getBounds()
+ {
+ return new Rectangle(minX, minY, width, height);
+ }
+
+ public final int getMinX()
+ {
+ return minX;
+ }
+
+ public final int getMinY()
+ {
+ return minY;
+ }
+
+ public final int getWidth()
+ {
+ return width;
+ }
+
+ public final int getHeight()
+ {
+ return height;
+ }
+
+ public final int getNumBands()
+ {
+ return numBands;
+ }
+
+ public final int getNumDataElements()
+ {
+ return numDataElements;
+ }
+
+ public final int getTransferType()
+ {
+ return sampleModel.getTransferType();
+ }
+
+ public DataBuffer getDataBuffer()
+ {
+ return dataBuffer;
+ }
+
+ public SampleModel getSampleModel()
+ {
+ return sampleModel;
+ }
+
+ public Object getDataElements(int x, int y, Object outData)
+ {
+ return sampleModel.getDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ outData, dataBuffer);
+ }
+
+ public Object getDataElements(int x, int y, int w, int h,
+ Object outData)
+ {
+ return sampleModel.getDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, outData, dataBuffer);
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray)
+ {
+ return sampleModel.getPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ iArray, dataBuffer);
+ }
+
+ public float[] getPixel(int x, int y, float[] fArray)
+ {
+ return sampleModel.getPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ fArray, dataBuffer);
+ }
+
+ public double[] getPixel(int x, int y, double[] dArray)
+ {
+ return sampleModel.getPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ dArray, dataBuffer);
+ }
+
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray)
+ {
+ return sampleModel.getPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, iArray, dataBuffer);
+ }
+
+ public float[] getPixels(int x, int y, int w, int h,
+ float[] fArray)
+ {
+ return sampleModel.getPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, fArray, dataBuffer);
+ }
+
+ public double[] getPixels(int x, int y, int w, int h,
+ double[] dArray)
+ {
+ return sampleModel.getPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, dArray, dataBuffer);
+ }
+
+ public int getSample(int x, int y, int b)
+ {
+ return sampleModel.getSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, dataBuffer);
+ }
+
+ public float getSampleFloat(int x, int y, int b)
+ {
+ return sampleModel.getSampleFloat(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, dataBuffer);
+ }
+
+ public double getSampleDouble(int x, int y, int b)
+ {
+ return sampleModel.getSampleDouble(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, dataBuffer);
+ }
+
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int[] iArray)
+ {
+ 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);
+ }
+
+ 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);
+ }
+
+ /**
+ * Create a String representing the stat of this Raster.
+ * @return A String representing the stat of this Raster.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+
+ result.append(getClass().getName());
+ result.append("[(");
+ result.append(minX).append(",").append(minY).append("), ");
+ result.append(width).append(" x ").append(height).append(",");
+ result.append(sampleModel).append(",");
+ result.append(dataBuffer);
+ result.append("]");
+
+ return result.toString();
+ }
+
+ // Map from datatype to bits
+ private static int getTypeBits(int dataType)
+ {
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ return 8;
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+ return 16;
+ case DataBuffer.TYPE_INT:
+ case DataBuffer.TYPE_FLOAT:
+ return 32;
+ case DataBuffer.TYPE_DOUBLE:
+ return 64;
+ default:
+ return 0;
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/image/RasterFormatException.java b/libjava/classpath/java/awt/image/RasterFormatException.java
new file mode 100644
index 00000000000..582c2ae5ab2
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RasterFormatException.java
@@ -0,0 +1,65 @@
+/* RasterFormatException.java -- indicates invalid layout in Raster
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * This exception is thrown when there is invalid layout information in
+ * <code>Raster</code>
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Raster
+ * @status updated to 1.4
+ */
+public class RasterFormatException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 96598996116164315L;
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public RasterFormatException(String message)
+ {
+ super(message);
+ }
+} // class RasterFormatException
diff --git a/libjava/classpath/java/awt/image/RasterOp.java b/libjava/classpath/java/awt/image/RasterOp.java
new file mode 100644
index 00000000000..e081ca3d2ad
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RasterOp.java
@@ -0,0 +1,57 @@
+/* RasterOp.java --
+ Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+public interface RasterOp
+{
+ WritableRaster filter(Raster src, WritableRaster dest);
+
+ Rectangle2D getBounds2D(Raster src);
+
+ WritableRaster createCompatibleDestRaster(Raster src);
+
+ Point2D getPoint2D(Point2D srcPoint, Point2D destPoint);
+
+ RenderingHints getRenderingHints();
+}
+
diff --git a/libjava/classpath/java/awt/image/RenderedImage.java b/libjava/classpath/java/awt/image/RenderedImage.java
new file mode 100644
index 00000000000..b35f8602129
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RenderedImage.java
@@ -0,0 +1,70 @@
+/* RenderedImage.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Rectangle;
+import java.util.Vector;
+
+/**
+ * NEEDS DOCUMENTATION
+ */
+public interface RenderedImage
+{
+ Vector getSources();
+ Object getProperty(String name);
+ String[] getPropertyNames();
+ ColorModel getColorModel();
+ SampleModel getSampleModel();
+ int getWidth();
+ int getHeight();
+ int getMinX();
+ int getMinY();
+ int getNumXTiles();
+ int getNumYTiles();
+ int getMinTileX();
+ int getMinTileY();
+ int getTileWidth();
+ int getTileHeight();
+ int getTileGridXOffset();
+ int getTileGridYOffset();
+ Raster getTile(int x, int y);
+ Raster getData();
+ Raster getData(Rectangle r);
+ WritableRaster copyData(WritableRaster raster);
+} // interface RenderedImage
diff --git a/libjava/classpath/java/awt/image/ReplicateScaleFilter.java b/libjava/classpath/java/awt/image/ReplicateScaleFilter.java
new file mode 100644
index 00000000000..3841e49d538
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ReplicateScaleFilter.java
@@ -0,0 +1,244 @@
+/* ReplicateScaleFilter.java -- Java class for filtering images
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * This filter should be used for fast scaling of images where the result
+ * does not need to ensure straight lines are still straight, etc. The
+ * exact method is not defined by Sun but some sort of fast Box filter should
+ * probably be correct.
+ * <br>
+ * Currently this filter does nothing and needs to be implemented.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class ReplicateScaleFilter extends ImageFilter
+{
+ public ReplicateScaleFilter(int width, int height) {
+ destHeight = height;
+ destWidth = width;
+ }
+
+ /**
+ * The height of the destination image.
+ */
+ protected int destHeight;
+
+ /**
+ * The width of the destination image.
+ */
+ protected int destWidth;
+
+ /**
+ * The height of the source image.
+ */
+ protected int srcHeight;
+
+ /**
+ * The width of the source image.
+ */
+ protected int srcWidth;
+
+ /**
+ *
+ */
+ protected int srcrows[];
+
+ /**
+ *
+ */
+ protected int srccols[];
+
+ /**
+ *
+ */
+ protected Object outpixbuf;
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method. A filter can override this
+ * method to intercept these calls from the producer in order to
+ * change either the width or the height before in turn calling
+ * the consumer's <code>setDimensions</code> method.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void setDimensions(int width, int height)
+ {
+ srcWidth = width;
+ srcHeight = height;
+
+ /* If either destHeight or destWidth is < 0, the image should
+ maintain its original aspect ratio. When both are < 0,
+ just maintain the original width and height. */
+ if (destWidth < 0 && destHeight < 0)
+ {
+ destWidth = width;
+ destHeight = height;
+ }
+ else if (destWidth < 0)
+ {
+ destWidth = (int) (width * ((double) destHeight / srcHeight));
+ }
+ else if (destHeight < 0)
+ {
+ destHeight = (int) (height * ((double) destWidth / srcWidth));
+ }
+
+ consumer.setDimensions(destWidth, destHeight);
+ }
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ *
+ * @param props the list of properties associated with this image
+ */
+ public void setProperties(Hashtable props)
+ {
+ props.put("filters", "ReplicateScaleFilter");
+ consumer.setProperties(props);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize)
+ {
+ double rx = ((double) srcWidth) / destWidth;
+ double ry = ((double) srcHeight) / destHeight;
+
+ int destScansize = (int) Math.round(scansize / rx);
+
+ byte[] destPixels = replicatePixels(x, y, w, h,
+ model, pixels, offset, scansize,
+ rx, ry, destScansize);
+
+ consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry),
+ (int) Math.ceil(w/rx), (int) Math.ceil(h/ry),
+ model, destPixels, 0, destScansize);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize)
+ {
+ double rx = ((double) srcWidth) / destWidth;
+ double ry = ((double) srcHeight) / destHeight;
+
+ int destScansize = (int) Math.round(scansize / rx);
+
+ int[] destPixels = replicatePixels(x, y, w, h,
+ model, pixels, offset, scansize,
+ rx, ry, destScansize);
+
+ consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry),
+ (int) Math.ceil(w/rx), (int) Math.ceil(h/ry),
+ model, destPixels, 0, destScansize);
+ }
+
+ private byte[] replicatePixels(int srcx, int srcy, int srcw, int srch,
+ ColorModel model, byte[] srcPixels,
+ int srcOffset, int srcScansize,
+ double rx, double ry, int destScansize)
+ {
+ byte[] destPixels =
+ new byte[(int) Math.ceil(srcw/rx) * (int) Math.ceil(srch/ry)];
+
+ int a, b;
+ for (int i = 0; i < destPixels.length; i++)
+ {
+ a = (int) ((int) ( ((double) i) / destScansize) * ry) * srcScansize;
+ b = (int) ((i % destScansize) * rx);
+ if ((a + b + srcOffset) < srcPixels.length)
+ destPixels[i] = srcPixels[a + b + srcOffset];
+ }
+
+ return destPixels;
+ }
+
+ private int[] replicatePixels(int srcx, int srcy, int srcw, int srch,
+ ColorModel model, int[] srcPixels,
+ int srcOffset, int srcScansize,
+ double rx, double ry, int destScansize)
+ {
+ int[] destPixels =
+ new int[(int) Math.ceil(srcw/rx) * (int) Math.ceil(srch/ry)];
+
+ int a, b;
+ for (int i = 0; i < destPixels.length; i++)
+ {
+ a = (int) ((int) ( ((double) i) / destScansize) * ry) * srcScansize;
+ b = (int) ((i % destScansize) * rx);
+ if ((a + b + srcOffset) < srcPixels.length)
+ destPixels[i] = srcPixels[a + b + srcOffset];
+ }
+
+ return destPixels;
+ }
+}
+
diff --git a/libjava/classpath/java/awt/image/RescaleOp.java b/libjava/classpath/java/awt/image/RescaleOp.java
new file mode 100644
index 00000000000..35b42f79ccd
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RescaleOp.java
@@ -0,0 +1,218 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+/**
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public class RescaleOp implements BufferedImageOp, RasterOp
+{
+ private float[] scale;
+ private float[] offsets;
+ private RenderingHints hints = null;
+
+ public RescaleOp(float[] scaleFactors,
+ float[] offsets,
+ RenderingHints hints)
+ {
+ this.scale = scaleFactors;
+ this.offsets = offsets;
+ this.hints = hints;
+ }
+
+ public RescaleOp(float scaleFactor,
+ float offset,
+ RenderingHints hints)
+ {
+ scale = new float[]{ scaleFactor };
+ offsets = new float[]{offset};
+ this.hints = hints;
+ }
+
+ public final float[] getScaleFactors(float[] scaleFactors)
+ {
+ if (scaleFactors == null)
+ scaleFactors = new float[scale.length];
+ System.arraycopy(scale, 0, scaleFactors, 0, scale.length);
+ return scaleFactors;
+ }
+
+ public final float[] getOffsets(float[] offsets)
+ {
+ if (offsets == null)
+ offsets = new float[this.offsets.length];
+ System.arraycopy(this.offsets, 0, offsets, 0, this.offsets.length);
+ return offsets;
+ }
+
+ public final int getNumFactors()
+ {
+ return scale.length;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getRenderingHints()
+ */
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage)
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ // TODO Make sure premultiplied alpha is handled correctly.
+ // TODO See that color conversion is handled.
+ // TODO figure out how to use rendering hints.
+ if (scale.length != offsets.length)
+ throw new IllegalArgumentException();
+
+ ColorModel scm = src.getColorModel();
+ if (dst == null) dst = createCompatibleDestImage(src, null);
+
+ WritableRaster wsrc = src.getRaster();
+ WritableRaster wdst = dst.getRaster();
+
+ // Share constant across colors except alpha
+ if (scale.length == 1 || scale.length == scm.getNumColorComponents())
+ {
+ // Construct a raster that doesn't include an alpha band.
+ int[] subbands = new int[scm.getNumColorComponents()];
+ for (int i=0; i < subbands.length; i++) subbands[i] = i;
+ wsrc =
+ wsrc.createWritableChild(wsrc.minX, wsrc.minY, wsrc.width, wsrc.height,
+ wsrc.minX, wsrc.minY, subbands);
+ }
+ // else all color bands
+
+ filter(wsrc, wdst);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ if (dest == null) dest = src.createCompatibleWritableRaster();
+
+ // Required sanity checks
+ if (src.numBands != dest.numBands || scale.length != offsets.length)
+ throw new IllegalArgumentException();
+ if (scale.length != 1 && scale.length != src.numBands)
+ throw new IllegalArgumentException();
+
+ // Create scaling arrays if needed
+ float[] lscale = scale;
+ float[] loff = offsets;
+ if (scale.length == 1)
+ {
+ lscale = new float[src.numBands];
+ Arrays.fill(lscale, scale[0]);
+ loff = new float[src.numBands];
+ Arrays.fill(loff, offsets[0]);
+ }
+
+ // TODO The efficiency here can be improved for various data storage
+ // patterns, aka SampleModels.
+ float[] pixel = new float[src.numBands];
+ for (int y = src.minY; y < src.height + src.minY; y++)
+ for (int x = src.minX; x < src.width + src.minX; x++)
+ {
+ src.getPixel(x, y, pixel);
+ for (int b = 0; b < src.numBands; b++)
+ pixel[b] = pixel[b] * lscale[b] + loff[b];
+ dest.setPixel(x, y, pixel);
+ }
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ if (dstCM == null) dstCM = src.getColorModel();
+ WritableRaster wr = src.getRaster().createCompatibleWritableRaster();
+ BufferedImage image
+ = new BufferedImage(dstCM, wr, src.isPremultiplied, null);
+ return image;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public final Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst) {
+ if (dst == null) dst = (Point2D) src.clone();
+ else dst.setLocation(src);
+ return dst;
+ }
+
+}
diff --git a/libjava/classpath/java/awt/image/SampleModel.java b/libjava/classpath/java/awt/image/SampleModel.java
new file mode 100644
index 00000000000..257e30a5bd5
--- /dev/null
+++ b/libjava/classpath/java/awt/image/SampleModel.java
@@ -0,0 +1,477 @@
+/* Copyright (C) 2000, 2001, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public abstract class SampleModel
+{
+ /** Width of image described. */
+ protected int width;
+
+ /** Height of image described. */
+ protected int height;
+
+ /** Number of bands in the image described. */
+ protected int numBands;
+
+ /**
+ * The DataBuffer type that is used to store the data of the image
+ * described.
+ */
+ protected int dataType;
+
+ public SampleModel(int dataType, int w, int h, int numBands)
+ {
+ if ((w <= 0) || (h <= 0))
+ throw new IllegalArgumentException((w <= 0 ? " width<=0" : " width is ok")
+ +(h <= 0 ? " height<=0" : " height is ok"));
+
+ // FIXME: How can an int be greater than Integer.MAX_VALUE?
+ // FIXME: How do we identify an unsupported data type?
+
+ this.dataType = dataType;
+ this.width = w;
+ this.height = h;
+ this.numBands = numBands;
+ }
+
+ public final int getWidth()
+ {
+ return width;
+ }
+
+ public final int getHeight()
+ {
+ return height;
+ }
+
+ public final int getNumBands()
+ {
+ return numBands;
+ }
+
+ public abstract int getNumDataElements();
+
+ public final int getDataType()
+ {
+ return dataType;
+ }
+
+ public int getTransferType()
+ {
+ // FIXME: Is this a reasonable default implementation?
+ return dataType;
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ if (iArray == null) iArray = new int[numBands];
+ for (int b=0; b<numBands; b++) iArray[b] = getSample(x, y, b, data);
+ return iArray;
+ }
+
+ /**
+ *
+ * This method is provided as a faster alternative to getPixel(),
+ * that can be used when there is no need to decode the pixel into
+ * separate sample values.
+ *
+ * @param obj An array to return the pixel data in. If null, an
+ * array of the right type and size will be created.
+ *
+ * @return A single pixel as an array object of a primitive type,
+ * based on the transfer type. Eg. if transfer type is
+ * DataBuffer.TYPE_USHORT, then a short[] object is returned.
+ */
+ public abstract Object getDataElements(int x, int y, Object obj,
+ DataBuffer data);
+
+
+ public Object getDataElements(int x, int y, int w, int h, Object obj,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int numDataElements = getNumDataElements();
+ int dataSize = numDataElements*size;
+
+ if (obj == null)
+ {
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ obj = new byte[dataSize];
+ break;
+ case DataBuffer.TYPE_USHORT:
+ obj = new short[dataSize];
+ break;
+ case DataBuffer.TYPE_INT:
+ obj = new int[dataSize];
+ break;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ }
+ Object pixelData = null;
+ int outOffset = 0;
+ for (int yy = y; yy<(y+h); yy++)
+ {
+ for (int xx = x; xx<(x+w); xx++)
+ {
+ pixelData = getDataElements(xx, yy, pixelData, data);
+ System.arraycopy(pixelData, 0, obj, outOffset,
+ numDataElements);
+ outOffset += numDataElements;
+ }
+ }
+ return obj;
+ }
+
+ public abstract void setDataElements(int x, int y, Object obj,
+ DataBuffer data);
+
+ public void setDataElements(int x, int y, int w, int h,
+ Object obj, DataBuffer data)
+ {
+ int size = w*h;
+ int numDataElements = getNumDataElements();
+ int dataSize = numDataElements*size;
+
+ Object pixelData;
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ pixelData = new byte[numDataElements];
+ break;
+ case DataBuffer.TYPE_USHORT:
+ pixelData = new short[numDataElements];
+ break;
+ case DataBuffer.TYPE_INT:
+ pixelData = new int[numDataElements];
+ break;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ int inOffset = 0;
+
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(obj, inOffset, pixelData, 0,
+ numDataElements);
+ setDataElements(xx, yy, pixelData, data);
+ inOffset += numDataElements;
+ }
+ }
+ }
+
+ public float[] getPixel(int x, int y, float[] fArray, DataBuffer data)
+ {
+ if (fArray == null) fArray = new float[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ fArray[b] = getSampleFloat(x, y, b, data);
+ }
+ return fArray;
+ }
+
+ public double[] getPixel(int x, int y, double[] dArray, DataBuffer data) {
+ if (dArray == null) dArray = new double[numBands];
+ for (int b=0; b<numBands; b++)
+ {
+ dArray[b] = getSampleDouble(x, y, b, data);
+ }
+ return dArray;
+ }
+
+ /* FIXME: Should it return a banded or pixel interleaved array of
+ samples? (Assume interleaved.) */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ int[] pixel = null;
+ if (iArray == null) iArray = new int[w*h*numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ pixel = getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, iArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return iArray;
+ }
+
+ /* FIXME: Should it return a banded or pixel interleaved array of
+ samples? (Assume interleaved.) */
+ public float[] getPixels(int x, int y, int w, int h, float[] fArray,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ float[] pixel = null;
+ if (fArray == null) fArray = new float[w*h*numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ pixel = getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, fArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return fArray;
+ }
+
+ /* FIXME: Should it return a banded or pixel interleaved array of
+ samples? (Assume interleaved.) */
+ public double[] getPixels(int x, int y, int w, int h, double[] dArray,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ double[] pixel = null;
+ if (dArray == null) dArray = new double[w*h*numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ pixel = getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, dArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return dArray;
+ }
+
+ public abstract int getSample(int x, int y, int b, DataBuffer data);
+
+ public float getSampleFloat(int x, int y, int b, DataBuffer data)
+ {
+ return getSample(x, y, b, data);
+ }
+
+ public double getSampleDouble(int x, int y, int b, DataBuffer data)
+ {
+ return getSampleFloat(x, y, b, data);
+ }
+
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int[] iArray, DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ if (iArray == null) iArray = new int[size];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ iArray[outOffset++] = getSample(xx, yy, b, data);
+ }
+ }
+ return iArray;
+ }
+
+ public float[] getSamples(int x, int y, int w, int h, int b,
+ float[] fArray, DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ if (fArray == null) fArray = new float[size];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ fArray[outOffset++] = getSampleFloat(xx, yy, b, data);
+ }
+ }
+ return fArray;
+ }
+
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double[] dArray, DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ if (dArray == null) dArray = new double[size];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ dArray[outOffset++] = getSampleDouble(xx, yy, b, data);
+ }
+ }
+ return dArray;
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ public void setPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ int[] pixel = new int[numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(iArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ public void setPixels(int x, int y, int w, int h, float[] fArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ float[] pixel = new float[numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(fArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ public void setPixels(int x, int y, int w, int h, double[] dArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ double[] pixel = new double[numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(dArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ public abstract void setSample(int x, int y, int b, int s,
+ DataBuffer data);
+
+ public void setSample(int x, int y, int b, float s,
+ DataBuffer data)
+ {
+ setSample(x, y, b, (int) s, data);
+ }
+
+ public void setSample(int x, int y, int b, double s,
+ DataBuffer data)
+ {
+ setSample(x, y, b, (float) s, data);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ int[] iArray, DataBuffer data)
+ {
+ int size = w*h;
+ int inOffset = 0;
+ for (int yy=y; yy<(y+h); yy++)
+ for (int xx=x; xx<(x+w); xx++)
+ setSample(xx, yy, b, iArray[inOffset++], data);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ float[] fArray, DataBuffer data)
+ {
+ int size = w*h;
+ int inOffset = 0;
+ for (int yy=y; yy<(y+h); yy++)
+ for (int xx=x; xx<(x+w); xx++)
+ setSample(xx, yy, b, fArray[inOffset++], data);
+
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ double[] dArray, DataBuffer data) {
+ int size = w*h;
+ int inOffset = 0;
+ for (int yy=y; yy<(y+h); yy++)
+ for (int xx=x; xx<(x+w); xx++)
+ setSample(xx, yy, b, dArray[inOffset++], data);
+ }
+
+ public abstract SampleModel createCompatibleSampleModel(int w, int h);
+
+ /**
+ * Return a SampleModel with a subset of the bands in this model.
+ *
+ * Selects bands.length bands from this sample model. The bands chosen
+ * are specified in the indices of bands[]. This also permits permuting
+ * the bands as well as taking a subset. Thus, giving an array with
+ * 1, 2, 3, ..., numbands, will give an identical sample model.
+ *
+ * @param bands Array with band indices to include.
+ * @return A new sample model
+ */
+ public abstract SampleModel createSubsetSampleModel(int[] bands);
+
+ public abstract DataBuffer createDataBuffer();
+
+ public abstract int[] getSampleSize();
+
+ public abstract int getSampleSize(int band);
+}
diff --git a/libjava/classpath/java/awt/image/ShortLookupTable.java b/libjava/classpath/java/awt/image/ShortLookupTable.java
new file mode 100644
index 00000000000..5915a7939a3
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ShortLookupTable.java
@@ -0,0 +1,162 @@
+/* ShortLookupTable.java -- Java class for a pixel translation table.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * ShortLookupTable represents translation arrays for pixel values. It wraps
+ * one or more data arrays for each layer (or component) in an image, such as
+ * Alpha, R, G, and B. When doing translation, the offset is subtracted from
+ * the pixel values to allow a subset of an array to be used.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @version 1.0
+ */
+public class ShortLookupTable extends LookupTable
+{
+ // Array of translation tables.
+ private short data[][];
+
+ /**
+ * Creates a new <code>ShortLookupTable</code> instance.
+ *
+ * Offset is subtracted from pixel values when looking up in the translation
+ * tables. If data.length is one, the same table is applied to all pixel
+ * components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param data Array of lookup tables.
+ * @exception IllegalArgumentException if offset &lt; 0 or data.length &lt; 1.
+ */
+ public ShortLookupTable(int offset, short[][] data)
+ throws IllegalArgumentException
+ {
+ super(offset, data.length);
+ this.data = data;
+ }
+
+ /**
+ * Creates a new <code>ShortLookupTable</code> instance.
+ *
+ * Offset is subtracted from pixel values when looking up in the translation
+ * table. The same table is applied to all pixel components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param data Lookup table for all components.
+ * @exception IllegalArgumentException if offset &lt; 0.
+ */
+ public ShortLookupTable(int offset, short[] data)
+ throws IllegalArgumentException
+ {
+ super(offset, 1);
+ this.data = new short[][] {data};
+ }
+
+ /** Return the lookup tables. */
+ public final short[][] getTable()
+ {
+ return data;
+ }
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dst Destination array for values, or null.
+ * @return Translated values for the pixel.
+ */
+ public int[] lookupPixel(int[] src, int[] dst)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if (dst == null)
+ dst = new int[src.length];
+
+ if (data.length == 1)
+ 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];
+
+ return dst;
+ }
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @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
+ {
+ if (dst == null)
+ 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];
+ else
+ for (int i=0; i < src.length; i++)
+ dst[i] = data[i][((int)src[i]) - offset];
+
+ return dst;
+
+ }
+}
diff --git a/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java b/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java
new file mode 100644
index 00000000000..6ccce753bd3
--- /dev/null
+++ b/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java
@@ -0,0 +1,449 @@
+/* Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import gnu.java.awt.BitMaskExtent;
+import gnu.java.awt.Buffers;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class SinglePixelPackedSampleModel extends SampleModel
+{
+ private int scanlineStride;
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;
+
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int[] bitMasks)
+ {
+ this(dataType, w, h, w, bitMasks);
+ }
+
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int scanlineStride, int[] bitMasks)
+ {
+ super(dataType, w, h, bitMasks.length);
+
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_INT:
+ break;
+ default:
+ throw new IllegalArgumentException("SinglePixelPackedSampleModel unsupported dataType");
+ }
+
+ this.scanlineStride = scanlineStride;
+ this.bitMasks = bitMasks;
+
+ bitOffsets = new int[numBands];
+ sampleSize = new int[numBands];
+
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b=0; b<numBands; b++)
+ {
+ extent.setMask(bitMasks[b]);
+ sampleSize[b] = extent.bitWidth;
+ bitOffsets[b] = extent.leastSignificantBit;
+ }
+ }
+
+ public int getNumDataElements()
+ {
+ return 1;
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ /* FIXME: We can avoid recalculation of bit offsets and sample
+ sizes here by passing these from the current instance to a
+ special private constructor. */
+ return new SinglePixelPackedSampleModel(dataType, w, h, bitMasks);
+ }
+
+
+ /**
+ * 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.
+ */
+ public DataBuffer createDataBuffer()
+ {
+ int size;
+
+ // 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 - 1) + width;
+
+ return Buffers.createBuffer(getDataType(), size);
+ }
+
+
+ public int[] getSampleSize()
+ {
+ return sampleSize;
+ }
+
+ public int getSampleSize(int band)
+ {
+ return sampleSize[band];
+ }
+
+ public int getOffset(int x, int y)
+ {
+ return scanlineStride*y + x;
+ }
+
+ public int[] getBitOffsets()
+ {
+ return bitOffsets;
+ }
+
+ public int[] getBitMasks()
+ {
+ return bitMasks;
+ }
+
+ public int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ // FIXME: Is this the right way to interpret bands?
+
+ int numBands = bands.length;
+
+ int[] bitMasks = new int[numBands];
+
+ for (int b=0; b<numBands; b++)
+ bitMasks[b] = this.bitMasks[bands[b]];
+
+ return new SinglePixelPackedSampleModel(dataType, width, height,
+ scanlineStride, bitMasks);
+ }
+
+ public Object getDataElements(int x, int y, Object obj,
+ DataBuffer data)
+ {
+ int offset = scanlineStride*y + x + data.getOffset();
+
+ return Buffers.getData(data, offset, obj,
+ 0, // destination offset,
+ 1 // length
+ );
+ }
+
+ /**
+ * 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 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)
+ */
+ public Object getDataElements(int x, int y, int w, int h, Object obj,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int dataSize = size;
+ Object pixelData = null;
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ pixelData = ((DataBufferByte) data).getData();
+ if (obj == null) obj = new byte[dataSize];
+ break;
+ case DataBuffer.TYPE_USHORT:
+ pixelData = ((DataBufferUShort) data).getData();
+ if (obj == null) obj = new short[dataSize];
+ break;
+ case DataBuffer.TYPE_INT:
+ pixelData = ((DataBufferInt) data).getData();
+ if (obj == null) obj = new int[dataSize];
+ break;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ 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);
+ }
+ else
+ {
+ // Since we do not need the full width we need to copy line by line.
+ int outOffset = 0;
+ int dataOffset = scanlineStride*y + x + data.getOffset();
+ for (int yy = y; yy<(y+h); yy++)
+ {
+ System.arraycopy(pixelData, dataOffset, obj, outOffset, w);
+ dataOffset += scanlineStride;
+ outOffset += w;
+ }
+ }
+ return obj;
+ }
+
+
+ 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++)
+ iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b];
+
+ return iArray;
+ }
+
+ 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++)
+ {
+ int lineOffset = offset;
+ for (x=0; x<w; x++)
+ {
+ int samples = data.getElem(lineOffset++);
+ for (int b=0; b<numBands; b++)
+ iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
+ }
+ offset += scanlineStride;
+ }
+ return iArray;
+ }
+
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ int samples = data.getElem(offset);
+ return (samples & bitMasks[b]) >>> bitOffsets[b];
+ }
+
+ /**
+ * This method implements a more efficient way to set data elements than the default
+ * implementation of the super class. It sets the data elements line by line instead
+ * of pixel by pixel.
+ * @param x The x-coordinate of the data elements in <code>obj</code>.
+ * @param y The y-coordinate of the data elements in <code>obj</code>.
+ * @param w The width of the data elements in <code>obj</code>.
+ * @param h The height of the data elements in <code>obj</code>.
+ * @param obj The primitive array containing the data elements to set.
+ * @param data The DataBuffer to store the data elements into.
+ * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
+ */
+ public void setDataElements(int x, int y, int w, int h,
+ Object obj, DataBuffer data)
+ {
+
+ Object pixelData;
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ pixelData = ((DataBufferByte) data).getData();
+ break;
+ case DataBuffer.TYPE_USHORT:
+ pixelData = ((DataBufferUShort) data).getData();
+ break;
+ case DataBuffer.TYPE_INT:
+ pixelData = ((DataBufferInt) data).getData();
+ break;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+
+ int inOffset = 0;
+ int dataOffset = scanlineStride*y + x + data.getOffset();
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ System.arraycopy(obj,inOffset,pixelData,dataOffset,w);
+ dataOffset += scanlineStride;
+ inOffset += w;
+ }
+ }
+
+
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x + data.getOffset();
+
+ int transferType = getTransferType();
+ if (getTransferType() != data.getDataType())
+ {
+ throw new IllegalArgumentException("transfer type ("+
+ getTransferType()+"), "+
+ "does not match data "+
+ "buffer type (" +
+ data.getDataType() +
+ ").");
+ }
+
+ try
+ {
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] in = (byte[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferUShort out = (DataBufferUShort) data;
+ short[] in = (short[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] in = (int[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ // FIXME: Fill in the other possible types.
+ default:
+ throw new InternalError();
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe)
+ {
+ String msg = "While writing data elements" +
+ ", x="+x+", y="+y+
+ ", width="+width+", height="+height+
+ ", scanlineStride="+scanlineStride+
+ ", offset="+offset+
+ ", data.getSize()="+data.getSize()+
+ ", data.getOffset()="+data.getOffset()+
+ ": " +
+ aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
+ }
+ }
+
+ 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++)
+ samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b];
+
+ data.setElem(offset, samples);
+ }
+
+ /**
+ * This method implements a more efficient way to set pixels than the default
+ * implementation of the super class. It copies the pixel components directly
+ * from the input array instead of creating a intermediate buffer.
+ * @param x The x-coordinate of the pixel rectangle in <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle in <code>obj</code>.
+ * @param w The width of the pixel rectangle in <code>obj</code>.
+ * @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)
+ */
+ public void setPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ int[] pixel = new int[numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ int offset = scanlineStride*yy + x;
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ int samples = 0;
+ for (int b=0; b<numBands; b++)
+ samples |= (iArray[inOffset+b] << bitOffsets[b]) & bitMasks[b];
+ data.setElem(0, offset, samples);
+ inOffset += numBands;
+ offset += 1;
+ }
+ }
+ }
+
+
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ int samples = data.getElem(offset);
+ int bitMask = bitMasks[b];
+ samples &= ~bitMask;
+ samples |= (s << bitOffsets[b]) & bitMask;
+ data.setElem(offset, samples);
+ }
+
+ /**
+ * Creates a String with some information about this SampleModel.
+ * @return A String describing this SampleModel.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+ result.append(getClass().getName());
+ result.append("[");
+ result.append("scanlineStride=").append(scanlineStride);
+ for(int i=0; i < bitMasks.length; i+=1)
+ {
+ result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
+ }
+
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/TileObserver.java b/libjava/classpath/java/awt/image/TileObserver.java
new file mode 100644
index 00000000000..99aafbce81c
--- /dev/null
+++ b/libjava/classpath/java/awt/image/TileObserver.java
@@ -0,0 +1,47 @@
+/* TileObserver.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * NEEDS DOCUMENTATION
+ */
+public interface TileObserver
+{
+ void tileUpdate(WritableRenderedImage src, int x, int y, boolean writable);
+} // interface TileObserver
diff --git a/libjava/classpath/java/awt/image/VolatileImage.java b/libjava/classpath/java/awt/image/VolatileImage.java
new file mode 100644
index 00000000000..308654162ae
--- /dev/null
+++ b/libjava/classpath/java/awt/image/VolatileImage.java
@@ -0,0 +1,253 @@
+/* VolatileImage.java -- a hardware-accelerated image buffer
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Transparency;
+import java.awt.ImageCapabilities;
+
+/**
+ * VolatileImage represents a hardware-accelerated graphics buffer.
+ * The native graphics system may free or damage the resources
+ * occupied by a VolatileImage at any time. As such, one must
+ * frequently check the "validity" of the image buffer's resources.
+ *
+ * A volatile image's "validity" depends on multiple factors. Its
+ * resources may have become unavailble in which case you must
+ * reallocate them. If you move the image from one output device to
+ * another, you may need to recreate the image's resources if the new
+ * output device's capabilities don't match the old one's. Finally,
+ * if the contents of the image's buffer have been damaged you must
+ * re-render the image.
+ *
+ * VolatileImages should always be created using either
+ * Component.createVolatileImage or
+ * GraphicsConfiguration.createCompatibleVolatileImage.
+ */
+public abstract class VolatileImage extends Image
+ implements Transparency
+{
+ /**
+ * One of validate's possible return values. Indicates that the
+ * image buffer matches its graphics configuration's capabilities
+ * and that its resources are initialized and ready to be drawn
+ * into. Also implies that any existing image rendered to the
+ * buffer is intact and need not be re-rendered.
+ */
+ public static final int IMAGE_OK = 0;
+
+ /**
+ * One of validate's possible return values. Indicates that the
+ * image buffer has been restored, meaning that it is valid and
+ * ready-to-use but that its previous contents have been lost. This
+ * return value implies that the image needs to be re-rendered.
+ */
+ public static final int IMAGE_RESTORED = 1;
+
+ /**
+ * One of validate's possible return values. Indicates that the
+ * image buffer type is unsupported by the current graphics
+ * configuration. The graphics configuration may have changed, for
+ * example if the image moved from one output device to another.
+ * This return value implies that the image buffer's resources
+ * should be re-acquired.
+ */
+ public static final int IMAGE_INCOMPATIBLE = 2;
+
+ /**
+ * This image's transparency type. One of Transparency.BITMASK,
+ * Transparency.OPAQUE or Transparency.TRANSLUCENT.
+ *
+ * @since 1.5
+ */
+ protected int transparency;
+
+ /**
+ * Default constructor. VolatileImages should not be created
+ * directly. Rather, you should use Component.createVolatileImage
+ * or GraphicsConfiguration.createCompatibleVolatileImage.
+ */
+ public VolatileImage()
+ {
+ }
+
+ /**
+ * Returns an image representing the current state of the volatile
+ * image buffer. The returned image is static meaning that it is
+ * not updated after being created. It is a snapshot of the
+ * volatile image buffer at the time getSnapshot is called.
+ *
+ * This method, which reads pixels from the volatile image buffer,
+ * may be less-performant than methods that write pixels since
+ * VolatileImages are typically optimized for writing.
+ *
+ * @return a BufferedImage representing this VolatileImage
+ */
+ public abstract BufferedImage getSnapshot();
+
+ /**
+ * Returns the width of this image buffer.
+ *
+ * @return the width of this VolatileImage
+ */
+ public abstract int getWidth();
+
+ /**
+ * Returns the height of this image buffer.
+ *
+ * @return the height of this VolatileImage
+ */
+ public abstract int getHeight();
+
+ /**
+ * Calling this method is equivalent to calling
+ * getSnapshot().getSource(). The ImageProducer produces pixels
+ * from the BufferedImage snapshot and not from the VolatileImage
+ * itself. Thus, changes to the VolatileImage that occur after this
+ * ImageProducer has been retrieved will not be reflected in the
+ * produced pixels.
+ *
+ * This method, which reads pixels from the volatile image buffer,
+ * may be less-performant than methods that write pixels since
+ * VolatileImages are typically optimized for writing.
+ *
+ * @return an ImageProducer for a static BufferedImage snapshot of
+ * this image buffer
+ */
+ public ImageProducer getSource()
+ {
+ return getSnapshot().getSource();
+ }
+
+ /**
+ * Releases the system resources taken by this image.
+ */
+ public void flush()
+ {
+ }
+
+ /**
+ * Returns a Graphics2D object that can be used to draw onto this
+ * image. This method is present for backwards-compatibility. It
+ * simply returns the result of createGraphics.
+ *
+ * @return a Graphics2D object that can be used to draw onto this
+ * image
+ */
+ public Graphics getGraphics()
+ {
+ return createGraphics();
+ }
+
+ /**
+ * Returns a Graphics2D object that can be used to draw onto this
+ * image.
+ *
+ * @return a Graphics2D object that can be used to draw onto this
+ * image
+ */
+ public abstract Graphics2D createGraphics();
+
+ /**
+ * Validates and restores this image. If the image buffer has
+ * become unavailable for further use since the last call to
+ * validate, validate will allocate a new image buffer. The image
+ * is also "validated" against the GraphicsConfiguration parameter.
+ *
+ * "Validating" the image means checking that the capabilities it
+ * requires of the output device are indeed supported by the given
+ * output device. If the image's characteristics, which can be
+ * highly output device-specific, are not supported by the graphics
+ * configuration, then IMAGE_INCOMPATIBLE will be returned. This
+ * can happen, for example, if this image was created on one output
+ * device, then validated against a different output device with
+ * different capabilities. Calling validate with a NULL gc argument
+ * causes validate to skip the validation test.
+ *
+ * @param gc graphics configuration against which to validate or
+ * NULL
+ *
+ * @return a code indicating the result of validation. One of:
+ * <ul>
+ * <li><code>IMAGE_OK</code> if the image did not need to be
+ * validated and didn't need to be restored</li>
+ * <li><code>IMAGE_RESTORED</code> if the image may need to be
+ * re-rendered.</li>
+ * <li><code>IMAGE_INCOMPATIBLE</code> if this image's
+ * requirements are not fulfilled by the graphics configuration
+ * parameter. This implies that you need to create a new
+ * VolatileImage for the different GraphicsConfiguration or
+ * Component. This return value implies nothing about whether the
+ * image is valid or needs to be re-rendered.</li>
+ * </ul>
+ */
+ public abstract int validate(GraphicsConfiguration gc);
+
+ /**
+ * Returns true if the contents of the image buffer have been
+ * damaged or if the image buffer's resources have been reclaimed by
+ * the graphics system. You should call this method after a series
+ * of rendering operations to or from the image, to see if the image
+ * buffer needs to be revalidated or the image re-rendered.
+ *
+ * @return true if the validate should be called, false otherwise
+ */
+ public abstract boolean contentsLost();
+
+ /**
+ * Returns the capabilities of this image buffer.
+ *
+ * @return the capabilities of this image buffer
+ */
+ public abstract ImageCapabilities getCapabilities();
+
+ /**
+ * Returns the transparency type of this image.
+ *
+ * @return Transparency.OPAQUE, Transparency.BITMASK or
+ * Transparency.TRANSLUCENT
+ */
+ public int getTransparency()
+ {
+ return transparency;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/WritableRaster.java b/libjava/classpath/java/awt/image/WritableRaster.java
new file mode 100644
index 00000000000..2e5462fd92e
--- /dev/null
+++ b/libjava/classpath/java/awt/image/WritableRaster.java
@@ -0,0 +1,265 @@
+/* Copyright (C) 2000, 2002, 2003 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.image;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class WritableRaster extends Raster
+{
+ protected WritableRaster(SampleModel sampleModel, Point origin)
+ {
+ this(sampleModel, sampleModel.createDataBuffer(), origin);
+ }
+
+ protected WritableRaster(SampleModel sampleModel,
+ DataBuffer dataBuffer, Point origin)
+ {
+ this(sampleModel, dataBuffer,
+ new Rectangle(origin != null ? origin.x : 0,
+ origin != null ? origin.y : 0,
+ sampleModel.getWidth(), sampleModel.getHeight()),
+ origin,
+ null);
+ }
+
+ protected WritableRaster(SampleModel sampleModel,
+ DataBuffer dataBuffer,
+ Rectangle aRegion,
+ Point sampleModelTranslate,
+ WritableRaster parent)
+ {
+ super(sampleModel, dataBuffer, aRegion, sampleModelTranslate,
+ parent);
+ }
+
+ public WritableRaster getWritableParent()
+ {
+ return (WritableRaster) getParent();
+ }
+
+ public WritableRaster createWritableTranslatedChild(int childMinX,
+ 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);
+ }
+
+ 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
+
+ // FIXME: Throw RasterFormatException if child bounds extends
+ // beyond the bounds of this raster.
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ 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);
+ }
+
+ public void setDataElements(int x, int y, Raster inRaster)
+ {
+ 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)
+ {
+ sampleModel.setDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, inData, dataBuffer);
+ }
+
+ public void setRect(Raster srcRaster)
+ {
+ setRect(0, 0, 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 target = getBounds().intersection(targetUnclipped);
+
+ if (target.isEmpty()) return;
+
+ int sx = target.x - dx;
+ int sy = target.y - dy;
+
+ // FIXME: Do tests on rasters and use get/set data instead.
+
+ /* The JDK documentation seems to imply this implementation.
+ (the trucation of higher bits), but an implementation using
+ get/setDataElements would be more efficient. None of the
+ implementations would do anything sensible when the sample
+ models don't match.
+
+ But this is probably not the place to consider such
+ optimizations.*/
+
+ int[] pixels = srcRaster.getPixels(sx, sy,
+ target.width, target.height,
+ (int[]) null);
+
+ setPixels(target.x, target.y, target.width, target.height, pixels);
+ }
+
+ public void setPixel(int x, int y, int[] iArray)
+ {
+ sampleModel.setPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ iArray, dataBuffer);
+ }
+
+ public void setPixel(int x, int y, float[] fArray)
+ {
+ sampleModel.setPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ fArray, dataBuffer);
+ }
+
+ public void setPixel(int x, int y, double[] dArray)
+ {
+ sampleModel.setPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ dArray, dataBuffer);
+ }
+
+ public void setPixels(int x, int y, int w, int h, int[] iArray)
+ {
+ sampleModel.setPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, iArray, dataBuffer);
+ }
+
+ public void setPixels(int x, int y, int w, int h, float[] fArray)
+ {
+ sampleModel.setPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, fArray, dataBuffer);
+ }
+
+ public void setPixels(int x, int y, int w, int h, double[] dArray)
+ {
+ sampleModel.setPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, dArray, dataBuffer);
+ }
+
+ public void setSample(int x, int y, int b, int s)
+ {
+ sampleModel.setSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ public void setSample(int x, int y, int b, float s)
+ {
+ sampleModel.setSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ public void setSample(int x, int y, int b, double s)
+ {
+ sampleModel.setSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ int[] iArray)
+ {
+ sampleModel.setSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, iArray, dataBuffer);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ float[] fArray)
+ {
+ sampleModel.setSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, fArray, dataBuffer);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ double[] dArray)
+ {
+ sampleModel.setSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, dArray, dataBuffer);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/WritableRenderedImage.java b/libjava/classpath/java/awt/image/WritableRenderedImage.java
new file mode 100644
index 00000000000..4ed9f101371
--- /dev/null
+++ b/libjava/classpath/java/awt/image/WritableRenderedImage.java
@@ -0,0 +1,56 @@
+/* WritableRenderedImage.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Point;
+
+/**
+ * NEEDS DOCUMENTATION
+ */
+public interface WritableRenderedImage extends RenderedImage
+{
+ void addTileObserver(TileObserver to);
+ void removeTileObserver(TileObserver to);
+ WritableRaster getWritableTile(int x, int y);
+ void releaseWritableTile(int x, int y);
+ boolean isTileWritable(int x, int y);
+ Point[] getWritableTileIndices();
+ boolean hasTileWriters();
+ void setData(Raster r);
+} // interface WritableRenderedImage
diff --git a/libjava/classpath/java/awt/image/package.html b/libjava/classpath/java/awt/image/package.html
new file mode 100644
index 00000000000..50fa99d138f
--- /dev/null
+++ b/libjava/classpath/java/awt/image/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.image package.
+ Copyright (C) 2002 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 - java.awt.image</title></head>
+
+<body>
+<p>Image consumers, producers and filters.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java b/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java
new file mode 100644
index 00000000000..729d857ac89
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java
@@ -0,0 +1,56 @@
+/* ContextualRenderedImageFactory.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
+
+/**
+ * STUBBED
+ */
+public interface ContextualRenderedImageFactory extends RenderedImageFactory
+{
+ RenderContext mapRenderContext(int i, RenderContext context,
+ ParameterBlock block, RenderableImage image);
+ RenderedImage create(RenderContext context, ParameterBlock block);
+ Rectangle2D getBounds2D(ParameterBlock block);
+ Object getProperty(ParameterBlock block, String name);
+ String[] getPropertyNames();
+ boolean isDynamic();
+} // interface ContextualRenderedImageFactory
diff --git a/libjava/classpath/java/awt/image/renderable/ParameterBlock.java b/libjava/classpath/java/awt/image/renderable/ParameterBlock.java
new file mode 100644
index 00000000000..879d3c4fb90
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/ParameterBlock.java
@@ -0,0 +1,308 @@
+/* ParameterBlock.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.image.RenderedImage;
+import java.io.Serializable;
+import java.util.Vector;
+
+public class ParameterBlock implements Cloneable, Serializable
+{
+ private static final long serialVersionUID = -7577115551785240750L;
+ protected Vector sources;
+ protected Vector parameters;
+
+ public ParameterBlock()
+ {
+ this(new Vector(), new Vector());
+ }
+
+ public ParameterBlock(Vector sources)
+ {
+ this(sources, new Vector());
+ }
+
+ public ParameterBlock(Vector sources, Vector parameters)
+ {
+ this.sources = sources;
+ this.parameters = parameters;
+ }
+
+ public Object shallowClone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // impossible
+ }
+ }
+
+ public Object clone()
+ {
+ ParameterBlock pb = (ParameterBlock) shallowClone();
+ if (sources != null)
+ pb.sources = (Vector) sources.clone();
+ if (parameters != null)
+ pb.parameters = (Vector) parameters.clone();
+ return pb;
+ }
+
+ public ParameterBlock addSource(Object source)
+ {
+ sources.add(source);
+ return this;
+ }
+
+ public Object getSource(int index)
+ {
+ return sources.get(index);
+ }
+
+ public ParameterBlock setSource(Object source, int index)
+ {
+ sources.ensureCapacity(index);
+ sources.set(index, source);
+ return this;
+ }
+
+ public RenderedImage getRenderedSource(int index)
+ {
+ return (RenderedImage) sources.get(index);
+ }
+
+ public RenderableImage getRenderableSource(int index)
+ {
+ return (RenderableImage) sources.get(index);
+ }
+
+ public int getNumSources()
+ {
+ return sources.size();
+ }
+
+ public Vector getSources()
+ {
+ return sources;
+ }
+
+ public void setSources(Vector sources)
+ {
+ this.sources = sources;
+ }
+
+ public void removeSources()
+ {
+ if (sources != null)
+ sources.clear();
+ }
+
+ public int getNumParameters()
+ {
+ return parameters.size();
+ }
+
+ public Vector getParameters()
+ {
+ return parameters;
+ }
+
+ public void setParameters(Vector parameters)
+ {
+ this.parameters = parameters;
+ }
+
+ public void removeParameters()
+ {
+ if (parameters != null)
+ parameters.clear();
+ }
+
+ public ParameterBlock add(Object o)
+ {
+ parameters.add(o);
+ return this;
+ }
+
+ public ParameterBlock add(byte b)
+ {
+ return add(new Byte(b));
+ }
+
+ public ParameterBlock add(char c)
+ {
+ return add(new Character(c));
+ }
+
+ public ParameterBlock add(short s)
+ {
+ return add(new Short(s));
+ }
+
+ public ParameterBlock add(int i)
+ {
+ return add(new Integer(i));
+ }
+
+ public ParameterBlock add(long l)
+ {
+ return add(new Long(l));
+ }
+
+ public ParameterBlock add(float f)
+ {
+ return add(new Float(f));
+ }
+
+ public ParameterBlock add(double d)
+ {
+ return add(new Double(d));
+ }
+
+ public ParameterBlock set(Object o, int index)
+ {
+ parameters.ensureCapacity(index);
+ parameters.set(index, o);
+ return this;
+ }
+
+ public ParameterBlock set(byte b, int index)
+ {
+ return set(new Byte(b), index);
+ }
+
+ public ParameterBlock set(char c, int index)
+ {
+ return set(new Character(c), index);
+ }
+
+ public ParameterBlock set(short s, int index)
+ {
+ return set(new Short(s), index);
+ }
+
+ public ParameterBlock set(int i, int index)
+ {
+ return set(new Integer(i), index);
+ }
+
+ public ParameterBlock set(long l, int index)
+ {
+ return set(new Long(l), index);
+ }
+
+ public ParameterBlock set(float f, int index)
+ {
+ return set(new Float(f), index);
+ }
+
+ public ParameterBlock set(double d, int index)
+ {
+ return set(new Double(d), index);
+ }
+
+ public Object getObjectParameter(int index)
+ {
+ return parameters.get(index);
+ }
+
+ public byte getByteParameter(int index)
+ {
+ return ((Byte) parameters.get(index)).byteValue();
+ }
+
+ public char getCharParameter(int index)
+ {
+ return ((Character) parameters.get(index)).charValue();
+ }
+
+ public short getShortParameter(int index)
+ {
+ return ((Short) parameters.get(index)).shortValue();
+ }
+
+ public int getIntParameter(int index)
+ {
+ return ((Integer) parameters.get(index)).intValue();
+ }
+
+ public long getLongParameter(int index)
+ {
+ return ((Long) parameters.get(index)).longValue();
+ }
+
+ public float getFloatParameter(int index)
+ {
+ return ((Float) parameters.get(index)).floatValue();
+ }
+
+ public double getDoubleParameter(int index)
+ {
+ return ((Double) parameters.get(index)).doubleValue();
+ }
+
+ public Class[] getParamClasses()
+ {
+ int i = parameters.size();
+ Class[] result = new Class[i];
+ while (--i >= 0)
+ {
+ Class c = parameters.get(i).getClass();
+ if (c == Byte.class)
+ result[i] = byte.class;
+ else if (c == Character.class)
+ result[i] = char.class;
+ else if (c == Short.class)
+ result[i] = short.class;
+ else if (c == Integer.class)
+ result[i] = int.class;
+ else if (c == Long.class)
+ result[i] = long.class;
+ else if (c == Float.class)
+ result[i] = float.class;
+ else if (c == Double.class)
+ result[i] = double.class;
+ else
+ result[i] = c;
+ }
+ return result;
+ }
+} // class ParameterBlock
diff --git a/libjava/classpath/java/awt/image/renderable/RenderContext.java b/libjava/classpath/java/awt/image/renderable/RenderContext.java
new file mode 100644
index 00000000000..67f0b8adb23
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderContext.java
@@ -0,0 +1,141 @@
+/* RenderContext.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+
+public class RenderContext implements Cloneable
+{
+ private AffineTransform xform;
+ private Shape aoi;
+ private RenderingHints hints;
+
+ public RenderContext(AffineTransform xform, Shape aoi, RenderingHints hints)
+ {
+ this.xform = xform;
+ this.aoi = aoi;
+ this.hints = hints;
+ }
+
+ public RenderContext(AffineTransform xform)
+ {
+ this(xform, null, null);
+ }
+
+ public RenderContext(AffineTransform xform, RenderingHints hints)
+ {
+ this(xform, null, hints);
+ }
+
+ public RenderContext(AffineTransform xform, Shape aoi)
+ {
+ this(xform, aoi, null);
+ }
+
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ public void setRenderingHints(RenderingHints hints)
+ {
+ this.hints = hints;
+ }
+
+ public void setTransform(AffineTransform xform)
+ {
+ this.xform = xform;
+ }
+
+ public void preConcatenateTransform(AffineTransform pre)
+ {
+ preConcetenateTransform (pre);
+ }
+
+ /** @deprecated */
+ public void preConcetenateTransform(AffineTransform pre)
+ {
+ xform.preConcatenate (pre);
+ }
+
+ public void concatenateTransform(AffineTransform post)
+ {
+ concetenateTransform (post);
+ }
+
+ /** @deprecated */
+ public void concetenateTransform(AffineTransform post)
+ {
+ xform.concatenate (post);
+ }
+
+ public AffineTransform getTransform()
+ {
+ return xform;
+ }
+
+ public void setAreaOfInterest(Shape aoi)
+ {
+ this.aoi = aoi;
+ }
+
+ public Shape getAreaOfInterest()
+ {
+ return aoi;
+ }
+
+ public Object clone()
+ {
+ try
+ {
+ RenderContext copy = (RenderContext) super.clone();
+ if (xform != null)
+ copy.xform = (AffineTransform) xform.clone();
+ if (hints != null)
+ copy.hints = (RenderingHints) hints.clone();
+ return copy;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // impossible
+ }
+ }
+} // class RenderContext
diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImage.java b/libjava/classpath/java/awt/image/renderable/RenderableImage.java
new file mode 100644
index 00000000000..45d2eb7ebf0
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderableImage.java
@@ -0,0 +1,62 @@
+/* RenderableImage.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+public interface RenderableImage
+{
+ String HINTS_OBSERVED = "HINTS_OBSERVED";
+
+ Vector getSources();
+ Object getProperty(String name);
+ String[] getPropertyNames();
+ boolean isDynamic();
+ float getWidth();
+ float getHeight();
+ float getMinX();
+ float getMinY();
+ RenderedImage createScaledRendering(int w, int h, RenderingHints hints);
+ RenderedImage createDefaultRendering();
+ RenderedImage createRendering(RenderContext context);
+
+} // interface RenderableImage
+
diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java b/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java
new file mode 100644
index 00000000000..5385a82a317
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java
@@ -0,0 +1,157 @@
+/* RenderableImageOp.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+public class RenderableImageOp implements RenderableImage
+{
+ private final ContextualRenderedImageFactory crif;
+ private ParameterBlock block;
+
+ public RenderableImageOp(ContextualRenderedImageFactory crif,
+ ParameterBlock block)
+ {
+ this.crif = crif;
+ this.block = (ParameterBlock) block.clone();
+ }
+
+ public Vector getSources()
+ {
+ if (block.sources == null)
+ return null;
+ int size = block.sources.size();
+ Vector v = new Vector();
+ for (int i = 0; i < size; i++)
+ {
+ Object o = block.sources.get(i);
+ if (o instanceof RenderableImage)
+ v.add(o);
+ }
+ return v;
+ }
+
+ public Object getProperty(String name)
+ {
+ return crif.getProperty(block, name);
+ }
+
+ public String[] getPropertyNames()
+ {
+ return crif.getPropertyNames();
+ }
+
+ public boolean isDynamic()
+ {
+ return crif.isDynamic();
+ }
+
+ public float getWidth()
+ {
+ return (float) crif.getBounds2D(block).getWidth();
+ }
+
+ public float getHeight()
+ {
+ return (float) crif.getBounds2D(block).getHeight();
+ }
+
+ public float getMinX()
+ {
+ return (float) crif.getBounds2D(block).getX();
+ }
+
+ public float getMinY()
+ {
+ return (float) crif.getBounds2D(block).getY();
+ }
+
+ public ParameterBlock setParameterBlock(ParameterBlock block)
+ {
+ ParameterBlock result = this.block;
+ this.block = (ParameterBlock) block.clone();
+ return result;
+ }
+
+ public ParameterBlock getParameterBlock()
+ {
+ return block;
+ }
+
+ public RenderedImage createScaledRendering(int w, int h,
+ RenderingHints hints)
+ {
+ if (w == 0)
+ if (h == 0)
+ throw new IllegalArgumentException();
+ else
+ w = Math.round(h * getWidth() / getHeight());
+ if (h == 0)
+ h = Math.round(w * getHeight() / getWidth());
+ AffineTransform xform = AffineTransform.getScaleInstance(w * getWidth(),
+ h * getHeight());
+ return createRendering(new RenderContext(xform, hints));
+ }
+
+ public RenderedImage createDefaultRendering()
+ {
+ return createRendering(new RenderContext(new AffineTransform()));
+ }
+
+ public RenderedImage createRendering(RenderContext context)
+ {
+ ParameterBlock copy = (ParameterBlock) block.clone();
+ int i = block.sources.size();
+ while (--i >= 0)
+ {
+ Object o = block.sources.get(i);
+ if (o instanceof RenderableImage)
+ {
+ RenderableImage ri = (RenderableImage) o;
+ RenderContext rc = crif.mapRenderContext(i, context, block, ri);
+ copy.sources.set(i, ri.createRendering(rc));
+ }
+ }
+ // Now copy.sources should be only RenderedImages.
+ return crif.create(context, copy);
+ }
+} // class RenderableImageOp
diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java b/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java
new file mode 100644
index 00000000000..78f3051ea99
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java
@@ -0,0 +1,79 @@
+/* RenderableImageProducer.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageProducer;
+
+public class RenderableImageProducer implements ImageProducer, Runnable
+{
+ public RenderableImageProducer(RenderableImage image, RenderContext context)
+ {
+ throw new Error("not implemented");
+ }
+
+ public void setRenderContext(RenderContext context)
+ {
+ }
+
+ public void addConsumer(ImageConsumer consumer)
+ {
+ }
+
+ public boolean isConsumer(ImageConsumer consumer)
+ {
+ return false;
+ }
+
+ public void removeConsumer(ImageConsumer consumer)
+ {
+ }
+
+ public void startProduction(ImageConsumer consumer)
+ {
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer consumer)
+ {
+ }
+
+ public void run()
+ {
+ }
+} // class RenderableImageProducer
diff --git a/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java b/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java
new file mode 100644
index 00000000000..6ff4cb03176
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java
@@ -0,0 +1,47 @@
+/* RenderedImageFactory.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+
+public interface RenderedImageFactory
+{
+ RenderedImage create(ParameterBlock block, RenderingHints hints);
+} // interface RenderedImageFactory
diff --git a/libjava/classpath/java/awt/image/renderable/package.html b/libjava/classpath/java/awt/image/renderable/package.html
new file mode 100644
index 00000000000..a24237e7238
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.image.renderable package.
+ Copyright (C) 2002 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 - java.awt.image.renderable</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/package.html b/libjava/classpath/java/awt/package.html
new file mode 100644
index 00000000000..c5ff9881af1
--- /dev/null
+++ b/libjava/classpath/java/awt/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt package.
+ Copyright (C) 2002 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 - java.awt</title></head>
+
+<body>
+<p>Abstract Window Toolkit classes.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/peer/ButtonPeer.java b/libjava/classpath/java/awt/peer/ButtonPeer.java
new file mode 100644
index 00000000000..a55fc2236db
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ButtonPeer.java
@@ -0,0 +1,46 @@
+/* ButtonPeer.java -- Peer interface for buttons
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface ButtonPeer extends ComponentPeer
+{
+ void setLabel (String label);
+
+} // interface ButtonPeer
+
diff --git a/libjava/classpath/java/awt/peer/CanvasPeer.java b/libjava/classpath/java/awt/peer/CanvasPeer.java
new file mode 100644
index 00000000000..4b33835a455
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/CanvasPeer.java
@@ -0,0 +1,45 @@
+/* CanvasPeer.java -- Peer interface for a canvas
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface CanvasPeer extends ComponentPeer
+{
+
+} // interface CanvasPeer
+
diff --git a/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java b/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java
new file mode 100644
index 00000000000..5213dc90693
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java
@@ -0,0 +1,46 @@
+/* CheckboxMenuItemPeer.java -- Peer interface for checkbox menu items
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface CheckboxMenuItemPeer extends MenuItemPeer
+{
+ void setState (boolean state);
+
+} // interface CheckboxMenuItemPeer
+
diff --git a/libjava/classpath/java/awt/peer/CheckboxPeer.java b/libjava/classpath/java/awt/peer/CheckboxPeer.java
new file mode 100644
index 00000000000..8b23b3f6f33
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/CheckboxPeer.java
@@ -0,0 +1,52 @@
+/* CheckboxPeer.java -- Interface for checkbox peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.CheckboxGroup;
+
+public interface CheckboxPeer extends ComponentPeer
+{
+ void setCheckboxGroup (CheckboxGroup group);
+
+ void setLabel (String label);
+
+ void setState (boolean state);
+
+} // interface CheckboxPeer
+
diff --git a/libjava/classpath/java/awt/peer/ChoicePeer.java b/libjava/classpath/java/awt/peer/ChoicePeer.java
new file mode 100644
index 00000000000..8ed11072e15
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ChoicePeer.java
@@ -0,0 +1,54 @@
+/* ChoicePeer.java -- Peer for choice box
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface ChoicePeer extends ComponentPeer
+{
+ void add (String item, int index);
+
+ void addItem (String item, int index);
+
+ void remove (int index);
+
+ void removeAll();
+
+ void select (int index);
+
+} // interface ChoicePeer
+
diff --git a/libjava/classpath/java/awt/peer/ComponentPeer.java b/libjava/classpath/java/awt/peer/ComponentPeer.java
new file mode 100644
index 00000000000..7ed8f6051db
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ComponentPeer.java
@@ -0,0 +1,187 @@
+/* ComponentPeer.java -- Toplevel component peer
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.BufferCapabilities;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Toolkit;
+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;
+
+public interface ComponentPeer
+{
+ int checkImage(Image img, int width, int height,
+ ImageObserver ob);
+ Image createImage(ImageProducer prod);
+ Image createImage(int width, int height);
+ void disable();
+ void dispose();
+ void enable();
+ ColorModel getColorModel();
+ FontMetrics getFontMetrics(Font f);
+ Graphics getGraphics();
+ Point getLocationOnScreen();
+ Dimension getMinimumSize();
+ Dimension getPreferredSize();
+ Toolkit getToolkit();
+ void handleEvent(AWTEvent e);
+ void hide();
+
+ /**
+ * Part of the earlier 1.1 API, replaced by isFocusable().
+ */
+ boolean isFocusTraversable();
+ boolean isFocusable();
+ Dimension minimumSize();
+ Dimension preferredSize();
+ void paint(Graphics graphics);
+ boolean prepareImage(Image img, int width, int height,
+ ImageObserver ob);
+ void print(Graphics graphics);
+ void repaint(long tm, int x, int y, int width, int height);
+
+ /**
+ * Part of the earlier 1.1 API, apparently replaced by argument
+ * form of the same method.
+ */
+ void requestFocus();
+ boolean requestFocus (Component source, boolean bool1, boolean bool2, long x);
+
+ void reshape(int x, int y, int width, int height);
+ void setBackground(Color color);
+ void setBounds(int x, int y, int width, int height);
+
+ /**
+ * Part of the earlier 1.1 API, apparently no longer needed.
+ */
+ void setCursor(Cursor cursor);
+
+ void setEnabled(boolean enabled);
+ void setFont(Font font);
+ void setForeground(Color color);
+ void setVisible(boolean visible);
+ void show();
+
+ /**
+ * Get the graphics configuration of the component. The color model
+ * of the component can be derived from the configuration.
+ */
+ GraphicsConfiguration getGraphicsConfiguration();
+
+ /**
+ * Part of an older API, no longer needed.
+ */
+ void setEventMask (long mask);
+
+ // Methods below are introduced since 1.1
+ boolean isObscured();
+ boolean canDetermineObscurity();
+ void coalescePaintEvent(PaintEvent e);
+ void updateCursorImmediately();
+ boolean handlesWheelScrolling();
+
+ /**
+ * A convenience method that creates a volatile image. The volatile
+ * image is created on the screen device on which this component is
+ * displayed, in the device's current graphics configuration.
+ *
+ * @param width width of the image
+ * @param height height of the image
+ *
+ * @see VolatileImage
+ *
+ * @since 1.2
+ */
+ VolatileImage createVolatileImage(int width, int height);
+
+ /**
+ * Create a number of image buffers that implement a buffering
+ * strategy according to the given capabilities.
+ *
+ * @param numBuffers the number of buffers
+ * @param caps the buffering capabilities
+ *
+ * @throws AWTException if the specified buffering strategy is not
+ * implemented
+ *
+ * @since 1.2
+ */
+ void createBuffers(int numBuffers, BufferCapabilities caps)
+ throws AWTException;
+
+ /**
+ * Return the back buffer of this component.
+ *
+ * @return the back buffer of this component.
+ *
+ * @since 1.2
+ */
+ Image getBackBuffer();
+
+ /**
+ * Perform a page flip, leaving the contents of the back buffer in
+ * the specified state.
+ *
+ * @param contents the state in which to leave the back buffer
+ *
+ * @since 1.2
+ */
+ void flip(BufferCapabilities.FlipContents contents);
+
+ /**
+ * Destroy the resources created by createBuffers.
+ *
+ * @since 1.2
+ */
+ void destroyBuffers();
+}
diff --git a/libjava/classpath/java/awt/peer/ContainerPeer.java b/libjava/classpath/java/awt/peer/ContainerPeer.java
new file mode 100644
index 00000000000..f1373a16472
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ContainerPeer.java
@@ -0,0 +1,59 @@
+/* ContainerPeer.java -- Interface for container peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.peer;
+
+import java.awt.Insets;
+
+public interface ContainerPeer extends ComponentPeer
+{
+ Insets insets();
+
+ Insets getInsets();
+
+ void beginValidate();
+
+ void endValidate();
+
+ void beginLayout();
+
+ void endLayout();
+
+ boolean isPaintPending();
+
+} // interface ContainerPeer
+
diff --git a/libjava/classpath/java/awt/peer/DialogPeer.java b/libjava/classpath/java/awt/peer/DialogPeer.java
new file mode 100644
index 00000000000..e26d64ff96a
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/DialogPeer.java
@@ -0,0 +1,48 @@
+/* DialogPeer.java -- Interface for dialog box peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface DialogPeer extends WindowPeer
+{
+ void setResizable (boolean resizeable);
+
+ void setTitle (String title);
+
+} // interface DialogPeer
+
diff --git a/libjava/classpath/java/awt/peer/FileDialogPeer.java b/libjava/classpath/java/awt/peer/FileDialogPeer.java
new file mode 100644
index 00000000000..7db1798162a
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/FileDialogPeer.java
@@ -0,0 +1,52 @@
+/* FileDialogPeer.java -- Interface for file selection dialog box peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.io.FilenameFilter;
+
+public interface FileDialogPeer extends DialogPeer
+{
+ void setFile (String file);
+
+ void setDirectory (String dir);
+
+ void setFilenameFilter (FilenameFilter ff);
+
+} // interface FileDialogPeer
+
diff --git a/libjava/classpath/java/awt/peer/FontPeer.java b/libjava/classpath/java/awt/peer/FontPeer.java
new file mode 100644
index 00000000000..f0ba6d830c8
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/FontPeer.java
@@ -0,0 +1,45 @@
+/* FontPeer.java -- Interface for font peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface FontPeer
+{
+
+} // interface FontPeer
+
diff --git a/libjava/classpath/java/awt/peer/FramePeer.java b/libjava/classpath/java/awt/peer/FramePeer.java
new file mode 100644
index 00000000000..13498ff2f67
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/FramePeer.java
@@ -0,0 +1,55 @@
+/* FramePeer.java -- Interface for frame peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Image;
+import java.awt.MenuBar;
+import java.awt.Rectangle;
+
+public interface FramePeer extends WindowPeer
+{
+ void setIconImage(Image image);
+ void setMenuBar(MenuBar mb);
+ void setResizable(boolean resizable);
+ void setTitle(String title);
+ int getState();
+ void setState(int state);
+ void setMaximizedBounds(Rectangle r);
+} // interface FramePeer
+
diff --git a/libjava/classpath/java/awt/peer/LabelPeer.java b/libjava/classpath/java/awt/peer/LabelPeer.java
new file mode 100644
index 00000000000..d0fca462fdc
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/LabelPeer.java
@@ -0,0 +1,46 @@
+/* LabelPeer.java -- Interface for simple text lable peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface LabelPeer extends ComponentPeer
+{
+ void setAlignment(int alignment);
+ void setText(String text);
+} // interface LabelPeer
+
diff --git a/libjava/classpath/java/awt/peer/LightweightPeer.java b/libjava/classpath/java/awt/peer/LightweightPeer.java
new file mode 100644
index 00000000000..93cad7a0318
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/LightweightPeer.java
@@ -0,0 +1,45 @@
+/* LightweightPeer.java -- Interface for lightweight peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface LightweightPeer extends ComponentPeer
+{
+
+} // interface LightweightPeer
+
diff --git a/libjava/classpath/java/awt/peer/ListPeer.java b/libjava/classpath/java/awt/peer/ListPeer.java
new file mode 100644
index 00000000000..c0f765d1655
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ListPeer.java
@@ -0,0 +1,61 @@
+/* ListPeer.java -- Interface for list box peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Dimension;
+
+public interface ListPeer extends ComponentPeer
+{
+ void add(String item, int index);
+ void addItem(String item, int index);
+ void clear();
+ void delItems(int start_index, int end_index);
+ void deselect(int index);
+ int[] getSelectedIndexes();
+ void makeVisible(int index);
+ Dimension minimumSize(int s);
+ Dimension preferredSize(int s);
+ void removeAll();
+ void select(int index);
+ void setMultipleMode(boolean multi);
+ void setMultipleSelections(boolean multi);
+ Dimension getPreferredSize(int s);
+ Dimension getMinimumSize(int s);
+} // interface ListPeer
+
diff --git a/libjava/classpath/java/awt/peer/MenuBarPeer.java b/libjava/classpath/java/awt/peer/MenuBarPeer.java
new file mode 100644
index 00000000000..c5f7c581ff5
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MenuBarPeer.java
@@ -0,0 +1,48 @@
+/* MenuBarPeer.java -- Interface for menu bar peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Menu;
+
+public interface MenuBarPeer extends MenuComponentPeer
+{
+ void addHelpMenu(Menu menu);
+ void delMenu(int index);
+} // interface MenuBarPeer
+
diff --git a/libjava/classpath/java/awt/peer/MenuComponentPeer.java b/libjava/classpath/java/awt/peer/MenuComponentPeer.java
new file mode 100644
index 00000000000..1b10ca1f4c7
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MenuComponentPeer.java
@@ -0,0 +1,45 @@
+/* MenuComponentPeer.java --
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface MenuComponentPeer
+{
+ void dispose();
+} // interface MenuComponentPeer
+
diff --git a/libjava/classpath/java/awt/peer/MenuItemPeer.java b/libjava/classpath/java/awt/peer/MenuItemPeer.java
new file mode 100644
index 00000000000..3ba1027e501
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MenuItemPeer.java
@@ -0,0 +1,48 @@
+/* MenuItemPeer.java -- Interface for menu item peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface MenuItemPeer extends MenuComponentPeer
+{
+ void disable();
+ void enable();
+ void setEnabled(boolean enabled);
+ void setLabel(String text);
+} // interface MenuItemPeer
+
diff --git a/libjava/classpath/java/awt/peer/MenuPeer.java b/libjava/classpath/java/awt/peer/MenuPeer.java
new file mode 100644
index 00000000000..c51ea73bb6c
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MenuPeer.java
@@ -0,0 +1,48 @@
+/* MenuPeer.java -- Interface for menu peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.MenuItem;
+
+public interface MenuPeer extends MenuItemPeer
+{
+ void addItem (MenuItem item);
+ void delItem (int index);
+}
+
diff --git a/libjava/classpath/java/awt/peer/PanelPeer.java b/libjava/classpath/java/awt/peer/PanelPeer.java
new file mode 100644
index 00000000000..192632e46b3
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/PanelPeer.java
@@ -0,0 +1,45 @@
+/* PanelPeer.java -- Interface for panel peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface PanelPeer extends ContainerPeer
+{
+
+} // interface PanelPeer
+
diff --git a/libjava/classpath/java/awt/peer/PopupMenuPeer.java b/libjava/classpath/java/awt/peer/PopupMenuPeer.java
new file mode 100644
index 00000000000..2e8f4bbedc5
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/PopupMenuPeer.java
@@ -0,0 +1,53 @@
+/* PopupMenuPeer.java -- Interface for popup menu peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Component;
+import java.awt.Event;
+
+public interface PopupMenuPeer extends MenuPeer
+{
+ /**
+ * Part of the older API, replaced by event version instead.
+ */
+ void show (Component origin, int x, int y);
+
+ void show (Event e);
+} // interface PopupMenuPeer
+
diff --git a/libjava/classpath/java/awt/peer/RobotPeer.java b/libjava/classpath/java/awt/peer/RobotPeer.java
new file mode 100644
index 00000000000..db81c809d72
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/RobotPeer.java
@@ -0,0 +1,54 @@
+/* RobotPeer.java -- Interface for programatically driving GUI
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Rectangle;
+
+public interface RobotPeer
+{
+ void mouseMove (int x, int y);
+ void mousePress (int buttons);
+ void mouseRelease (int buttons);
+ void mouseWheel (int wheelAmt);
+ void keyPress (int keycode);
+ void keyRelease (int keycode);
+ int getRGBPixel (int x, int y);
+ int[] getRGBPixels (Rectangle screen);
+} // interface RobotPeer
+
diff --git a/libjava/classpath/java/awt/peer/ScrollPanePeer.java b/libjava/classpath/java/awt/peer/ScrollPanePeer.java
new file mode 100644
index 00000000000..de4331e04d1
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ScrollPanePeer.java
@@ -0,0 +1,52 @@
+/* ScrollPanePeer.java -- Interface for scrollable panes
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Adjustable;
+
+public interface ScrollPanePeer extends ContainerPeer
+{
+ int getHScrollbarHeight();
+ int getVScrollbarWidth();
+ void setScrollPosition(int h, int v);
+ void childResized(int width, int height);
+ void setUnitIncrement(Adjustable item, int inc);
+ void setValue(Adjustable item, int value);
+} // interface ScollPanePeer
+
diff --git a/libjava/classpath/java/awt/peer/ScrollbarPeer.java b/libjava/classpath/java/awt/peer/ScrollbarPeer.java
new file mode 100644
index 00000000000..fe4f24d649f
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ScrollbarPeer.java
@@ -0,0 +1,47 @@
+/* ScrollbarPeer.java -- Interface for scrollbar peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface ScrollbarPeer extends ComponentPeer
+{
+ void setLineIncrement(int inc);
+ void setPageIncrement(int inc);
+ void setValues(int value, int visible, int min, int max);
+} // interface ScrollbarPeer
+
diff --git a/libjava/classpath/java/awt/peer/TextAreaPeer.java b/libjava/classpath/java/awt/peer/TextAreaPeer.java
new file mode 100644
index 00000000000..354e46d9cc6
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/TextAreaPeer.java
@@ -0,0 +1,53 @@
+/* TextAreaPeer.java -- Interface for text area peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Dimension;
+
+public interface TextAreaPeer extends TextComponentPeer
+{
+ void insert(String text, int pos);
+ void insertText(String text, int pos);
+ Dimension minimumSize(int rows, int cols);
+ Dimension getMinimumSize(int rows, int cols);
+ Dimension preferredSize(int rows, int cols);
+ Dimension getPreferredSize(int rows, int cols);
+ void replaceRange(String text, int start_pos, int end_pos);
+ void replaceText(String text, int start_pos, int end_pos);
+} // interface TextAreaPeer
diff --git a/libjava/classpath/java/awt/peer/TextComponentPeer.java b/libjava/classpath/java/awt/peer/TextComponentPeer.java
new file mode 100644
index 00000000000..cacc7d8de4e
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/TextComponentPeer.java
@@ -0,0 +1,57 @@
+/* TextComponentPeer.java -- Superclass interface for text components
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Rectangle;
+
+public interface TextComponentPeer extends ComponentPeer
+{
+ int getSelectionEnd();
+ int getSelectionStart();
+ String getText();
+ void setText(String text);
+ void select(int start_pos, int end_pos);
+ void setEditable(boolean editable);
+ int getCaretPosition();
+ void setCaretPosition(int pos);
+ int getIndexAtPoint(int x, int y);
+ Rectangle getCharacterBounds(int pos);
+ long filterEvents(long filter);
+} // interface TextComponentPeer
+
diff --git a/libjava/classpath/java/awt/peer/TextFieldPeer.java b/libjava/classpath/java/awt/peer/TextFieldPeer.java
new file mode 100644
index 00000000000..e68d6663fdc
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/TextFieldPeer.java
@@ -0,0 +1,52 @@
+/* TextFieldPeer.java -- Interface for text field peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Dimension;
+
+public interface TextFieldPeer extends TextComponentPeer
+{
+ Dimension minimumSize(int len);
+ Dimension preferredSize(int len);
+ Dimension getMinimumSize(int len);
+ Dimension getPreferredSize(int len);
+ void setEchoChar(char echo_char);
+ void setEchoCharacter(char echo_char);
+} // interface TextFieldPeer
+
diff --git a/libjava/classpath/java/awt/peer/WindowPeer.java b/libjava/classpath/java/awt/peer/WindowPeer.java
new file mode 100644
index 00000000000..8f136dd2d85
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/WindowPeer.java
@@ -0,0 +1,46 @@
+/* WindowPeer.java -- Interface for window peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface WindowPeer extends ContainerPeer
+{
+ void toBack();
+ void toFront();
+} // interface WindowPeer
+
diff --git a/libjava/classpath/java/awt/peer/package.html b/libjava/classpath/java/awt/peer/package.html
new file mode 100644
index 00000000000..7a7458c177f
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.peer package.
+ Copyright (C) 2002 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 - java.awt.peer</title></head>
+
+<body>
+<p>Interfaces for using native interface components.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/print/Book.java b/libjava/classpath/java/awt/print/Book.java
new file mode 100644
index 00000000000..b084a1723f1
--- /dev/null
+++ b/libjava/classpath/java/awt/print/Book.java
@@ -0,0 +1,159 @@
+/* Book.java -- A mixed group of pages to print.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+import java.util.Vector;
+
+/**
+ * This class allows documents to be created with different paper types,
+ * page formatters, and painters.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Book implements Pageable
+{
+ /**
+ * Painter objects for the book.
+ */
+ Vector printables = new Vector();
+
+ /**
+ * Page formats for the book.
+ */
+ Vector page_formats = new Vector();
+
+ /**
+ * Initializes a new instance of <code>Book</code> that is empty.
+ */
+ public Book()
+ {
+ }
+
+ /**
+ * Returns the number of pages in this book.
+ *
+ * @return The number of pages in this book.
+ */
+ public int getNumberOfPages()
+ {
+ return printables.size();
+ }
+
+ /**
+ * This method returns the <code>PageFormat</code> object for the
+ * specified page.
+ *
+ * @param page_number The number of the page to get information for, where
+ * page numbers start at 0.
+ *
+ * @return The <code>PageFormat</code> object for the specified page.
+ *
+ * @exception IndexOutOfBoundsException If the page number is not valid.
+ */
+ public PageFormat getPageFormat(int page_number)
+ {
+ return (PageFormat) page_formats.elementAt(page_number);
+ }
+
+ /**
+ * This method returns the <code>Printable</code> object for the
+ * specified page.
+ *
+ * @param page_number The number of the page to get information for, where
+ * page numbers start at 0.
+ *
+ * @return The <code>Printable</code> object for the specified page.
+ *
+ * @exception IndexOutOfBoundsException If the page number is not valid.
+ */
+ public Printable getPrintable(int page_number)
+ {
+ return (Printable) printables.elementAt(page_number);
+ }
+
+ /**
+ * This method appends a page to the end of the book.
+ *
+ * @param printable The <code>Printable</code> for this page.
+ * @param page_format The <code>PageFormat</code> for this page.
+ *
+ * @exception NullPointerException If either argument is <code>null</code>.
+ */
+ public void append(Printable printable, PageFormat page_format)
+ {
+ append(printable, page_format, 1);
+ }
+
+ /**
+ * This method appends the specified number of pages to the end of the book.
+ * Each one will be associated with the specified <code>Printable</code>
+ * and <code>PageFormat</code>.
+ *
+ * @param printable The <code>Printable</code> for this page.
+ * @param page_format The <code>PageFormat</code> for this page.
+ * @param num_pages The number of pages to append.
+ *
+ * @exception NullPointerException If any argument is <code>null</code>.
+ */
+ public void append(Printable printable, PageFormat page_format, int num_pages)
+ {
+ for (int i = 0; i < num_pages; i++)
+ {
+ printables.addElement(printable);
+ page_formats.addElement(page_format);
+ }
+ }
+
+ /**
+ * This method changes the <code>Printable</code> and <code>PageFormat</code>
+ * for the specified page. The page must already exist or an exception
+ * will be thrown.
+ *
+ * @param page_num The page number to alter.
+ * @param printable The new <code>Printable</code> for the page.
+ * @param page_format The new <code>PageFormat</code> for the page.
+ *
+ * @throws IndexOutOfBoundsException If the specified page does not exist.
+ */
+ public void setPage(int page_num, Printable printable, PageFormat page_format)
+ {
+ printables.setElementAt(printable, page_num);
+ page_formats.setElementAt(page_format, page_num);
+ }
+}
diff --git a/libjava/classpath/java/awt/print/PageFormat.java b/libjava/classpath/java/awt/print/PageFormat.java
new file mode 100644
index 00000000000..6399552de44
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PageFormat.java
@@ -0,0 +1,292 @@
+/* PageFormat.java -- Information about the page format
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This class contains information about the desired page format to
+ * use for printing a particular set of pages.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class PageFormat implements Cloneable
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * A constant for a landscaped page orientation. Used by
+ * <code>getOrientation</code> and <code>setOrientation</code>.
+ */
+public static final int LANDSCAPE = 0;
+
+/**
+ * A constant for a portrait page orientation. Used by
+ * <code>getOrientation</code> and <code>setOrientation</code>.
+ */
+public static final int PORTRAIT = 1;
+
+/**
+ * A constant for a reversed landscaped page orientation. This is
+ * the orientation used by Macintosh's for landscape. The origin is
+ * in the upper right hand corner instead of the upper left. The
+ * X and Y axes are reversed. Used by <code>getOrientation</code> and
+ * <code>setOrientation</code>.
+ */
+public static final int REVERSE_LANDSCAPE = 2;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+// The page orientation
+private int orientation;
+
+// The paper type
+private Paper paper;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * This method creates a default page layout, which will be in portrait
+ * format.
+ */
+public
+PageFormat()
+{
+ this.paper = new Paper();
+ this.orientation = PORTRAIT;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * This method returns the width of the page, in 1/72nd's of an inch. The
+ * "width" measured depends on orientation.
+ *
+ * @return The width of the page.
+ */
+public double
+getWidth()
+{
+ return(paper.getWidth());
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the height of the page, in 1/72nd's of an inch.
+ * The "height" measured depends on the orientation.
+ *
+ * @return The height of the page.
+ */
+public double
+getHeight()
+{
+ return(paper.getHeight());
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the X coordinate value of the upper leftmost
+ * drawable area of the paper.
+ *
+ * @return The upper leftmost imageable X coordinate.
+ */
+public double
+getImageableX()
+{
+ return(paper.getImageableX());
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the Y coordinate value of the upper leftmost
+ * drawable area of the paper.
+ *
+ * @return The upper leftmost imageable Y coordinate.
+ */
+public double
+getImageableY()
+{
+ return(paper.getImageableY());
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the imageable width of the paper, in 1/72nd's of
+ * an inch.
+ *
+ * @return The imageable width of the paper.
+ */
+public double
+getImageableWidth()
+{
+ return(paper.getImageableWidth());
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the imageable height of the paper, in 1/72nd's of
+ * an inch.
+ *
+ * @return The imageable height of the paper.
+ */
+public double getImageableHeight()
+{
+ return(paper.getImageableHeight());
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a copy of the <code>paper</code> object being used for this
+ * page format.
+ *
+ * @return A copy of the <code>Paper</code> object for this format.
+ */
+public Paper
+getPaper()
+{
+ return((Paper)paper.clone());
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the <code>Paper</code> object to be used by this page format.
+ *
+ * @param paper The new <code>Paper</code> object for this page format.
+ */
+public void
+setPaper(Paper paper)
+{
+ this.paper = paper;
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the current page orientation. The value returned
+ * will be one of the page orientation constants from this class.
+ *
+ * @return The current page orientation.
+ */
+public int
+getOrientation()
+{
+ return(orientation);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the page orientation for this format to the
+ * specified value. It must be one of the page orientation constants
+ * from this class or an exception will be thrown.
+ *
+ * @param orientation The new page orientation.
+ *
+ * @exception IllegalArgumentException If the specified page orientation
+ * value is not one of the constants from this class.
+ */
+public void
+setOrientation(int orientation) throws IllegalArgumentException
+{
+ if ((orientation != PORTRAIT) &&
+ (orientation != LANDSCAPE) &&
+ (orientation != REVERSE_LANDSCAPE))
+ throw new IllegalArgumentException("Bad page orientation value: " +
+ orientation);
+
+ this.orientation = orientation;
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns a matrix used for transforming user space
+ * coordinates to page coordinates. The value returned will be six
+ * doubles as described in <code>java.awt.geom.AffineTransform</code>.
+ *
+ * @return The transformation matrix for this page format.
+ */
+public double[]
+getMatrix()
+{
+ throw new RuntimeException("Not implemented since I don't know what to do");
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns a copy of this object.
+ *
+ * @return A copy of this object.
+ */
+public Object
+clone()
+{
+ try
+ {
+ return(super.clone());
+ }
+ catch(CloneNotSupportedException e)
+ {
+ return(null);
+ }
+}
+
+} // class PageFormat
+
diff --git a/libjava/classpath/java/awt/print/Pageable.java b/libjava/classpath/java/awt/print/Pageable.java
new file mode 100644
index 00000000000..12fa542a8c6
--- /dev/null
+++ b/libjava/classpath/java/awt/print/Pageable.java
@@ -0,0 +1,113 @@
+/* Pageable.java -- Pages to be printed
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This interface represents pages that are to be printed.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Pageable
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * This constant is returned when <code>getNumberOfPages()</code>
+ * cannot determine the number of pages available for printing.
+ */
+int UNKNOWN_NUMBER_OF_PAGES = -1;
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * This method returns the number of pages this object contains, or
+ * <code>UNKNOWN_NUMBER_OF_PAGES</code> if it cannot determine the number
+ * of pages to be printed.
+ *
+ * @return The number of pages to be printed, or
+ * <code>UNKNOWN_NUMBER_OF_PAGES</code> if this is unknown.
+ */
+int
+getNumberOfPages();
+
+/*************************************************************************/
+
+/**
+ * This method returns the <code>PageFormat</code> instance for the
+ * specified page. Page numbers start at zero. An exception is thrown if
+ * the requested page does not exist.
+ *
+ * @param pageIndex The index of the page to return the
+ * <code>PageFormat</code> for.
+ *
+ * @return The <code>PageFormat</code> for the requested page.
+ *
+ * @exception IndexOutOfBoundsException If the requested page number does
+ * not exist.
+ */
+PageFormat
+getPageFormat(int pageIndex) throws IndexOutOfBoundsException;
+
+/*************************************************************************/
+
+/**
+ * This method returns the <code>Printable</code> instance for the
+ * specified page. Page numbers start at zero. An exception is thrown if
+ * the requested page does not exist.
+ *
+ * @param pageIndex The index of the page to return the
+ * <code>Printable</code> for.
+ *
+ * @return The <code>Printable</code> for the requested page.
+ *
+ * @exception IndexOutOfBoundsException If the requested page number does
+ * not exist.
+ */
+Printable
+getPrintable(int pageIndex) throws IndexOutOfBoundsException;
+
+} // interface Pageable
+
diff --git a/libjava/classpath/java/awt/print/Paper.java b/libjava/classpath/java/awt/print/Paper.java
new file mode 100644
index 00000000000..4579da3ea3c
--- /dev/null
+++ b/libjava/classpath/java/awt/print/Paper.java
@@ -0,0 +1,236 @@
+/* Paper.java -- Information about a paper type.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This class describes a particular type of paper.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Paper implements Cloneable
+{
+
+/*
+ * Instance Variables
+ */
+
+// Height of the paper
+private double height;
+
+// Width of the paper
+private double width;
+
+// Upper left imageable X coordinate
+private double imageableX;
+
+// Upper left imageable Y coordinate
+private double imageableY;
+
+// Imageable width of the page
+private double imageableWidth;
+
+// Imageable height of the page
+private double imageableHeight;
+
+/*************************************************************************/
+
+/*
+ * Constructor
+ */
+
+/**
+ * This method creates a letter sized paper with one inch margins
+ */
+public
+Paper()
+{
+ width = 8.5 * 72;
+ height = 11 * 72;
+ imageableX = 72;
+ imageableY = 72;
+ imageableWidth = width - (2 * 72);
+ imageableHeight = height - (2 * 72);
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the height of the paper in 1/72nds of an inch.
+ *
+ * @return The height of the paper in 1/72nds of an inch.
+ */
+public double
+getHeight()
+{
+ return(height);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the width of the paper in 1/72nds of an inch.
+ *
+ * @return The width of the paper in 1/72nds of an inch.
+ */
+public double
+getWidth()
+{
+ return(width);
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the X coordinate of the upper left hand corner
+ * of the imageable area of the paper.
+ *
+ * @return The X coordinate of the upper left hand corner of the imageable
+ * area of the paper.
+ */
+public double
+getImageableX()
+{
+ return(imageableX);
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the Y coordinate of the upper left hand corner
+ * of the imageable area of the paper.
+ *
+ * @return The Y coordinate of the upper left hand corner of the imageable
+ * area of the paper.
+ */
+public double
+getImageableY()
+{
+ return(imageableY);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the width of the imageable area of the paper.
+ *
+ * @return The width of the imageable area of the paper.
+ */
+public double
+getImageableWidth()
+{
+ return(imageableWidth);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the height of the imageable area of the paper.
+ *
+ * @return The height of the imageable area of the paper.
+ */
+public double
+getImageableHeight()
+{
+ return(imageableHeight);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the size of the paper to the specified width and
+ * height, which are specified in 1/72nds of an inch.
+ *
+ * @param width The width of the paper in 1/72nds of an inch.
+ * @param height The height of the paper in 1/72nds of an inch.
+ */
+public void
+setSize(double width, double height)
+{
+ this.width = width;
+ this.height = height;
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the imageable area of the paper by specifying the
+ * coordinates of the upper left hand corner of that area, and its
+ * length and height. All values are in 1/72nds of an inch.
+ *
+ * @param imageableX The X coordinate of the upper left hand corner of
+ * the imageable area, in 1/72nds of an inch.
+ * @param imageableY The Y coordinate of the upper left hand corner of
+ * the imageable area, in 1/72nds of an inch.
+ * @param imageableWidth The width of the imageable area of the paper,
+ * in 1/72nds of an inch.
+ * @param imageableHeight The heigth of the imageable area of the paper,
+ * in 1/72nds of an inch.
+ */
+public void
+setImageableArea(double imageableX, double imageableY,
+ double imageableWidth, double imageableHeight)
+{
+ this.imageableX = imageableX;
+ this.imageableY = imageableY;
+ this.imageableWidth = imageableWidth;
+ this.imageableHeight = imageableHeight;
+}
+
+/*************************************************************************/
+
+/**
+ * This method creates a copy of this object.
+ *
+ * @return A copy of this object.
+ */
+public Object
+clone()
+{
+ try
+ {
+ return(super.clone());
+ }
+ catch(CloneNotSupportedException e)
+ {
+ return(null);
+ }
+}
+
+} // class Paper
+
diff --git a/libjava/classpath/java/awt/print/Printable.java b/libjava/classpath/java/awt/print/Printable.java
new file mode 100644
index 00000000000..775167e669d
--- /dev/null
+++ b/libjava/classpath/java/awt/print/Printable.java
@@ -0,0 +1,80 @@
+/* Printable.java -- Renders a page to the print device
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.print;
+
+import java.awt.Graphics;
+
+
+/**
+ * This interface provides a mechanism for the actual printing of pages to the
+ * printer. The object implementing this interface performs the page
+ * rendering.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Printable
+{
+ /**
+ * This value is returned by the <code>print()</code> method to indicate
+ * that the requested page exists and has been printed.
+ */
+ int PAGE_EXISTS = 0;
+
+ /**
+ * This value is returned by the <code>print()</code> method to indicate
+ * that the requested page number does not exist.
+ */
+ int NO_SUCH_PAGE = 1;
+
+ /**
+ * This method prints the specified page to the specified graphics
+ * context in the specified format. The pages are numbered starting
+ * from zero.
+ *
+ * @param graphics The graphics context to render the pages on.
+ * @param format The format in which to print the page.
+ * @param page_number The page number to print, where numbers start at zero.
+ *
+ * @return <code>PAGE_EXISTS</code> if the requested page exists and was
+ * successfully printed, <code>NO_SUCH_PAGE</code> otherwise.
+ *
+ * @exception PrinterException If an error occurs during printing.
+ */
+ int print(Graphics graphics, PageFormat format, int page_number)
+ throws PrinterException;
+}
diff --git a/libjava/classpath/java/awt/print/PrinterAbortException.java b/libjava/classpath/java/awt/print/PrinterAbortException.java
new file mode 100644
index 00000000000..4580630790d
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterAbortException.java
@@ -0,0 +1,71 @@
+/* PrinterAbortException.java -- Indicates the print job was aborted
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This exception is thrown when the print job is aborted, either by the
+ * user or by the application.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class PrinterAbortException extends PrinterException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 4725169026278854136L;
+
+ /**
+ * Create a new instance with no detailed error message.
+ */
+ public PrinterAbortException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public PrinterAbortException(String message)
+ {
+ super(message);
+ }
+} // class PrinterAbortException
diff --git a/libjava/classpath/java/awt/print/PrinterException.java b/libjava/classpath/java/awt/print/PrinterException.java
new file mode 100644
index 00000000000..c105f549de4
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterException.java
@@ -0,0 +1,71 @@
+/* PrinterException.java -- generic problem in the printing subsystem
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This is the generic toplevel exception for printing errors. Subclasses
+ * provide more detailed descriptions of the problem.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class PrinterException extends Exception
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -3757589981158265819L;
+
+ /**
+ * Create a new instance with no detailed error message.
+ */
+ public PrinterException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public PrinterException(String message)
+ {
+ super(message);
+ }
+} // class PrinterException
diff --git a/libjava/classpath/java/awt/print/PrinterGraphics.java b/libjava/classpath/java/awt/print/PrinterGraphics.java
new file mode 100644
index 00000000000..5ca64190424
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterGraphics.java
@@ -0,0 +1,61 @@
+/* PrinterGraphics.java -- Hook to return print job controller.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This interface is implemented by the <code>Graphics</code> instance
+ * that is used for rendering pages. It provides a hook to return the
+ * object that is controlling the print job.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface PrinterGraphics
+{
+
+/**
+ * This method returns the instance of <code>PrinterJob</code> that is
+ * controlling this print job.
+ *
+ * @return The <code>PrinterJob</code> that is controlling this print job.
+ */
+PrinterJob
+getPrinterJob();
+
+} // interface PrinterGraphics
+
diff --git a/libjava/classpath/java/awt/print/PrinterIOException.java b/libjava/classpath/java/awt/print/PrinterIOException.java
new file mode 100644
index 00000000000..c646acdec3a
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterIOException.java
@@ -0,0 +1,98 @@
+/* PrinterIOException.java -- The print job encountered an I/O error
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+import java.io.IOException;
+
+/**
+ * This exception is thrown when the print job encounters an I/O problem
+ * of some kind.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class PrinterIOException extends PrinterException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 5850870712125932846L;
+
+ /**
+ * The exception that caused this (duplicates Throwable).
+ *
+ * @serial the I/O exception that terminated the job
+ */
+ private final IOException mException;
+
+ /**
+ * Initializes a new instance with the given cause.
+ *
+ * @param mException the cause
+ */
+ public PrinterIOException(IOException mException)
+ {
+ super(mException == null ? null : mException.toString());
+ initCause(mException);
+ this.mException = mException;
+ }
+
+ /**
+ * Gets the underlying <code>IOException</code> that caused this exception.
+ * This legacy method has been replaced by {@link #getCause()}.
+ *
+ * @return the cause
+ */
+ public IOException getIOException()
+ {
+ return mException;
+ }
+
+ /**
+ * Gets the cause.
+ *
+ * @return the cause
+ */
+ public Throwable getCause()
+ {
+ return mException;
+ }
+} // class PrinterIOException
+
diff --git a/libjava/classpath/java/awt/print/PrinterJob.java b/libjava/classpath/java/awt/print/PrinterJob.java
new file mode 100644
index 00000000000..e61ab61bc77
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterJob.java
@@ -0,0 +1,299 @@
+/* PrinterJob.java -- This job is the printer control class
+ Copyright (C) 1999, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+import java.awt.HeadlessException;
+
+import javax.print.PrintService;
+import javax.print.attribute.PrintRequestAttributeSet;
+
+/**
+ * This class controls printing.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class PrinterJob
+{
+ // The print service associated with this job
+ private PrintService printer = null;
+
+ /**
+ * Creates a new print job.
+ *
+ * @return A <code>PrinterJob</code> object for the newly created print job.
+ */
+ public static PrinterJob getPrinterJob()
+ {
+ // FIXME: Need to fix this to load a default implementation instance.
+ return null;
+ }
+
+ /**
+ * Initializes a new instance of <code>PrinterJob</code>.
+ */
+ public PrinterJob()
+ {
+ }
+
+ /**
+ * Returns the number of copies to be printed.
+ *
+ * @return The number of copies to be printed.
+ */
+ public abstract int getCopies();
+
+ /**
+ * Sets the number of copies to be printed.
+ *
+ * @param copies The number of copies to be printed.
+ */
+ public abstract void setCopies(int copies);
+
+ /**
+ * Returns the name of the print job.
+ *
+ * @return The name of the print job.
+ */
+ public abstract String getJobName();
+
+ /**
+ * Sets the name of the print job.
+ *
+ * @param job_name The name of the print job.
+ */
+ public abstract void setJobName(String job_name);
+
+ /**
+ * Returns the printing user name.
+ *
+ * @return The printing username.
+ */
+ public abstract String getUserName();
+
+ /**
+ * Cancels an in progress print job.
+ */
+ public abstract void cancel();
+
+ /**
+ * Tests whether or not this job has been cancelled.
+ *
+ * @return <code>true</code> if this job has been cancelled, <code>false</code>
+ * otherwise.
+ */
+ public abstract boolean isCancelled();
+
+ /**
+ * Returns an instance of the default page which will have the default
+ * paper and orientation.
+ *
+ * @return A default instance of <code>PageFormat</code>.
+ */
+ public PageFormat defaultPage()
+ {
+ return new PageFormat();
+ }
+
+ /**
+ * Clones the specified <code>PageFormat</code> object then alters the
+ * clone so that it represents the default page format.
+ *
+ * @param page_format The <code>PageFormat</code> to clone.
+ *
+ * @return A new default page format.
+ */
+ public abstract PageFormat defaultPage(PageFormat page_format);
+
+ /**
+ * Displays a dialog box to the user which allows the page format
+ * attributes to be modified.
+ *
+ * @param page_format The <code>PageFormat</code> object to modify.
+ *
+ * @return The modified <code>PageFormat</code>.
+ */
+ public abstract PageFormat pageDialog(PageFormat page_format)
+ throws HeadlessException;
+
+ /**
+ * @since 1.4
+ */
+ public PageFormat pageDialog(PrintRequestAttributeSet attributes)
+ throws HeadlessException
+ {
+ // FIXME: Implement this for real.
+ return pageDialog((PageFormat) null);
+ }
+
+ /**
+ * Prints the pages.
+ */
+ public abstract void print () throws PrinterException;
+
+ /**
+ * Prints the page with given attributes.
+ */
+ public abstract void print (PrintRequestAttributeSet attributes)
+ throws PrinterException;
+
+ /**
+ * Displays a dialog box to the user which allows the print job
+ * attributes to be modified.
+ *
+ * @return <code>false</code> if the user cancels the dialog box,
+ * <code>true</code> otherwise.
+ */
+ public abstract boolean printDialog()
+ throws HeadlessException;
+
+ /**
+ * Displays a dialog box to the user which allows the print job
+ * attributes to be modified.
+ *
+ * @return <code>false</code> if the user cancels the dialog box,
+ * <code>true</code> otherwise.
+ */
+ public boolean printDialog(PrintRequestAttributeSet attributes)
+ throws HeadlessException
+ {
+ // FIXME: Implement this for real.
+ return printDialog();
+ }
+
+ /**
+ * This sets the pages that are to be printed.
+ *
+ * @param pageable The pages to be printed, which may not be <code>null</code>.
+ */
+ public abstract void setPageable(Pageable pageable);
+
+ /**
+ * Sets this specified <code>Printable</code> as the one to use for
+ * rendering the pages on the print device.
+ *
+ * @param printable The <code>Printable</code> for the print job.
+ */
+ public abstract void setPrintable(Printable printable);
+
+ /**
+ * Sets the <code>Printable</code> and the page format for the pages
+ * to be printed.
+ *
+ * @param printable The <code>Printable</code> for the print job.
+ * @param page_format The <code>PageFormat</code> for the print job.
+ */
+ public abstract void setPrintable(Printable printable, PageFormat page_format);
+
+ /**
+ * Makes any alterations to the specified <code>PageFormat</code>
+ * necessary to make it work with the current printer. The alterations
+ * are made to a clone of the input object, which is then returned.
+ *
+ * @param page_format The <code>PageFormat</code> to validate.
+ *
+ * @return The validated <code>PageFormat</code>.
+ */
+ public abstract PageFormat validatePage(PageFormat page_format);
+
+ /**
+ * Find and return 2D image print services.
+ *
+ * This is the same as calling PrintServiceLookup.lookupPrintServices()
+ * with Pageable service-specified DocFlavor.
+ * @return Array of PrintService objects, could be empty.
+ * @since 1.4
+ */
+ public static PrintService[] lookupPrintServices()
+ {
+ return new PrintService[0];
+ // FIXME:
+ // Enable this when javax.print has this implemented.
+// return PrintServiceLookup.lookupPrintServices(
+// new DocFlavor("application/x-java-jvm-local-objectref",
+// "java.awt.print.Pageable"),
+// null);
+ }
+
+ /**
+ * Find and return 2D image stream print services.
+ *
+ * This is the same as calling
+ * StreamPrintServiceFactory.lookupStreamPrintServices()
+ * with Pageable service-specified DocFlavor.
+ * @param mimeType The output format mime type, or null for any type.
+ * @return Array of stream print services, could be empty.
+ * @since 1.4
+ */
+ // FIXME:
+ // Enable when javax.print has StreamPrintServiceFactory
+// public static StreamPrintServiceFactory[] lookupStreamPrintServices(String mimeType)
+// {
+// return StreamPrintServiceFactory.lookupStreamServiceFactories(
+// new DocFlavor("application/x-java-jvm-local-objectref",
+// "java.awt.print.Pageable"),
+// mimeType);
+// }
+
+ /**
+ * Return the printer for this job. If print services aren't supported by
+ * the subclass, returns null.
+ *
+ * @return The associated PrintService.
+ * @since 1.4
+ */
+ public PrintService getPrintService()
+ {
+ return null;
+ }
+
+ /**
+ * Change the printer for this print job to service. Subclasses that
+ * support setting the print service override this method. Throws
+ * PrinterException when the class doesn't support setting the printer,
+ * the service doesn't support Pageable or Printable interfaces for 2D
+ * print output.
+ * @param service The new printer to use.
+ * @throws PrinterException if service is not valid.
+ */
+ public void setPrintService(PrintService service)
+ throws PrinterException
+ {
+ throw new PrinterException();
+ }
+}
diff --git a/libjava/classpath/java/awt/print/package.html b/libjava/classpath/java/awt/print/package.html
new file mode 100644
index 00000000000..50abcbfad63
--- /dev/null
+++ b/libjava/classpath/java/awt/print/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.print package.
+ Copyright (C) 2002 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 - java.awt.print</title></head>
+
+<body>
+<p>Classes for printer jobs, pages, paper sizes, graphics and formats.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/beans/AppletInitializer.java b/libjava/classpath/java/beans/AppletInitializer.java
new file mode 100644
index 00000000000..69dc2cae50e
--- /dev/null
+++ b/libjava/classpath/java/beans/AppletInitializer.java
@@ -0,0 +1,61 @@
+/* java.beans.AppletInitializer
+ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.beans;
+
+import java.applet.Applet;
+import java.beans.beancontext.BeanContext;
+
+
+/** This interface is a mechanism for the initialization of a Java
+ * Bean that is also an Applet. It is used by
+ * <code>Beans.instantiate()</code>.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @since 1.2
+ */
+public interface AppletInitializer
+{
+ /** Activate the applet. */
+ void activate (Applet applet);
+
+ /** This method will be called by <code>Beans.instantiate()</code>
+ * to associated the new Applet with its AppletContext, AppletStub,
+ * and Container.
+ */
+ void initialize (Applet applet, BeanContext context);
+}
diff --git a/libjava/classpath/java/beans/BeanDescriptor.java b/libjava/classpath/java/beans/BeanDescriptor.java
new file mode 100644
index 00000000000..21227b2fee0
--- /dev/null
+++ b/libjava/classpath/java/beans/BeanDescriptor.java
@@ -0,0 +1,89 @@
+/* java.beans.BeanDescriptor
+ Copyright (C) 1998, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+/**
+ ** BeanDescriptor describes general information about a Bean, plus
+ ** stores the Bean's Class and it's customizer's Class.<P>
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 31 May 1998
+ **/
+
+public class BeanDescriptor extends FeatureDescriptor {
+ Class beanClass;
+ Class customizerClass;
+
+ /** Create a new BeanDescriptor with the given beanClass and
+ ** no customizer class.
+ ** @param beanClass the class of the Bean.
+ **/
+ public BeanDescriptor(Class beanClass) {
+ this(beanClass,null);
+ }
+
+ /** Create a new BeanDescriptor with the given bean class and
+ ** customizer class.
+ ** @param beanClass the class of the Bean.
+ ** @param customizerClass the class of the Bean's Customizer.
+ **/
+ public BeanDescriptor(Class beanClass, Class customizerClass) {
+ this.beanClass = beanClass;
+ this.customizerClass = customizerClass;
+
+ // Set the FeatureDescriptor programmatic name.
+ String name = beanClass.getName();
+ int lastInd = name.lastIndexOf('.');
+ if (lastInd != -1)
+ name = name.substring(lastInd + 1);
+
+ setName(name);
+ }
+
+ /** Get the Bean's class. **/
+ public Class getBeanClass() {
+ return beanClass;
+ }
+
+ /** Get the Bean's customizer's class. **/
+ public Class getCustomizerClass() {
+ return customizerClass;
+ }
+}
diff --git a/libjava/classpath/java/beans/BeanInfo.java b/libjava/classpath/java/beans/BeanInfo.java
new file mode 100644
index 00000000000..525500a389c
--- /dev/null
+++ b/libjava/classpath/java/beans/BeanInfo.java
@@ -0,0 +1,181 @@
+/* java.beans.BeanInfo
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+/**
+ ** BeanInfo can be implemented in order to provide explicit information to the Introspector.
+ **
+ ** When you write a BeanInfo class, you implement this interface
+ ** and provide explicit information by returning a non-null
+ ** value from the appropriate method. If you wish the
+ ** Introspector to determine certain information in the normal
+ ** way, just return null (or in the case of int methods, return
+ ** -1). There is a class called SimpleBeanInfo which returns
+ ** null from all methods, which you may extend and only
+ ** override the methods you wish to override.<P>
+ **
+ ** When you have written the class, give it the name
+ ** <CODE>&lt;Bean Class Name&gt;BeanInfo</CODE> and place it in
+ ** the same package as the Bean, or in the bean info search path
+ ** (see Introspector for information on search paths).<P>
+ **
+ ** A simple note about the way the Introspector interacts with
+ ** BeanInfo. Introspectors look at a Bean class and determine
+ ** if there is a BeanInfo class with it. If there is not a
+ ** BeanInfo class, it will behave as if the BeanInfo class
+ ** provided was a SimpleBeanInfo class (i.e. it will determine
+ ** all information automatically).<P>If there is a BeanInfo
+ ** class, then any methods that do *not* return null are
+ ** regarded as providing definitive information about the class
+ ** and all of its superclasses for those information types.
+ ** Even if a parent BeanInfo class explicitly returns that
+ ** information, it will not be used.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 28 Jul 1998
+ **/
+
+public interface BeanInfo {
+ /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+ int ICON_COLOR_16x16 = 1;
+ /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+ int ICON_COLOR_32x32 = 2;
+ /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+ int ICON_MONO_16x16 = 3;
+ /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+ int ICON_MONO_32x32 = 4;
+
+ /** Get the general description of this Bean type.
+ ** @return the BeanDescriptor for the Bean, or null if
+ ** the BeanDescriptor should be obtained by
+ ** Introspection.
+ **/
+ BeanDescriptor getBeanDescriptor();
+
+ /** Get the events this Bean type fires.
+ ** @return the EventDescriptors representing events this
+ ** Bean fires. Returns <CODE>null</CODE> if the
+ ** events are to be acquired by Introspection.
+ **/
+ EventSetDescriptor[] getEventSetDescriptors();
+
+ /** Get the "default" event, basically the one a RAD tool
+ ** user is most likely to select.
+ ** @return the index into the getEventSetDescriptors()
+ ** that the user is most likely to use. Returns
+ ** <CODE>-1</CODE> if there is no default event.
+ **/
+ int getDefaultEventIndex();
+
+ /** Get the properties (get/set method pairs) this Bean
+ ** type supports.
+ ** @return the PropertyDescriptors representing the
+ ** properties this Bean type supports.
+ ** Returns <CODE>null</CODE> if the properties
+ ** are to be obtained by Introspection.
+ **/
+ PropertyDescriptor[] getPropertyDescriptors();
+
+ /** Get the "default" property, basically the one a RAD
+ ** tool user is most likely to select.
+ ** @return the index into the getPropertyDescriptors()
+ ** that the user is most likely to use. Returns
+ ** <CODE>-1</CODE> if there is no default event.
+ **/
+ int getDefaultPropertyIndex();
+
+ /** Get the methods this Bean type supports.
+ ** @return the MethodDescriptors representing the
+ ** methods this Bean type supports. Returns
+ ** <CODE>null</CODE> if the methods are to be
+ ** obtained by Introspection.
+ **/
+ MethodDescriptor[] getMethodDescriptors();
+
+ /** Get additional BeanInfos representing this Bean.
+ ** In this version of JavaBeans, this method is used so
+ ** that space and time can be saved by reading a BeanInfo
+ ** for each class in the hierarchy (super, super(super),
+ ** and so on).<P>
+ **
+ ** The order of precedence when two pieces of BeanInfo
+ ** conflict (such as two PropertyDescriptors that have
+ ** the same name), in order from highest precedence to
+ ** lowest, is:
+ ** <OL>
+ ** <LI>This BeanInfo object.</LI>
+ ** <LI><CODE>getAdditionalBeanInfo()[getAdditionalBeanInfo().length]</CODE></LI>
+ ** <LI> ... </LI>
+ ** <LI><CODE>getAdditionalBeanInfo()[1]</CODE></LI>
+ ** <LI><CODE>getAdditionalBeanInfo()[0]</CODE></LI>
+ ** </OL><P>
+ **
+ ** <STRONG>Spec Note:</STRONG> It is possible that
+ ** returning <CODE>null</CODE> from this method could
+ ** stop Introspection in its tracks, but it is unclear
+ ** from the spec whether this is the case.
+ **
+ ** @return additional BeanInfos representing this Bean.
+ ** <CODE>null</CODE> may be returned (see Spec
+ ** Note, above).
+ **/
+ BeanInfo[] getAdditionalBeanInfo();
+
+ /** Get a visual icon for this Bean.
+ ** A Bean does not have to support icons, and if it does
+ ** support icons, it does not have to support every single
+ ** type. Sun recommends that if you only support one
+ ** type, you support 16x16 color. Sun also notes that you
+ ** should try to use a type (like GIF) that allows for
+ ** transparent pixels, so that the background of the RAD
+ ** tool can show through.<P>
+ **
+ ** <STRONG>Spec Note:</STRONG> If you do not support the
+ ** type of icon that is being asked for, but you do
+ ** support another type, it is unclear whether you should
+ ** return the other type or not. I would presume not.
+ **
+ ** @param iconType the type of icon to get (see the
+ ** ICON_* constants in this class).
+ ** @return the icon, or null if that type of icon is
+ ** unsupported by this Bean.
+ **/
+ java.awt.Image getIcon(int iconType);
+}
diff --git a/libjava/classpath/java/beans/Beans.java b/libjava/classpath/java/beans/Beans.java
new file mode 100644
index 00000000000..ffcb83fc1f3
--- /dev/null
+++ b/libjava/classpath/java/beans/Beans.java
@@ -0,0 +1,368 @@
+/* java.beans.Beans
+ Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.beans;
+
+import gnu.java.beans.DummyAppletStub;
+import gnu.java.io.ClassLoaderObjectInputStream;
+
+import java.applet.Applet;
+import java.beans.beancontext.BeanContext;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.net.URL;
+
+/**
+ * <code>Beans</code> provides some helper methods that allow the basic
+ * operations of Bean-ness.
+ *
+ * @author John Keiser
+ * @author Robert Schuster
+ *
+ * @since 1.1
+ * @status updated to 1.4
+ *
+ */
+public class Beans
+{
+ static boolean designTime = false;
+ static boolean guiAvailable = true;
+
+ /**
+ * Once again, we have a java.beans class with only
+ * static methods that can be instantiated. When
+ * will the madness end? :)
+ */
+ public Beans()
+ {
+ // Does intentionally nothing here.
+ }
+
+ /** Creates a bean.
+ * <p>This is a convenience method that calls <code>instantiate(cl, beanName, null, null)</code>.</p>
+ *
+ * @see instantiate(ClassLoader, String, BeanContext, AppletInitializer)
+ * @param cl ClassLoader to be used or <code>null</code> for the system classloader.
+ * @param beanName Name of a serialized bean or class name.
+ * @return A newly created bean.
+ * @throws IOException If access of an IO resource failed.
+ * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
+ */
+ public static Object instantiate(ClassLoader cl, String beanName)
+ throws IOException, ClassNotFoundException
+ {
+ return instantiate(cl, beanName, null, null);
+ }
+
+ /** Creates a bean.
+ *
+ * <p>This is a convenience method that calls <code>instantiate(cl, beanName, beanContext, null)</code>.</p>
+ *
+ * @see instantiate(ClassLoader, String, BeanContext, AppletInitializer)
+ * @param cl ClassLoader to be used or <code>null</code> for the system classloader.
+ * @param beanName Name of a serialized bean or class name.
+ * @param beanContext Context to which the newly created Bean should be added.
+ * @return A newly created bean.
+ * @throws IOException If access of an IO resource failed.
+ * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
+ */
+ public static Object instantiate(
+ ClassLoader cl,
+ String beanName,
+ BeanContext beanContext)
+ throws IOException, ClassNotFoundException
+ {
+ return instantiate(cl, beanName, beanContext, null);
+ }
+
+ /** Instantiates a bean according to Beans 1.0.
+ *
+ * <p>In Beans 1.0 the instantiation scheme is as follows:</p>
+ * <p>The name should be dot-separated (e.g "place.for.beans.myBean") and indicate either a
+ * serialized object or a class name. In the first case all dots in the name are replaced with
+ * slashes ('/') and ".ser" is appended ("place.for.beans.myBean" becomes "place/for/beans/myBean.ser").
+ * The bean is then loaded as an application or system resource depending on whether a
+ * <code>ClassLoader</code> was provided.</p>
+ *
+ * <p>If no such resource exists or if it contains no bean the name is interpreted as a class name of
+ * which an instance is then created.</p>
+ *
+ * <p>If a <code>BeanContext</code> instance is available the created bean is added to it.</p>
+ *
+ * <p>If the created Bean is an <code>Applet</code> or subclass and an <code>AppletInitializer</code>
+ * instance is available the applet is initialized and afterwards activated using the initializer. Additionally
+ * every instantiated <code>Applet</code> bean is initialized using the {@link Applet.init} method.
+ * Furthermore every applet gets a default <code>AppletStub</code>. The <code>Applet</code>'s
+ * document base is the location of the ".ser" file if it was deserialized or the location of its class
+ * file if it was instantiated.</p>
+ *
+ * <p>A <code>ClassNotFoundException</code> is not only thrown when a class name was unknown
+ * but even when the class has public no-argument constructor
+ * (<code>IllegalAccessException</code> is wrapped) or an exception is thrown while
+ * invoking such a constructor (causing exception is wrapped).</p>
+ *
+ * @param cl ClassLoader to be used or <code>null</code> for the system classloader.
+ * @param beanName Name of a serialized bean or class name.
+ * @param beanContext Context to which the newly created Bean should be added.
+ * @param initializer The AppletInitializer which is used for initializing <code>Applet</code> beans.
+ * @return A newly created bean.
+ * @throws IOException If access of an IO resource failed.
+ * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
+ */
+ public static Object instantiate(
+ ClassLoader cl,
+ String beanName,
+ BeanContext beanContext,
+ AppletInitializer initializer)
+ throws IOException, ClassNotFoundException
+ {
+ Object bean = null;
+ URL beanLocation = null;
+ URL classLocation = null;
+
+ // Converts bean name into a resource name (eg. "a.b.c" -> "a/b/c").
+ String resourceName = beanName.replace('.', '/');
+
+ /* Tries to get an input stream of the Bean, reading it as a system resource
+ * if no ClassLoader is present or as an application resource if a classloader
+ * is given.
+ */
+ beanLocation =
+ (cl == null)
+ ? ClassLoader.getSystemResource(resourceName + ".ser")
+ : cl.getResource(resourceName + ".ser");
+
+ // Reads the serialized Bean from the returned URL.
+ if (beanLocation != null)
+ {
+ // Deserializes the bean instance.
+ ObjectInputStream ois =
+ (cl == null)
+ ? new ObjectInputStream(beanLocation.openStream())
+ : new ClassLoaderObjectInputStream(
+ beanLocation.openStream(),
+ cl);
+
+ bean = ois.readObject();
+
+ /* Implementation note: The result of ObjectInputStream.readObject()
+ * may have been null at this point (its a valid value to deserialize)
+ * and we explicitly want to try instantiation in such a case
+ * (this is important for compatibility).
+ */
+ }
+
+ // Instantiates the Bean using reflective instantiation if it has not been created yet.
+ if (bean == null)
+ {
+ // Makes sure that the deserialization was NOT done.
+ beanLocation = null;
+
+ Class beanClass;
+ if (cl == null)
+ {
+ beanClass = Class.forName(beanName);
+ classLocation =
+ ClassLoader.getSystemResource(resourceName + ".class");
+ }
+ else
+ {
+ beanClass = cl.loadClass(beanName);
+ classLocation = cl.getResource(resourceName + ".class");
+ }
+
+ // Instantiates and optionally registers the new bean.
+ try
+ {
+ bean = beanClass.newInstance();
+ }
+ catch(Exception e) {
+ /* Wraps all kinds of Exceptions in a ClassNotFoundException (this behavior
+ * matches with official >= 1.5, this was different for <=1.4)
+ */
+ throw new ClassNotFoundException(null, e);
+ }
+ }
+
+ /* Applet beans are treated in the following way:
+ * - all AppletS get a default AppletStub
+ * - all AppletS are initialized using the AppletInitializer instance (if it is available)
+ * - as every other Bean Applets are added to a BeanContext if one is available
+ * - each instantiated Applet is initialized using Applet.init() (this is not done for deserialized ones)
+ * - finally AppletS get activated using the AppletInitializerS activate-Method
+ *
+ * The order of operations is important for compatibility.
+ */
+ Applet applet = null;
+ if (bean instanceof Applet)
+ {
+ // Makes a second instanceof call unneccessary (instanceof is expensive).
+ applet = (Applet) bean;
+
+ /* The AppletStub's code and document base is set as follows:
+ * The code base is always the URL from where the class data originated
+ * (without the package name).
+ * If the Applet was deserialized the document base is the location of
+ * the serialized instance (usually the ".ser" file) otherwise its the URL
+ * from where the class data originated (usually the absolute directory
+ * location of the ".class" file).
+ */
+ applet.setStub(
+ new DummyAppletStub(
+ applet
+ .getClass()
+ .getProtectionDomain()
+ .getCodeSource()
+ .getLocation(),
+ (beanLocation == null) ? classLocation : beanLocation));
+
+ // Runs the Applet's initialization using an AppletInitializer.
+ if (initializer != null)
+ {
+ initializer.initialize(applet, beanContext);
+ }
+ }
+
+ // Adds the new bean to its BeanContext.
+ if (beanContext != null)
+ {
+ beanContext.add(bean);
+ }
+
+ if (applet != null)
+ {
+
+ // Initializes an instantiated (not deserialized) Applet using its own method.
+ if (beanLocation == null)
+ {
+ applet.init();
+ }
+
+ // Runs the Applet's activation using an AppletInitializer.
+ if (initializer != null)
+ {
+ initializer.activate(applet);
+ }
+ }
+
+ return bean;
+ }
+
+ /**
+ * Returns the Bean as a different class type.
+ * This should be used instead of casting to get a new
+ * type view of a Bean, because in the future there may
+ * be new types of Bean, even Beans spanning multiple
+ * Objects.
+ *
+ * @param bean the Bean to cast.
+ * @param newClass the Class to cast it to.
+ *
+ * @return the Bean as a new view, or if the operation
+ * could not be performed, the Bean itself.
+ */
+ public static Object getInstanceOf(Object bean, Class newClass)
+ {
+ return bean;
+ }
+
+ /**
+ * Determines whether the Bean can be cast to a different
+ * class type.
+ * This should be used instead of instanceof to determine
+ * a Bean's castability, because in the future there may
+ * be new types of Bean, even Beans spanning multiple
+ * Objects.
+ *
+ * @param bean the Bean to cast.
+ * @param newClass the Class to cast it to.
+ *
+ * @return whether the Bean can be cast to the class type
+ * in question.
+ */
+ public static boolean isInstanceOf(Object bean, Class newBeanClass)
+ {
+ return newBeanClass.isInstance(bean);
+ }
+
+ /**
+ * Returns whether the GUI is available to use.
+ * <p>Defaults to true.</p>
+ *
+ * @return whether the GUI is available to use.
+ */
+ public static boolean isGuiAvailable()
+ {
+ return guiAvailable;
+ }
+
+ /**
+ * Returns whether it is design time. Design time means
+ * we are in a RAD tool.
+ * <p>Defaults to false.</p>
+ *
+ * @return whether it is design time.
+ */
+ public static boolean isDesignTime()
+ {
+ return designTime;
+ }
+
+ /**
+ * Sets whether the GUI is available to use.
+ *
+ * @param guiAvailable whether the GUI is available to use.
+ */
+ public static void setGuiAvailable(boolean guiAvailable)
+ throws SecurityException
+ {
+ Beans.guiAvailable = guiAvailable;
+ }
+
+ /**
+ * Sets whether it is design time. Design time means we
+ * are in a RAD tool.
+ *
+ * @param designTime whether it is design time.
+ */
+ public static void setDesignTime(boolean designTime)
+ throws SecurityException
+ {
+ Beans.designTime = designTime;
+ }
+
+}
diff --git a/libjava/classpath/java/beans/Customizer.java b/libjava/classpath/java/beans/Customizer.java
new file mode 100644
index 00000000000..b36c89f8846
--- /dev/null
+++ b/libjava/classpath/java/beans/Customizer.java
@@ -0,0 +1,86 @@
+/* java.beans.Customizer
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+/**
+ ** You may explicitly provide a Customizer for your Bean
+ ** class, which allows you complete control of the editing
+ ** of the Bean.<P>
+ **
+ ** A Customizer is meant to be embedded in an RAD tool,
+ ** and thus must be a descendant of <CODE>java.awt.Component</CODE>.<P>
+ **
+ ** It must also have a constructor with no arguments. This
+ ** is the constructor that will be called by the RAD tool to
+ ** instantiate the Customizer.<P>
+ **
+ ** Over its lifetime, an instance of a Customizer will only
+ ** customize one single Bean. A new instance of the
+ ** Customizer will be instantiated to edit any other Beans.<P>
+ **
+ ** The Customizer is responsible for notifying its
+ ** PropertyChangeListeners of any changes that are made,
+ ** according to the rules of PropertyChangeListeners (i.e.
+ ** notify the clients <EM>after</EM> the property has
+ ** changed).
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ ** @see java.beans.BeanDescriptor.getCustomizerClass()
+ **/
+
+public interface Customizer {
+ /** Set the object to Customize. This will always be a
+ ** Bean that had a BeanDescriptor indicating this
+ ** Customizer.
+ ** @param bean the Bean to customize.
+ **/
+ void setObject(Object bean);
+
+ /** Add a PropertyChangeListener.
+ ** @param l the PropertyChangeListener to add.
+ **/
+ void addPropertyChangeListener(PropertyChangeListener l);
+
+ /** Remove a PropertyChangeListener.
+ ** @param l the PropertyChangeListener to remove.
+ **/
+ void removePropertyChangeListener(PropertyChangeListener l);
+}
diff --git a/libjava/classpath/java/beans/DesignMode.java b/libjava/classpath/java/beans/DesignMode.java
new file mode 100644
index 00000000000..39805d50c18
--- /dev/null
+++ b/libjava/classpath/java/beans/DesignMode.java
@@ -0,0 +1,93 @@
+/* java.beans.DesignMode
+ Copyright (C) 1999 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.beans;
+
+/**
+ * <code>BeanContextChild</code> implementors implement this to get information about whether they are in a design time or runtime environment.
+ * The reason this is restricted to <code>BeanContextChild</code>ren is that
+ * only things in the <code>BeanContext</code> hierarchy are given this
+ * information in the first place.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextChild
+ */
+
+public interface DesignMode {
+ /**
+ * Use this name when firing <code>PropertyChangeEvent</code>s from your Bean.
+ * @fixme Check whether PROPERTYNAME is set to same value as Sun.
+ */
+ String PROPERTYNAME = "designTime";
+
+ /**
+ * The environment will call this method on your
+ * <code>BeanContextChild</code> when it is registered in a parent
+ * <code>BeanContext</code> or when behavior needs to switch from
+ * design time to runtime behavior (or vice versa).
+ * <P>
+ *
+ * <code>BeanContext</code>s are required to fire
+ * <code>PropertyChangeEvent</code>s when properties change.
+ * <code>designTime</code> is a property, and therefore when you
+ * implement <code>setDesignTime()</code>, you need to fire a
+ * <code>PropertyChangeEvent</code> with the old value, the new
+ * value and using <code>PROPERTYNAME</code> as the property name.
+ *
+ * @param designTime the new value of design time,
+ * <code>true</code> if it is design time,
+ * <code>false</code> if it is runtime.
+ *
+ * @fixme I'm frankly not really sure whether it's the case that
+ * the BeanContext can <em>change</em> the status of the Bean from
+ * design time to runtime. But it appears that it may be so.
+ *
+ * @see java.util.PropertyChangeEvent
+ * @see java.beans.beancontext.BeanContext
+ * @see #PROPERTYNAME
+ */
+ void setDesignTime(boolean designTime);
+
+ /**
+ * This method should tell whether it is design time or runtime.
+ * @return <code>true</code> if design time, <code>false</code> if
+ * runtime.
+ */
+ boolean isDesignTime();
+}
diff --git a/libjava/classpath/java/beans/EventHandler.java b/libjava/classpath/java/beans/EventHandler.java
new file mode 100644
index 00000000000..9c85893e0f3
--- /dev/null
+++ b/libjava/classpath/java/beans/EventHandler.java
@@ -0,0 +1,606 @@
+/* java.beans.EventHandler
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * <p>EventHandler forms a bridge between dynamically created listeners and
+ * arbitrary properties and methods.</p>
+ *
+ * <p>You can use this class to easily create listener implementations for
+ * some basic interactions between an event source and its target. Using
+ * the three static methods named <code>create</code> you can create
+ * these listener implementations.</p>
+ *
+ * <p>See the documentation of each method for usage examples.</p>
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Robert Schuster (thebohemian@gmx.net)
+ * @since 1.4
+ */
+public class EventHandler implements InvocationHandler
+{
+ // The name of the method that will be implemented. If null, any method.
+ private String listenerMethod;
+
+ // The object to call action on.
+ private Object target;
+
+ // The name of the method or property setter in target.
+ private String action;
+
+ // The property to extract from an event passed to listenerMethod.
+ private String property;
+
+ // The target objects Class.
+ private Class targetClass;
+
+ // String class doesn't already have a capitalize routine.
+ private String capitalize(String s)
+ {
+ return s.substring(0, 1).toUpperCase() + s.substring(1);
+ }
+
+ /**
+ * Creates a new <code>EventHandler</code> instance.
+ *
+ * <p>Typical creation is done with the create method, not by knewing an
+ * EventHandler.</p>
+ *
+ * <p>This constructs an EventHandler that will connect the method
+ * listenerMethodName to target.action, extracting eventPropertyName from
+ * the first argument of listenerMethodName. and sending it to action.</p>
+ *
+ * <p>Throws a <code>NullPointerException</code> if the <code>target</code>
+ * argument is <code>null</code>.
+ *
+ * @param target Object that will perform the action.
+ * @param action A property or method of the target.
+ * @param eventPropertyName A readable property of the inbound event.
+ * @param listenerMethodName The listener method name triggering the action.
+ */
+ public EventHandler(Object target, String action, String eventPropertyName,
+ String listenerMethodName)
+ {
+ this.target = target;
+
+ // Retrieving the class is done for two reasons:
+ // 1) The class object is needed very frequently in the invoke() method.
+ // 2) The constructor should throw a NullPointerException if target is null.
+ targetClass = target.getClass();
+
+ this.action = action; // Turn this into a method or do we wait till
+ // runtime
+ property = eventPropertyName;
+ listenerMethod = listenerMethodName;
+ }
+
+ /**
+ * Returns the event property name.
+ */
+ public String getEventPropertyName()
+ {
+ return property;
+ }
+
+ /**
+ * Returns the listener's method name.
+ */
+ public String getListenerMethodName()
+ {
+ return listenerMethod;
+ }
+
+ /**
+ * Returns the target object.
+ */
+ public Object getTarget()
+ {
+ return target;
+ }
+
+ /**
+ * Returns the action method name.
+ */
+ public String getAction()
+ {
+ return action;
+ }
+
+ // Fetch a qualified property like a.b.c from object o. The properties can
+ // be boolean isProp or object getProp properties.
+ //
+ // Returns a length 2 array with the first entry containing the value
+ // extracted from the property, and the second entry contains the class of
+ // the method return type.
+ //
+ // We play this game because if the method returns a native type, the return
+ // value will be a wrapper. If we then take the type of the wrapper and use
+ // it to locate the action method that takes the native type, it won't match.
+ private Object[] getProperty(Object o, String prop)
+ {
+ // Isolate the first property name from a.b.c.
+ int pos;
+ String rest = null;
+ if ((pos = prop.indexOf('.')) != -1)
+ {
+ rest = prop.substring(pos + 1);
+ prop = prop.substring(0, pos);
+ }
+
+ // Find a method named getProp. It could be isProp instead.
+ Method getter;
+ try
+ {
+ // Look for boolean property getter isProperty
+ getter = o.getClass().getMethod("is" + capitalize(prop),
+ null);
+ }
+ catch (NoSuchMethodException nsme1)
+ {
+ try {
+ // Look for regular property getter getProperty
+ getter = o.getClass().getMethod("get" + capitalize(prop),
+ null);
+ } catch(NoSuchMethodException nsme2) {
+ try {
+ // Finally look for a method of the name prop
+ getter = o.getClass().getMethod(prop, null);
+ } catch(NoSuchMethodException nsme3) {
+ // Ok, give up with an intelligent hint for the user.
+ throw new RuntimeException("Method not called: Could not find a property or method '" + prop
+ + "' in " + o.getClass() + " while following the property argument '" + property + "'.");
+ }
+ }
+ }
+ try {
+ Object val = getter.invoke(o, null);
+
+ if (rest != null)
+ return getProperty(val, rest);
+
+ return new Object[] {val, getter.getReturnType()};
+ } catch(InvocationTargetException ite) {
+ throw new RuntimeException("Method not called: Property or method '" + prop + "' has thrown an exception.", ite);
+ } catch(IllegalAccessException iae) {
+ // This cannot happen because we looked up method with Class.getMethod()
+ // which returns public methods only.
+ throw (InternalError) new InternalError("Non-public method was invoked.").initCause(iae);
+ }
+ }
+
+ /**
+ * Invokes the <code>EventHandler</code>.
+ *
+ * <p>This method is normally called by the listener's proxy implementation.</p>
+ *
+ * @param proxy The listener interface that is implemented using
+ * the proxy mechanism.
+ * @param method The method that was called on the proxy instance.
+ * @param arguments The arguments which where given to the method.
+ * @throws Throwable <code>NoSuchMethodException</code> is thrown when the EventHandler's
+ * action method or property cannot be found.
+ */
+ public Object invoke(Object proxy, Method method, Object[] arguments)
+ {
+ try {
+ // The method instance of the target object. We have to find out which
+ // one we have to invoke.
+ Method actionMethod = null;
+
+ // Listener methods that weren't specified are ignored. If listenerMethod
+ // is null, then all listener methods are processed.
+ if (listenerMethod != null && !method.getName().equals(listenerMethod))
+ return null;
+
+ // If a property is defined we definitely need a valid object at
+ // arguments[0] that can be used to retrieve a value to which the
+ // property of the target gets set.
+ if(property != null) {
+ // Extracts the argument. We will let it fail with a NullPointerException
+ // the caller used a listener method that has no arguments.
+ Object event = arguments[0];
+
+ // Obtains the property XXX propertyType keeps showing up null - why?
+ // because the object inside getProperty changes, but the ref variable
+ // can't change this way, dolt! need a better way to get both values out
+ // - need method and object to do the invoke and get return type
+ Object v[] = getProperty(event, property);
+ Object[] args = new Object[] { v[0] };
+
+ // Changes the class array that controls which method signature we are going
+ // to look up in the target object.
+ Class[] argTypes = new Class[] { initClass((Class) v[1]) };
+
+ // Tries to find a setter method to which we can apply the
+ while(argTypes[0] != null) {
+ try
+ {
+ // Look for a property setter for action.
+ actionMethod = targetClass.getMethod("set" + capitalize(action), argTypes);
+
+ return actionMethod.invoke(target, args);
+ }
+ catch (NoSuchMethodException e)
+ {
+ // If action as property didn't work, try as method later.
+ }
+
+ argTypes[0] = nextClass(argTypes[0]);
+ }
+
+ // We could not find a suitable setter method. Now we try again interpreting
+ // action as the method name itself.
+ // Since we probably have changed the block local argTypes array
+ // we need to rebuild it.
+ argTypes = new Class[] { initClass((Class) v[1]) };
+
+ // Tries to find a setter method to which we can apply the
+ while(argTypes[0] != null) {
+ try
+ {
+ actionMethod = targetClass.getMethod(action, argTypes);
+
+ return actionMethod.invoke(target, args);
+ }
+ catch (NoSuchMethodException e)
+ {
+ }
+
+ argTypes[0] = nextClass(argTypes[0]);
+ }
+
+ throw new RuntimeException("Method not called: Could not find a public method named '"
+ + action + "' in target " + targetClass + " which takes a '"
+ + v[1] + "' argument or a property of this type.");
+ }
+
+ // If property was null we will search for a no-argument method here.
+ // Note: The ordering of method lookups is important because we want to prefer no-argument
+ // calls like the JDK does. This means if we have actionMethod() and actionMethod(Event) we will
+ // call the first *EVEN* if we have a valid argument for the second method. This is behavior compliant
+ // to the JDK.
+ // If actionMethod() is not available but there is a actionMethod(Event) we take this. That makes us
+ // more specification compliant than the JDK itself because this one will fail in such a case.
+ try
+ {
+ actionMethod = targetClass.getMethod(action, null);
+ }
+ catch(NoSuchMethodException nsme)
+ {
+ // Note: If we want to be really strict the specification says that a no-argument method should
+ // accept an EventObject (or subclass I guess). However since the official implementation is broken
+ // anyways, it's more flexible without the EventObject restriction and we are compatible on everything
+ // else this can stay this way.
+ if(arguments != null && arguments.length >= 1/* && arguments[0] instanceof EventObject*/) {
+ Class[] targetArgTypes = new Class[] { initClass(arguments[0].getClass()) };
+
+ while(targetArgTypes[0] != null) {
+ try
+ {
+ // If no property exists we expect the first element of the arguments to be
+ // an EventObject which is then applied to the target method.
+
+ actionMethod = targetClass.getMethod(action, targetArgTypes);
+
+ return actionMethod.invoke(target, new Object[] { arguments[0] });
+ }
+ catch(NoSuchMethodException nsme2)
+ {
+
+ }
+
+ targetArgTypes[0] = nextClass(targetArgTypes[0]);
+ }
+
+ }
+ }
+
+ // If we do not have a Method instance at this point this means that all our tries
+ // failed. The JDK throws an ArrayIndexOutOfBoundsException in this case.
+ if(actionMethod == null)
+ throw new ArrayIndexOutOfBoundsException(0);
+
+ // Invoke target.action(property)
+ return actionMethod.invoke(target, null);
+ } catch(InvocationTargetException ite) {
+ throw new RuntimeException(ite.getCause());
+ } catch(IllegalAccessException iae) {
+ // Cannot happen because we always use getMethod() which returns public
+ // methods only. Otherwise there is something seriously broken in
+ // GNU Classpath.
+ throw (InternalError) new InternalError("Non-public method was invoked.").initCause(iae);
+ }
+ }
+
+ /**
+ * <p>Returns the primitive type for every wrapper class or the
+ * class itself if it is no wrapper class.</p>
+ *
+ * <p>This is needed because to be able to find both kinds of methods:
+ * One that takes a wrapper class as the first argument and one that
+ * accepts a primitive instead.</p>
+ */
+ private Class initClass(Class klass) {
+ if(klass == Boolean.class) {
+ return Boolean.TYPE;
+ } else if(klass == Byte.class) {
+ return Byte.TYPE;
+ } else if(klass == Short.class) {
+ return Short.TYPE;
+ } else if(klass == Integer.class) {
+ return Integer.TYPE;
+ } else if(klass == Long.class) {
+ return Long.TYPE;
+ } else if(klass == Float.class) {
+ return Float.TYPE;
+ } else if(klass == Double.class) {
+ return Double.TYPE;
+ } else {
+ return klass;
+ }
+ }
+
+ /**
+ *
+ *
+ * @param klass
+ * @return
+ */
+ private Class nextClass(Class klass) {
+ if(klass == Boolean.TYPE) {
+ return Boolean.class;
+ } else if(klass == Byte.TYPE) {
+ return Byte.class;
+ } else if(klass == Short.TYPE) {
+ return Short.class;
+ } else if(klass == Integer.TYPE) {
+ return Integer.class;
+ } else if(klass == Long.TYPE) {
+ return Long.class;
+ } else if(klass == Float.TYPE) {
+ return Float.class;
+ } else if(klass == Double.TYPE) {
+ return Double.class;
+ } else {
+ return klass.getSuperclass();
+ }
+ }
+
+ /**
+ * <p>Constructs an implementation of <code>listenerInterface</code>
+ * to dispatch events.</p>
+ *
+ * <p>You can use such an implementation to simply call a public
+ * no-argument method of an arbitrary target object or to forward
+ * the first argument of the listener method to the target method.</p>
+ *
+ * <p>Call this method like:</p>
+ * <code>
+ * button.addActionListener((ActionListener)
+ * EventHandler.create(ActionListener.class, target, "dispose"));
+ * </code>
+ *
+ * <p>to achieve the following behavior:</p>
+ * <code>
+ * button.addActionListener(new ActionListener() {
+ * public void actionPerformed(ActionEvent ae) {
+ * target.dispose();
+ * }
+ * });
+ * </code>
+ *
+ * <p>That means if you need a listener implementation that simply calls a
+ * a no-argument method on a given instance for <strong>each</strong>
+ * method of the listener interface.</p>
+ *
+ * <p>Note: The <code>action</code> is interpreted as a method name. If your target object
+ * has no no-argument method of the given name the EventHandler tries to find
+ * a method with the same name but which can accept the first argument of the
+ * listener method. Usually this will be an event object but any other object
+ * will be forwarded, too. Keep in mind that using a property name instead of a
+ * real method here is wrong and will throw an <code>ArrayIndexOutOfBoundsException</code>
+ * whenever one of the listener methods is called.<p/>
+ *
+ * <p>The <code>EventHandler</code> will automatically convert primitives
+ * to their wrapper class and vice versa. Furthermore it will call
+ * a target method if it accepts a superclass of the type of the
+ * first argument of the listener method.</p>
+ *
+ * <p>In case that the method of the target object throws an exception
+ * it will be wrapped in a <code>RuntimeException</code> and thrown out
+ * of the listener method.</p>
+ *
+ * <p>In case that the method of the target object cannot be found an
+ * <code>ArrayIndexOutOfBoundsException</code> will be thrown when the
+ * listener method is invoked.</p>
+ *
+ * <p>A call to this method is equivalent to:
+ * <code>create(listenerInterface, target, action, null, null)</code></p>
+ *
+ * @param listenerInterface Listener interface to implement.
+ * @param target Object to invoke action on.
+ * @param action Target property or method to invoke.
+ * @return A constructed proxy object.
+ */
+ public static Object create(Class listenerInterface, Object target, String action)
+ {
+ return create(listenerInterface, target, action, null, null);
+ }
+
+ /**
+ * <p>Constructs an implementation of <code>listenerInterface</code>
+ * to dispatch events.</p>
+ *
+ * <p>Use this method if you want to create an implementation that retrieves
+ * a property value from the <b>first</b> argument of the listener method
+ * and applies it to the target's property or method. This first argument
+ * of the listener is usually an event object but any other object is
+ * valid, too.</p>
+ *
+ * <p>You can set the value of <code>eventPropertyName</code> to "prop"
+ * to denote the retrieval of a property named "prop" from the event
+ * object. In case that no such property exists the <code>EventHandler</code>
+ * will try to find a method with that name.</p>
+ *
+ * <p>If you set <code>eventPropertyName</code> to a value like this "a.b.c"
+ * <code>EventHandler</code> will recursively evaluate the properties "a", "b"
+ * and "c". Again if no property can be found the <code>EventHandler</code>
+ * tries a method name instead. This allows mixing the names, too: "a.toString"
+ * will retrieve the property "a" from the event object and will then call
+ * the method "toString" on it.</p>
+ *
+ * <p>An exception thrown in any of these methods will provoke a
+ * <code>RuntimeException</code> to be thrown which contains an
+ * <code>InvocationTargetException</code> containing the triggering exception.</p>
+ *
+ * <p>If you set <code>eventPropertyName</code> to a non-null value the
+ * <code>action</code> parameter will be interpreted as a property name
+ * or a method name of the target object.</p>
+ *
+ * <p>Any object retrieved from the event object and applied to the
+ * target will converted from primitives to their wrapper class or
+ * vice versa or applied to a method that accepts a superclass
+ * of the object.</p>
+ *
+ * <p>Examples:</p>
+ * <p>The following code:</p><code>
+ * button.addActionListener(
+ * new ActionListener() {
+ * public void actionPerformed(ActionEvent ae) {
+ * Object o = ae.getSource().getClass().getName();
+ * textField.setText((String) o);
+ * }
+ * });
+ * </code>
+ *
+ * <p>Can be expressed using the <code>EventHandler</code> like this:</p>
+ * <p>
+ * <code>button.addActionListener((ActionListener)
+ * EventHandler.create(ActionListener.class, textField, "text", "source.class.name");
+ * <code>
+ * </p>
+ *
+ * <p>As said above you can specify the target as a method, too:</p>
+ * <p>
+ * <code>button.addActionListener((ActionListener)
+ * EventHandler.create(ActionListener.class, textField, "setText", "source.class.name");
+ * <code>
+ * </p>
+ *
+ * <p>Furthermore you can use method names in the property:</p>
+ * <p>
+ * <code>button.addActionListener((ActionListener)
+ * EventHandler.create(ActionListener.class, textField, "setText", "getSource.getClass.getName");
+ * <code>
+ * </p>
+ *
+ * <p>Finally you can mix names:</p>
+ * <p>
+ * <code>button.addActionListener((ActionListener)
+ * EventHandler.create(ActionListener.class, textField, "setText", "source.getClass.name");
+ * <code>
+ * </p>
+ *
+ * <p>A call to this method is equivalent to:
+ * <code>create(listenerInterface, target, action, null, null)</code>
+ * </p>
+ *
+ * @param listenerInterface Listener interface to implement.
+ * @param target Object to invoke action on.
+ * @param action Target property or method to invoke.
+ * @param eventPropertyName Name of property to extract from event.
+ * @return A constructed proxy object.
+ */
+ public static Object create(Class listenerInterface, Object target,
+ String action, String eventPropertyName)
+ {
+ return create(listenerInterface, target, action, eventPropertyName, null);
+ }
+
+ /**
+ * <p>Constructs an implementation of <code>listenerInterface</code>
+ * to dispatch events.</p>
+ *
+ * <p>Besides the functionality described for {@link create(Class, Object, String)}
+ * and {@link create(Class, Object, String, String)} this method allows you
+ * to filter the listener method that should have an effect. Look at these
+ * method's documentation for more information about the <code>EventHandler</code>'s
+ * usage.</p>
+ *
+ * <p>If you want to call <code>dispose</code> on a <code>JFrame</code> instance
+ * when the <code>WindowListener.windowClosing()</code> method was invoked use
+ * the following code:</p>
+ * <p>
+ * <code>
+ * EventHandler.create(WindowListener.class, jframeInstance, "dispose", null, "windowClosing");
+ * </code>
+ * </p>
+ *
+ * <p>A <code>NullPointerException</code> is thrown if the <code>listenerInterface</code>
+ * or <code>target</code> argument are <code>null</code>.
+ *
+ * @param listenerInterface Listener interface to implement.
+ * @param target Object to invoke action on.
+ * @param action Target method name to invoke.
+ * @param eventPropertyName Name of property to extract from event.
+ * @param listenerMethodName Listener method to implement.
+ * @return A constructed proxy object.
+ */
+ public static Object create(Class listenerInterface, Object target,
+ String action, String eventPropertyName,
+ String listenerMethodName)
+ {
+ // Create EventHandler instance
+ EventHandler eh = new EventHandler(target, action, eventPropertyName,
+ listenerMethodName);
+
+ // Create proxy object passing in the event handler
+ Object proxy = Proxy.newProxyInstance(listenerInterface.getClassLoader(),
+ new Class[] {listenerInterface},
+ eh);
+
+ return proxy;
+ }
+
+}
diff --git a/libjava/classpath/java/beans/EventSetDescriptor.java b/libjava/classpath/java/beans/EventSetDescriptor.java
new file mode 100644
index 00000000000..8624e643476
--- /dev/null
+++ b/libjava/classpath/java/beans/EventSetDescriptor.java
@@ -0,0 +1,442 @@
+/* java.beans.EventSetDescriptor
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import gnu.java.lang.ClassHelper;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Vector;
+
+/**
+ ** EventSetDescriptor describes the hookup between an event source
+ ** class and an event listener class.
+ **
+ ** EventSets have several attributes: the listener class, the events
+ ** that can be fired to the listener (methods in the listener class), and
+ ** an add and remove listener method from the event firer's class.<P>
+ **
+ ** The methods have these constraints on them:<P>
+ ** <UL>
+ ** <LI>event firing methods: must have <CODE>void</CODE> return value. Any
+ ** parameters and exceptions are allowed. May be public, protected or
+ ** package-protected. (Don't ask me why that is, I'm just following the spec.
+ ** The only place it is even mentioned is in the Java Beans white paper, and
+ ** there it is only implied.)</LI>
+ ** <LI>add listener method: must have <CODE>void</CODE> return value. Must
+ ** take exactly one argument, of the listener class's type. May fire either
+ ** zero exceptions, or one exception of type <CODE>java.util.TooManyListenersException</CODE>.
+ ** Must be public.</LI>
+ ** <LI>remove listener method: must have <CODE>void</CODE> return value.
+ ** Must take exactly one argument, of the listener class's type. May not
+ ** fire any exceptions. Must be public.</LI>
+ ** </UL>
+ **
+ ** A final constraint is that event listener classes must extend from EventListener.<P>
+ **
+ ** There are also various design patterns associated with some of the methods
+ ** of construction. Those are explained in more detail in the appropriate
+ ** constructors.<P>
+ **
+ ** <STRONG>Documentation Convention:</STRONG> for proper
+ ** Internalization of Beans inside an RAD tool, sometimes there
+ ** are two names for a property or method: a programmatic, or
+ ** locale-independent name, which can be used anywhere, and a
+ ** localized, display name, for ease of use. In the
+ ** documentation I will specify different String values as
+ ** either <EM>programmatic</EM> or <EM>localized</EM> to
+ ** make this distinction clear.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 31 May 1998
+ **/
+
+public class EventSetDescriptor extends FeatureDescriptor {
+ private Method addListenerMethod;
+ private Method removeListenerMethod;
+ private Class listenerType;
+ private MethodDescriptor[] listenerMethodDescriptors;
+ private Method[] listenerMethods;
+
+ private boolean unicast;
+ private boolean inDefaultEventSet = true;
+
+ /** Create a new EventSetDescriptor.
+ ** This version of the constructor enforces the rules imposed on the methods
+ ** described at the top of this class, as well as searching for:<P>
+ ** <OL>
+ ** <LI>The event-firing method must be non-private with signature
+ ** <CODE>void &lt;listenerMethodName&gt;(&lt;eventSetName&gt;Event)</CODE>
+ ** (where <CODE>&lt;eventSetName&gt;</CODE> has its first character capitalized
+ ** by the constructor and the Event is a descendant of
+ ** <CODE>java.util.EventObject</CODE>) in class <CODE>listenerType</CODE>
+ ** (any exceptions may be thrown).
+ ** <B>Implementation note:</B> Note that there could conceivably be multiple
+ ** methods with this type of signature (example: java.util.MouseEvent vs.
+ ** my.very.own.MouseEvent). In this implementation, all methods fitting the
+ ** description will be put into the <CODE>EventSetDescriptor</CODE>, even
+ ** though the spec says only one should be chosen (they probably weren't thinking as
+ ** pathologically as I was). I don't like arbitrarily choosing things.
+ ** If your class has only one such signature, as most do, you'll have no problems.</LI>
+ ** <LI>The add and remove methods must be public and named
+ ** <CODE>void add&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> and
+ ** <CODE>void remove&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> in
+ ** in class <CODE>eventSourceClass</CODE>, where
+ ** <CODE>&lt;eventSetName&gt;</CODE> will have its first letter capitalized.
+ ** Standard exception rules (see class description) apply.</LI>
+ ** </OL>
+ ** @param eventSourceClass the class containing the add/remove listener methods.
+ ** @param eventSetName the programmatic name of the event set, generally starting
+ ** with a lowercase letter (i.e. fooManChu instead of FooManChu). This will be used
+ ** to generate the name of the event object as well as the names of the add and
+ ** remove methods.
+ ** @param listenerType the class containing the event firing method.
+ ** @param listenerMethodName the name of the event firing method.
+ ** @exception IntrospectionException if listenerType is not an EventListener,
+ ** or if methods are not found or are invalid.
+ **/
+ public EventSetDescriptor(Class eventSourceClass,
+ String eventSetName,
+ Class listenerType,
+ String listenerMethodName) throws IntrospectionException {
+ setName(eventSetName);
+ if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Listener type is not an EventListener.");
+ }
+
+ String[] names = new String[1];
+ names[0] = listenerMethodName;
+
+ try {
+ eventSetName = Character.toUpperCase(eventSetName.charAt(0)) + eventSetName.substring(1);
+ } catch(StringIndexOutOfBoundsException e) {
+ eventSetName = "";
+ }
+
+ findMethods(eventSourceClass,listenerType,names,"add"+eventSetName+"Listener","remove"+eventSetName+"Listener",eventSetName+"Event");
+ this.listenerType = listenerType;
+ checkAddListenerUnicast();
+ if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+ throw new IntrospectionException("Listener remove method throws exceptions.");
+ }
+ }
+
+ /** Create a new EventSetDescriptor.
+ ** This form of the constructor allows you to specify the names of the methods and adds
+ ** no new constraints on top of the rules already described at the top of the class.<P>
+ **
+ ** @param eventSourceClass the class containing the add and remove listener methods.
+ ** @param eventSetName the programmatic name of the event set, generally starting
+ ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+ ** @param listenerType the class containing the event firing methods.
+ ** @param listenerMethodNames the names of the even firing methods.
+ ** @param addListenerMethodName the name of the add listener method.
+ ** @param removeListenerMethodName the name of the remove listener method.
+ ** @exception IntrospectionException if listenerType is not an EventListener
+ ** or if methods are not found or are invalid.
+ **/
+ public EventSetDescriptor(Class eventSourceClass,
+ String eventSetName,
+ Class listenerType,
+ String[] listenerMethodNames,
+ String addListenerMethodName,
+ String removeListenerMethodName) throws IntrospectionException {
+ setName(eventSetName);
+ if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Listener type is not an EventListener.");
+ }
+
+ findMethods(eventSourceClass,listenerType,listenerMethodNames,addListenerMethodName,removeListenerMethodName,null);
+ this.listenerType = listenerType;
+ checkAddListenerUnicast();
+ if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+ throw new IntrospectionException("Listener remove method throws exceptions.");
+ }
+ }
+
+ /** Create a new EventSetDescriptor.
+ ** This form of constructor allows you to explicitly say which methods do what, and
+ ** no reflection is done by the EventSetDescriptor. The methods are, however,
+ ** checked to ensure that they follow the rules set forth at the top of the class.
+ ** @param eventSetName the programmatic name of the event set, generally starting
+ ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+ ** @param listenerType the class containing the listenerMethods.
+ ** @param listenerMethods the event firing methods.
+ ** @param addListenerMethod the add listener method.
+ ** @param removeListenerMethod the remove listener method.
+ ** @exception IntrospectionException if the listenerType is not an EventListener,
+ ** or any of the methods are invalid.
+ **/
+ public EventSetDescriptor(String eventSetName,
+ Class listenerType,
+ Method[] listenerMethods,
+ Method addListenerMethod,
+ Method removeListenerMethod) throws IntrospectionException {
+ setName(eventSetName);
+ if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Listener type is not an EventListener.");
+ }
+
+ this.listenerMethods = listenerMethods;
+ this.addListenerMethod = addListenerMethod;
+ this.removeListenerMethod = removeListenerMethod;
+ this.listenerType = listenerType;
+ checkMethods();
+ checkAddListenerUnicast();
+ if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+ throw new IntrospectionException("Listener remove method throws exceptions.");
+ }
+ }
+
+ /** Create a new EventSetDescriptor.
+ ** This form of constructor allows you to explicitly say which methods do what, and
+ ** no reflection is done by the EventSetDescriptor. The methods are, however,
+ ** checked to ensure that they follow the rules set forth at the top of the class.
+ ** @param eventSetName the programmatic name of the event set, generally starting
+ ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+ ** @param listenerType the class containing the listenerMethods.
+ ** @param listenerMethodDescriptors the event firing methods.
+ ** @param addListenerMethod the add listener method.
+ ** @param removeListenerMethod the remove listener method.
+ ** @exception IntrospectionException if the listenerType is not an EventListener,
+ ** or any of the methods are invalid.
+ **/
+ public EventSetDescriptor(String eventSetName,
+ Class listenerType,
+ MethodDescriptor[] listenerMethodDescriptors,
+ Method addListenerMethod,
+ Method removeListenerMethod) throws IntrospectionException {
+ setName(eventSetName);
+ if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Listener type is not an EventListener.");
+ }
+
+ this.listenerMethodDescriptors = listenerMethodDescriptors;
+ this.listenerMethods = new Method[listenerMethodDescriptors.length];
+ for(int i=0;i<this.listenerMethodDescriptors.length;i++) {
+ this.listenerMethods[i] = this.listenerMethodDescriptors[i].getMethod();
+ }
+
+ this.addListenerMethod = addListenerMethod;
+ this.removeListenerMethod = removeListenerMethod;
+ this.listenerType = listenerType;
+ checkMethods();
+ checkAddListenerUnicast();
+ if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+ throw new IntrospectionException("Listener remove method throws exceptions.");
+ }
+ }
+
+ /** Get the class that contains the event firing methods. **/
+ public Class getListenerType() {
+ return listenerType;
+ }
+
+ /** Get the event firing methods. **/
+ public Method[] getListenerMethods() {
+ return listenerMethods;
+ }
+
+ /** Get the event firing methods as MethodDescriptors. **/
+ public MethodDescriptor[] getListenerMethodDescriptors() {
+ if(listenerMethodDescriptors == null) {
+ listenerMethodDescriptors = new MethodDescriptor[listenerMethods.length];
+ for(int i=0;i<listenerMethods.length;i++) {
+ listenerMethodDescriptors[i] = new MethodDescriptor(listenerMethods[i]);
+ }
+ }
+ return listenerMethodDescriptors;
+ }
+
+ /** Get the add listener method. **/
+ public Method getAddListenerMethod() {
+ return addListenerMethod;
+ }
+
+ /** Get the remove listener method. **/
+ public Method getRemoveListenerMethod() {
+ return removeListenerMethod;
+ }
+
+ /** Set whether or not multiple listeners may be added.
+ ** @param unicast whether or not multiple listeners may be added.
+ **/
+ public void setUnicast(boolean unicast) {
+ this.unicast = unicast;
+ }
+
+ /** Get whether or not multiple listeners may be added. (Defaults to false.) **/
+ public boolean isUnicast() {
+ return unicast;
+ }
+
+ /** Set whether or not this is in the default event set.
+ ** @param inDefaultEventSet whether this is in the default event set.
+ **/
+ public void setInDefaultEventSet(boolean inDefaultEventSet) {
+ this.inDefaultEventSet = inDefaultEventSet;
+ }
+
+ /** Get whether or not this is in the default event set. (Defaults to true.)**/
+ public boolean isInDefaultEventSet() {
+ return inDefaultEventSet;
+ }
+
+ private void checkAddListenerUnicast() throws IntrospectionException {
+ Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
+ if(addListenerExceptions.length > 1) {
+ throw new IntrospectionException("Listener add method throws too many exceptions.");
+ } else if(addListenerExceptions.length == 1
+ && !java.util.TooManyListenersException.class.isAssignableFrom(addListenerExceptions[0])) {
+ throw new IntrospectionException("Listener add method throws too many exceptions.");
+ }
+ }
+
+ private void checkMethods() throws IntrospectionException {
+ if(!addListenerMethod.getDeclaringClass().isAssignableFrom(removeListenerMethod.getDeclaringClass())
+ && !removeListenerMethod.getDeclaringClass().isAssignableFrom(addListenerMethod.getDeclaringClass())) {
+ throw new IntrospectionException("add and remove listener methods do not come from the same class. This is bad.");
+ }
+ if(!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
+ || addListenerMethod.getParameterTypes().length != 1
+ || !listenerType.equals(addListenerMethod.getParameterTypes()[0])
+ || !Modifier.isPublic(addListenerMethod.getModifiers())) {
+ throw new IntrospectionException("Add Listener Method invalid.");
+ }
+ if(!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
+ || removeListenerMethod.getParameterTypes().length != 1
+ || !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
+ || removeListenerMethod.getExceptionTypes().length > 0
+ || !Modifier.isPublic(removeListenerMethod.getModifiers())) {
+ throw new IntrospectionException("Remove Listener Method invalid.");
+ }
+
+ for(int i=0;i<listenerMethods.length;i++) {
+ if(!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
+ || Modifier.isPrivate(listenerMethods[i].getModifiers())) {
+ throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " non-void or private.");
+ }
+ if(!listenerMethods[i].getDeclaringClass().isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " not from class " + listenerType.getName());
+ }
+ }
+ }
+
+ private void findMethods(Class eventSourceClass,
+ Class listenerType,
+ String listenerMethodNames[],
+ String addListenerMethodName,
+ String removeListenerMethodName,
+ String absurdEventClassCheckName) throws IntrospectionException {
+
+ /* Find add listener method and remove listener method. */
+ Class[] listenerArgList = new Class[1];
+ listenerArgList[0] = listenerType;
+ try {
+ this.addListenerMethod = eventSourceClass.getMethod(addListenerMethodName,listenerArgList);
+ } catch(SecurityException E) {
+ throw new IntrospectionException("SecurityException trying to access method " + addListenerMethodName + ".");
+ } catch(NoSuchMethodException E) {
+ throw new IntrospectionException("Could not find method " + addListenerMethodName + ".");
+ }
+
+ if(this.addListenerMethod == null || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+ throw new IntrospectionException("Add listener method does not exist, is not public, or is not void.");
+ }
+
+ try {
+ this.removeListenerMethod = eventSourceClass.getMethod(removeListenerMethodName,listenerArgList);
+ } catch(SecurityException E) {
+ throw new IntrospectionException("SecurityException trying to access method " + removeListenerMethodName + ".");
+ } catch(NoSuchMethodException E) {
+ throw new IntrospectionException("Could not find method " + removeListenerMethodName + ".");
+ }
+ if(this.removeListenerMethod == null || !this.removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+ throw new IntrospectionException("Remove listener method does not exist, is not public, or is not void.");
+ }
+
+ /* Find the listener methods. */
+ Method[] methods;
+ try {
+ methods = ClassHelper.getAllMethods(listenerType);
+ } catch(SecurityException E) {
+ throw new IntrospectionException("Security: You cannot access fields in this class.");
+ }
+
+ Vector chosenMethods = new Vector();
+ boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
+ for(int i=0;i<methods.length;i++) {
+ if(Modifier.isPrivate(methods[i].getModifiers())) {
+ continue;
+ }
+ Method currentMethod = methods[i];
+ Class retval = currentMethod.getReturnType();
+ if(retval.equals(java.lang.Void.TYPE)) {
+ for(int j=0;j<listenerMethodNames.length;j++) {
+ if(currentMethod.getName().equals(listenerMethodNames[j])
+ && (absurdEventClassCheckName == null
+ || (currentMethod.getParameterTypes().length == 1
+ && ((currentMethod.getParameterTypes()[0]).getName().equals(absurdEventClassCheckName)
+ || (currentMethod.getParameterTypes()[0]).getName().endsWith("."+absurdEventClassCheckName)
+ )
+ )
+ )
+ ) {
+ chosenMethods.addElement(currentMethod);
+ listenerMethodFound[j] = true;
+ }
+ }
+ }
+ }
+
+ /* Make sure we found all the methods we were looking for. */
+ for(int i=0;i<listenerMethodFound.length;i++) {
+ if(!listenerMethodFound[i]) {
+ throw new IntrospectionException("Could not find event method " + listenerMethodNames[i]);
+ }
+ }
+
+ /* Now that we've chosen the listener methods we want, store them. */
+ this.listenerMethods = new Method[chosenMethods.size()];
+ for(int i=0;i<chosenMethods.size();i++) {
+ this.listenerMethods[i] = (Method)chosenMethods.elementAt(i);
+ }
+ }
+}
diff --git a/libjava/classpath/java/beans/ExceptionListener.java b/libjava/classpath/java/beans/ExceptionListener.java
new file mode 100644
index 00000000000..0eeb8a9561f
--- /dev/null
+++ b/libjava/classpath/java/beans/ExceptionListener.java
@@ -0,0 +1,57 @@
+/* ExceptionListener.java -- listen for recoverable internal exceptions
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+/**
+ * This interface allows a class to monitor internal exceptions, to try to
+ * recover from them.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface ExceptionListener
+{
+ /**
+ * Fired after an exception occurs.
+ *
+ * @param e the trapped exception
+ */
+ void exceptionThrown(Exception e);
+} // interface ExceptionListener
diff --git a/libjava/classpath/java/beans/Expression.java b/libjava/classpath/java/beans/Expression.java
new file mode 100644
index 00000000000..20b04f1c190
--- /dev/null
+++ b/libjava/classpath/java/beans/Expression.java
@@ -0,0 +1,133 @@
+/* java.beans.Expression
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+/**
+ * class Expression
+ *
+ * An Expression captures the execution of an object method that
+ * returns a value. It stores an object, the method to call, and the
+ * arguments to pass to the method.
+ *
+ * @since 1.4
+ */
+public class Expression extends Statement
+{
+ // This is a placeholder to indicate that value hasn't been set
+ // yet;
+ private static final Object unset = new Object();
+
+ // The value to return. This is equal to unset until getValue is called.
+ private Object value;
+
+
+ /**
+ * Constructor
+ *
+ * Constructs an Expression representing the invocation of
+ * object.methodName(arg[0], arg[1], ...); However, it will never
+ * be executed. Instead, value will always be returned.
+ *
+ * @param value The value to return.
+ * @param target The object to invoke the method on.
+ * @param methodName The object method to invoke.
+ * @param arguments An array of arguments to pass to the method.
+ */
+ public Expression(Object value, Object target, String methodName,
+ Object[] arguments)
+ {
+ super(target, methodName, arguments);
+ this.value = value;
+ }
+
+ /**
+ * Constructor
+ *
+ * Constructs an Expression representing the invocation of
+ * object.methodName(arg[0], arg[1], ...);
+ *
+ * @param target The object to invoke the method on.
+ * @param methodName The object method to invoke.
+ * @param arguments An array of arguments to pass to the method.
+ */
+ public Expression(Object target, String methodName, Object[] arguments)
+ {
+ super(target, methodName, arguments);
+ this.value = unset;
+ }
+
+ /**
+ * Return the result of executing the method.
+ *
+ * If the cached value has not yet been set, the method is
+ * executed in the same way as Statement.execute(), except that
+ * the value is cached, and then returned. If the value has been
+ * set, it is returned without executing the method again.
+ *
+ * @return the result of executing the method.
+ * @exception Exception if an error occurs
+ */
+ public Object getValue() throws Exception
+ {
+ if (value == unset)
+ value = doExecute();
+ return value;
+ }
+
+ /**
+ * Set the cached value to be returned by getValue()
+ *
+ * @param value the value to cache and return.
+ */
+ public void setValue(Object value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Return a string representation of this expression.
+ */
+ public String toString()
+ {
+ String result = super.toString();
+ if (value != unset)
+ return value.getClass().getName() + " " + result;
+ return result;
+ }
+}
diff --git a/libjava/classpath/java/beans/FeatureDescriptor.java b/libjava/classpath/java/beans/FeatureDescriptor.java
new file mode 100644
index 00000000000..aeb40949099
--- /dev/null
+++ b/libjava/classpath/java/beans/FeatureDescriptor.java
@@ -0,0 +1,232 @@
+/* java.beans.FeatureDescriptor
+ Copyright (C) 1998, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * FeatureDescriptor is the common superclass for all JavaBeans Descriptor
+ * classes. JavaBeans descriptors are abstract descriptors of properties,
+ * events, methods, beans, etc.<P>
+ *
+ * <STRONG>Documentation Convention:</STRONG> for proper
+ * Internalization of Beans inside an RAD tool, sometimes there
+ * are two names for a property or method: a programmatic, or
+ * locale-independent name, which can be used anywhere, and a
+ * localized, display name, for ease of use. In the
+ * documentation I will specify different String values as
+ * either <EM>programmatic</EM> or <EM>localized</EM> to
+ * make this distinction clear.
+ *
+ * @author John Keiser
+ * @since 1.1
+ */
+
+public class FeatureDescriptor
+{
+ String name;
+ String displayName;
+ String shortDescription;
+ boolean expert;
+ boolean hidden;
+ boolean preferred;
+
+ Hashtable valueHash;
+
+ /**
+ * Instantiate this FeatureDescriptor with appropriate default values.
+ */
+ public FeatureDescriptor()
+ {
+ valueHash = new Hashtable();
+ }
+
+ /**
+ * Get the programmatic name of this feature.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Set the programmatic name of this feature.
+ *
+ * @param name the new name for this feature.
+ */
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * Get the localized (display) name of this feature.
+ *
+ * @returns The localized display name of this feature or falls
+ * back to the programmatic name.
+ */
+ public String getDisplayName()
+ {
+ return (displayName == null) ? name : displayName;
+ }
+
+ /**
+ * Set the localized (display) name of this feature.
+ *
+ * @param displayName the new display name for this feature.
+ */
+ public void setDisplayName(String displayName)
+ {
+ this.displayName = displayName;
+ }
+
+ /**
+ * Get the localized short description for this feature.
+ *
+ * @returns A short localized description of this feature or
+ * what <code>getDisplayName</code> returns in case, that no short description
+ * is available.
+ */
+ public String getShortDescription()
+ {
+ return (shortDescription == null) ? getDisplayName() : shortDescription;
+ }
+
+ /**
+ * Set the localized short description for this feature.
+ *
+ * @param shortDescription the new short description for this feature.
+ */
+ public void setShortDescription(String shortDescription)
+ {
+ this.shortDescription = shortDescription;
+ }
+
+ /**
+ * Indicates whether this feature is for expert use only.
+ *
+ * @return true if for use by experts only,
+ * or false if anyone can use it.
+ */
+ public boolean isExpert()
+ {
+ return expert;
+ }
+
+ /**
+ * Set whether this feature is for expert use only.
+ *
+ * @param expert true if for use by experts only,
+ * or false if anyone can use it.
+ */
+ public void setExpert(boolean expert)
+ {
+ this.expert = expert;
+ }
+
+ /**
+ * Indicates whether this feature is for use by tools only.
+ * If it is for use by tools only, then it should not be displayed.
+ *
+ * @return true if tools only should use it,
+ * or false if anyone can see it.
+ */
+ public boolean isHidden()
+ {
+ return hidden;
+ }
+
+ /**
+ * Set whether this feature is for use by tools only.
+ * If it is for use by tools only, then it should not be displayed.
+ *
+ * @param hidden true if tools only should use it,
+ * or false if anyone can see it.
+ */
+ public void setHidden(boolean hidden)
+ {
+ this.hidden = hidden;
+ }
+
+ public boolean isPreferred ()
+ {
+ return preferred;
+ }
+
+ public void setPreferred (boolean preferred)
+ {
+ this.preferred = preferred;
+ }
+
+ /**
+ * Get an arbitrary value set with setValue().
+ *
+ * @param name the programmatic name of the key.
+ *
+ * @return the value associated with this name,
+ * or null if there is none.
+ */
+ public Object getValue(String name)
+ {
+ return valueHash.get(name);
+ }
+
+ /**
+ * Set an arbitrary string-value pair with this feature.
+ *
+ * @param name the programmatic name of the key.
+ * @param value the value to associate with the name.
+ */
+ public void setValue(String name, Object value)
+ {
+ valueHash.put(name, value);
+ }
+
+ /**
+ * Get a list of the programmatic key names set with setValue().
+ *
+ * @return an Enumerator over all the programmatic key names associated
+ * with this feature.
+ */
+ public Enumeration attributeNames()
+ {
+ return valueHash.keys();
+ }
+}
diff --git a/libjava/classpath/java/beans/IndexedPropertyDescriptor.java b/libjava/classpath/java/beans/IndexedPropertyDescriptor.java
new file mode 100644
index 00000000000..efdc7b40238
--- /dev/null
+++ b/libjava/classpath/java/beans/IndexedPropertyDescriptor.java
@@ -0,0 +1,307 @@
+/* java.beans.IndexedPropertyDescriptor
+ Copyright (C) 1998, 2003 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.beans;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+
+/**
+ ** IndexedPropertyDescriptor describes information about a JavaBean
+ ** indexed property, by which we mean an array-like property that
+ ** has been exposed via a pair of get and set methods and another
+ ** pair that allows you to get to the property by an index.<P>
+ **
+ ** An example property would have four methods like this:<P>
+ ** <CODE>FooBar[] getFoo()</CODE><BR>
+ ** <CODE>void setFoo(FooBar[])</CODE><BR>
+ ** <CODE>FooBar getFoo(int)</CODE><BR>
+ ** <CODE>void setFoo(int,FooBar)</CODE><P>
+ **
+ ** The constraints put on get and set methods are:<P>
+ ** <OL>
+ ** <LI>There must be at least a get(int) or a set(int,...) method.
+ ** Nothing else is required. <B>Spec note:</B>One nice restriction
+ ** would be that if there is a get() there must be a get(int), same
+ ** with set, but that is not in the spec and is fairly harmless.)</LI>
+ ** <LI>A get array method must have signature
+ ** <CODE>&lt;propertyType&gt;[] &lt;getMethodName&gt;()</CODE></LI>
+ ** <LI>A set array method must have signature
+ ** <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;[])</CODE></LI>
+ ** <LI>A get index method must have signature
+ ** <CODE>&lt;propertyType&gt; &lt;getMethodName&gt;(int)</CODE></LI>
+ ** <LI>A set index method must have signature
+ ** <CODE>void &lt;setMethodName&gt;(int,&lt;propertyType&gt;)</CODE></LI>
+ ** <LI>All these methods may throw any exception.</LI>
+ ** <LI>All these methods must be public.</LI>
+ ** </OL>
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+
+public class IndexedPropertyDescriptor extends PropertyDescriptor {
+ private Class indexedPropertyType;
+ private Method setIndex;
+ private Method getIndex;
+
+ /** Create a new IndexedPropertyDescriptor by introspection.
+ ** This form of constructor creates the PropertyDescriptor by
+ ** looking for getter methods named <CODE>get&lt;name&gt;()</CODE>
+ ** and setter methods named
+ ** <CODE>set&lt;name&gt;()</CODE> in class
+ ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
+ ** first letter capitalized by the constructor.<P>
+ **
+ ** <B>Implementation note:</B> If there is a get(int) method,
+ ** then the return type of that method is used to find the
+ ** remaining methods. If there is no get method, then the
+ ** set(int) method is searched for exhaustively and that type
+ ** is used to find the others.<P>
+ **
+ ** <B>Spec note:</B>
+ ** If there is no get(int) method and multiple set(int) methods with
+ ** the same name and the correct parameters (different type of course),
+ ** then an IntrospectionException is thrown. While Sun's spec
+ ** does not state this, it can make Bean behavior different on
+ ** different systems (since method order is not guaranteed) and as
+ ** such, can be treated as a bug in the spec. I am not aware of
+ ** whether Sun's implementation catches this.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param beanClass the class the get and set methods live in.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public IndexedPropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
+ super(name);
+ String capitalized;
+ try {
+ capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ } catch(StringIndexOutOfBoundsException e) {
+ capitalized = "";
+ }
+ findMethods(beanClass, "get" + capitalized, "set" + capitalized, "get" + capitalized, "set" + capitalized);
+ }
+
+ /** Create a new IndexedPropertyDescriptor by introspection.
+ ** This form of constructor allows you to specify the
+ ** names of the get and set methods to search for.<P>
+ **
+ ** <B>Implementation note:</B> If there is a get(int) method,
+ ** then the return type of that method is used to find the
+ ** remaining methods. If there is no get method, then the
+ ** set(int) method is searched for exhaustively and that type
+ ** is used to find the others.<P>
+ **
+ ** <B>Spec note:</B>
+ ** If there is no get(int) method and multiple set(int) methods with
+ ** the same name and the correct parameters (different type of course),
+ ** then an IntrospectionException is thrown. While Sun's spec
+ ** does not state this, it can make Bean behavior different on
+ ** different systems (since method order is not guaranteed) and as
+ ** such, can be treated as a bug in the spec. I am not aware of
+ ** whether Sun's implementation catches this.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param beanClass the class the get and set methods live in.
+ ** @param getMethodName the name of the get array method.
+ ** @param setMethodName the name of the set array method.
+ ** @param getIndexName the name of the get index method.
+ ** @param setIndexName the name of the set index method.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public IndexedPropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
+ super(name);
+ findMethods(beanClass, getMethodName, setMethodName, getIndexName, setIndexName);
+ }
+
+ /** Create a new PropertyDescriptor using explicit Methods.
+ ** Note that the methods will be checked for conformance to standard
+ ** Property method rules, as described above at the top of this class.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param getMethod the get array method.
+ ** @param setMethod the set array method.
+ ** @param getIndex the get index method.
+ ** @param setIndex the set index method.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public IndexedPropertyDescriptor(String name, Method getMethod, Method setMethod, Method getIndex, Method setIndex) throws IntrospectionException {
+ super(name);
+ if(getMethod != null && getMethod.getParameterTypes().length > 0) {
+ throw new IntrospectionException("get method has parameters");
+ }
+ if(getMethod != null && setMethod.getParameterTypes().length != 1) {
+ throw new IntrospectionException("set method does not have exactly one parameter");
+ }
+ if(getMethod != null && setMethod != null) {
+ if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
+ throw new IntrospectionException("set and get methods do not share the same type");
+ }
+ if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
+ && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
+ throw new IntrospectionException("set and get methods are not in the same class.");
+ }
+ }
+
+ if(getIndex != null && (getIndex.getParameterTypes().length != 1
+ || !(getIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
+ throw new IntrospectionException("get index method has wrong parameters");
+ }
+ if(setIndex != null && (setIndex.getParameterTypes().length != 2
+ || !(setIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
+ throw new IntrospectionException("set index method has wrong parameters");
+ }
+ if(getIndex != null && setIndex != null) {
+ if(!getIndex.getReturnType().equals(setIndex.getParameterTypes()[1])) {
+ throw new IntrospectionException("set index methods do not share the same type");
+ }
+ if(!getIndex.getDeclaringClass().isAssignableFrom(setIndex.getDeclaringClass())
+ && !setIndex.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
+ throw new IntrospectionException("get and set index methods are not in the same class.");
+ }
+ }
+
+ if(getIndex != null && getMethod != null && !getIndex.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())
+ && !getMethod.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
+ throw new IntrospectionException("methods are not in the same class.");
+ }
+
+ if(getIndex != null && getMethod != null && !Array.newInstance(getIndex.getReturnType(),0).getClass().equals(getMethod.getReturnType())) {
+ throw new IntrospectionException("array methods do not match index methods.");
+ }
+
+ this.getMethod = getMethod;
+ this.setMethod = setMethod;
+ this.getIndex = getIndex;
+ this.setIndex = setIndex;
+ this.indexedPropertyType = getIndex != null ? getIndex.getReturnType() : setIndex.getParameterTypes()[1];
+ this.propertyType = getMethod != null ? getMethod.getReturnType() : (setMethod != null ? setMethod.getParameterTypes()[0] : Array.newInstance(this.indexedPropertyType,0).getClass());
+ }
+
+ public Class getIndexedPropertyType() {
+ return indexedPropertyType;
+ }
+
+ public Method getIndexedReadMethod() {
+ return getIndex;
+ }
+
+ public Method getIndexedWriteMethod() {
+ return setIndex;
+ }
+
+ private void findMethods(Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
+ try {
+ if(getIndexName != null) {
+ try {
+ Class[] getArgs = new Class[1];
+ getArgs[0] = java.lang.Integer.TYPE;
+ getIndex = beanClass.getMethod(getIndexName,getArgs);
+ indexedPropertyType = getIndex.getReturnType();
+ } catch(NoSuchMethodException E) {
+ }
+ }
+ if(getIndex != null) {
+ if(setIndexName != null) {
+ try {
+ Class[] setArgs = new Class[2];
+ setArgs[0] = java.lang.Integer.TYPE;
+ setArgs[1] = indexedPropertyType;
+ setIndex = beanClass.getMethod(setIndexName,setArgs);
+ if(!setIndex.getReturnType().equals(java.lang.Void.TYPE)) {
+ throw new IntrospectionException(setIndexName + " has non-void return type");
+ }
+ } catch(NoSuchMethodException E) {
+ }
+ }
+ } else if(setIndexName != null) {
+ Method[] m = beanClass.getMethods();
+ for(int i=0;i<m.length;i++) {
+ Method current = m[i];
+ if(current.getName().equals(setIndexName)
+ && current.getParameterTypes().length == 2
+ && (current.getParameterTypes()[0]).equals(java.lang.Integer.TYPE)
+ && current.getReturnType().equals(java.lang.Void.TYPE)) {
+ if(setIndex != null) {
+ throw new IntrospectionException("Multiple, different set methods found that fit the bill!");
+ } else {
+ setIndex = current;
+ indexedPropertyType = current.getParameterTypes()[1];
+ }
+ }
+ }
+ if(setIndex == null) {
+ throw new IntrospectionException("Cannot find get or set methods.");
+ }
+ } else {
+ throw new IntrospectionException("Cannot find get or set methods.");
+ }
+
+ Class arrayType = Array.newInstance(indexedPropertyType,0).getClass();
+
+ Class[] setArgs = new Class[1];
+ setArgs[0] = arrayType;
+ try {
+ setMethod = beanClass.getMethod(setMethodName,setArgs);
+ if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+ setMethod = null;
+ }
+ } catch(NoSuchMethodException E) {
+ }
+
+ Class[] getArgs = new Class[0];
+ try {
+ getMethod = beanClass.getMethod(getMethodName,getArgs);
+ if(!getMethod.getReturnType().equals(arrayType)) {
+ getMethod = null;
+ }
+ } catch(NoSuchMethodException E) {
+ }
+ } catch(SecurityException E) {
+ throw new IntrospectionException("SecurityException while trying to find methods.");
+ }
+ }
+}
diff --git a/libjava/classpath/java/beans/IntrospectionException.java b/libjava/classpath/java/beans/IntrospectionException.java
new file mode 100644
index 00000000000..7bb83dac5b3
--- /dev/null
+++ b/libjava/classpath/java/beans/IntrospectionException.java
@@ -0,0 +1,67 @@
+/* IntrospectionException -- thrown when an exception occurs in introspection
+ Copyright (C) 1998, 2002 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.beans;
+
+/**
+ * IntrospectionException is thrown when the Introspector fails. Typical
+ * causes are the inability to map a name to its Class, or specifying a
+ * wrong type signature.
+ *
+ * @author John Keiser
+ * @see Introspector
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class IntrospectionException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -3728150539969542619L;
+
+ /**
+ * Instantiate this exception with the given message.
+ *
+ * @param msg the message for the exception
+ */
+ public IntrospectionException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/beans/Introspector.java b/libjava/classpath/java/beans/Introspector.java
new file mode 100644
index 00000000000..02781b46e0d
--- /dev/null
+++ b/libjava/classpath/java/beans/Introspector.java
@@ -0,0 +1,608 @@
+/* java.beans.Introspector
+ Copyright (C) 1998, 2002, 2003 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.beans;
+
+import gnu.java.beans.BeanInfoEmbryo;
+import gnu.java.beans.ExplicitBeanInfo;
+import gnu.java.beans.IntrospectionIncubator;
+import gnu.java.lang.ClassHelper;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * Introspector is the class that does the bulk of the
+ * design-time work in Java Beans. Every class must have
+ * a BeanInfo in order for an RAD tool to use it; but, as
+ * promised, you don't have to write the BeanInfo class
+ * yourself if you don't want to. All you have to do is
+ * call getBeanInfo() in the Introspector and it will use
+ * standard JavaBeans-defined method signatures to
+ * determine the information about your class.<P>
+ *
+ * Don't worry about it too much, though: you can provide
+ * JavaBeans with as much customized information as you
+ * want, or as little as you want, using the BeanInfo
+ * interface (see BeanInfo for details).<P>
+ *
+ * <STRONG>Order of Operations</STRONG><P>
+ *
+ * When you call getBeanInfo(class c), the Introspector
+ * first searches for BeanInfo class to see if you
+ * provided any explicit information. It searches for a
+ * class named &lt;bean class name&gt;BeanInfo in different
+ * packages, first searching the bean class's package
+ * and then moving on to search the beanInfoSearchPath.<P>
+ *
+ * If it does not find a BeanInfo class, it acts as though
+ * it had found a BeanInfo class returning null from all
+ * methods (meaning it should discover everything through
+ * Introspection). If it does, then it takes the
+ * information it finds in the BeanInfo class to be
+ * canonical (that is, the information speaks for its
+ * class as well as all superclasses).<P>
+ *
+ * When it has introspected the class, calls
+ * getBeanInfo(c.getSuperclass) and adds that information
+ * to the information it has, not adding to any information
+ * it already has that is canonical.<P>
+ *
+ * <STRONG>Introspection Design Patterns</STRONG><P>
+ *
+ * When the Introspector goes in to read the class, it
+ * follows a well-defined order in order to not leave any
+ * methods unaccounted for. Its job is to step over all
+ * of the public methods in a class and determine whether
+ * they are part of a property, an event, or a method (in
+ * that order).
+ *
+ *
+ * <STRONG>Properties:</STRONG><P>
+ *
+ * <OL>
+ * <LI>If there is a <CODE>public boolean isXXX()</CODE>
+ * method, then XXX is a read-only boolean property.
+ * <CODE>boolean getXXX()</CODE> may be supplied in
+ * addition to this method, although isXXX() is the
+ * one that will be used in this case and getXXX()
+ * will be ignored. If there is a
+ * <CODE>public void setXXX(boolean)</CODE> method,
+ * it is part of this group and makes it a read-write
+ * property.</LI>
+ * <LI>If there is a
+ * <CODE>public &lt;type&gt; getXXX(int)</CODE>
+ * method, then XXX is a read-only indexed property of
+ * type &lt;type&gt;. If there is a
+ * <CODE>public void setXXX(int,&lt;type&gt;)</CODE>
+ * method, then it is a read-write indexed property of
+ * type &lt;type&gt;. There may also be a
+ * <CODE>public &lt;type&gt;[] getXXX()</CODE> and a
+ * <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ * method as well.</LI>
+ * <LI>If there is a
+ * <CODE>public void setXXX(int,&lt;type&gt;)</CODE>
+ * method, then it is a write-only indexed property of
+ * type &lt;type&gt;. There may also be a
+ * <CODE>public &lt;type&gt;[] getXXX()</CODE> and a
+ * <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ * method as well.</LI>
+ * <LI>If there is a
+ * <CODE>public &lt;type&gt; getXXX()</CODE> method,
+ * then XXX is a read-only property of type
+ * &lt;type&gt;. If there is a
+ * <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ * method, then it will be used for the property and
+ * the property will be considered read-write.</LI>
+ * <LI>If there is a
+ * <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ * method, then as long as XXX is not already used as
+ * the name of a property, XXX is assumed to be a
+ * write-only property of type &lt;type&gt;.</LI>
+ * <LI>In all of the above cases, if the setXXX() method
+ * throws <CODE>PropertyVetoException</CODE>, then the
+ * property in question is assumed to be constrained.
+ * No properties are ever assumed to be bound
+ * (<STRONG>Spec Note:</STRONG> this is not in the
+ * spec, it just makes sense). See PropertyDescriptor
+ * for a description of bound and constrained
+ * properties.</LI>
+ * </OL>
+ *
+ * <STRONG>Events:</STRONG><P>
+ *
+ * If there is a pair of methods,
+ * <CODE>public void addXXX(&lt;type&gt;)</CODE> and
+ * <CODE>public void removeXXX(&lt;type&gt;)</CODE>, where
+ * &lt;type&gt; is a descendant of
+ * <CODE>java.util.EventListener</CODE>, then the pair of
+ * methods imply that this Bean will fire events to
+ * listeners of type &lt;type&gt;.<P>
+ *
+ * If the addXXX() method throws
+ * <CODE>java.util.TooManyListenersException</CODE>, then
+ * the event set is assumed to be <EM>unicast</EM>. See
+ * EventSetDescriptor for a discussion of unicast event
+ * sets.<P>
+ *
+ * <STRONG>Spec Note:</STRONG> the spec seems to say that
+ * the listener type's classname must be equal to the XXX
+ * part of addXXX() and removeXXX(), but that is not the
+ * case in Sun's implementation, so I am assuming it is
+ * not the case in general.<P>
+ *
+ * <STRONG>Methods:</STRONG><P>
+ *
+ * Any public methods (including those which were used
+ * for Properties or Events) are used as Methods.
+ *
+ * @author John Keiser
+ * @since JDK1.1
+ * @see java.beans.BeanInfo
+ */
+public class Introspector {
+
+ public static final int USE_ALL_BEANINFO = 1;
+ public static final int IGNORE_IMMEDIATE_BEANINFO = 2;
+ public static final int IGNORE_ALL_BEANINFO = 3;
+
+ static String[] beanInfoSearchPath = {"gnu.java.beans.info"};
+ static Hashtable beanInfoCache = new Hashtable();
+
+ private Introspector() {}
+
+ /**
+ * Get the BeanInfo for class <CODE>beanClass</CODE>,
+ * first by looking for explicit information, next by
+ * using standard design patterns to determine
+ * information about the class.
+ *
+ * @param beanClass the class to get BeanInfo about.
+ * @return the BeanInfo object representing the class.
+ */
+ public static BeanInfo getBeanInfo(Class beanClass)
+ throws IntrospectionException
+ {
+ BeanInfo cachedInfo;
+ synchronized(beanClass)
+ {
+ cachedInfo = (BeanInfo)beanInfoCache.get(beanClass);
+ if(cachedInfo != null)
+ {
+ return cachedInfo;
+ }
+ cachedInfo = getBeanInfo(beanClass,null);
+ beanInfoCache.put(beanClass,cachedInfo);
+ return cachedInfo;
+ }
+ }
+
+ /**
+ * Flush all of the Introspector's internal caches.
+ *
+ * @since 1.2
+ */
+ public static void flushCaches()
+ {
+ beanInfoCache.clear();
+
+ // Clears all the intermediate ExplicitInfo instances which
+ // have been created.
+ // This makes sure we have to retrieve stuff like BeanDescriptors
+ // again. (Remember that FeatureDescriptor can be modified by the user.)
+ ExplicitInfo.flushCaches();
+ }
+
+ /**
+ * Flush the Introspector's internal cached information for a given
+ * class.
+ *
+ * @param clz the class to be flushed.
+ * @throws NullPointerException if clz is null.
+ * @since 1.2
+ */
+ public static void flushFromCaches(Class clz)
+ {
+ synchronized (clz)
+ {
+ beanInfoCache.remove(clz);
+ }
+ }
+
+ /**
+ * Get the BeanInfo for class <CODE>beanClass</CODE>,
+ * first by looking for explicit information, next by
+ * using standard design patterns to determine
+ * information about the class. It crawls up the
+ * inheritance tree until it hits <CODE>topClass</CODE>.
+ *
+ * @param beanClass the Bean class.
+ * @param stopClass the class to stop at.
+ * @return the BeanInfo object representing the class.
+ */
+ public static BeanInfo getBeanInfo(Class beanClass, Class stopClass)
+ throws IntrospectionException
+ {
+ ExplicitInfo explicit = new ExplicitInfo(beanClass, stopClass);
+
+ IntrospectionIncubator ii = new IntrospectionIncubator();
+ ii.setPropertyStopClass(explicit.propertyStopClass);
+ ii.setEventStopClass(explicit.eventStopClass);
+ ii.setMethodStopClass(explicit.methodStopClass);
+ ii.addMethods(beanClass.getMethods());
+
+ BeanInfoEmbryo currentInfo = ii.getBeanInfoEmbryo();
+ PropertyDescriptor[] p = explicit.explicitPropertyDescriptors;
+ if(p!=null)
+ {
+ for(int i=0;i<p.length;i++)
+ {
+ if(!currentInfo.hasProperty(p[i]))
+ {
+ currentInfo.addProperty(p[i]);
+ }
+ }
+ if(explicit.defaultProperty != -1)
+ {
+ currentInfo.setDefaultPropertyName(p[explicit.defaultProperty].getName());
+ }
+ }
+ EventSetDescriptor[] e = explicit.explicitEventSetDescriptors;
+ if(e!=null)
+ {
+ for(int i=0;i<e.length;i++)
+ {
+ if(!currentInfo.hasEvent(e[i]))
+ {
+ currentInfo.addEvent(e[i]);
+ }
+ }
+ if(explicit.defaultEvent != -1)
+ {
+ currentInfo.setDefaultEventName(e[explicit.defaultEvent].getName());
+ }
+ }
+ MethodDescriptor[] m = explicit.explicitMethodDescriptors;
+ if(m!=null)
+ {
+ for(int i=0;i<m.length;i++)
+ {
+ if(!currentInfo.hasMethod(m[i]))
+ {
+ currentInfo.addMethod(m[i]);
+ }
+ }
+ }
+
+ // Sets the info's BeanDescriptor to the one we extracted from the
+ // explicit BeanInfo instance(s) if they contained one. Otherwise we
+ // create the BeanDescriptor from scratch.
+ // Note: We do not create a copy the retrieved BeanDescriptor which will allow
+ // the user to modify the instance while it is cached. However this is how
+ // the RI does it.
+ currentInfo.setBeanDescriptor(
+ (explicit.explicitBeanDescriptor == null ?
+ new BeanDescriptor(beanClass, null) :
+ explicit.explicitBeanDescriptor));
+
+ currentInfo.setAdditionalBeanInfo(explicit.explicitBeanInfo);
+ currentInfo.setIcons(explicit.im);
+
+ return currentInfo.getBeanInfo();
+ }
+
+ /**
+ * Get the search path for BeanInfo classes.
+ *
+ * @return the BeanInfo search path.
+ */
+ public static String[] getBeanInfoSearchPath()
+ {
+ return beanInfoSearchPath;
+ }
+
+ /**
+ * Set the search path for BeanInfo classes.
+ * @param beanInfoSearchPath the new BeanInfo search
+ * path.
+ */
+ public static void setBeanInfoSearchPath(String[] beanInfoSearchPath)
+ {
+ Introspector.beanInfoSearchPath = beanInfoSearchPath;
+ }
+
+ /**
+ * A helper method to convert a name to standard Java
+ * naming conventions: anything with two capitals as the
+ * first two letters remains the same, otherwise the
+ * first letter is decapitalized. URL = URL, I = i,
+ * MyMethod = myMethod.
+ *
+ * @param name the name to decapitalize.
+ * @return the decapitalized name.
+ */
+ public static String decapitalize(String name)
+ {
+ try
+ {
+ if(!Character.isUpperCase(name.charAt(0)))
+ {
+ return name;
+ }
+ else
+ {
+ try
+ {
+ if(Character.isUpperCase(name.charAt(1)))
+ {
+ return name;
+ }
+ else
+ {
+ char[] c = name.toCharArray();
+ c[0] = Character.toLowerCase(c[0]);
+ return new String(c);
+ }
+ }
+ catch(StringIndexOutOfBoundsException E)
+ {
+ char[] c = new char[1];
+ c[0] = Character.toLowerCase(name.charAt(0));
+ return new String(c);
+ }
+ }
+ }
+ catch(StringIndexOutOfBoundsException E)
+ {
+ return name;
+ }
+ catch(NullPointerException E)
+ {
+ return null;
+ }
+ }
+
+ static BeanInfo copyBeanInfo(BeanInfo b)
+ {
+ java.awt.Image[] icons = new java.awt.Image[4];
+ for(int i=1;i<=4;i++)
+ {
+ icons[i-1] = b.getIcon(i);
+ }
+
+ return new ExplicitBeanInfo(b.getBeanDescriptor(),
+ b.getAdditionalBeanInfo(),
+ b.getPropertyDescriptors(),
+ b.getDefaultPropertyIndex(),
+ b.getEventSetDescriptors(),
+ b.getDefaultEventIndex(),
+ b.getMethodDescriptors(),
+ icons);
+ }
+}
+
+class ExplicitInfo
+{
+ BeanDescriptor explicitBeanDescriptor;
+ BeanInfo[] explicitBeanInfo;
+
+ PropertyDescriptor[] explicitPropertyDescriptors;
+ EventSetDescriptor[] explicitEventSetDescriptors;
+ MethodDescriptor[] explicitMethodDescriptors;
+
+ int defaultProperty;
+ int defaultEvent;
+
+ java.awt.Image[] im = new java.awt.Image[4];
+
+ Class propertyStopClass;
+ Class eventStopClass;
+ Class methodStopClass;
+
+ static Hashtable explicitBeanInfos = new Hashtable();
+ static Vector emptyBeanInfos = new Vector();
+
+ ExplicitInfo(Class beanClass, Class stopClass)
+ {
+ while(beanClass != null && !beanClass.equals(stopClass))
+ {
+
+ BeanInfo explicit = findExplicitBeanInfo(beanClass);
+
+
+ if(explicit != null)
+ {
+
+ if(explicitBeanDescriptor == null)
+ {
+ explicitBeanDescriptor = explicit.getBeanDescriptor();
+ }
+
+ if(explicitBeanInfo == null)
+ {
+ explicitBeanInfo = explicit.getAdditionalBeanInfo();
+ }
+
+ if(explicitPropertyDescriptors == null)
+ {
+ if(explicit.getPropertyDescriptors() != null)
+ {
+ explicitPropertyDescriptors = explicit.getPropertyDescriptors();
+ defaultProperty = explicit.getDefaultPropertyIndex();
+ propertyStopClass = beanClass;
+ }
+ }
+
+ if(explicitEventSetDescriptors == null)
+ {
+ if(explicit.getEventSetDescriptors() != null)
+ {
+ explicitEventSetDescriptors = explicit.getEventSetDescriptors();
+ defaultEvent = explicit.getDefaultEventIndex();
+ eventStopClass = beanClass;
+ }
+ }
+
+ if(explicitMethodDescriptors == null)
+ {
+ if(explicit.getMethodDescriptors() != null)
+ {
+ explicitMethodDescriptors = explicit.getMethodDescriptors();
+ methodStopClass = beanClass;
+ }
+ }
+
+ if(im[0] == null && im[1] == null
+ && im[2] == null && im[3] == null)
+ {
+ im[0] = explicit.getIcon(0);
+ im[1] = explicit.getIcon(1);
+ im[2] = explicit.getIcon(2);
+ im[3] = explicit.getIcon(3);
+ }
+ }
+ beanClass = beanClass.getSuperclass();
+ }
+
+ if(propertyStopClass == null)
+ {
+ propertyStopClass = stopClass;
+ }
+
+ if(eventStopClass == null)
+ {
+ eventStopClass = stopClass;
+ }
+
+ if(methodStopClass == null)
+ {
+ methodStopClass = stopClass;
+ }
+ }
+
+ /** Throws away all cached data and makes sure we re-instantiate things
+ * like BeanDescriptors again.
+ */
+ static void flushCaches() {
+ explicitBeanInfos.clear();
+ emptyBeanInfos.clear();
+ }
+
+ static BeanInfo findExplicitBeanInfo(Class beanClass)
+ {
+ BeanInfo retval = (BeanInfo)explicitBeanInfos.get(beanClass);
+ if(retval != null)
+ {
+ return retval;
+ }
+ else if(emptyBeanInfos.indexOf(beanClass) != -1)
+ {
+ return null;
+ }
+ else
+ {
+ retval = reallyFindExplicitBeanInfo(beanClass);
+ if(retval != null)
+ {
+ explicitBeanInfos.put(beanClass,retval);
+ }
+ else
+ {
+ emptyBeanInfos.addElement(beanClass);
+ }
+ return retval;
+ }
+ }
+
+ static BeanInfo reallyFindExplicitBeanInfo(Class beanClass)
+ {
+ ClassLoader beanClassLoader = beanClass.getClassLoader();
+ BeanInfo beanInfo;
+
+ beanInfo = getBeanInfo(beanClassLoader, beanClass.getName() + "BeanInfo");
+ if (beanInfo == null)
+ {
+ String newName;
+ newName = ClassHelper.getTruncatedClassName(beanClass) + "BeanInfo";
+
+ for(int i = 0; i < Introspector.beanInfoSearchPath.length; i++)
+ {
+ if (Introspector.beanInfoSearchPath[i].equals(""))
+ beanInfo = getBeanInfo(beanClassLoader, newName);
+ else
+ beanInfo = getBeanInfo(beanClassLoader,
+ Introspector.beanInfoSearchPath[i] + "."
+ + newName);
+
+ // Returns the beanInfo if it exists and the described class matches
+ // the one we searched.
+ if (beanInfo != null && beanInfo.getBeanDescriptor() != null &&
+ beanInfo.getBeanDescriptor().getBeanClass() == beanClass)
+
+ return beanInfo;
+ }
+ }
+
+ return beanInfo;
+ }
+
+ /**
+ * Returns an instance of the given class name when it can be loaded
+ * through the given class loader, or null otherwise.
+ */
+ private static BeanInfo getBeanInfo(ClassLoader cl, String infoName)
+ {
+ try
+ {
+ return (BeanInfo) Class.forName(infoName, true, cl).newInstance();
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ return null;
+ }
+ catch (IllegalAccessException iae)
+ {
+ return null;
+ }
+ catch (InstantiationException ie)
+ {
+ return null;
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/beans/MethodDescriptor.java b/libjava/classpath/java/beans/MethodDescriptor.java
new file mode 100644
index 00000000000..123dba60cc9
--- /dev/null
+++ b/libjava/classpath/java/beans/MethodDescriptor.java
@@ -0,0 +1,88 @@
+/* java.beans.MethodDescriptor
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.lang.reflect.Method;
+
+/** MethodDescriptor describes information about a JavaBeans method.
+ ** It's a fairly straightforward class (at least something in this
+ ** package is straightforward!).
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+public class MethodDescriptor extends FeatureDescriptor {
+ private Method m;
+ private ParameterDescriptor[] parameterDescriptors;
+
+ /** Create a new MethodDescriptor.
+ ** This method sets the name to the name of the method (Method.getName()).
+ ** @param m the method it will represent.
+ **/
+ public MethodDescriptor(Method m) {
+ setName(m.getName());
+ this.m = m;
+ }
+
+ /** Create a new MethodDescriptor.
+ ** This method sets the name to the name of the method (Method.getName()).
+ ** @param m the method it will represent.
+ ** @param parameterDescriptors descriptions of the parameters (especially names).
+ **/
+ public MethodDescriptor(Method m, ParameterDescriptor[] parameterDescriptors) {
+ setName(m.getName());
+ this.m = m;
+ this.parameterDescriptors = parameterDescriptors;
+ }
+
+ /** Get the parameter descriptors from this method.
+ ** Since MethodDescriptor has no way of determining what
+ ** the parameter names were, this defaults to null.
+ **/
+ public ParameterDescriptor[] getParameterDescriptors() {
+ return parameterDescriptors;
+ }
+
+ /** Get the method this MethodDescriptor represents. **/
+ public Method getMethod() {
+ return m;
+ }
+}
+
diff --git a/libjava/classpath/java/beans/ParameterDescriptor.java b/libjava/classpath/java/beans/ParameterDescriptor.java
new file mode 100644
index 00000000000..8ea93a9bd8d
--- /dev/null
+++ b/libjava/classpath/java/beans/ParameterDescriptor.java
@@ -0,0 +1,52 @@
+/* java.beans.MethodDescriptor
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+/** ParameterDescriptor represents a single parameter to a method.
+ ** As it turns out, FeatureDescriptor is sufficient to hold all
+ ** the information. Use its constructor and methods to set
+ ** the appropriate values.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+public class ParameterDescriptor extends FeatureDescriptor {
+
+}
diff --git a/libjava/classpath/java/beans/PropertyChangeEvent.java b/libjava/classpath/java/beans/PropertyChangeEvent.java
new file mode 100644
index 00000000000..3e3f948e32a
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyChangeEvent.java
@@ -0,0 +1,189 @@
+/* PropertyChangeEvent.java -- describes a change in a property
+ Copyright (C) 1998, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.util.EventObject;
+
+/**
+ * PropertyChangeEvents are fired in the PropertyChange and VetoableChange
+ * event classes. They represent the old and new values as well as the
+ * source Bean. If the old or new value is a primitive type, it must be
+ * wrapped in the appropriate wrapper type (java.lang.Integer for int, etc.,
+ * etc.).
+ *
+ * <p>If the old or new values are unknown (although why that would be I do
+ * not know), they may be null. Also, if the set of properties itself has
+ * changed, the name should be null, and the old and new values may also be
+ * null. Right now Sun put in a propagationId, reserved for future use. Read
+ * the comments on the constructor and on setPropagationId for more
+ * information.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status udpated to 1.4
+ */
+public class PropertyChangeEvent extends EventObject
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 7042693688939648123L;
+
+ /**
+ * The name of the property that changed, may be null. Package visible for
+ * use by PropertyChangeSupport.
+ *
+ * @serial the changed property name
+ */
+ final String propertyName;
+
+ /**
+ * The new value of the property, may be null. Package visible for use by
+ * PropertyChangeSupport.
+ *
+ * @serial the new property value
+ */
+ final Object newValue;
+
+ /**
+ * The old value of the property, may be null. Package visible for use by
+ * PropertyChangeSupport.
+ *
+ * @serial the old property value
+ */
+ final Object oldValue;
+
+ /**
+ * The propagation ID, reserved for future use. May be null.
+ *
+ * @see #getPropagationId()
+ * @serial the Propagation ID
+ */
+ private Object propagationId;
+
+ /**
+ * Create a new PropertyChangeEvent. Remember that if you received a
+ * PropertyChangeEvent and are sending a new one, you should also set the
+ * propagation ID from the old PropertyChangeEvent.
+ *
+ * @param source the Bean containing the property
+ * @param propertyName the property's name
+ * @param oldVal the old value of the property
+ * @param newVal the new value of the property
+ * @throws IllegalArgumentException if source is null
+ */
+ public PropertyChangeEvent(Object source, String propertyName,
+ Object oldVal, Object newVal)
+ {
+ super(source);
+ this.propertyName = propertyName;
+ oldValue = oldVal;
+ newValue = newVal;
+ }
+
+ /**
+ * Get the property name. May be null if multiple properties changed.
+ *
+ * @return the property name
+ */
+ public String getPropertyName()
+ {
+ return propertyName;
+ }
+
+ /**
+ * Get the property's new value. May be null if multiple properties changed.
+ *
+ * @return the property's new value
+ */
+ public Object getNewValue()
+ {
+ return newValue;
+ }
+
+ /**
+ * Get the property's old value. May be null if multiple properties changed.
+ *
+ * @return the property's old value
+ */
+ public Object getOldValue()
+ {
+ return oldValue;
+ }
+
+ /**
+ * Set the propagation ID. This is a way for the event to be passed from
+ * hand to hand and retain a little extra state. Right now it is unused,
+ * but it should be propagated anyway so that future versions of JavaBeans
+ * can use it, for God knows what.
+ *
+ * @param propagationId the propagation ID
+ * @see #getPropagationId()
+ */
+ public void setPropagationId(Object propagationId)
+ {
+ this.propagationId = propagationId;
+ }
+
+ /**
+ * Get the propagation ID. Right now, it is not used for anything.
+ *
+ * @return the propagation ID
+ * @see #setPropagationId(Object)
+ */
+ public Object getPropagationId()
+ {
+ return propagationId;
+ }
+
+ /**
+ * Utility method to rollback a change.
+ *
+ * @param event the event to rollback
+ * @return a new event with old and new swapped
+ */
+ PropertyChangeEvent rollback()
+ {
+ PropertyChangeEvent result
+ = new PropertyChangeEvent(source, propertyName, newValue, oldValue);
+ result.propagationId = propagationId;
+ return result;
+ }
+} // class PropertyChangeEvent
diff --git a/libjava/classpath/java/beans/PropertyChangeListener.java b/libjava/classpath/java/beans/PropertyChangeListener.java
new file mode 100644
index 00000000000..a97e6e1c2e9
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyChangeListener.java
@@ -0,0 +1,61 @@
+/* PropertyChangeListener.java -- listen for changes in a bound property
+ Copyright (C) 1998, 2000, 2002 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.beans;
+
+import java.util.EventListener;
+
+/**
+ * PropertyChangeListener allows a class to monitor properties of a Bean for
+ * changes. A propertyChange() event will only be fired <em>after</em> the
+ * property has changed.
+ *
+ * @author John Keiser
+ * @see PropertyChangeSupport
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface PropertyChangeListener extends EventListener
+{
+ /**
+ * Fired after a Bean's property has changed.
+ *
+ * @param e the change (containing the old and new values)
+ */
+ void propertyChange(PropertyChangeEvent e);
+} // interface PropertyChangeListener
diff --git a/libjava/classpath/java/beans/PropertyChangeListenerProxy.java b/libjava/classpath/java/beans/PropertyChangeListenerProxy.java
new file mode 100644
index 00000000000..68a8153032b
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyChangeListenerProxy.java
@@ -0,0 +1,102 @@
+/* PropertyChangeListenerProxy.java -- adds a name to a property listener
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.util.EventListenerProxy;
+
+/**
+ * This class provides an extension to <code>PropertyChangeListener</code> -
+ * associating a name with the listener. This can be used to filter the
+ * changes that one is interested in.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status udpated to 1.4
+ */
+public class PropertyChangeListenerProxy extends EventListenerProxy
+ implements PropertyChangeListener
+{
+ /**
+ * The name of the property to listen for. Package visible for use by
+ * PropertyChangeSupport.
+ */
+ final String propertyName;
+
+ /**
+ * Create a new proxy which filters property change events and only passes
+ * changes to the named property on to the delegate. A null propertyName
+ * or listener does not fail now, but may cause a NullPointerException down
+ * the road.
+ *
+ * @param propertyName the property's name to filter on
+ * @param listener the delegate listener
+ */
+ public PropertyChangeListenerProxy(String propertyName,
+ PropertyChangeListener listener)
+ {
+ super(listener);
+ this.propertyName = propertyName;
+ }
+
+ /**
+ * Forwards the event on to the delegate if the property name matches.
+ *
+ * @param event the event to pass on, if it meets the filter
+ * @throws NullPointerException if the delegate this was created with is null
+ */
+ public void propertyChange(PropertyChangeEvent event)
+ {
+ // Note: Sun does not filter, under the assumption that since
+ // PropertyChangeSupport unwraps proxys, this method should never be
+ // called by normal use of listeners.
+ String name = event == null ? null : event.getPropertyName();
+ if (name == null ? propertyName == null : name.equals(propertyName))
+ ((PropertyChangeListener) getListener()).propertyChange(event);
+ }
+
+ /**
+ * Gets the name of the property this proxy is filtering on.
+ *
+ * @return the property name
+ */
+ public String getPropertyName()
+ {
+ return propertyName;
+ }
+} // class PropertyChangeListenerProxy
diff --git a/libjava/classpath/java/beans/PropertyChangeSupport.java b/libjava/classpath/java/beans/PropertyChangeSupport.java
new file mode 100644
index 00000000000..a0e64af4d29
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyChangeSupport.java
@@ -0,0 +1,488 @@
+/* PropertyChangeSupport.java -- support to manage property change listeners
+ Copyright (C) 1998, 1999, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Vector;
+
+/**
+ * PropertyChangeSupport makes it easy to fire property change events and
+ * handle listeners. It allows chaining of listeners, as well as filtering
+ * by property name. In addition, it will serialize only those listeners
+ * which are serializable, ignoring the others without problem. This class
+ * is thread-safe.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class PropertyChangeSupport implements Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 6401253773779951803L;
+
+ /**
+ * Maps property names (String) to named listeners (PropertyChangeSupport).
+ * If this is a child instance, this field will be null.
+ *
+ * @serial the map of property names to named listener managers
+ * @since 1.2
+ */
+ private Hashtable children;
+
+ /**
+ * The non-null source object for any generated events.
+ *
+ * @serial the event source
+ */
+ private final Object source;
+
+ /**
+ * A field to compare serialization versions - this class uses version 2.
+ *
+ * @serial the serialization format
+ */
+ private static final int propertyChangeSupportSerializedDataVersion = 2;
+
+ /**
+ * The list of all registered property listeners. If this instance was
+ * created by user code, this only holds the global listeners (ie. not tied
+ * to a name), and may be null. If it was created by this class, as a
+ * helper for named properties, then this vector will be non-null, and this
+ * instance appears as a value in the <code>children</code> hashtable of
+ * another instance, so that the listeners are tied to the key of that
+ * hashtable entry.
+ */
+ private transient Vector listeners;
+
+ /**
+ * Create a PropertyChangeSupport to work with a specific source bean.
+ *
+ * @param source the source bean to use
+ * @throws NullPointerException if source is null
+ */
+ public PropertyChangeSupport(Object source)
+ {
+ this.source = source;
+ if (source == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Adds a PropertyChangeListener to the list of global listeners. All
+ * property change events will be sent to this listener. The listener add
+ * is not unique: that is, <em>n</em> adds with the same listener will
+ * result in <em>n</em> events being sent to that listener for every
+ * property change. Adding a null listener may cause a NullPointerException
+ * down the road. This method will unwrap a PropertyChangeListenerProxy,
+ * registering the underlying delegate to the named property list.
+ *
+ * @param l the listener to add
+ */
+ public synchronized void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ if (l instanceof PropertyChangeListenerProxy)
+ {
+ PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
+ addPropertyChangeListener(p.propertyName,
+ (PropertyChangeListener) p.getListener());
+ }
+ else
+ {
+ if (listeners == null)
+ listeners = new Vector();
+ listeners.add(l);
+ }
+ }
+
+ /**
+ * Removes a PropertyChangeListener from the list of global listeners. If
+ * any specific properties are being listened on, they must be deregistered
+ * by themselves; this will only remove the general listener to all
+ * properties. If <code>add()</code> has been called multiple times for a
+ * particular listener, <code>remove()</code> will have to be called the
+ * same number of times to deregister it. This method will unwrap a
+ * PropertyChangeListenerProxy, removing the underlying delegate from the
+ * named property list.
+ *
+ * @param l the listener to remove
+ */
+ public synchronized void
+ removePropertyChangeListener(PropertyChangeListener l)
+ {
+ if (l instanceof PropertyChangeListenerProxy)
+ {
+ PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
+ removePropertyChangeListener(p.propertyName,
+ (PropertyChangeListener) p.getListener());
+ }
+ else if (listeners != null)
+ {
+ listeners.remove(l);
+ if (listeners.isEmpty())
+ listeners = null;
+ }
+ }
+
+ /**
+ * Returns an array of all registered property change listeners. Those that
+ * were registered under a name will be wrapped in a
+ * <code>PropertyChangeListenerProxy</code>, so you must check whether the
+ * listener is an instance of the proxy class in order to see what name the
+ * real listener is registered under. If there are no registered listeners,
+ * this returns an empty array.
+ *
+ * @return the array of registered listeners
+ * @see PropertyChangeListenerProxy
+ * @since 1.4
+ */
+ public synchronized PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ ArrayList list = new ArrayList();
+ if (listeners != null)
+ list.addAll(listeners);
+ if (children != null)
+ {
+ int i = children.size();
+ Iterator iter = children.entrySet().iterator();
+ while (--i >= 0)
+ {
+ Entry e = (Entry) iter.next();
+ String name = (String) e.getKey();
+ Vector v = ((PropertyChangeSupport) e.getValue()).listeners;
+ int j = v.size();
+ while (--j >= 0)
+ list.add(new PropertyChangeListenerProxy
+ (name, (PropertyChangeListener) v.get(j)));
+ }
+ }
+ return (PropertyChangeListener[])
+ list.toArray(new PropertyChangeListener[list.size()]);
+ }
+
+ /**
+ * Adds a PropertyChangeListener listening on the specified property. Events
+ * will be sent to the listener only if the property name matches. The
+ * listener add is not unique; that is, <em>n</em> adds on a particular
+ * property for a particular listener will result in <em>n</em> events
+ * being sent to that listener when that property is changed. The effect is
+ * cumulative, too; if you are registered to listen to receive events on
+ * all property changes, and then you register on a particular property,
+ * you will receive change events for that property twice. Adding a null
+ * listener may cause a NullPointerException down the road. This method
+ * will unwrap a PropertyChangeListenerProxy, registering the underlying
+ * delegate to the named property list if the names match, and discarding
+ * it otherwise.
+ *
+ * @param propertyName the name of the property to listen on
+ * @param l the listener to add
+ * @throws NullPointerException if propertyName is null
+ */
+ public synchronized void addPropertyChangeListener(String propertyName,
+ PropertyChangeListener l)
+ {
+ while (l instanceof PropertyChangeListenerProxy)
+ {
+ PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
+ if (propertyName == null ? p.propertyName != null
+ : ! propertyName.equals(p.propertyName))
+ return;
+ l = (PropertyChangeListener) p.getListener();
+ }
+ PropertyChangeSupport s = null;
+ if (children == null)
+ children = new Hashtable();
+ else
+ s = (PropertyChangeSupport) children.get(propertyName);
+ if (s == null)
+ {
+ s = new PropertyChangeSupport(source);
+ s.listeners = new Vector();
+ children.put(propertyName, s);
+ }
+ s.listeners.add(l);
+ }
+
+ /**
+ * Removes a PropertyChangeListener from listening to a specific property.
+ * If <code>add()</code> has been called multiple times for a particular
+ * listener on a property, <code>remove()</code> will have to be called the
+ * same number of times to deregister it. This method will unwrap a
+ * PropertyChangeListenerProxy, removing the underlying delegate from the
+ * named property list if the names match.
+ *
+ * @param propertyName the property to stop listening on
+ * @param l the listener to remove
+ * @throws NullPointerException if propertyName is null
+ */
+ public synchronized void
+ removePropertyChangeListener(String propertyName, PropertyChangeListener l)
+ {
+ if (children == null)
+ return;
+ PropertyChangeSupport s
+ = (PropertyChangeSupport) children.get(propertyName);
+ if (s == null)
+ return;
+ while (l instanceof PropertyChangeListenerProxy)
+ {
+ PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
+ if (propertyName == null ? p.propertyName != null
+ : ! propertyName.equals(p.propertyName))
+ return;
+ l = (PropertyChangeListener) p.getListener();
+ }
+ s.listeners.remove(l);
+ if (s.listeners.isEmpty())
+ {
+ children.remove(propertyName);
+ if (children.isEmpty())
+ children = null;
+ }
+ }
+
+ /**
+ * Returns an array of all property change listeners registered under the
+ * given property name. If there are no registered listeners, this returns
+ * an empty array.
+ *
+ * @return the array of registered listeners
+ * @throws NullPointerException if propertyName is null
+ * @since 1.4
+ */
+ public synchronized PropertyChangeListener[]
+ getPropertyChangeListeners(String propertyName)
+ {
+ if (children == null)
+ return new PropertyChangeListener[0];
+ PropertyChangeSupport s
+ = (PropertyChangeSupport) children.get(propertyName);
+ if (s == null)
+ return new PropertyChangeListener[0];
+ return (PropertyChangeListener[])
+ s.listeners.toArray(new PropertyChangeListener[s.listeners.size()]);
+ }
+
+ /**
+ * Fire a PropertyChangeEvent containing the old and new values of the
+ * property to all the global listeners, and to all the listeners for the
+ * specified property name. This does nothing if old and new are non-null
+ * and equal.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value
+ * @param newVal the new value
+ */
+ public void firePropertyChange(String propertyName,
+ Object oldVal, Object newVal)
+ {
+ firePropertyChange(new PropertyChangeEvent(source, propertyName,
+ oldVal, newVal));
+ }
+
+ /**
+ * Fire a PropertyChangeEvent containing the old and new values of the
+ * property to all the global listeners, and to all the listeners for the
+ * specified property name. This does nothing if old and new are equal.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value
+ * @param newVal the new value
+ */
+ public void firePropertyChange(String propertyName, int oldVal, int newVal)
+ {
+ if (oldVal != newVal)
+ firePropertyChange(new PropertyChangeEvent(source, propertyName,
+ new Integer(oldVal),
+ new Integer(newVal)));
+ }
+
+ /**
+ * Fire a PropertyChangeEvent containing the old and new values of the
+ * property to all the global listeners, and to all the listeners for the
+ * specified property name. This does nothing if old and new are equal.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value
+ * @param newVal the new value
+ */
+ public void firePropertyChange(String propertyName,
+ boolean oldVal, boolean newVal)
+ {
+ if (oldVal != newVal)
+ firePropertyChange(new PropertyChangeEvent(source, propertyName,
+ Boolean.valueOf(oldVal),
+ Boolean.valueOf(newVal)));
+ }
+
+ /**
+ * Fire a PropertyChangeEvent to all the global listeners, and to all the
+ * listeners for the specified property name. This does nothing if old and
+ * new values of the event are equal.
+ *
+ * @param event the event to fire
+ * @throws NullPointerException if event is null
+ */
+ public void firePropertyChange(PropertyChangeEvent event)
+ {
+ if (event.oldValue != null && event.oldValue.equals(event.newValue))
+ return;
+ Vector v = listeners; // Be thread-safe.
+ if (v != null)
+ {
+ int i = v.size();
+ while (--i >= 0)
+ ((PropertyChangeListener) v.get(i)).propertyChange(event);
+ }
+ Hashtable h = children; // Be thread-safe.
+ if (h != null && event.propertyName != null)
+ {
+ PropertyChangeSupport s
+ = (PropertyChangeSupport) h.get(event.propertyName);
+ if (s != null)
+ {
+ v = s.listeners; // Be thread-safe.
+ int i = v == null ? 0 : v.size();
+ while (--i >= 0)
+ ((PropertyChangeListener) v.get(i)).propertyChange(event);
+ }
+ }
+ }
+
+ /**
+ * Tell whether the specified property is being listened on or not. This
+ * will only return <code>true</code> if there are listeners on all
+ * properties or if there is a listener specifically on this property.
+ *
+ * @param propertyName the property that may be listened on
+ * @return whether the property is being listened on
+ * @throws NullPointerException if propertyName is null
+ */
+ public synchronized boolean hasListeners(String propertyName)
+ {
+ return listeners != null || (children != null
+ && children.get(propertyName) != null);
+ }
+
+ /**
+ * Saves the state of the object to the stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if anything goes wrong
+ * @serialData this writes out a null-terminated list of serializable
+ * global property change listeners (the listeners for a named
+ * property are written out as the global listeners of the
+ * children, when the children hashtable is saved)
+ */
+ private synchronized void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ s.defaultWriteObject();
+ if (listeners != null)
+ {
+ int i = listeners.size();
+ while (--i >= 0)
+ if (listeners.get(i) instanceof Serializable)
+ s.writeObject(listeners.get(i));
+ }
+ s.writeObject(null);
+ }
+
+ /**
+ * Reads the object back from stream (deserialization).
+ *
+ * XXX Since serialization for 1.1 streams was not documented, this may
+ * not work if propertyChangeSupportSerializedDataVersion is 1.
+ *
+ * @param s the stream to read from
+ * @throws IOException if reading the stream fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData this reads in a null-terminated list of serializable
+ * global property change listeners (the listeners for a named
+ * property are written out as the global listeners of the
+ * children, when the children hashtable is saved)
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ PropertyChangeListener l = (PropertyChangeListener) s.readObject();
+ while (l != null)
+ {
+ addPropertyChangeListener(l);
+ l = (PropertyChangeListener) s.readObject();
+ }
+ // Sun is not as careful with children as we are, and lets some proxys
+ // in that can never receive events. So, we clean up anything that got
+ // serialized, to make sure our invariants hold.
+ if (children != null)
+ {
+ int i = children.size();
+ Iterator iter = children.entrySet().iterator();
+ while (--i >= 0)
+ {
+ Entry e = (Entry) iter.next();
+ String name = (String) e.getKey();
+ PropertyChangeSupport pcs = (PropertyChangeSupport) e.getValue();
+ if (pcs.listeners == null)
+ pcs.listeners = new Vector();
+ if (pcs.children != null)
+ pcs.listeners.addAll
+ (Arrays.asList(pcs.getPropertyChangeListeners(name)));
+ if (pcs.listeners.size() == 0)
+ iter.remove();
+ else
+ pcs.children = null;
+ }
+ if (children.size() == 0)
+ children = null;
+ }
+ }
+} // class PropertyChangeSupport
diff --git a/libjava/classpath/java/beans/PropertyDescriptor.java b/libjava/classpath/java/beans/PropertyDescriptor.java
new file mode 100644
index 00000000000..416d468576f
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyDescriptor.java
@@ -0,0 +1,583 @@
+/* java.beans.PropertyDescriptor
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.beans;
+
+import java.lang.reflect.Method;
+
+/**
+ ** PropertyDescriptor describes information about a JavaBean property,
+ ** by which we mean a property that has been exposed via a pair of
+ ** get and set methods. (There may be no get method, which means
+ ** the property is write-only, or no set method, which means the
+ ** the property is read-only.)<P>
+ **
+ ** The constraints put on get and set methods are:<P>
+ ** <OL>
+ ** <LI>A get method must have signature
+ ** <CODE>&lt;propertyType&gt; &lt;getMethodName&gt;()</CODE></LI>
+ ** <LI>A set method must have signature
+ ** <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;)</CODE></LI>
+ ** <LI>Either method type may throw any exception.</LI>
+ ** <LI>Both methods must be public.</LI>
+ ** </OL>
+ **
+ ** @author John Keiser
+ ** @author Robert Schuster (thebohemian@gmx.net)
+ ** @since 1.1
+ ** @status updated to 1.4
+ **/
+
+public class PropertyDescriptor extends FeatureDescriptor
+{
+ Class propertyType;
+ Method getMethod;
+ Method setMethod;
+
+ Class propertyEditorClass;
+ boolean bound;
+ boolean constrained;
+
+ PropertyDescriptor(String name)
+ {
+ setName(name);
+ }
+
+ /** Create a new PropertyDescriptor by introspection.
+ ** This form of constructor creates the PropertyDescriptor by
+ ** looking for a getter method named <CODE>get&lt;name&gt;()</CODE>
+ ** (or, optionally, if the property is boolean,
+ ** <CODE>is&lt;name&gt;()</CODE>) and
+ ** <CODE>set&lt;name&gt;()</CODE> in class
+ ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
+ ** first letter capitalized by the constructor.<P>
+ **
+ ** Note that using this constructor the given property must be read- <strong>and</strong>
+ ** writeable. If the implementation does not both, a read and a write method, an
+ ** <code>IntrospectionException</code> is thrown.
+ **
+ ** <B>Implementation note:</B> If there is both are both isXXX and
+ ** getXXX methods, the former is used in preference to the latter.
+ ** We do not check that an isXXX method returns a boolean. In both
+ ** cases, this matches the behaviour of JDK 1.4<P>
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param beanClass the class the get and set methods live in.
+ ** @exception IntrospectionException if the methods are not found
+ ** or invalid.
+ **/
+ public PropertyDescriptor(String name, Class beanClass)
+ throws IntrospectionException
+ {
+ setName(name);
+ if (name.length() == 0)
+ {
+ throw new IntrospectionException("empty property name");
+ }
+ String caps = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ findMethods(beanClass, "is" + caps, "get" + caps, "set" + caps);
+
+ if (getMethod == null)
+ {
+ throw new IntrospectionException(
+ "Cannot find a is" + caps + " or get" + caps + " method");
+ }
+
+ if (setMethod == null)
+ {
+ throw new IntrospectionException(
+ "Cannot find a " + caps + " method");
+ }
+
+ // finally check the methods compatibility
+ propertyType = checkMethods(getMethod, setMethod);
+ }
+
+ /** Create a new PropertyDescriptor by introspection.
+ ** This form of constructor allows you to specify the
+ ** names of the get and set methods to search for.<P>
+ **
+ ** <B>Implementation note:</B> If there is a get method (or
+ ** boolean isXXX() method), then the return type of that method
+ ** is used to find the set method. If there is no get method,
+ ** then the set method is searched for exhaustively.<P>
+ **
+ ** <B>Spec note:</B>
+ ** If there is no get method and multiple set methods with
+ ** the same name and a single parameter (different type of course),
+ ** then an IntrospectionException is thrown. While Sun's spec
+ ** does not state this, it can make Bean behavior different on
+ ** different systems (since method order is not guaranteed) and as
+ ** such, can be treated as a bug in the spec. I am not aware of
+ ** whether Sun's implementation catches this.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param beanClass the class the get and set methods live in.
+ ** @param getMethodName the name of the get method or <code>null</code> if the property is write-only.
+ ** @param setMethodName the name of the set method or <code>null</code> if the property is read-only.
+ ** @exception IntrospectionException if the methods are not found
+ ** or invalid.
+ **/
+ public PropertyDescriptor(
+ String name,
+ Class beanClass,
+ String getMethodName,
+ String setMethodName)
+ throws IntrospectionException
+ {
+ setName(name);
+ findMethods(beanClass, getMethodName, null, setMethodName);
+
+ if (getMethod == null && getMethodName != null)
+ {
+ throw new IntrospectionException(
+ "Cannot find a getter method called " + getMethodName);
+ }
+
+ if (setMethod == null && setMethodName != null)
+ {
+ throw new IntrospectionException(
+ "Cannot find a setter method called " + setMethodName);
+ }
+
+ propertyType = checkMethods(getMethod, setMethod);
+ }
+
+ /** Create a new PropertyDescriptor using explicit Methods.
+ ** Note that the methods will be checked for conformance to standard
+ ** Property method rules, as described above at the top of this class.
+ **<br>
+ ** It is possible to call this method with both <code>Method</code> arguments
+ ** being <code>null</code>. In such a case the property type is <code>null</code>.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param readMethod the read method or <code>null</code> if the property is write-only.
+ ** @param writeMethod the write method or <code>null</code> if the property is read-only.
+ ** @exception IntrospectionException if the methods are not found
+ ** or invalid.
+ **/
+ public PropertyDescriptor(
+ String name,
+ Method readMethod,
+ Method writeMethod)
+ throws IntrospectionException
+ {
+ setName(name);
+ getMethod = readMethod;
+ setMethod = writeMethod;
+ propertyType = checkMethods(getMethod, setMethod);
+ }
+
+ /** Get the property type.
+ ** This is the type the get method returns and the set method
+ ** takes in.
+ **/
+ public Class getPropertyType()
+ {
+ return propertyType;
+ }
+
+ /** Get the get method. Why they call it readMethod here and
+ ** get everywhere else is beyond me.
+ **/
+ public Method getReadMethod()
+ {
+ return getMethod;
+ }
+
+ /** Sets the read method.<br/>
+ * The read method is used to retrieve the value of a property. A legal
+ * read method must have no arguments. Its return type must not be
+ * <code>void</code>. If this methods succeeds the property type
+ * is adjusted to the return type of the read method.<br/>
+ * <br/>
+ * It is legal to set the read and the write method to <code>null</code>
+ * or provide method which have been declared in distinct classes.
+ *
+ * @param readMethod The new method to be used or <code>null</code>.
+ * @throws IntrospectionException If the given method is invalid.
+ * @since 1.2
+ */
+ public void setReadMethod(Method readMethod) throws IntrospectionException
+ {
+ propertyType = checkMethods(readMethod, setMethod);
+
+ getMethod = readMethod;
+ }
+
+ /** Get the set method. Why they call it writeMethod here and
+ ** set everywhere else is beyond me.
+ **/
+ public Method getWriteMethod()
+ {
+ return setMethod;
+ }
+
+ /** Sets the write method.<br/>
+ * The write method is used to set the value of a property. A legal write method
+ * must have a single argument which can be assigned to the property. If no
+ * read method exists the property type changes to the argument type of the
+ * write method.<br/>
+ * <br/>
+ * It is legal to set the read and the write method to <code>null</code>
+ * or provide method which have been declared in distinct classes.
+ *
+ * @param writeMethod The new method to be used or <code>null</code>.
+ * @throws IntrospectionException If the given method is invalid.
+ * @since 1.2
+ */
+ public void setWriteMethod(Method writeMethod)
+ throws IntrospectionException
+ {
+ propertyType = checkMethods(getMethod, writeMethod);
+
+ setMethod = writeMethod;
+ }
+
+ /** Get whether the property is bound. Defaults to false. **/
+ public boolean isBound()
+ {
+ return bound;
+ }
+
+ /** Set whether the property is bound.
+ ** As long as the the bean implements addPropertyChangeListener() and
+ ** removePropertyChangeListener(), setBound(true) may safely be called.<P>
+ ** If these things are not true, then the behavior of the system
+ ** will be undefined.<P>
+ **
+ ** When a property is bound, its set method is required to fire the
+ ** <CODE>PropertyChangeListener.propertyChange())</CODE> event
+ ** after the value has changed.
+ ** @param bound whether the property is bound or not.
+ **/
+ public void setBound(boolean bound)
+ {
+ this.bound = bound;
+ }
+
+ /** Get whether the property is constrained. Defaults to false. **/
+ public boolean isConstrained()
+ {
+ return constrained;
+ }
+
+ /** Set whether the property is constrained.
+ ** If the set method throws <CODE>java.beans.PropertyVetoException</CODE>
+ ** (or subclass thereof) and the bean implements addVetoableChangeListener()
+ ** and removeVetoableChangeListener(), then setConstrained(true) may safely
+ ** be called. Otherwise, the system behavior is undefined.
+ ** <B>Spec note:</B> given those strict parameters, it would be nice if it
+ ** got set automatically by detection, but oh well.<P>
+ ** When a property is constrained, its set method is required to:<P>
+ ** <OL>
+ ** <LI>Fire the <CODE>VetoableChangeListener.vetoableChange()</CODE>
+ ** event notifying others of the change and allowing them a chance to
+ ** say it is a bad thing.</LI>
+ ** <LI>If any of the listeners throws a PropertyVetoException, then
+ ** it must fire another vetoableChange() event notifying the others
+ ** of a reversion to the old value (though, of course, the change
+ ** was never made). Then it rethrows the PropertyVetoException and
+ ** exits.</LI>
+ ** <LI>If all has gone well to this point, the value may be changed.</LI>
+ ** </OL>
+ ** @param constrained whether the property is constrained or not.
+ **/
+ public void setConstrained(boolean constrained)
+ {
+ this.constrained = constrained;
+ }
+
+ /** Get the PropertyEditor class. Defaults to null. **/
+ public Class getPropertyEditorClass()
+ {
+ return propertyEditorClass;
+ }
+
+ /** Set the PropertyEditor class. If the class does not implement
+ ** the PropertyEditor interface, you will likely get an exception
+ ** late in the game.
+ ** @param propertyEditorClass the PropertyEditor class for this
+ ** class to use.
+ **/
+ public void setPropertyEditorClass(Class propertyEditorClass)
+ {
+ this.propertyEditorClass = propertyEditorClass;
+ }
+
+ private void findMethods(
+ Class beanClass,
+ String getMethodName1,
+ String getMethodName2,
+ String setMethodName)
+ throws IntrospectionException
+ {
+ try
+ {
+ // Try the first get method name
+ if (getMethodName1 != null)
+ {
+ try
+ {
+ getMethod =
+ beanClass.getMethod(getMethodName1, new Class[0]);
+ }
+ catch (NoSuchMethodException e)
+ {}
+ }
+
+ // Fall back to the second get method name
+ if (getMethod == null && getMethodName2 != null)
+ {
+ try
+ {
+ getMethod =
+ beanClass.getMethod(getMethodName2, new Class[0]);
+ }
+ catch (NoSuchMethodException e)
+ {}
+ }
+
+ // Try the set method name
+ if (setMethodName != null)
+ {
+ if (getMethod != null)
+ {
+ // If there is a get method, use its return type to help
+ // select the corresponding set method.
+ Class propertyType = getMethod.getReturnType();
+ if (propertyType == Void.TYPE)
+ {
+ String msg =
+ "The property's read method has return type 'void'";
+ throw new IntrospectionException(msg);
+ }
+
+ Class[] setArgs = new Class[] { propertyType };
+ try
+ {
+ setMethod = beanClass.getMethod(setMethodName, setArgs);
+ }
+ catch (NoSuchMethodException e)
+ {}
+ }
+ else if (getMethodName1 == null && getMethodName2 == null)
+ {
+ // If this is a write-only property, choose the first set method
+ // with the required name, one parameter and return type 'void'
+ Method[] methods = beanClass.getMethods();
+ for (int i = 0; i < methods.length; i++)
+ {
+ if (methods[i].getName().equals(setMethodName)
+ && methods[i].getParameterTypes().length == 1
+ && methods[i].getReturnType() == Void.TYPE)
+ {
+ setMethod = methods[i];
+ break;
+ }
+ }
+ }
+ }
+ }
+ catch (SecurityException e)
+ {
+ // FIXME -- shouldn't we just allow SecurityException to propagate?
+ String msg =
+ "SecurityException thrown on attempt to access methods.";
+ throw new IntrospectionException(msg);
+ }
+ }
+
+ /** Checks whether the given <code>Method</code> instances are legal read and
+ * write methods. The following requirements must be met:<br/>
+ * <ul>
+ * <li>the read method must not have an argument</li>
+ * <li>the read method must have a non void return type</li>
+ * <li>the read method may not exist</li>
+ * <li>the write method must have a single argument</li>
+ * <li>the property type and the read method's return type must be assignable from the
+ * write method's argument type</li>
+ * <li>the write method may not exist</li>
+ * </ul>
+ * While checking the methods a common new property type is calculated. If the method
+ * succeeds this property type is returned.<br/>
+ * <br/>
+ * For compatibility this has to be noted:<br/>
+ * The two methods are allowed to be defined in two distinct classes and may both be null.
+ *
+ * @param readMethod The new read method to check.
+ * @param writeMethod The new write method to check.
+ * @return The common property type of the two method.
+ * @throws IntrospectionException If any of the above requirements are not met.
+ */
+ private Class checkMethods(Method readMethod, Method writeMethod)
+ throws IntrospectionException
+ {
+ Class newPropertyType = propertyType;
+
+ // a valid read method has zero arguments and a non-void return type.
+ if (readMethod != null)
+ {
+ if (readMethod.getParameterTypes().length > 0)
+ {
+ throw new IntrospectionException("read method has unexpected parameters");
+ }
+
+ newPropertyType = readMethod.getReturnType();
+
+ if (newPropertyType == Void.TYPE)
+ {
+ throw new IntrospectionException("read method return type is void");
+ }
+ }
+
+ // a valid write method has one argument which can be assigned to the property
+ if (writeMethod != null)
+ {
+ if (writeMethod.getParameterTypes().length != 1)
+ {
+ String msg = "write method does not have exactly one parameter";
+ throw new IntrospectionException(msg);
+ }
+
+ if (readMethod == null)
+ {
+ // changes the property type if there is no read method
+ newPropertyType = writeMethod.getParameterTypes()[0];
+ }
+ else
+ {
+ // checks whether the write method can be assigned to the return type of the read
+ // method (if this is not the case, the methods are not compatible)
+ // note: newPropertyType may be null if no methods or method names have been
+ // delivered in the constructor.
+ if (newPropertyType != null
+ && !newPropertyType.isAssignableFrom(
+ writeMethod.getParameterTypes()[0]))
+ {
+ // note: newPropertyType is the same as readMethod.getReturnType() at this point
+ throw new IntrospectionException("read and write method are not compatible");
+ }
+
+ /* note: the check whether both method are defined in related classes makes sense but is not
+ * done in the JDK.
+ * I leave this code here in case someone at Sun decides to add that functionality in later versions (rschuster)
+ if ((!readMethod
+ .getDeclaringClass()
+ .isAssignableFrom(writeMethod.getDeclaringClass()))
+ && (!writeMethod
+ .getDeclaringClass()
+ .isAssignableFrom(readMethod.getDeclaringClass())))
+ {
+ String msg =
+ "set and get methods are not in the same class.";
+ throw new IntrospectionException(msg);
+ }
+ */
+
+ }
+ }
+
+ return newPropertyType;
+ }
+
+ /** Compares this <code>PropertyDescriptor</code> against the
+ * given object.
+ * Two PropertyDescriptors are equals if
+ * <ul>
+ * <li>the read methods are equal</li>
+ * <li>the write methods are equal</li>
+ * <li>the property types are equals</li>
+ * <li>the property editor classes are equal</li>
+ * <li>the flags (constrained and bound) are equal</li>
+ * </ul>
+ * @return Whether both objects are equal according to the rules given above.
+ * @since 1.4
+ */
+ public boolean equals(Object o)
+ {
+ if (o instanceof PropertyDescriptor)
+ {
+ PropertyDescriptor that = (PropertyDescriptor) o;
+
+ // compares the property types and checks the case where both are null
+ boolean samePropertyType =
+ (propertyType == null)
+ ? that.propertyType == null
+ : propertyType.equals(that.propertyType);
+
+ // compares the property editor classes and checks the case where both are null
+ boolean samePropertyEditorClass =
+ (propertyEditorClass == null)
+ ? that.propertyEditorClass == null
+ : propertyEditorClass.equals(that.propertyEditorClass);
+
+ // compares the flags for equality
+ boolean sameFlags =
+ bound == that.bound && constrained == that.constrained;
+
+ // compares the read methods and checks the case where both are null
+ boolean sameReadMethod =
+ (getMethod == null)
+ ? that.getMethod == null
+ : getMethod.equals(that.getMethod);
+
+ boolean sameWriteMethod =
+ (setMethod == null)
+ ? that.setMethod == null
+ : setMethod.equals(that.setMethod);
+
+ return samePropertyType
+ && sameFlags
+ && sameReadMethod
+ && sameWriteMethod
+ && samePropertyEditorClass;
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+
+}
diff --git a/libjava/classpath/java/beans/PropertyEditor.java b/libjava/classpath/java/beans/PropertyEditor.java
new file mode 100644
index 00000000000..d1c5103419f
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyEditor.java
@@ -0,0 +1,209 @@
+/* java.beans.PropertyEditor
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+/**
+ ** PropertyEditors are custom GUI editors for specific types of values.
+ **
+ ** A PropertyEditor can be used, for example, if you are editing a type of value
+ ** that can be more easily represented graphically, such as a Point, or one that
+ ** can be more easily represented by a list, such as a boolean (true/false).<P>
+ **
+ ** A PropertyEditor must be able to display its contents when asked to and
+ ** be able to allow the user to change its underlying field value. However, it
+ ** is not the PropertyEditor's responsibility to make the change to the
+ ** underlying Object; in fact, the PropertyEditor does not even know about the
+ ** Object it is actually editing--only about the property it is currently
+ ** editing. When a change is made to the property, the PropertyEditor must
+ ** simply fire a PropertyChangeEvent and allow the RAD tool to actually set
+ ** the property in the underlying Bean.<P>
+ **
+ ** PropertyEditors should not change the Objects they are given by setValue().
+ ** These Objects may or may not be the actual Objects which are properties of
+ ** the Bean being edited. Instead, PropertyEditors should create a new Object
+ ** and fire a PropertyChangeEvent with the old and new values.<P>
+ **
+ ** PropertyEditors also must support the ability to return a Java
+ ** initialization string. See the getJavaInitializationString() method for
+ ** details.<P>
+ **
+ ** There are several different ways a PropertyEditor may display and control
+ ** editing of its value. When multiple types of input and display are
+ ** given by a single PropertyEditor, the RAD tool may decide which of the call
+ ** to support. Some RAD tools may even be text-only, so even if you support
+ ** a graphical set and get, it may choose the text set and get whenever it can.
+ ** <OL>
+ ** <LI>Every PropertyEditor must support getValue() and setValue(). For
+ ** setValue(), the component must only support it when the argument is
+ ** the same type that the PropertyEditor supports.</LI>
+ ** <LI>Every PropertyEditor must support getJavaInitializationString().</LI>
+ ** <LI>You may support painting the value yourself if you wish. To do this,
+ ** have isPaintable() return true and implement the paintValue() method.
+ ** This method does not determine in any way how the value is edited;
+ ** merely how it is displayed.</LI>
+ ** <LI>Let the caller of the PropertyEditor give the user a text input. Do
+ ** this by returning a non-null String from getAsText(). If you support
+ ** text input, you *must* support setAsText().</LI>
+ ** <LI>Give the caller a set of possible values, such as "true"/"false", that
+ ** the user must select from. To do this, return the list of Strings
+ ** from the getTags() method. The RAD tool may choose to implement the
+ ** user input any way it wishes, and only guarantees that setAsText() will
+ ** only be called with one of the Strings returned from getTags().</LI>
+ ** <LI>You may support a whole custom editing control by supporting
+ ** getCustomEditor(). To do this, return true from supportsCustomEditor()
+ ** and return a Component that does the job. It is the component's job,
+ ** or the PropertyEditor's job, to make sure that when the editor changes
+ ** its value, the PropertyChangeEvent is thrown.</LI>
+ ** </OL>
+ **
+ ** The PropertyEditor for a particular Bean can be found using the
+ ** PropertyEditorManager class, which goes through a series of different
+ ** checks to find the appropriate class.<P>
+ **
+ ** A PropertyChangeEvent should be thrown from the PropertyEditor whenever a
+ ** bound property (a property PropertyDescriptor.isBound() set to true)
+ ** changes. When this happens, the editor itself should *not* change the value
+ ** itself, but rather allow the RAD tool to call setValue() or setAsText().
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 30 June 1998
+ ** @see java.beans.PropertyEditorManager
+ ** @see java.beans.PropertyEditorSupport
+ **/
+
+public interface PropertyEditor {
+ /** Called by the RAD tool to set the value of this property for the PropertyEditor.
+ ** If the property type is native, it should be wrapped in the appropriate
+ ** wrapper type.
+ ** @param value the value to set this property to.
+ **/
+ void setValue(Object value);
+
+ /** Accessor method to get the current value the PropertyEditor is working with.
+ ** If the property type is native, it will be wrapped in the appropriate
+ ** wrapper type.
+ ** @return the current value of the PropertyEditor.
+ **/
+ Object getValue();
+
+
+ /** Set the value of this property using a String.
+ ** Whether or not this PropertyEditor is editing a String type, this converts
+ ** the String into the type of the PropertyEditor.
+ ** @param text the text to set it to.
+ ** @exception IllegalArgumentException if the String is in the wrong format or setAsText() is not supported.
+ **/
+ void setAsText(String text) throws IllegalArgumentException;
+
+ /** Get the value of this property in String format.
+ ** Many times this can simply use Object.toString().<P>
+ ** Return null if you do not support getAsText()/setAsText().
+ ** <code>setAsText(getAsText())</code> should be valid; i.e. the stuff you spit out in
+ ** getAsText() should be able to go into setAsText().
+ ** @return the value of this property in String format.
+ **/
+ String getAsText();
+
+ /** Get a list of possible Strings which this property type can have.
+ ** The value of these will be used by the RAD tool to construct some sort
+ ** of list box or to check text box input, and the resulting String passed
+ ** to setAsText() should be one of these. Note, however, that like most things
+ ** with this mammoth, unwieldy interface, this is not guaranteed. Thus, you
+ ** must check the value in setAsText() anyway.
+ ** @return the list of possible String values for this property type.
+ **/
+ String[] getTags();
+
+
+ /** The RAD tool calls this to find out whether the PropertyEditor can paint itself.
+ ** @return true if it can paint itself graphically, false if it cannot.
+ **/
+ boolean isPaintable();
+
+ /** The RAD tool calls this to paint the actual value of the property.
+ ** The Graphics context will have the same current font, color, etc. as the
+ ** parent Container. You may safely change the font, color, etc. and not
+ ** change them back.<P>
+ ** This method should do a silent no-op if isPaintable() is false.
+ ** @param g the Graphics context to paint on
+ ** @param bounds the rectangle you have reserved to work in
+ **/
+ void paintValue(java.awt.Graphics g, java.awt.Rectangle bounds);
+
+
+ /** The RAD tool calls this to find out whether the PropertyEditor supports a custom component to edit and display itself.
+ ** @return true if getCustomEditor() will return a component, false if not.
+ **/
+ boolean supportsCustomEditor();
+
+ /** The RAD tool calls this to grab the component that can edit this type.
+ ** The component may be painted anywhere the RAD tool wants to paint it--
+ ** even in its own window.<P>
+ ** The component must hook up with the PropertyEditor and, whenever a
+ ** change to the value is made, fire a PropertyChangeEvent to the source.<P>
+ ** @return the custom editor for this property type.
+ **/
+ java.awt.Component getCustomEditor();
+
+
+ /** Adds a property change listener to this PropertyEditor.
+ ** @param listener the listener to add
+ **/
+ void addPropertyChangeListener(PropertyChangeListener listener);
+
+ /** Removes a property change listener from this PropertyEditor.
+ ** @param listener the listener to remove
+ **/
+ void removePropertyChangeListener(PropertyChangeListener listener);
+
+ /** Get a Java language-specific String which could be used to create an Object
+ ** of the specified type. Every PropertyEditor must support this.<P>
+ ** The reason for this is that while most RAD tools will serialize the Beans
+ ** and deserialize them at runtime, some RAD tools will generate code that
+ ** creates the Beans. Examples of Java initialization strings would be:<P>
+ ** <OL>
+ ** <LI><CODE>2</CODE></LI>
+ ** <LI><CODE>"I am a String"</CODE></LI>
+ ** <LI><CODE>new MyObject(2, "String", new StringBuffer())</CODE></LI>
+ ** </OL>
+ ** @return the initialization string for this object in Java.
+ **/
+ String getJavaInitializationString();
+}
diff --git a/libjava/classpath/java/beans/PropertyEditorManager.java b/libjava/classpath/java/beans/PropertyEditorManager.java
new file mode 100644
index 00000000000..da2a5678c5c
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyEditorManager.java
@@ -0,0 +1,215 @@
+/* java.beans.PropertyEditorManager
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import gnu.java.beans.editors.ColorEditor;
+import gnu.java.beans.editors.FontEditor;
+import gnu.java.beans.editors.NativeBooleanEditor;
+import gnu.java.beans.editors.NativeByteEditor;
+import gnu.java.beans.editors.NativeDoubleEditor;
+import gnu.java.beans.editors.NativeFloatEditor;
+import gnu.java.beans.editors.NativeIntEditor;
+import gnu.java.beans.editors.NativeLongEditor;
+import gnu.java.beans.editors.NativeShortEditor;
+import gnu.java.beans.editors.StringEditor;
+import gnu.java.lang.ClassHelper;
+
+import java.awt.Color;
+import java.awt.Font;
+
+/**
+ * PropertyEditorManager is used to find property editors
+ * for various types (not necessarily Beans).<P>
+ *
+ * It first checks to see if the property editor is
+ * already registered; if it is, that property editor is
+ * used. Next it takes the type's classname and appends
+ * "Editor" to it, and searches first in the class's
+ * package and then in the property editor search path.
+ *
+ * <p>Default property editors are provided for:</p>
+ *
+ * <ol>
+ * <li>boolean, byte, short, int, long, float, and double</li>
+ * <li>java.lang.String</li>
+ * <li>java.awt.Color</li>
+ * <li>java.awt.Font</li>
+ * </ol>
+ *
+ * <p><strong>Spec Suggestion:</strong> Perhaps an editor for
+ * Filename or something like it should be provided. As well
+ * as char.</p>
+ *
+ * @author John Keiser
+ * @since 1.1
+ * @version 1.1.0, 29 Jul 1998
+ */
+
+public class PropertyEditorManager
+{
+ static java.util.Hashtable editors = new java.util.Hashtable();
+ static String[] editorSearchPath = { "gnu.java.beans.editors",
+ "sun.beans.editors" };
+
+ static
+ {
+ registerEditor(Boolean.TYPE, NativeBooleanEditor.class);
+ registerEditor(Byte.TYPE, NativeByteEditor.class);
+ registerEditor(Short.TYPE, NativeShortEditor.class);
+ registerEditor(Integer.TYPE, NativeIntEditor.class);
+ registerEditor(Long.TYPE, NativeLongEditor.class);
+ registerEditor(Float.TYPE, NativeFloatEditor.class);
+ registerEditor(Double.TYPE, NativeDoubleEditor.class);
+ registerEditor(String.class, StringEditor.class);
+ registerEditor(Color.class, ColorEditor.class);
+ registerEditor(Font.class, FontEditor.class);
+ }
+
+ /**
+ * Beats me why this class can be instantiated, but there
+ * you have it.
+ */
+ public PropertyEditorManager()
+ {
+ // Do nothing here
+ }
+
+ /**
+ * Register an editor for a class. Replaces old editor
+ * if there was one registered before.
+ *
+ * @param editedClass the class that the property editor
+ * will edit.
+ * @param editorClass the PropertyEditor class.
+ */
+ public static void registerEditor(Class editedClass, Class editorClass)
+ {
+ editors.put(editedClass, editorClass);
+ }
+
+ /**
+ * Returns a new instance of the property editor for the
+ * specified class.
+ *
+ * @param editedClass the class that the property editor
+ * will edit.
+ * @return a PropertyEditor instance that can edit the
+ * specified class.
+ */
+ public static PropertyEditor findEditor(Class editedClass)
+ {
+ try
+ {
+ Class found = (Class)editors.get(editedClass);
+ if(found != null)
+ {
+ return (PropertyEditor)found.newInstance();
+ }
+
+ ClassLoader contextClassLoader
+ = Thread.currentThread().getContextClassLoader();
+
+ try
+ {
+ found = Class.forName(editedClass.getName()+"Editor", true,
+ contextClassLoader);
+ registerEditor(editedClass,found);
+ return (PropertyEditor)found.newInstance();
+ }
+ catch(ClassNotFoundException E)
+ {
+ }
+
+ String appendName
+ = "."
+ + ClassHelper.getTruncatedClassName(editedClass)
+ + "Editor";
+ synchronized(editorSearchPath)
+ {
+ for(int i=0;i<editorSearchPath.length;i++)
+ {
+ try
+ {
+ found = Class.forName(editorSearchPath[i] + appendName,
+ true, contextClassLoader);
+ registerEditor(editedClass,found);
+ return (PropertyEditor)found.newInstance();
+ }
+ catch(ClassNotFoundException E)
+ {
+ }
+ }
+ }
+ }
+ catch(InstantiationException E)
+ {
+ }
+ catch(IllegalAccessException E)
+ {
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the editor search path.
+ * As a minor departure from the spec, the default value
+ * for the editor search path is "gnu.java.beans.editors",
+ * "sun.beans.editors".
+ *
+ * @return the editor search path.
+ */
+ public static String[] getEditorSearchPath()
+ {
+ return editorSearchPath;
+ }
+
+ /**
+ * Set the editor search path.
+ *
+ * @param editorSearchPath the new value for the editor search path.
+ */
+ public static void setEditorSearchPath(String[] editorSearchPath)
+ {
+ synchronized(editorSearchPath)
+ {
+ PropertyEditorManager.editorSearchPath = editorSearchPath;
+ }
+ }
+}
diff --git a/libjava/classpath/java/beans/PropertyEditorSupport.java b/libjava/classpath/java/beans/PropertyEditorSupport.java
new file mode 100644
index 00000000000..bb68e0e3145
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyEditorSupport.java
@@ -0,0 +1,265 @@
+/* java.beans.PropertyEditorSupport
+ Copyright (C) 1998, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+
+/**
+ * PropertyEditorSupport helps with PropertyEditors,
+ * implementing base functionality that they usually must
+ * have but which is a pain to implement. You may extend
+ * from this class or use it as a standalone.<P>
+ *
+ * This class does not do any painting or actual editing.
+ * For that, you must use or extend it. See the
+ * PropertyEditor class for better descriptions of what
+ * the various methods do.
+ *
+ * @author John Keiser
+ * @author Robert Schuster
+ * @since 1.1
+ * @status updated to 1.5
+ */
+public class PropertyEditorSupport implements PropertyEditor
+{
+ Object eventSource;
+ Object value;
+ PropertyChangeSupport pSupport;
+
+ /** Call this constructor when you are deriving from
+ * PropertyEditorSupport.
+ *
+ * Using this constructor the event source is this PropertyEditorSupport
+ * instance itself.
+ *
+ * @since 1.5
+ * @specnote this was <code>protected</code> prior to 1.5
+ */
+ public PropertyEditorSupport()
+ {
+ eventSource = this;
+ pSupport = new PropertyChangeSupport(this);
+ }
+
+ /** Call this constructor when you are using
+ * PropertyEditorSupport as a helper object.
+ *
+ * This constructor throws a NullPointerException when <code>source</code> is <code>null</code>,
+ * for compatibility reasons with J2SDK 1.5.0 .
+ *
+ * @param source The source to use when firing
+ * property change events.
+ * @since 1.5
+ * @specnote this was <code>protected</code> prior to 1.5
+ */
+ public PropertyEditorSupport(Object source)
+ {
+ // note: constructor rejects source being null for the sake of compatibility
+ // with official 1.5.0 implementation
+ if (source == null)
+ throw new NullPointerException("Event source must not be null.");
+
+ eventSource = source;
+ pSupport = new PropertyChangeSupport(eventSource);
+ }
+
+ /** Sets the current value of the property and a property change
+ * event is fired to all registered PropertyChangeListener instances.
+ *
+ * @param newValue The new value for the property.
+ */
+ public void setValue(Object newValue)
+ {
+ value = newValue;
+
+ // specification in java.beans.PropertyChangeEvent says
+ // that without a property name (first argument) the
+ // new and the old value should always be null
+ pSupport.firePropertyChange(null, null, null);
+ }
+
+ /** Gets the current value of the property.
+ *
+ * @return the current value of the property.
+ */
+ public Object getValue()
+ {
+ return value;
+ }
+
+ /** Gets whether this object is paintable or not.
+ *
+ * @return <CODE>false</CODE>
+ */
+ public boolean isPaintable()
+ {
+ return false;
+ }
+
+ /** Paints this object. This class does nothing in
+ * this method.
+ */
+ public void paintValue(java.awt.Graphics g, java.awt.Rectangle r)
+ {
+ }
+
+ /** Gets the Java initialization String for the current
+ * value of the Object. This class returns gibberish or
+ * null (though the spec does not say which).<P>
+ * <STRONG>Implementation Note:</STRONG> This class
+ * returns the string "@$#^" to make sure the code will
+ * be broken, so that you will know to override it when
+ * you create your own property editor.
+ *
+ * @return the Java initialization string.
+ */
+ public String getJavaInitializationString()
+ {
+ return "@$#^";
+ }
+
+ /** Gets the value as text.
+ * In this class, you cannot count on getAsText() doing
+ * anything useful, although in this implementation I
+ * do toString().
+ *
+ * @return the value as text.
+ */
+ public String getAsText()
+ {
+ return value != null ? value.toString() : "null";
+ }
+
+ /** Sets the value as text.
+ * In this class, you cannot count on setAsText() doing
+ * anything useful across implementations.
+ * <STRONG>Implementation Note:</STRONG> In this
+ * implementation it checks if the String is "null", and
+ * if it is, sets the value to null, otherwise it throws
+ * an IllegalArgumentException.
+ *
+ * @param s the text to convert to a new value.
+ * @exception IllegalArgumentException if the text is
+ * malformed.
+ */
+ public void setAsText(String s) throws IllegalArgumentException
+ {
+ if (s.equals("null"))
+ setValue(null);
+ else
+ throw new IllegalArgumentException();
+ }
+
+ /** Returns a list of possible choices for the value.
+ *
+ * @return <CODE>null</CODE>
+ */
+ public String[] getTags()
+ {
+ return null;
+ }
+
+ /** Returns a custom component to edit the value.
+ *
+ * @return <CODE>null</CODE> in this class.
+ */
+ public java.awt.Component getCustomEditor()
+ {
+ return null;
+ }
+
+ /** Finds out whether this property editor supports a
+ * custom component to edit its value.
+ *
+ * @return <CODE>false</CODE> in this class.
+ */
+ public boolean supportsCustomEditor()
+ {
+ return false;
+ }
+
+ /** Adds a property change listener to this property editor.
+ *
+ * @param l the listener to add.
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ pSupport.addPropertyChangeListener(l);
+ }
+
+ /** Removes a property change listener from this property editor.
+ *
+ * @param l the listener to remove.
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ pSupport.removePropertyChangeListener(l);
+ }
+
+ /** Notifies people that we've changed, although we don't
+ * tell them just how.
+ */
+ public void firePropertyChange()
+ {
+ pSupport.firePropertyChange(null, null, null);
+ }
+
+ /** Returns the bean that is used as the source of events.
+ *
+ * @return The event source object
+ * @since 1.5
+ */
+ public Object getSource()
+ {
+ return eventSource;
+ }
+
+ /** Sets the bean that is used as the source of events
+ * when property changes occur.
+ *
+ * The event source bean is for informational purposes only
+ * and should not be changed by the <code>PropertyEditor</code>.
+ *
+ * @param source
+ * @since 1.5
+ */
+ public void setSource(Object source)
+ {
+ eventSource = source;
+ }
+}
diff --git a/libjava/classpath/java/beans/PropertyVetoException.java b/libjava/classpath/java/beans/PropertyVetoException.java
new file mode 100644
index 00000000000..1f0399b4bfb
--- /dev/null
+++ b/libjava/classpath/java/beans/PropertyVetoException.java
@@ -0,0 +1,85 @@
+/* PropertyVetoException.java -- thrown to veto a proposed property change
+ Copyright (C) 1998, 2000, 2002 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.beans;
+
+/**
+ * PropertyVetoException is thrown when a VetoableChangeListener doesn't
+ * like the proposed change.
+ *
+ * @author John Keiser
+ * @see VetoableChangeListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class PropertyVetoException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 129596057694162164L;
+
+ /**
+ * The vetoed change.
+ *
+ * @serial the event that was vetoed
+ */
+ private final PropertyChangeEvent evt;
+
+ /**
+ * Instantiate this exception with the given message and property change.
+ *
+ * @param msg the reason for the veto
+ * @param changeEvent the PropertyChangeEvent that was thrown
+ */
+ public PropertyVetoException(String msg, PropertyChangeEvent changeEvent)
+ {
+ super(msg);
+ evt = changeEvent;
+ }
+
+ /**
+ * Get the PropertyChange event that was vetoed.
+ *
+ * @return the vetoed change
+ */
+ public PropertyChangeEvent getPropertyChangeEvent()
+ {
+ return evt;
+ }
+}
diff --git a/libjava/classpath/java/beans/SimpleBeanInfo.java b/libjava/classpath/java/beans/SimpleBeanInfo.java
new file mode 100644
index 00000000000..cfb96048498
--- /dev/null
+++ b/libjava/classpath/java/beans/SimpleBeanInfo.java
@@ -0,0 +1,139 @@
+/* java.beans.SimpleBeanInfo
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+
+/**
+ ** SimpleBeanInfo is a class you may extend to more easily
+ ** provide select information to the Introspector. It
+ ** implements all of the methods in BeanInfo by returning
+ ** null and forces the Introspector to behave exactly as
+ ** if there were no BeanInfo class at all (Introspecting
+ ** everything).<P>
+ **
+ ** Overriding one or two of these functions
+ ** to give explicit information on only those things you
+ ** wish to give explicit information is perfectly safe,
+ ** and even desirable.<P>
+ **
+ ** See the BeanInfo class for information on what the
+ ** various methods actually do.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ ** @see java.beans.BeanInfo
+ **/
+
+public class SimpleBeanInfo implements BeanInfo {
+ /** Force Introspection of the general bean info.
+ ** @return <CODE>null</CODE>.
+ **/
+ public BeanDescriptor getBeanDescriptor() {
+ return null;
+ }
+
+ /** Force Introspection of the events this Bean type
+ ** fires.
+ ** @return <CODE>null</CODE>
+ **/
+ public EventSetDescriptor[] getEventSetDescriptors() {
+ return null;
+ }
+
+ /** Say that there is no "default" event set.
+ ** @return <CODE>-1</CODE>.
+ **/
+ public int getDefaultEventIndex() {
+ return -1;
+ }
+
+ /** Force Introspection of the Bean properties.
+ ** @return <CODE>null</CODE>.
+ **/
+ public PropertyDescriptor[] getPropertyDescriptors() {
+ return null;
+ }
+
+ /** Say that there is no "default" property.
+ ** @return <CODE>-1</CODE>.
+ **/
+ public int getDefaultPropertyIndex() {
+ return -1;
+ }
+
+ /** Force Introspection of the Bean's methods.
+ ** @return <CODE>null</CODE>.
+ **/
+ public MethodDescriptor[] getMethodDescriptors() {
+ return null;
+ }
+
+ /** Tell the Introspector to go look for other BeanInfo
+ ** itself.
+ ** @return <CODE>null</CODE>.
+ **/
+ public BeanInfo[] getAdditionalBeanInfo() {
+ return null;
+ }
+
+ /** Say that this Bean has no icons.
+ ** @param iconType the type of icon
+ ** @return <CODE>null</CODE>.
+ **/
+ public Image getIcon(int iconType) {
+ return null;
+ }
+
+ /** Helper method to load an image using the Bean class
+ ** getResource() method on the BeanInfo class (using
+ ** getClass(), since you'll extend this class to get
+ ** the BeanInfo). Basically it's assumed that the Bean
+ ** and its BeanInfo are both loaded by the same
+ ** ClassLoader, generally a reasonable assumption.
+ ** @param location the URL relative
+ ** @return the Image in question.
+ **/
+ public Image loadImage(String location) {
+ return Toolkit.getDefaultToolkit().getImage(getClass().getResource(location));
+ }
+}
+
diff --git a/libjava/classpath/java/beans/Statement.java b/libjava/classpath/java/beans/Statement.java
new file mode 100644
index 00000000000..01f86dd286f
--- /dev/null
+++ b/libjava/classpath/java/beans/Statement.java
@@ -0,0 +1,326 @@
+/* java.beans.Statement
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * class Statement
+ *
+ * A Statement captures the execution of an object method. It stores
+ * the object, the method to call, and the arguments to the method and
+ * provides the ability to execute the method on the object, using the
+ * provided arguments.
+ *
+ * @since 1.4
+ */
+public class Statement
+{
+ private Object target;
+ private String methodName;
+ private Object[] arguments;
+
+ // One or the other of these will get a value after execute is
+ // called once, but not both.
+ private transient Method method;
+ private transient Constructor ctor;
+
+ /**
+ * Constructs a statement representing the invocation of
+ * object.methodName(arg[0], arg[1], ...);
+ *
+ * @param target The object to invoke the method on.
+ * @param methodName The object method to invoke.
+ * @param arguments An array of arguments to pass to the method.
+ */
+ public Statement(Object target, String methodName, Object[] arguments)
+ {
+ this.target = target;
+ this.methodName = methodName;
+ this.arguments = arguments;
+ }
+
+ /**
+ * Execute the statement.
+ *
+ * Finds the specified method in the target object and calls it with
+ * the arguments given in the constructor.
+ *
+ * The most specific method according to the JLS(15.11) is used when
+ * there are multiple methods with the same name.
+ *
+ * Execute performs some special handling for methods and
+ * parameters:
+ *
+ * Static methods can be executed by providing the class as a
+ * target.
+ *
+ * The method name new is reserved to call the constructor
+ * new() will construct an object and return it. Not useful unless
+ * an expression :-)
+ *
+ * If the target is an array, get and set as defined in
+ * java.util.List are recognized as valid methods and mapped to the
+ * methods of the same name in java.lang.reflect.Array.
+ *
+ * The native datatype wrappers Boolean, Byte, Character, Double,
+ * Float, Integer, Long, and Short will map to methods that have
+ * native datatypes as parameters, in the same way as Method.invoke.
+ * However, these wrappers also select methods that actually take
+ * the wrapper type as an argument.
+ *
+ * The Sun spec doesn't deal with overloading between int and
+ * Integer carefully. If there are two methods, one that takes an
+ * Integer and the other taking an int, the method chosen is not
+ * specified, and can depend on the order in which the methods are
+ * declared in the source file.
+ *
+ * @throws Exception if an exception occurs while locating or
+ * invoking the method.
+ */
+ public void execute() throws Exception
+ {
+ doExecute();
+ }
+
+ private static Class wrappers[] =
+ {
+ Boolean.class, Byte.class, Character.class, Double.class, Float.class,
+ Integer.class, Long.class, Short.class
+ };
+
+ private static Class natives[] =
+ {
+ Boolean.TYPE, Byte.TYPE, Character.TYPE, Double.TYPE, Float.TYPE,
+ Integer.TYPE, Long.TYPE, Short.TYPE
+ };
+
+ // Given a wrapper class, return the native class for it. For
+ // example, if c is Integer, Integer.TYPE is returned.
+ private Class unwrap(Class c)
+ {
+ for (int i = 0; i < wrappers.length; i++)
+ if (c == wrappers[i])
+ return natives[i];
+ return null;
+ }
+
+ // Return true if all args can be assigned to params, false
+ // otherwise. Arrays are guaranteed to be the same length.
+ private boolean compatible(Class[] params, Class[] args)
+ {
+ for (int i = 0; i < params.length; i++)
+ {
+ // Treat Integer like int if appropriate
+ Class nativeType = unwrap(args[i]);
+ if (nativeType != null && params[i].isPrimitive()
+ && params[i].isAssignableFrom(nativeType))
+ continue;
+ if (params[i].isAssignableFrom(args[i]))
+ continue;
+
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return true if the method arguments in first are more specific
+ * than the method arguments in second, i.e. all args in first can
+ * be assigned to those in second.
+ *
+ * A method is more specific if all parameters can also be fed to
+ * the less specific method, because, e.g. the less specific method
+ * accepts a base class of the equivalent argument for the more
+ * specific one.
+ *
+ * @param first a <code>Class[]</code> value
+ * @param second a <code>Class[]</code> value
+ * @return a <code>boolean</code> value
+ */
+ private boolean moreSpecific(Class[] first, Class[] second)
+ {
+ for (int j=0; j < first.length; j++)
+ {
+ if (second[j].isAssignableFrom(first[j]))
+ continue;
+ return false;
+ }
+ return true;
+ }
+
+ final Object doExecute() throws Exception
+ {
+ Class klazz = (target instanceof Class)
+ ? (Class) target : target.getClass();
+ Object args[] = (arguments == null) ? new Object[0] : arguments;
+ Class argTypes[] = new Class[args.length];
+ for (int i = 0; i < args.length; i++)
+ argTypes[i] = args[i].getClass();
+
+ if (target.getClass().isArray())
+ {
+ // FIXME: invoke may have to be used. For now, cast to Number
+ // and hope for the best. If caller didn't behave, we go boom
+ // and throw the exception.
+ if (methodName.equals("get") && argTypes.length == 1)
+ return Array.get(target, ((Number)args[0]).intValue());
+ if (methodName.equals("set") && argTypes.length == 2)
+ {
+ Object obj = Array.get(target, ((Number)args[0]).intValue());
+ Array.set(target, ((Number)args[0]).intValue(), args[1]);
+ return obj;
+ }
+ throw new NoSuchMethodException("No matching method for statement " + toString());
+ }
+
+ // If we already cached the method, just use it.
+ if (method != null)
+ return method.invoke(target, args);
+ else if (ctor != null)
+ return ctor.newInstance(args);
+
+ // Find a matching method to call. JDK seems to go through all
+ // this to find the method to call.
+
+ // if method name or length don't match, skip
+ // Need to go through each arg
+ // If arg is wrapper - check if method arg is matchable builtin
+ // or same type or super
+ // - check that method arg is same or super
+
+ if (methodName.equals("new") && target instanceof Class)
+ {
+ Constructor ctors[] = klazz.getConstructors();
+ for (int i = 0; i < ctors.length; i++)
+ {
+ // Skip methods with wrong number of args.
+ Class ptypes[] = ctors[i].getParameterTypes();
+ System.out.println("ptypeslen = " + ptypes.length);
+ System.out.println("ptypes = " + ptypes);
+ System.out.println("ctor = " + ctors[i].getName());
+ for (int j=0; j < ptypes.length; j++) {
+ System.out.println("param = " + ptypes[i].getName());
+
+ }
+
+
+ if (ptypes.length != args.length)
+ continue;
+
+ // Check if method matches
+ if (!compatible(ptypes, argTypes))
+ continue;
+
+ // Use method[i] if it is more specific.
+ // FIXME: should this check both directions and throw if
+ // neither is more specific?
+ if (ctor == null)
+ {
+ ctor = ctors[i];
+ continue;
+ }
+ Class mptypes[] = ctor.getParameterTypes();
+ if (moreSpecific(ptypes, mptypes))
+ ctor = ctors[i];
+ }
+ if (ctor == null)
+ throw new InstantiationException("No matching constructor for statement " + toString());
+ return ctor.newInstance(args);
+ }
+
+ Method methods[] = klazz.getMethods();
+
+ for (int i = 0; i < methods.length; i++)
+ {
+ // Skip methods with wrong name or number of args.
+ if (!methods[i].getName().equals(methodName))
+ continue;
+ Class ptypes[] = methods[i].getParameterTypes();
+ if (ptypes.length != args.length)
+ continue;
+
+ // Check if method matches
+ if (!compatible(ptypes, argTypes))
+ continue;
+
+ // Use method[i] if it is more specific.
+ // FIXME: should this check both directions and throw if
+ // neither is more specific?
+ if (method == null)
+ {
+ method = methods[i];
+ continue;
+ }
+ Class mptypes[] = method.getParameterTypes();
+ if (moreSpecific(ptypes, mptypes))
+ method = methods[i];
+ }
+ if (method == null)
+ throw new NoSuchMethodException("No matching method for statement " + toString());
+ return method.invoke(target, args);
+ }
+
+
+
+ /** Return the statement arguments. */
+ public Object[] getArguments() { return arguments; }
+
+ /** Return the statement method name. */
+ public String getMethodName() { return methodName; }
+
+ /** Return the statement object. */
+ public Object getTarget() { return target; }
+
+ /** Return a string representation. */
+ public String toString()
+ {
+ String result = target.getClass().getName() + "." + methodName + "(";
+ String sep = "";
+ for (int i = 0; i < arguments.length; i++)
+ {
+ result = result + sep + arguments[i].getClass().getName();
+ sep = ", ";
+ }
+ result = result + ")";
+ return result;
+ }
+}
diff --git a/libjava/classpath/java/beans/TODO b/libjava/classpath/java/beans/TODO
new file mode 100644
index 00000000000..08e1d25ee5f
--- /dev/null
+++ b/libjava/classpath/java/beans/TODO
@@ -0,0 +1,4 @@
+- add AppletStub and AppletContext to java.beans.Beans.instantiate().
+- make Introspector more efficient.
+- basic Introspection tests are in, but more tests are probably in order.
+- 1.2 support (waiting on java.lang.Package, mainly)
diff --git a/libjava/classpath/java/beans/VetoableChangeListener.java b/libjava/classpath/java/beans/VetoableChangeListener.java
new file mode 100644
index 00000000000..5107954b033
--- /dev/null
+++ b/libjava/classpath/java/beans/VetoableChangeListener.java
@@ -0,0 +1,73 @@
+/* VetoableChangeListener.java -- listen for a change which can be vetoed
+ Copyright (C) 1998, 2000, 2002 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.beans;
+
+import java.util.EventListener;
+
+/**
+ * VetoableChangeListener allows a class to monitor proposed changes to
+ * properties of a Bean and, if desired, prevent them from occurring. A
+ * vetoableChange() event will be fired <em>after</em> the property change has
+ * been requested, but before it is permanent. If any listener rejects the
+ * change by throwing the PropertyChangeException, a new vetoableChange()
+ * event will be fired to all listeners who received a vetoableChange() event
+ * in the first place, informing them to revert back to the old value. Thus,
+ * the listener that threw the exception the first time should be prepared
+ * to rethrow it the second time. The value, of course, never actually changed.
+ *
+ * <p><strong>Note:</strong> This class may not be reliably used to determine
+ * whether a property has actually changed. Use the PropertyChangeListener
+ * interface for that instead.
+ *
+ * @author John Keiser
+ * @see java.beans.PropertyChangeListener
+ * @see java.beans.VetoableChangeSupport
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface VetoableChangeListener extends EventListener
+{
+ /**
+ * Fired before a Bean's property changes.
+ *
+ * @param e the change (containing the old and new values)
+ * @throws PropertyVetoException if the change is vetoed by the listener
+ */
+ void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException;
+} // interface VetoableChangeListener
diff --git a/libjava/classpath/java/beans/VetoableChangeListenerProxy.java b/libjava/classpath/java/beans/VetoableChangeListenerProxy.java
new file mode 100644
index 00000000000..56ca5a38c7f
--- /dev/null
+++ b/libjava/classpath/java/beans/VetoableChangeListenerProxy.java
@@ -0,0 +1,102 @@
+/* VetoableChangeListenerProxy.java -- adds a name to a vetoable listener
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.util.EventListenerProxy;
+
+/**
+ * This class provides an extension to <code>VetoableChangeListener</code> -
+ * associating a name with the listener. This can be used to filter the
+ * changes that one is interested in.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status udpated to 1.4
+ */
+public class VetoableChangeListenerProxy extends EventListenerProxy
+ implements VetoableChangeListener
+{
+ /**
+ * The name of the property to listen for. Package visible for use by
+ * VetoableChangeSupport.
+ */
+ final String propertyName;
+
+ /**
+ * Create a new proxy which filters property change events and only passes
+ * changes to the named property on to the delegate.
+ *
+ * @param propertyName the property's name to filter on
+ * @param listener the delegate listener
+ */
+ public VetoableChangeListenerProxy(String propertyName,
+ VetoableChangeListener listener)
+ {
+ super(listener);
+ this.propertyName = propertyName;
+ }
+
+ /**
+ * Forwards the event on to the delegate if the property name matches.
+ *
+ * @param event the event to pass on, if it meets the filter
+ * @throws NullPointerException if the delegate this was created with is null
+ * @throws PropertyVetoException if the change is vetoed by the listener
+ */
+ public void vetoableChange(PropertyChangeEvent event)
+ throws PropertyVetoException
+ {
+ // Note: Sun does not filter, under the assumption that since
+ // VetoableChangeSupport unwraps proxys, this method should never be
+ // called by normal use of listeners.
+ String name = event == null ? null : event.getPropertyName();
+ if (name == null ? propertyName == null : name.equals(propertyName))
+ ((VetoableChangeListener) getListener()).vetoableChange(event);
+ }
+
+ /**
+ * Gets the name of the property this proxy is filtering on.
+ *
+ * @return the property name
+ */
+ public String getPropertyName()
+ {
+ return propertyName;
+ }
+} // class VetoableChangeListenerProxy
diff --git a/libjava/classpath/java/beans/VetoableChangeSupport.java b/libjava/classpath/java/beans/VetoableChangeSupport.java
new file mode 100644
index 00000000000..dce8dffd341
--- /dev/null
+++ b/libjava/classpath/java/beans/VetoableChangeSupport.java
@@ -0,0 +1,530 @@
+/* VetoableChangeSupport.java -- support to manage vetoable change listeners
+ Copyright (C) 1998, 1999, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Vector;
+
+/**
+ * VetoableChangeSupport makes it easy to fire vetoable change events and
+ * handle listeners. It allows chaining of listeners, as well as filtering
+ * by property name. In addition, it will serialize only those listeners
+ * which are serializable, ignoring the others without problem. This class
+ * is thread-safe.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class VetoableChangeSupport implements Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5090210921595982017L;
+
+ /**
+ * Maps property names (String) to named listeners (VetoableChangeSupport).
+ * If this is a child instance, this field will be null.
+ *
+ * @serial the map of property names to named listener managers
+ * @since 1.2
+ */
+ private Hashtable children;
+
+ /**
+ * The non-null source object for any generated events.
+ *
+ * @serial the event source
+ */
+ private final Object source;
+
+ /**
+ * A field to compare serialization versions - this class uses version 2.
+ *
+ * @serial the serialization format
+ */
+ private static final int vetoableChangeSupportSerializedDataVersion = 2;
+
+ /**
+ * The list of all registered vetoable listeners. If this instance was
+ * created by user code, this only holds the global listeners (ie. not tied
+ * to a name), and may be null. If it was created by this class, as a
+ * helper for named properties, then this vector will be non-null, and this
+ * instance appears as a value in the <code>children</code> hashtable of
+ * another instance, so that the listeners are tied to the key of that
+ * hashtable entry.
+ */
+ private transient Vector listeners;
+
+ /**
+ * Create a VetoableChangeSupport to work with a specific source bean.
+ *
+ * @param source the source bean to use
+ * @throws NullPointerException if source is null
+ */
+ public VetoableChangeSupport(Object source)
+ {
+ this.source = source;
+ if (source == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Adds a VetoableChangeListener to the list of global listeners. All
+ * vetoable change events will be sent to this listener. The listener add
+ * is not unique: that is, <em>n</em> adds with the same listener will
+ * result in <em>n</em> events being sent to that listener for every
+ * vetoable change. Adding a null listener may cause a NullPointerException
+ * down the road. This method will unwrap a VetoableChangeListenerProxy,
+ * registering the underlying delegate to the named property list.
+ *
+ * @param l the listener to add
+ */
+ public synchronized void addVetoableChangeListener(VetoableChangeListener l)
+ {
+ if (l instanceof VetoableChangeListenerProxy)
+ {
+ VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
+ addVetoableChangeListener(p.propertyName,
+ (VetoableChangeListener) p.getListener());
+ }
+ else
+ {
+ if (listeners == null)
+ listeners = new Vector();
+ listeners.add(l);
+ }
+ }
+
+ /**
+ * Removes a VetoableChangeListener from the list of global listeners. If
+ * any specific properties are being listened on, they must be deregistered
+ * by themselves; this will only remove the general listener to all
+ * properties. If <code>add()</code> has been called multiple times for a
+ * particular listener, <code>remove()</code> will have to be called the
+ * same number of times to deregister it. This method will unwrap a
+ * VetoableChangeListenerProxy, removing the underlying delegate from the
+ * named property list.
+ *
+ * @param l the listener to remove
+ */
+ public synchronized void
+ removeVetoableChangeListener(VetoableChangeListener l)
+ {
+ if (l instanceof VetoableChangeListenerProxy)
+ {
+ VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
+ removeVetoableChangeListener(p.propertyName,
+ (VetoableChangeListener) p.getListener());
+ }
+ else if (listeners != null)
+ {
+ listeners.remove(l);
+ if (listeners.isEmpty())
+ listeners = null;
+ }
+ }
+
+ /**
+ * Returns an array of all registered vetoable change listeners. Those that
+ * were registered under a name will be wrapped in a
+ * <code>VetoableChangeListenerProxy</code>, so you must check whether the
+ * listener is an instance of the proxy class in order to see what name the
+ * real listener is registered under. If there are no registered listeners,
+ * this returns an empty array.
+ *
+ * @return the array of registered listeners
+ * @see VetoableChangeListenerProxy
+ * @since 1.4
+ */
+ public synchronized VetoableChangeListener[] getVetoableChangeListeners()
+ {
+ ArrayList list = new ArrayList();
+ if (listeners != null)
+ list.addAll(listeners);
+ if (children != null)
+ {
+ int i = children.size();
+ Iterator iter = children.entrySet().iterator();
+ while (--i >= 0)
+ {
+ Entry e = (Entry) iter.next();
+ String name = (String) e.getKey();
+ Vector v = ((VetoableChangeSupport) e.getValue()).listeners;
+ int j = v.size();
+ while (--j >= 0)
+ list.add(new VetoableChangeListenerProxy
+ (name, (VetoableChangeListener) v.get(j)));
+ }
+ }
+ return (VetoableChangeListener[])
+ list.toArray(new VetoableChangeListener[list.size()]);
+ }
+
+ /**
+ * Adds a VetoableChangeListener listening on the specified property. Events
+ * will be sent to the listener only if the property name matches. The
+ * listener add is not unique; that is, <em>n</em> adds on a particular
+ * property for a particular listener will result in <em>n</em> events
+ * being sent to that listener when that property is changed. The effect is
+ * cumulative, too; if you are registered to listen to receive events on
+ * all vetoable changes, and then you register on a particular property,
+ * you will receive change events for that property twice. Adding a null
+ * listener may cause a NullPointerException down the road. This method
+ * will unwrap a VetoableChangeListenerProxy, registering the underlying
+ * delegate to the named property list if the names match, and discarding
+ * it otherwise.
+ *
+ * @param propertyName the name of the property to listen on
+ * @param l the listener to add
+ * @throws NullPointerException if propertyName is null
+ */
+ public synchronized void addVetoableChangeListener(String propertyName,
+ VetoableChangeListener l)
+ {
+ while (l instanceof VetoableChangeListenerProxy)
+ {
+ VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
+ if (propertyName == null ? p.propertyName != null
+ : ! propertyName.equals(p.propertyName))
+ return;
+ l = (VetoableChangeListener) p.getListener();
+ }
+ VetoableChangeSupport s = null;
+ if (children == null)
+ children = new Hashtable();
+ else
+ s = (VetoableChangeSupport) children.get(propertyName);
+ if (s == null)
+ {
+ s = new VetoableChangeSupport(source);
+ s.listeners = new Vector();
+ children.put(propertyName, s);
+ }
+ s.listeners.add(l);
+ }
+
+ /**
+ * Removes a VetoableChangeListener from listening to a specific property.
+ * If <code>add()</code> has been called multiple times for a particular
+ * listener on a property, <code>remove()</code> will have to be called the
+ * same number of times to deregister it. This method will unwrap a
+ * VetoableChangeListenerProxy, removing the underlying delegate from the
+ * named property list if the names match.
+ *
+ * @param propertyName the property to stop listening on
+ * @param l the listener to remove
+ * @throws NullPointerException if propertyName is null
+ */
+ public synchronized void
+ removeVetoableChangeListener(String propertyName, VetoableChangeListener l)
+ {
+ if (children == null)
+ return;
+ VetoableChangeSupport s
+ = (VetoableChangeSupport) children.get(propertyName);
+ if (s == null)
+ return;
+ while (l instanceof VetoableChangeListenerProxy)
+ {
+ VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
+ if (propertyName == null ? p.propertyName != null
+ : ! propertyName.equals(p.propertyName))
+ return;
+ l = (VetoableChangeListener) p.getListener();
+ }
+ s.listeners.remove(l);
+ if (s.listeners.isEmpty())
+ {
+ children.remove(propertyName);
+ if (children.isEmpty())
+ children = null;
+ }
+ }
+
+ /**
+ * Returns an array of all vetoable change listeners registered under the
+ * given property name. If there are no registered listeners, this returns
+ * an empty array.
+ *
+ * @return the array of registered listeners
+ * @throws NullPointerException if propertyName is null
+ * @since 1.4
+ */
+ public synchronized VetoableChangeListener[]
+ getVetoableChangeListeners(String propertyName)
+ {
+ if (children == null)
+ return new VetoableChangeListener[0];
+ VetoableChangeSupport s
+ = (VetoableChangeSupport) children.get(propertyName);
+ if (s == null)
+ return new VetoableChangeListener[0];
+ return (VetoableChangeListener[])
+ s.listeners.toArray(new VetoableChangeListener[s.listeners.size()]);
+ }
+
+ /**
+ * Fire a PropertyChangeEvent containing the old and new values of the
+ * property to all the global listeners, and to all the listeners for the
+ * specified property name. This does nothing if old and new are non-null
+ * and equal. If the change is vetoed, a new event is fired to notify
+ * listeners about the rollback before the exception is thrown.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value
+ * @param newVal the new value
+ * @throws PropertyVetoException if the change is vetoed by a listener
+ */
+ public void fireVetoableChange(String propertyName,
+ Object oldVal, Object newVal)
+ throws PropertyVetoException
+ {
+ fireVetoableChange(new PropertyChangeEvent(source, propertyName,
+ oldVal, newVal));
+ }
+
+ /**
+ * Fire a PropertyChangeEvent containing the old and new values of the
+ * property to all the global listeners, and to all the listeners for the
+ * specified property name. This does nothing if old and new are equal.
+ * If the change is vetoed, a new event is fired to notify listeners about
+ * the rollback before the exception is thrown.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value
+ * @param newVal the new value
+ * @throws PropertyVetoException if the change is vetoed by a listener
+ */
+ public void fireVetoableChange(String propertyName, int oldVal, int newVal)
+ throws PropertyVetoException
+ {
+ if (oldVal != newVal)
+ fireVetoableChange(new PropertyChangeEvent(source, propertyName,
+ new Integer(oldVal),
+ new Integer(newVal)));
+ }
+
+ /**
+ * Fire a PropertyChangeEvent containing the old and new values of the
+ * property to all the global listeners, and to all the listeners for the
+ * specified property name. This does nothing if old and new are equal.
+ * If the change is vetoed, a new event is fired to notify listeners about
+ * the rollback before the exception is thrown.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value
+ * @param newVal the new value
+ * @throws PropertyVetoException if the change is vetoed by a listener
+ */
+ public void fireVetoableChange(String propertyName,
+ boolean oldVal, boolean newVal)
+ throws PropertyVetoException
+ {
+ if (oldVal != newVal)
+ fireVetoableChange(new PropertyChangeEvent(source, propertyName,
+ Boolean.valueOf(oldVal),
+ Boolean.valueOf(newVal)));
+ }
+
+ /**
+ * Fire a PropertyChangeEvent to all the global listeners, and to all the
+ * listeners for the specified property name. This does nothing if old and
+ * new values of the event are equal. If the change is vetoed, a new event
+ * is fired to notify listeners about the rollback before the exception is
+ * thrown.
+ *
+ * @param event the event to fire
+ * @throws NullPointerException if event is null
+ * @throws PropertyVetoException if the change is vetoed by a listener
+ */
+ public void fireVetoableChange(PropertyChangeEvent event)
+ throws PropertyVetoException
+ {
+ if (event.oldValue != null && event.oldValue.equals(event.newValue))
+ return;
+ Vector v = listeners; // Be thread-safe.
+ if (v != null)
+ {
+ int i = v.size();
+ try
+ {
+ while (--i >= 0)
+ ((VetoableChangeListener) v.get(i)).vetoableChange(event);
+ }
+ catch (PropertyVetoException e)
+ {
+ event = event.rollback();
+ int limit = i;
+ i = v.size();
+ while (--i >= limit)
+ ((VetoableChangeListener) v.get(i)).vetoableChange(event);
+ throw e;
+ }
+ }
+ Hashtable h = children; // Be thread-safe.
+ if (h != null && event.propertyName != null)
+ {
+ VetoableChangeSupport s
+ = (VetoableChangeSupport) h.get(event.propertyName);
+ if (s != null)
+ {
+ Vector v1 = s.listeners; // Be thread-safe.
+ int i = v1 == null ? 0 : v1.size();
+ try
+ {
+ while (--i >= 0)
+ ((VetoableChangeListener) v1.get(i)).vetoableChange(event);
+ }
+ catch (PropertyVetoException e)
+ {
+ event = event.rollback();
+ int limit = i;
+ i = v.size();
+ while (--i >= 0)
+ ((VetoableChangeListener) v.get(i)).vetoableChange(event);
+ i = v1.size();
+ while (--i >= limit)
+ ((VetoableChangeListener) v1.get(i)).vetoableChange(event);
+ throw e;
+ }
+ }
+ }
+ }
+
+ /**
+ * Tell whether the specified property is being listened on or not. This
+ * will only return <code>true</code> if there are listeners on all
+ * properties or if there is a listener specifically on this property.
+ *
+ * @param propertyName the property that may be listened on
+ * @return whether the property is being listened on
+ * @throws NullPointerException if propertyName is null
+ */
+ public synchronized boolean hasListeners(String propertyName)
+ {
+ return listeners != null || (children != null
+ && children.get(propertyName) != null);
+ }
+
+ /**
+ * Saves the state of the object to the stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if anything goes wrong
+ * @serialData this writes out a null-terminated list of serializable
+ * global vetoable change listeners (the listeners for a named
+ * property are written out as the global listeners of the
+ * children, when the children hashtable is saved)
+ */
+ private synchronized void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ s.defaultWriteObject();
+ if (listeners != null)
+ {
+ int i = listeners.size();
+ while (--i >= 0)
+ if (listeners.get(i) instanceof Serializable)
+ s.writeObject(listeners.get(i));
+ }
+ s.writeObject(null);
+ }
+
+ /**
+ * Reads the object back from stream (deserialization).
+ *
+ * XXX Since serialization for 1.1 streams was not documented, this may
+ * not work if vetoableChangeSupportSerializedDataVersion is 1.
+ *
+ * @param s the stream to read from
+ * @throws IOException if reading the stream fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData this reads in a null-terminated list of serializable
+ * global vetoable change listeners (the listeners for a named
+ * property are written out as the global listeners of the
+ * children, when the children hashtable is saved)
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ VetoableChangeListener l = (VetoableChangeListener) s.readObject();
+ while (l != null)
+ {
+ addVetoableChangeListener(l);
+ l = (VetoableChangeListener) s.readObject();
+ }
+ // Sun is not as careful with children as we are, and lets some proxys
+ // in that can never receive events. So, we clean up anything that got
+ // serialized, to make sure our invariants hold.
+ if (children != null)
+ {
+ int i = children.size();
+ Iterator iter = children.entrySet().iterator();
+ while (--i >= 0)
+ {
+ Entry e = (Entry) iter.next();
+ String name = (String) e.getKey();
+ VetoableChangeSupport vcs = (VetoableChangeSupport) e.getValue();
+ if (vcs.listeners == null)
+ vcs.listeners = new Vector();
+ if (vcs.children != null)
+ vcs.listeners.addAll
+ (Arrays.asList(vcs.getVetoableChangeListeners(name)));
+ if (vcs.listeners.size() == 0)
+ iter.remove();
+ else
+ vcs.children = null;
+ }
+ if (children.size() == 0)
+ children = null;
+ }
+ }
+} // class VetoableChangeSupport
diff --git a/libjava/classpath/java/beans/Visibility.java b/libjava/classpath/java/beans/Visibility.java
new file mode 100644
index 00000000000..428f3a2073b
--- /dev/null
+++ b/libjava/classpath/java/beans/Visibility.java
@@ -0,0 +1,85 @@
+/* java.beans.Visibility
+ Copyright (C) 1998, 1999 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.beans;
+
+/**
+ * Visibility is an interface a Bean may implement so that the environment
+ * can tell the Bean whether there is a GUI or not, and so that the Bean
+ * can tell the environment whether it needs one or can run without one.
+ * <P>
+ *
+ * Sun decided not to use standard Introspection patterns so that these
+ * methods did not get included when the Introspector made its sweep on
+ * the class.
+ *
+ * @author John Keiser
+ * @since JDK1.1
+ * @version 1.1.0, 29 Jul 1998
+ */
+
+public interface Visibility {
+ /**
+ * Tells whether the Bean can run without a GUI or not.
+ * @return false if Bean can run without a GUI, else true.
+ */
+ boolean needsGui();
+
+ /**
+ * Tells whether Bean is trying not to use the GUI.
+ * If needsGui() is true, this method should always return false.
+ * @return true if definitely not using GUI, otherwise false.
+ */
+ boolean avoidingGui();
+
+ /**
+ * Tells the Bean not to use GUI methods.
+ * If needsGUI() is false, then after this method is called,
+ * avoidingGui() should return true.
+ */
+ void dontUseGui();
+
+ /**
+ * Tells the Bean it may use the GUI.
+ * The Bean is not required to use the GUI in this case, it is
+ * merely being <EM>permitted</EM> to use it. If needsGui() is
+ * false, avoidingGui() may return true or false after this method
+ * is called.
+ */
+ void okToUseGui();
+}
diff --git a/libjava/classpath/java/beans/XMLDecoder.java b/libjava/classpath/java/beans/XMLDecoder.java
new file mode 100644
index 00000000000..238fd6bed91
--- /dev/null
+++ b/libjava/classpath/java/beans/XMLDecoder.java
@@ -0,0 +1,307 @@
+/* java.beans.XMLDecoder --
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans;
+
+import gnu.java.beans.decoder.DefaultExceptionListener;
+import gnu.java.beans.decoder.PersistenceParser;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * The XMLDecoder reads XML data that is structured according to
+ * <a href="http://java.sun.com/products/jfc/tsc/articles/persistence3/javabeans.dtd">this</a> DTD
+ * and creates objects according to the content. Usually such data is generated using the
+ * {@link XMLEncoder} class.
+ * <p>
+ * An example XML document might look like this:
+ * <code>
+ * &lt;java&gt;
+ * &lt;string&gt;Hello World&lt;/string&gt;
+ * &lt;int&gt;200&lt;/int&gt;
+ * &lt;/java&gt;
+ * </code>
+ * <p>To read the <code>String</code> and the <code>Integer</code> instance the following can be used (assume
+ * the XML data can be obtained from the InputStream):</p>
+ * <code>
+ * XMLDecoder decoder = new XMLDecoder(inputStreamContainingXMLData);
+ * String message = (String) decoder.readObject();
+ * Integer number = (Integer) decoder.readObject();
+ * </code>
+ * <p>Besides this basic functionality the <code>XMLDecoder</code> has some more features that might come
+ * handy in certain situations:</p>
+ * <p>An owner object can be set using the <code>setOwner</code> method which can then be accessed when
+ * decoding. This feature is only useful if the XML data is aware of the owner object. Such data may
+ * look like this (assume that the owner object is a JFrame instance):</p>
+ * <code>
+ * &lt;java&gt;
+ * &lt;void method="getOwner"&gt;
+ * &lt;void method="setVisible"&gt;
+ * &lt;boolean&gt;true&lt;boolean&gt;
+ * &lt;/void&gt;
+ * &lt;/void&gt;
+ * &lt;/java&gt;
+ * </code>
+ * This accesses the <code>JFrame</code> and makes it visible using the <code>setVisible</code> method.
+ * <p>Please note that changing the owner <b>after</b> the having read the first object has no effect,
+ * because all object have been decoded then.</p>
+ * <p>If the <code>XMLDecoder</code> is created with no {@link ExceptionListener} instance a default one
+ * is used that prints an error message to <code>System.err</code> whenever a recoverable exception
+ * is thrown. Recovarable exceptions occur when the XML data cannot be interpreted correctly (e.g
+ * unknown classes or methods, invocation on null, ...). In general be very careful when the
+ * <code>XMLDecoder</code> provoked such exceptions because the resulting object(s) may be in an
+ * undesirable state.</p>
+ * <p>Note that changing the ExceptionListener instance after <code>readObject</code> has been called
+ * once has no effect because the decoding is completed then.</p>
+ * <p>At last one can provide a specific <code>ClassLoader</code> which is then used when <code>Class</code>
+ * objects are accessed. See {@link java.lang.Class#forName(String, boolean, ClassLoader)} for details
+ * on this.</p>
+ * <p>Note: If the <code>InputStream</code> instance given to any of the constructors is <code>null</code>
+ * the resulting <code>XMLDecoder</code> will be silently (without any exception) useless. Each call
+ * to <code>readObject</code> will return <code>null</code> and never throws an
+ * <code>ArrayIndexOutOfBoundsException</code>.</p>
+ *
+ * @author Robert Schuster
+ * @since 1.4
+ * @status updated to 1.5
+ */
+public class XMLDecoder
+{
+ private Object owner;
+
+ private ExceptionListener exceptionListener;
+
+ private InputStream inputStream;
+
+ private boolean isStreamClosed;
+
+ private ClassLoader classLoader;
+
+ private Iterator iterator;
+
+ /** Creates a XMLDecoder instance that parses the XML data of the given input stream.
+ * Using this constructor no special ClassLoader, a default ExceptionListener
+ * and no owner object is used.
+ *
+ * @param in InputStream to read XML data from.
+ */
+ public XMLDecoder(InputStream in)
+ {
+ this(in, null);
+ }
+
+ /** Creates a XMLDecoder instance that parses the XML data of the given input stream.
+ * Using this constructor no special ClassLoader and a default ExceptionListener
+ * is used.
+ *
+ * @param in InputStream to read XML data from.
+ * @param owner Owner object which can be accessed and modified while parsing.
+ */
+ public XMLDecoder(InputStream in, Object owner)
+ {
+ this(in, owner, null);
+ }
+
+ /** Creates a XMLDecoder instance that parses the XML data of the given input stream.
+ * If the ExceptionListener argument is null a default implementation is used.
+ *
+ * @param in InputStream to read XML data from.
+ * @param owner Owner object which can be accessed and modified while parsing.
+ * @param exceptionListener ExceptionListener instance to which exception notifications are send.
+ */
+ public XMLDecoder(
+ InputStream in,
+ Object owner,
+ ExceptionListener exceptionListener)
+ {
+ this(
+ in,
+ owner,
+ exceptionListener,
+ Thread.currentThread().getContextClassLoader());
+ }
+
+ /** Creates a XMLDecoder instance that parses the XML data of the given input stream.
+ * If the ExceptionListener argument is null a default implementation is used.
+ *
+ * @param in InputStream to read XML data from.
+ * @param owner Owner object which can be accessed and modified while parsing.
+ * @param exceptionListener ExceptionListener instance to which exception notifications are send.
+ * @param cl ClassLoader instance that is used for calls to <code>Class.forName(String, boolean, ClassLoader)</code>
+ * @since 1.5
+ */
+ public XMLDecoder(
+ InputStream in,
+ Object owner,
+ ExceptionListener listener,
+ ClassLoader cl)
+ {
+ // initially here was a check for the validity of the InputStream argument but some
+ // great engineers decided that this API should silently discard this and behave rather
+ // odd: readObject will always return null ...
+ inputStream = in;
+
+ setExceptionListener(listener);
+
+ // validity of this object is checked in Class.forName() and therefore may be null
+ classLoader = cl;
+
+ this.owner = owner;
+ }
+
+ /** Closes the stream associated with this decoder. This should be done after having read all
+ * decoded objects.
+ * <p>See the description of the {@link #readObject()} for the effect caused by <code>close</code>.</p>
+ */
+ public void close()
+ {
+ if (isStreamClosed)
+ {
+ return;
+ }
+
+ try
+ {
+ inputStream.close();
+ isStreamClosed = true;
+ }
+ catch (IOException e)
+ {
+ // bad style forced by original API design ...
+ }
+ }
+
+ /** Returns the ExceptionListener instance associated with this decoder.
+ * <p>See the description of {@link XMLDecoder} class for more information on the ExceptionListener.</p>
+ *
+ * @return Current ExceptionListener of the decoder.
+ */
+ public ExceptionListener getExceptionListener()
+ {
+ return exceptionListener;
+ }
+
+ /** Returns the owner object of the decoder. This method is usually called
+ * from within the parsed XML data.
+ * <p>See the description of {@link XMLDecoder} class for more information on the owner object.</p>
+ *
+ * @return The owner object of this decoder.
+ */
+ public Object getOwner()
+ {
+ return owner;
+ }
+
+ /** Returns the next available decoded object.
+ * <p>Note that the actual decoding takes place when the method is called for the first time.</p>
+ * <p>If the <code>close</code> method was already called a <code>NoSuchElementException</code>
+ * is thrown.</p>
+ * <p>If the InputStream instance used in the constructors was <code>null</code> this method
+ * will always return <code>null</code> itself.</p>
+ *
+ * @return The next object in a sequence decoded from XML data.
+ * @throws ArrayIndexOutOfBoundsException When no more objects are available.
+ */
+ public Object readObject() throws ArrayIndexOutOfBoundsException
+ {
+ // note: the RI does it this way ...
+ if(inputStream == null) {
+ return null;
+ }
+
+ // note: the original API documentation says nothing on what to do
+ // when the stream was closed before readObject is called but it actually
+ // throws a NoSuchElementException - this behaviour is imitated here
+ if (isStreamClosed)
+ {
+ throw new NoSuchElementException("Cannot read any objects - XMLDecoder was already closed.");
+ }
+
+ // creates the PersistenceParser (doing the parsing and decoding) and returns its
+ // Iterator on first invocation
+ if (iterator == null)
+ {
+ iterator =
+ new PersistenceParser(
+ inputStream,
+ exceptionListener,
+ classLoader,
+ this)
+ .iterator();
+ }
+
+ // note: done according to the official documentation
+ if (!iterator.hasNext())
+ {
+ throw new ArrayIndexOutOfBoundsException("No more objects available from this XMLDecoder.");
+ }
+
+ // returns just the next object if there was no problem
+ return iterator.next();
+ }
+
+ /** Sets the ExceptionListener instance to which notifications of exceptions are send
+ * while parsing the XML data.
+ * <p>See the description of {@link XMLDecoder} class for more information on the ExceptionListener.</p>
+ *
+ * @param listener
+ */
+ public void setExceptionListener(ExceptionListener listener)
+ {
+ // uses a default implementation when null
+ if (listener == null)
+ {
+ listener = new DefaultExceptionListener();
+ }
+ exceptionListener = listener;
+ }
+
+ /** Sets the owner object which can be accessed from the parsed XML data.
+ * <p>See the description of {@link XMLDecoder} class for more information on the owner object.</p>
+ *
+ * @param newOwner
+ */
+ public void setOwner(Object newOwner)
+ {
+ owner = newOwner;
+ }
+
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContext.java b/libjava/classpath/java/beans/beancontext/BeanContext.java
new file mode 100644
index 00000000000..3d1be7fc8e9
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContext.java
@@ -0,0 +1,272 @@
+/* java.beans.beancontext.BeanContext
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.beans.DesignMode;
+import java.beans.Visibility;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+
+/**
+ * Acts as a container for sub-beans and as a sub-bean,
+ * so that an entire hierarchy of beans can be made up of
+ * <code>BeanContext</code>s.
+ * <P>
+ *
+ * Since I can't sprinkle the <code>Collections</code> interface
+ * documentation with special information for <code>BeanContext</code>
+ * implementors, I'll have to document special requirements for
+ * implementors of those functions here.
+ * <P>
+ *
+ * <code><strong>add()</strong></code> or <code>addAll()</code>:
+ * <br>
+ * <OL>
+ * <LI>
+ * May add any <code>Object</code> into the hierarchy as well as a
+ * <code>BeanContextChild</code>, <code>BeanContext</code> or
+ * <code>BeanContextProxy</code> object.
+ * This way, any Bean can be in the hierarchy.
+ * </LI>
+ * <LI>
+ * Must synchronize on <code>BeanContext.globalHierarchyLock</code>.
+ * </LI>
+ * <LI>
+ * Don't add the <code>Object</code> if it's already there (only once
+ * per <code>BeanContext</code>).
+ * </LI>
+ * <LI>
+ * If it is a <code>BeanContextChild</code> implementor, call
+ * <code>setBeanContext()</code> on it. If it's a
+ * <code>BeanContextProxy</code> implementor, call
+ * <code>getBeanContextProxy().setBeanContext()</code> on it.
+ * If <code>setBeanContext()</code> vetoes the change, back out
+ * all changes so far and throw <code>IllegalStateException</code>.
+ * </LI>
+ * <LI>
+ * If it (or its proxy) implements <code>Visibility</code>, call
+ * <code>dontUseGui()</code> or <code>okToUseGui()</code> on it,
+ * depending on whether you (the <code>BeanContext</code>) feel like
+ * allowing it to use the GUI or not.
+ * </LI>
+ * <LI>
+ * If it implements <code>BeanContextChild</code> or
+ * <code>BeanContextProxy</code>, register yourself (the
+ * <code>BeanContext</code>) as both a
+ * <code>PropertyChangeListener</code> and
+ * <code>VetoableChangeListener</code> on the "beanContext"
+ * property (it may also add itself on any other properties it wishes
+ * to).
+ * </LI>
+ * <LI>
+ * If it is a listener or event source that you (the
+ * <code>BeanContext</code>) are interested in, you may register
+ * yourself to it or register it to you.
+ * </LI>
+ * <LI>
+ * Fire a <code>java.beans.beancontext.BeanContextMembershipEvent</code>
+ * before exiting. <code>addAll()</code> should wait until everything
+ * is done changing before firing the event (or events) so that if a
+ * failure occurs, the backing-out process can proceed without any
+ * events being fired at all.
+ * </LI>
+ * </OL>
+ * <P>
+ *
+ * <code><strong>remove()</strong></code> or <code>removeAll()</code>:
+ * <br>
+ * <OL>
+ * <LI>
+ * Must synchronize on <code>BeanContext.globalHierarchyLock</code>.
+ * </LI>
+ * <LI>
+ * If the specified <code>Object</code> is not a child of this
+ * <code>BeanContext</code>, just exit without performing any actions.
+ * </LI>
+ * <LI>
+ * Remove the <code>Object</code> from your collection of children.
+ * </LI>
+ * <LI>
+ * If it is a <code>BeanContextChild</code> implementor, call
+ * <code>setBeanContext(null)</code> on it. If it's a
+ * <code>BeanContextProxy</code> implementor, call
+ * <code>getBeanContextProxy().setBeanContext(null)</code> on it.
+ * If <code>setBeanContext()</code> vetoes the change, back out
+ * all changes so far and throw <code>IllegalStateException</code>.
+ * </LI>
+ * <LI>
+ * If you registered the <code>Object</code> to listen to you or
+ * registered yourself as a listener on the <code>Object</code> during
+ * <code>add()</code> or <code>addAll()</code>, undo the registration
+ * bycalling the appropriate <code>removeListener()</code> method.
+ * </LI>
+ * <LI>
+ * Fire a <code>java.beans.beancontext.BeanContextMembershipEvent</code>
+ * before exiting. <code>removeAll()</code> should wait until
+ * everything is done changing before firing the event (or events) so
+ * that if a failure occurs, the backing-out process can proceed
+ * without any events being fired at all.
+ * </LI>
+ * </OL>
+ * <P>
+ *
+ * <code>addAll()</code>, <code>removeAll()</code>,
+ * <code>retainAll()</code> and <code>clear()</code> do not need to be
+ * implemented, but may be if so desired.
+ * <P>
+ *
+ * Similarly, <code>Visibility</code> and <code>DesignMode</code> methods
+ * should propagate changed values to children that implement interfaces
+ * of the same name.
+ * <P>
+ *
+ * A hierarchy of beans is mainly useful so that different sets of beans
+ * can be established, each with their own set of resources.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContext
+ extends Collection, BeanContextChild, Visibility, DesignMode {
+
+ /**
+ * The global lock on changing any BeanContext hierarchy.
+ * It kinda sucks that there is only one lock, since there can be
+ * multiple hierarchies. Oh well, I didn't design, I just code.
+ * <P>
+ *
+ * Methods that must (or do) synchronize on the global lock:
+ * <BR>
+ * <UL>
+ * <LI>
+ * Implementors of <CODE>BeanContext.add()</CODE> and <code>addAll()</code>
+ * </LI>
+ * </UL>
+ * @fixme fill in the rest of the methods which use the global lock.
+ */
+ Object globalHierarchyLock = new Object();
+
+ /**
+ * Instantiate a Bean using this Bean's <code>ClassLoader</code>
+ * and this <code>BeanContext</code> as the parent.
+ * <P>
+ *
+ * This method exists mainly so that <code>BeanContext</code>
+ * implementations can perform extra actions on Beans that are
+ * created within them.
+ *
+ * @param beanName the name of the bean to instantiate
+ * @return the created Bean
+ *
+ * @see java.beans.Beans#instantiate(java.lang.ClassLoader,java.lang.String)
+ * @see java.beans.Beans#instantiate(java.lang.ClassLoader,java.lang.String,java.lang.BeanContext)
+ * @exception IOException if there is an I/O problem during
+ * instantiation.
+ * @exception ClassNotFoundException if a serialized Bean's class
+ * is not found.
+ */
+ Object instantiateChild(String beanName)
+ throws IOException,
+ ClassNotFoundException;
+
+ /**
+ * Get a resource. The <code>BeanContext</code> will typically
+ * call <code>ClassLoader.getResource()</code>, but may do it any
+ * way it wants to. This allows a <code>BeanContext</code> to
+ * have its own set of resources separate from the rest of the
+ * system.
+ * <P>
+ *
+ * Beans should call this method on their parent rather than the
+ * associated <code>ClassLoader</code> method.
+ * <P>
+ *
+ * I am assuming, but am not entirely sure, that if a
+ * <code>BeanContext</code> cannot find a resource, its
+ * responsibility is to call the <code>getResource</code> method
+ * of its parent <code>BeanContext</code>.
+ *
+ * @return a URL to the requested resource.
+ * @param resourceName the name of the resource requested.
+ * @param requestor a reference to the child requesting the resource.
+ * @see java.lang.ClassLoader#getResource(java.lang.String)
+ */
+ URL getResource(String resourceName, BeanContextChild requestor);
+
+ /**
+ * Get a resource as a stream. The <code>BeanContext</code> will
+ * typically call <code>ClassLoader.getResourceAsStream()</code>,
+ * but may do it any way it wants to. This allows a
+ * <code>BeanContext</code>'s children to have their own set of
+ * resources separate from the rest of the system.
+ * <P>
+ *
+ * Beans should call this method on their parent rather than the
+ * associated <code>ClassLoader</code> method.
+ * <P>
+ *
+ * I am assuming, but am not entirely sure, that if a
+ * <code>BeanContext</code> cannot find a resource, its
+ * responsibility is to call the <code>getResourceAsStream</code>
+ * method of its parent <code>BeanContext</code>.
+ *
+ * @return the requested resource as a stream.
+ * @param resourceName the name of the resource requested.
+ * @param requestor a reference to the child requesting the resource.
+ * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
+ */
+ InputStream getResourceAsStream(String resourceName, BeanContextChild requestor);
+
+ /**
+ * Add a listener on changes to the membership of this
+ * <code>BeanContext</code> object.
+ * @param listener the listener to add.
+ */
+ void addBeanContextMembershipListener(BeanContextMembershipListener listener);
+
+ /**
+ * Remove a listener on changes to the membership of this
+ * <code>BeanContext</code> object.
+ * @param listener the listener to remove.
+ */
+ void removeBeanContextMembershipListener(BeanContextMembershipListener listener);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextChild.java b/libjava/classpath/java/beans/beancontext/BeanContextChild.java
new file mode 100644
index 00000000000..d1115efac85
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextChild.java
@@ -0,0 +1,174 @@
+/* java.beans.beancontext.BeanContextChild
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+
+/**
+ * Beans implement this to get information about the execution environment and
+ * its services and to be placed in the hierarchy.
+ * <P>
+ *
+ * The difference between a <code>BeanContext</code> and a
+ * <code>BeanContextChild</code>, mainly, is that a
+ * <code>BeanContext</code> may be a parent.
+ * <P>
+ *
+ * <code>BeanContextChild</code> instances will be serialized at some
+ * point in their life, but you need to make sure your bean context does
+ * not contain a serializable reference (directly or indirectly) to the
+ * parent <code>BeanContext</code>, to any of the other
+ * <code>BeanContext</code>s in the tree, or to any resources obtained
+ * via the <code>BeanContextServices</code> interface. One way to do this
+ * is to mark any fields that contain such references as
+ * <code>transient</code>. Another way is to use a custom serializer.
+ * <P>
+ *
+ * If you do not do this, when the <code>BeanContext</code> is serialized,
+ * all the other <code>BeanContext</code>s and other unnecessary things
+ * will be serialized along with it.
+ * <P>
+ *
+ * Before dying, a <code>BeanContextChild</code> should call
+ * <code>getBeanContext().remove(this)</code> to detach from the
+ * hierarchy and exit cleanly.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContext
+ */
+
+public interface BeanContextChild {
+ /**
+ * Set the parent <code>BeanContext</code>.
+ * <P>
+ *
+ * This method is called from <code>BeanContext.add()</code> and
+ * should not be called directly.
+ * <P>
+ *
+ * When this Object is being added to a new BeanContext or moved
+ * from an old one, a non-null value will be passed in.
+ * <P>
+ *
+ * When this Object is being removed from the current
+ * <code>BeanContext</code>, <code>setBeanContext()</code> will
+ * receive the parameter <code>null</code>.
+ * <P>
+ *
+ * When being removed from the current <code>BeanContext</code>,
+ * it is the <code>BeanContextChild</code>'s responsibility to
+ * release all services it has obtained.
+ * <P>
+ *
+ * This change should generate <code>PropertyChangeEvent</code>
+ * and <code>VetoableChangeEvent</code>s with the property name
+ * "beanContext". If the change is vetoed, it must re-throw the
+ * exception and not change anything. In this way, the parent
+ * <code>BeanContextChild</code>, who has registered himself with
+ * you, will have a chance to remove this child from its
+ * collection.
+ * <P>
+ *
+ * If the Bean does not wish to change the parent or be removed
+ * from one, it may throw the <code>PropertyVetoException</code>.
+ * If you veto a <code>setBeanContext(null)</code> call, then you
+ * should try your hardest to remedy whatever problem is keeping
+ * you from being removed from the <code>BeanContext</code> so
+ * that you can <em>not</em> veto it the next time.
+ * Otherwise, nasty pathological recursion stuff could occur in
+ * certain situations.
+ * <P>
+ *
+ * If you do veto the change, you must first back out any changes
+ * you made prior to the veto. Best not to make any such changes
+ * prior to the veto in the first place.
+ * <P>
+ *
+ * This method is called from <code>BeanContext.add()</code> and
+ * should not be called directly.
+ *
+ * @param parent the new parent for the <code>BeanContextChild</code>,
+ * or <code>null</code> to signify removal from a tree.
+ * @exception PropertyVetoException if the
+ * <code>BeanContextChild</code> implementor does not
+ * wish to have its parent changed.
+ */
+ void setBeanContext(BeanContext parent)
+ throws PropertyVetoException;
+
+ /**
+ * Get the parent <code>BeanContext</code>.
+ * @return the parent <code>BeanContext</code>.
+ */
+ BeanContext getBeanContext();
+
+ /**
+ * Add a listener that will be notified when a specific property changes.
+ * @param prop the name of the property to listen on
+ * @param listener the listener to listen on the property.
+ */
+ void addPropertyChangeListener(String prop, PropertyChangeListener listener);
+
+ /**
+ * Remove a listener to a certain property.
+ * @param prop the name of the property being listened on
+ * @param listener the listener listening on the property.
+ */
+ void removePropertyChangeListener(String prop, PropertyChangeListener listener);
+
+ /**
+ * Add a listener that will be notified when a specific property
+ * change is requested (a PropertyVetoException may be thrown) as
+ * well as after the change is successfully made.
+ *
+ * @param prop the name of the property to listen on
+ * @param listener the listener to listen on the property.
+ */
+ void addVetoableChangeListener(String prop, VetoableChangeListener listener);
+
+ /**
+ * Remove a listener to a certain property.
+ * @param prop the name of the property being listened on
+ * @param listener the listener listening on the property.
+ */
+ void removeVetoableChangeListener(String prop, VetoableChangeListener listener);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextChildComponentProxy.java b/libjava/classpath/java/beans/beancontext/BeanContextChildComponentProxy.java
new file mode 100644
index 00000000000..a8d6e34045e
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextChildComponentProxy.java
@@ -0,0 +1,60 @@
+/* java.beans.beancontext.BeanContextChildComponentProxy
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.awt.Component;
+
+/**
+ * Interface for <code>BeanContextChild</code>s which wish to associate an
+ * AWT component with them. The proxy is provided because the
+ * <code>addPropertyChangeListener()</code> method would conflict with
+ * <code>Component</code> if you tried to extend.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextChildComponentProxy {
+ /**
+ * Get the <code>Component</code> associated with this <code>BeanContextChild</code>.
+ * @return the <code>Component</code> associated with this
+ * <code>BeanContextChild</code>.
+ */
+ Component getComponent();
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextChildSupport.java b/libjava/classpath/java/beans/beancontext/BeanContextChildSupport.java
new file mode 100644
index 00000000000..4444ad71377
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextChildSupport.java
@@ -0,0 +1,381 @@
+/* java.beans.beancontext.BeanContextChildSupport
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.VetoableChangeSupport;
+import java.io.Serializable;
+
+/**
+ * Support for creating a <code>BeanContextChild</code>.
+ * This class contains the most common implementations of the methods in
+ * the <code>BeanContextChild</code>
+ *
+ * @specnote This class is not very well specified. I had to "fill in the
+ * blanks" in most places with what I thought was reasonable
+ * behavior. If there are problems, let me know.
+ *
+ * @author John Keiser
+ * @since 1.2
+ * @see java.beans.beancontext.BeanContextChild
+ */
+public class BeanContextChildSupport
+ implements BeanContextChild, BeanContextServicesListener, Serializable
+{
+ static final long serialVersionUID = 6328947014421475877L;
+
+ /**
+ * The peer on which to perform <code>set</code> actions.
+ * This is here so that this class can be used as a peer.
+ * <P>
+ *
+ * When extending this class, this variable will be set to
+ * <code>this</code>.
+ */
+ public BeanContextChild beanContextChildPeer;
+
+ /**
+ * The parent <code>BeanContext</code>.
+ */
+ protected transient BeanContext beanContext;
+
+ /**
+ * If <code>setBeanContext()</code> was vetoed once before, this
+ * is set to <code>true</code> so that the next time, vetoes will
+ * be ignored.
+ */
+ protected transient boolean rejectedSetBCOnce;
+
+ /**
+ * Listeners are registered here and events are fired through here.
+ */
+ protected PropertyChangeSupport pcSupport;
+
+ /**
+ * Listeners are registered here and events are fired through here.
+ */
+ protected VetoableChangeSupport vcSupport;
+
+ /**
+ * Create a new <code>BeanContextChildSupport</code> with itself as the peer.
+ * This is meant to be used when you subclass
+ * <code>BeanContextChildSupport</code> to create your child.
+ */
+ public BeanContextChildSupport()
+ {
+ this (null);
+ }
+
+ /**
+ * Create a new <code>BeanContextChildSupport</code> with the specified peer.
+ * @param peer the peer to use, or <code>null</code> to specify
+ * <code>this</code>.
+ */
+ public BeanContextChildSupport (BeanContextChild peer)
+ {
+ if (peer == null)
+ {
+ peer = this;
+ }
+
+ beanContextChildPeer = peer;
+ pcSupport = new PropertyChangeSupport (peer);
+ vcSupport = new VetoableChangeSupport (peer);
+ }
+
+ /**
+ * Set the parent <code>BeanContext</code>.
+ * <P>
+ *
+ * When this Object is being added to a new BeanContext or moved
+ * from an old one, a non-null value will be passed in.
+ * <P>
+ *
+ * When this Object is being removed from the current
+ * <code>BeanContext</code>, <code>setBeanContext()</code> will
+ * receive the parameter <code>null</code>.
+ * <P>
+ *
+ * Order of events:
+ * <OL>
+ * <LI>
+ * If the new <code>BeanContext</code> is the same as the old
+ * one, nothing happens.
+ * </LI>
+ * <LI>
+ * If the change has not been rejected or vetoed before, call
+ * <code>validatePendingSetBeanContext()</code>. If this call
+ * returns <code>false</code>, the change is rejected and a
+ * <code>PropertyVetoException</code> is thrown.
+ * </LI>
+ * <LI>
+ * If the change has not been rejected or vetoed before,
+ * <code>VetoableChangeEvent</code>s are fired with the name
+ * <code>"beanContext"</code>, using the
+ * <code>fireVetoableChange()</code> method. If a veto
+ * occurs, reversion events are fired using the same method,
+ * the change is rejected, and the veto is rethrown.
+ * </LI>
+ * <LI>
+ * <code>releaseBeanContextResources()</code> is called.
+ * </LI>
+ * <LI>
+ * The change is made.
+ * </LI>
+ * <LI>
+ * <code>PropertyChangeEvent</code>s are fired using the
+ * <code>firePropertyChange()</code> method.
+ * </LI>
+ * <LI>
+ * <code>initializeBeanContextResources()</code> is called.
+ * </LI>
+ * </OL>
+ * <P>
+ *
+ * @param newBeanContext the new parent for the
+ * <code>BeanContextChild</code>, or <code>null</code> to
+ * signify removal from a tree.
+ * @exception PropertyVetoException if the
+ * <code>BeanContextChild</code> implementor does not
+ * wish to have its parent changed.
+ */
+ public void setBeanContext(BeanContext newBeanContext)
+ throws PropertyVetoException
+ {
+ synchronized (beanContextChildPeer)
+ {
+ if (newBeanContext == beanContext)
+ return;
+
+ if (!rejectedSetBCOnce)
+ {
+ if (!validatePendingSetBeanContext (newBeanContext))
+ {
+ rejectedSetBCOnce = true;
+ throw new PropertyVetoException ("validatePendingSetBeanContext() rejected change",
+ new PropertyChangeEvent(beanContextChildPeer, "beanContext", beanContext, newBeanContext));
+ }
+
+ try
+ {
+ fireVetoableChange ("beanContext", beanContext, newBeanContext);
+ }
+ catch (PropertyVetoException e)
+ {
+ rejectedSetBCOnce = true;
+ throw e;
+ }
+ }
+
+ releaseBeanContextResources ();
+
+ beanContext = newBeanContext;
+ rejectedSetBCOnce = false;
+
+ firePropertyChange ("beanContext", beanContext, newBeanContext);
+
+ initializeBeanContextResources ();
+ }
+ }
+
+ /**
+ * Get the parent <code>BeanContext</code>.
+ * @return the parent <code>BeanContext</code>.
+ */
+ public BeanContext getBeanContext()
+ {
+ return beanContext;
+ }
+
+ /**
+ * Get the peer (or <code>this</code> if there is no peer).
+ * @return the peer, or <code>this</code> if there is no peer.
+ */
+ public BeanContextChild getBeanContextChildPeer() {
+ return beanContextChildPeer;
+ }
+
+ /**
+ * Determine whether there is a peer.
+ * This is true iff <code>getBeanContextChildPeer() == this</code>.
+ * @return whether there is a peer.
+ */
+ public boolean isDelegated() {
+ return beanContextChildPeer == this;
+ }
+
+ /**
+ * Add a listener that will be notified when a specific property changes.
+ * @param propertyName the name of the property to listen on.
+ * @param listener the listener to listen on the property.
+ */
+ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ pcSupport.addPropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Remove a listener to a certain property.
+ *
+ * @param propertyName the name of the property being listened on.
+ * @param listener the listener listening on the property.
+ */
+ public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ pcSupport.removePropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Add a listener that will be notified when a specific property
+ * change is requested (a PropertyVetoException may be thrown) as
+ * well as after the change is successfully made.
+ *
+ * @param propertyName the name of the property to listen on.
+ * @param listener the listener to listen on the property.
+ */
+ public void addVetoableChangeListener(String propertyName, VetoableChangeListener listener) {
+ vcSupport.addVetoableChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Remove a listener to a certain property.
+ *
+ * @param propertyName the name of the property being listened on
+ * @param listener the listener listening on the property.
+ */
+ public void removeVetoableChangeListener(String propertyName, VetoableChangeListener listener) {
+ vcSupport.removeVetoableChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Fire a property change.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value of the property
+ * @param newVal the new value of the property
+ */
+ public void firePropertyChange(String propertyName, Object oldVal, Object newVal) {
+ pcSupport.firePropertyChange(propertyName, oldVal, newVal);
+ }
+
+ /**
+ * Fire a vetoable property change.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value of the property
+ * @param newVal the new value of the property
+ * @exception PropertyVetoException if the change is vetoed.
+ */
+ public void fireVetoableChange(String propertyName, Object oldVal, Object newVal)
+ throws PropertyVetoException {
+ vcSupport.fireVetoableChange(propertyName, oldVal, newVal);
+ }
+
+ /**
+ * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked.
+ * If you have a reference to such a service, it should be
+ * discarded and may no longer function properly.
+ * <code>getService()</code> will no longer work on the specified
+ * service class after this event has been fired.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation does
+ * nothing.
+ *
+ * @param event the service revoked event.
+ * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean)
+ */
+ public void serviceRevoked(BeanContextServiceRevokedEvent event) {
+ }
+
+ /**
+ * Called by <code>BeanContextServices</code> whenever a service is made available.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation does
+ * nothing.
+ *
+ * @param event the service revoked event, with useful information
+ * about the new service.
+ */
+ public void serviceAvailable(BeanContextServiceAvailableEvent event) {
+ }
+
+ /**
+ * Called by <code>setBeanContext()</code> to determine whether the set should be rejected.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation simply
+ * returns <code>true</code>.
+ *
+ * @param newBeanContext the new parent.
+ * @return whether to allow the parent to be changed to the new
+ * value.
+ */
+ public boolean validatePendingSetBeanContext(BeanContext newBeanContext) {
+ return true;
+ }
+
+ /**
+ * Called by <code>setBeanContext()</code> to release resources of a what will soon no longer be the parent.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation does
+ * nothing.
+ */
+ protected void releaseBeanContextResources() {
+ }
+
+ /**
+ * Called by <code>setBeanContext()</code> to grab resources when the parent has been set.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation does
+ * nothing.
+ */
+ protected void initializeBeanContextResources() {
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextContainerProxy.java b/libjava/classpath/java/beans/beancontext/BeanContextContainerProxy.java
new file mode 100644
index 00000000000..3df91038bfe
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextContainerProxy.java
@@ -0,0 +1,63 @@
+/* java.beans.beancontext.BeanContextContainerProxy
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.awt.Container;
+
+/**
+ * Interface for <code>BeanContext</code>s which wish to associate an
+ * AWT container with them. The proxy is provided because the
+ * <code>addPropertyChangeListener()</code> and <code>add()</code> methods
+ * would conflict with <code>Component</code> and <code>Container</code>
+ * if you tried to extend.
+ *
+ * @specnote It is unclear whether anything besides <code>BeanContext</code>s
+ * are allowed to implement this interface.
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextContainerProxy {
+ /**
+ * Get the <code>Container</code> associated with this <code>BeanContext</code>.
+ * @return the <code>Container</code> associated with this
+ * <code>BeanContext</code>.
+ */
+ Container getContainer();
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextEvent.java b/libjava/classpath/java/beans/beancontext/BeanContextEvent.java
new file mode 100644
index 00000000000..f326541b034
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextEvent.java
@@ -0,0 +1,110 @@
+/* java.beans.beancontext.BeanContextEvent
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.util.EventObject;
+
+/**
+ * Generic superclass for events fired by <code>BeanContext</code>s.
+ *
+ * @author John Keiser
+ * @since 1.2
+ */
+
+public abstract class BeanContextEvent extends EventObject
+{
+ private static final long serialVersionUID = 7267998073569045052L;
+
+ /**
+ * The <code>BeanContext</code> that most recently passed this
+ * event on.
+ */
+ protected BeanContext propagatedFrom;
+
+ /**
+ * Create a new event, from the specified <code>BeanContext</code>.
+ * <code>propagatedFrom</code> will be initialized to
+ * <code>null</code>.
+ *
+ * @param source the source of the event.
+ */
+ protected BeanContextEvent(BeanContext source)
+ {
+ super(source);
+ }
+
+ /**
+ * Get the <code>BeanContext</code> that originated this event.
+ * @return the originator of this event.
+ */
+ public BeanContext getBeanContext()
+ {
+ return (BeanContext)getSource();
+ }
+
+ /**
+ * Get the most recent propagator of this event.
+ * If this value is <code>null</code>, you have received the event
+ * straight from the source.
+ *
+ * @return the most recent propagator of this event.
+ */
+ public BeanContext getPropagatedFrom()
+ {
+ return propagatedFrom;
+ }
+
+ /**
+ * Tell whether this event has been propagated.
+ * @return <code>true</code> iff <code>getPropagatedFrom() != null</code>.
+ */
+ public boolean isPropagated()
+ {
+ return propagatedFrom != null;
+ }
+
+ /**
+ * Set the most recent propagator of this event.
+ * @param propagator the most recent propagator of this event.
+ */
+ public void setPropagatedFrom(BeanContext propagator)
+ {
+ propagatedFrom = propagator;
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextMembershipEvent.java b/libjava/classpath/java/beans/beancontext/BeanContextMembershipEvent.java
new file mode 100644
index 00000000000..31765426622
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextMembershipEvent.java
@@ -0,0 +1,112 @@
+/* java.beans.beancontext.BeanContextMembershipEvent
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans.beancontext;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Event fired when children are added to or removed from a <code>BeanContext</code>.
+ * Whether they were added or removed depends entirely on which method
+ * of the listener interface was called.
+ *
+ * @author John Keiser
+ * @since 1.2
+ * @see java.beans.beancontext.BeanContextMembershipListener
+ */
+public class BeanContextMembershipEvent extends BeanContextEvent {
+ /**
+ * The children that were added or removed.
+ */
+ protected Collection children;
+
+ /**
+ * Create a new membership event.
+ * @param context the event source.
+ * @param children the children added to or removed from the source.
+ */
+ public BeanContextMembershipEvent(BeanContext context, Collection children) {
+ super(context);
+ this.children = children;
+ }
+
+ /**
+ * Create a new membership event.
+ * @param context the event source.
+ * @param children the children added to or removed from the source.
+ */
+ public BeanContextMembershipEvent(BeanContext context, Object[] children) {
+ super(context);
+ this.children = Arrays.asList(children);
+ }
+
+ /**
+ * The number of children removed or added.
+ * @return the number of children removed or added.
+ */
+ public int size() {
+ return children.size();
+ }
+
+ /**
+ * An iterator that will step through all the children.
+ * @return an iterator over all the children.
+ */
+ public Iterator iterator() {
+ return children.iterator();
+ }
+
+ /**
+ * An array of the children.
+ * @return an array of the children.
+ */
+ public Object[] toArray() {
+ return children.toArray();
+ }
+
+ /**
+ * Tell whether the <code>Object</code> is one of the children added or removed.
+ * @param child the child to check.
+ * @return whether the <code>Object</code> is added or removed.
+ */
+ public boolean contains(Object child) {
+ return children.contains(child);
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextMembershipListener.java b/libjava/classpath/java/beans/beancontext/BeanContextMembershipListener.java
new file mode 100644
index 00000000000..d39c36c4b12
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextMembershipListener.java
@@ -0,0 +1,70 @@
+/* java.beans.beancontext.BeanContextMembershipListener
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.util.EventListener;
+
+/**
+ * This is the interface to which <code>BeanContextMembershipEvent</code>s are sent.
+ * This happens when children are added to or removed from a
+ * <code>BeanContext</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextMembershipListener extends EventListener {
+ /**
+ * When beans are added to a <code>BeanContext</code>,
+ * this method is called to fire the event.
+ *
+ * @param event the event, including which children were added.
+ * @see java.beans.beancontext.BeanContext#add(java.lang.Object)
+ */
+ void childrenAdded(BeanContextMembershipEvent event);
+
+ /**
+ * When beans are removed from a <code>BeanContext</code>,
+ * this method is called to fire the event.
+ *
+ * @param event the event, including which children were removed.
+ * @see java.beans.beancontext.BeanContext#remove(java.lang.Object)
+ */
+ void childrenRemoved(BeanContextMembershipEvent event);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextProxy.java b/libjava/classpath/java/beans/beancontext/BeanContextProxy.java
new file mode 100644
index 00000000000..49dd7a77f30
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextProxy.java
@@ -0,0 +1,65 @@
+/* java.beans.beancontext.BeanContextProxy
+ Copyright (C) 1999 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.beans.beancontext;
+
+/**
+ * Beans that wish to have a <code>BeanContextChild</code> or <code>BeanContext</code> associated with them
+ * but do not wish to implement those interfaces directly, can implement this interface.
+ * <P>
+ *
+ * Don't shoot yourself in the foot: if you already implement
+ * <code>BeanContextChild</code>, directly or indirectly, the whole
+ * workings of this package will be unpredictable because it is
+ * indeterminate as to whether the <code>BeanContextChild</code> is used
+ * in preference to its proxy or vice versa.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextProxy {
+ /**
+ * Return the <code>BeanContextChild</code> associated with this
+ * <code>Object</code>.
+ *
+ * @return the <code>BeanContextChild</code> associated with this
+ * <code>Object</code>.
+ */
+ BeanContextChild getBeanContextProxy();
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceAvailableEvent.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceAvailableEvent.java
new file mode 100644
index 00000000000..eea10f261b6
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceAvailableEvent.java
@@ -0,0 +1,95 @@
+/* java.beans.beancontext.BeanContextServiceAvailableEvent
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.util.Iterator;
+
+/**
+ * Event fired when new services become available through a <code>BeanContextServices</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextServicesListener
+ */
+
+public class BeanContextServiceAvailableEvent extends BeanContextEvent {
+ /**
+ * The <code>Class</code> representing the service which is now
+ * available.
+ */
+ protected Class serviceClass;
+
+ /**
+ * Create a new service available event.
+ * @param services the <code>BeanContextServices</code> through
+ * which the service is available. This is also the source
+ * of the event.
+ * @param serviceClass the service class that is now available.
+ */
+ public BeanContextServiceAvailableEvent(BeanContextServices services, Class serviceClass) {
+ super(services);
+ this.serviceClass = serviceClass;
+ }
+
+ /**
+ * Get the current service selectors of the service class.
+ * This is identical to <code>getSourceAsBeanContextServices().getCurrentServiceSelectors(getServiceClass())</code>
+ * @return the current service selectors of the service class.
+ */
+ public Iterator getCurrentServiceSelectors() {
+ return getSourceAsBeanContextServices().getCurrentServiceSelectors(serviceClass);
+ }
+
+ /**
+ * Get the newly available service class.
+ * @return the service class.
+ */
+ public Class getServiceClass() {
+ return serviceClass;
+ }
+
+ /**
+ * Get the <code>BeanContextServices</code> through which the new service is available.
+ * @return the <code>BeanContextServices</code> through which the
+ * new service is available.
+ */
+ public BeanContextServices getSourceAsBeanContextServices() {
+ return (BeanContextServices)getSource();
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceProvider.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceProvider.java
new file mode 100644
index 00000000000..c09b5815fd7
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceProvider.java
@@ -0,0 +1,138 @@
+/* java.beans.beancontext.BeanContextServiceProvider
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.util.Iterator;
+
+/**
+ * An actual factory for services.
+ * <P>
+ *
+ * It is the <code>BeanContextServiceProvider</code>'s responsibility to
+ * register itself with whatever <code>BeanContextServices</code> object
+ * it wishes to provide services through using the
+ * <code>addService()</code> method.
+ * <P>
+ *
+ * If for some reason it can no longer provide services for a particular
+ * class, this class must invoke
+ * <code>BeanContextServices.revokeService(serviceClass,this,true)</code>
+ * for all the places it has registered the service.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServiceProvider {
+ /**
+ * Get a service.
+ * Called from <code>BeanContextServices.getService()</code>.
+ *
+ * <p>If the requested service class is not available, or if this
+ * <code>BeanContextServiceProvider</code> chooses not honor the
+ * request for some reason, then this method will return
+ * <code>null</code>.</p>
+ *
+ * This method may throw unchecked exceptions, so watch out.
+ *
+ * @param services the <code>BeanContextServices</code> that wants
+ * to get the service. Only weak references to this will
+ * be retained, and it will never be changed, only queried
+ * in a read-only manner.
+ * @param requestor the actual requestor of the service. Only
+ * weak references to this will be retained, and it will
+ * never be changed, only queried in a read-only manner.
+ * @param serviceClass the <code>Class</code> of the service being
+ * requested.
+ * @param serviceSelector a parameter to customize the service
+ * returned with.
+ * @return an instance of <code>serviceClass</code> (such that
+ * <code>instanceof</code> serviceClass is true), or
+ * <code>null</code>.
+ * @see java.beans.beancontext.BeanContextServices#getService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Class,java.lang.Object,java.beans.beancontext.BeanContextServiceRevokedListener)
+ */
+ Object getService(BeanContextServices services, Object requestor, Class serviceClass, Object serviceSelector);
+
+ /**
+ * Release the service.
+ * <P>
+ *
+ * Called by <code>BeanContextServices.releaseService()</code>.
+ * <P>
+ *
+ * Most <code>BeanContextServiceProvider</code>s won't have to do
+ * anything here.
+ *
+ * @param services the <code>BeanContextServices</code> that wants
+ * to release the service. Only weak references to this will
+ * be retained, and it will never be changed, only queried
+ * in a read-only manner.
+ * @param requestor the original requestor of the service.
+ * @param service the service to relinquish
+ * @see java.beans.beancontext.BeanContextServices#releaseService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Object)
+ */
+ void releaseService(BeanContextServices services, Object requestor, Object service);
+
+ /**
+ * Get a list of valid service selectors for the specified service class.
+ * This method is called from
+ * <code>BeanContextServices.getCurrentServiceSelectors()</code>.
+ * <P>
+ *
+ * If the specified service class does not have a finite number of
+ * valid service selectors, it should return <code>null</code>.
+ * If it takes a general <code>Integer</code> parameter, for
+ * example, you may as well return <code>null</code> or the poor
+ * soul who called this method will be iterating all day.
+ * <P>
+ *
+ * If it has no valid service selectors, it should still return an empty
+ * <code>Iterator</code>.
+ *
+ * @param services the <code>BeanContextServices</code> that wants
+ * to get the service selectors. Only weak references to this will
+ * be retained, and it will never be changed, only queried
+ * in a read-only manner.
+ * @param serviceClass the service class to get selectors for.
+ * @return a list of valid service selectors for the service
+ * class, or <code>null</code>.
+ * @see java.beans.beancontext.BeanContextServices#getCurrentServiceSelectors(java.lang.Class)
+ */
+ Iterator getCurrentServiceSelectors(BeanContextServices services, Class serviceClass);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java
new file mode 100644
index 00000000000..690b94e2cc7
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java
@@ -0,0 +1,60 @@
+/* java.beans.beancontext.BeanContextServiceProviderBeanInfo
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.beans.BeanInfo;
+
+/**
+ * <code>BeanContextServiceProvider</code>s implement this to provide information about all of the services they provide.
+ * <P>
+ *
+ * This is apparently so that you can import a bunch of services into a
+ * RAD tool and it will know about all of them and export them to the
+ * user in a readable manner.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+public interface BeanContextServiceProviderBeanInfo extends BeanInfo {
+ /**
+ * Get <code>BeanInfo</code>s for all of the service classes of this <code>BeanInfoServiceProvider</code>.
+ * @return <code>BeanInfo</code>s for all provided service classes.
+ */
+ BeanInfo[] getServicesBeanInfo();
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedEvent.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedEvent.java
new file mode 100644
index 00000000000..dfa2b89b3ae
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedEvent.java
@@ -0,0 +1,110 @@
+/* java.beans.beancontext.BeanContextServiceRevokedEvent
+ Copyright (C) 1999, 2000 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.beans.beancontext;
+
+/**
+ * Event fired when services are revoked from a <code>BeanContextServices</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextServiceRevokedListener
+ */
+
+public class BeanContextServiceRevokedEvent extends BeanContextEvent {
+ /**
+ * The <code>Class</code> representing the service which is now
+ * available.
+ */
+ protected Class serviceClass;
+ private boolean invalidateRefs;
+
+ /**
+ * Create a new service revoked event.
+ * @param services the <code>BeanContextServices</code> through
+ * which the service was available. This is also the source
+ * of the event.
+ * @param serviceClass the service class that is now revoked.
+ * @param revokeNow whether the revocation is immediate for all
+ * classes or just a suggestion.
+ */
+ public BeanContextServiceRevokedEvent(BeanContextServices services, Class serviceClass, boolean revokeNow) {
+ super(services);
+ this.serviceClass = serviceClass;
+ invalidateRefs = revokeNow;
+ }
+
+ /**
+ * Get the revoked service class.
+ * @return the service class.
+ */
+ public Class getServiceClass() {
+ return serviceClass;
+ }
+
+ /**
+ * Tell whether the revoked service class is the same as the specified class.
+ * Identical to <code>getServiceClass().equals(c)</code>.
+ * @param c the class to compare.
+ * @return whether the clases are equal.
+ */
+ public boolean isServiceClass(Class c) {
+ return serviceClass.equals(c);
+ }
+
+ /**
+ * Get the <code>BeanContextServices</code> through which the service was available.
+ * @return the <code>BeanContextServices</code> through which the
+ * service was available.
+ */
+ public BeanContextServices getSourceAsBeanContextServices() {
+ return (BeanContextServices)getSource();
+ }
+
+ /**
+ * Tell whether current instances of the revoked service are usable or not.
+ * This is determined by whether the service was revoked
+ * immediately.
+ *
+ * @return whether current instances of the revoked service are
+ * usable.
+ */
+ public boolean isCurrentServiceInvalidNow() {
+ return invalidateRefs;
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedListener.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedListener.java
new file mode 100644
index 00000000000..101e6e191b0
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedListener.java
@@ -0,0 +1,62 @@
+/* java.beans.beancontext.BeanContextServiceRevokedListener
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.util.EventListener;
+
+/**
+ * Listens for service revoke events.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServiceRevokedListener extends EventListener {
+ /**
+ * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked.
+ * If you have a reference to such a service, it should be
+ * discarded and may no longer function properly.
+ * <code>getService()</code> will no longer work on the specified
+ * service class after this event has been fired.
+ *
+ * @param event the service revoked event.
+ * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean)
+ */
+ void serviceRevoked(BeanContextServiceRevokedEvent event);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServices.java b/libjava/classpath/java/beans/beancontext/BeanContextServices.java
new file mode 100644
index 00000000000..cb1950360af
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServices.java
@@ -0,0 +1,216 @@
+/* java.beans.beancontext.BeanContextServices
+ Copyright (C) 1999 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.beans.beancontext;
+
+import java.util.Iterator;
+import java.util.TooManyListenersException;
+
+/**
+ * Allows a <code>BeanContext</code> to provide services to its children.
+ *
+ * @specnote it is unclear whether a <code>BeanContextServices</code>
+ * should delegate unhandled requests to parents. I assume so.
+ * @author John Keiser
+ * @since 1.2
+ */
+
+public interface BeanContextServices
+ extends BeanContext, BeanContextServicesListener
+{
+ /**
+ * Register a service to make it available to others.
+ * This class may refuse to add the service based on whatever
+ * information it can gather, including whether the service
+ * provider is trusted.
+ *
+ * @param serviceClass the service class.
+ * @param provider the factory that will actually provide the service.
+ * @return whether the service was added or not.
+ */
+ boolean addService (Class serviceClass,
+ BeanContextServiceProvider provider);
+
+ /**
+ * Make it so that no one else can use this service.
+ * <P>
+ *
+ * If <code>revokeNow</code> is <code>false</code>, the only
+ * effect of this method is to make all subsequent calls to
+ * <code>getService()</code> on this service class fail.
+ * <P>
+ *
+ * If it is <code>true</code>, a message is also sent out to all
+ * listeners on the service and all references to it are released.
+ *
+ * @param serviceClass the service class to revoke.
+ * @param provider the service provider providing the service class.
+ * @param revokeNow whether to release all current references to
+ * the service.
+ */
+ void revokeService (Class serviceClass,
+ BeanContextServiceProvider provider,
+ boolean revokeNow);
+
+ /**
+ * Release your copy of this service.
+ * <P>
+ *
+ * If all copies of the service's class have been relinquished by
+ * the requestor, the <code>BeanContextServiceRevokedListener</code>
+ * previously registered by <code>getService()</code> will be
+ * unregistered.
+ *
+ * @param requestorChild the original <code>BeanContextChild</code>
+ * requesting the service.
+ * @param requestor the original requestor of the service.
+ * @param service the service to relinquish
+ * @see #getService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Class,java.lang.Object,java.beans.beancontext.BeanContextServiceRevokedListener)
+ */
+ void releaseService (BeanContextChild requestorChild, Object requestor,
+ Object service);
+
+ /**
+ * Get a service from this <code>BeanContextServices</code>.
+ * <P>
+ *
+ * The specified listener will be registered to receive a
+ * revocation notice for the specified serviceClass. One
+ * notification per service class per requestor object will be
+ * sent.
+ * <P>
+ *
+ * The listener will be unregistered when all services that were
+ * obtained by that requestor for that service class are released.
+ * <P>
+ *
+ * If the requested service class is not available, or if this
+ * <code>BeanContextServices</code> object chooses not honor the
+ * request because the service class has been revoked or for some
+ * other reason, then this method will return <code>null</code>.
+ * <P>
+ *
+ * This method may throw unchecked exceptions, so watch out.
+ *
+ * @specnote it is not specified what happens when two subsequent
+ * calls are made to <code>getService()</code> with the
+ * same requestor object and service class but different
+ * listeners. Which listener is to be notified?
+ *
+ * @param requestorChild the <code>BeanContextChild</code>
+ * associated with the requestor. Typically this will be
+ * the same as the requestor itself, but since any
+ * <code>Object</code>, even one outside the hierarchy, may
+ * make a request, this parameter is necessary. Only weak
+ * references to this will be retained, and it will never
+ * be changed, only queried in a read-only manner.
+ * @param requestor the actual requestor of the service. Only
+ * weak references to this will be retained, and it will
+ * never be changed, only queried in a read-only manner.
+ * @param serviceClass the <code>Class</code> of the service being
+ * requested.
+ * @param serviceSelector a parameter to customize the service
+ * returned with.
+ * @param listener a listener that will be notified if the service
+ * being requested is revoked.
+ * @return an instance of <code>serviceClass</code> (such that
+ * <code>instanceof</code> serviceClass is true), or
+ * <code>null</code>.
+ */
+ Object getService (BeanContextChild requestorChild, Object requestor,
+ Class serviceClass, Object serviceSelector,
+ BeanContextServiceRevokedListener listener)
+ throws TooManyListenersException;
+
+ /**
+ * Get a list of all service classes supported.
+ * <P>
+ *
+ * This method must synchronize on
+ * <code>BeanContext.globalHierarchyLock</code>.
+ *
+ * @return a list of all service classes supported.
+ * @see java.beans.beancontext.BeanContext#globalHierarchyLock
+ */
+ Iterator getCurrentServiceClasses ();
+
+ /**
+ * Get a list of valid service selectors for the specified service class.
+ * <P>
+ *
+ * If the specified service class does not have a finite number of
+ * valid service selectors, it should return <code>null</code>.
+ * If it takes a general <code>Integer</code> parameter, for
+ * example, you may as well return <code>null</code> or the poor
+ * soul who called this method will be iterating all day.
+ * <P>
+ *
+ * If it has no valid service selectors, it should still return an empty
+ * <code>Iterator</code>.
+ *
+ * @param serviceClass the service class to get selectors for.
+ * @return a list of valid service selectors for the service
+ * class, or <code>null</code>.
+ */
+ Iterator getCurrentServiceSelectors (Class serviceClass);
+
+ /**
+ * Tell whether the specified service class is available.
+ * Iff getService() could return a non-null value for the
+ * specified service, this method will return <code>true</code>.
+ *
+ * @param serviceClass the service class to check on.
+ * @return whether the specified service class is available.
+ */
+ boolean hasService (Class serviceClass);
+
+ /**
+ * Add a listener on all adds and removes of services.
+ * @param listener the listener to add.
+ */
+ void addBeanContextServicesListener (BeanContextServicesListener listener);
+
+ /**
+ * Remove a listener on all adds and removes of services.
+ * @specnote it is not certain whether this should remove this
+ * listener if it was specified in
+ * <code>getService()</code>.
+ * @param listener the listener to add.
+ */
+ void removeBeanContextServicesListener (BeanContextServicesListener listener);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServicesListener.java b/libjava/classpath/java/beans/beancontext/BeanContextServicesListener.java
new file mode 100644
index 00000000000..becc7cdb6e4
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServicesListener.java
@@ -0,0 +1,56 @@
+/* java.beans.beancontext.BeanContextServicesListener
+ Copyright (C) 1999 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.beans.beancontext;
+
+/**
+ * Listens for service add and revoke events.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServicesListener extends BeanContextServiceRevokedListener {
+ /**
+ * Called by <code>BeanContextServices</code> whenever a service is made available.
+ *
+ * @param event the service revoked event, with useful information
+ * about the new service.
+ */
+ void serviceAvailable(BeanContextServiceAvailableEvent event);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java b/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java
new file mode 100644
index 00000000000..b7c4a49d8a9
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java
@@ -0,0 +1,300 @@
+/* BeanContextServicesSupport.java --
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans.beancontext;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.TooManyListenersException;
+
+/**
+ * @author Michael Koch
+ * @since 1.2
+ */
+public class BeanContextServicesSupport
+ extends BeanContextSupport
+ implements BeanContextServices
+{
+ private static final long serialVersionUID = -8494482757288719206L;
+
+ protected class BCSSChild
+ extends BeanContextSupport.BCSChild
+ {
+ private static final long serialVersionUID = -6848044915271367103L;
+ }
+
+ protected class BCSSProxyServiceProvider
+ implements BeanContextServiceProvider,
+ BeanContextServiceRevokedListener
+ {
+ private static final long serialVersionUID = 7078212910685744490L;
+
+ public Iterator getCurrentServiceSelectors (BeanContextServices bcs,
+ Class serviceClass)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public Object getService (BeanContextServices bcs,
+ Object requestor,
+ Class serviceClass,
+ Object serviceSelector)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void releaseService (BeanContextServices bcs,
+ Object requestor,
+ Object service)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void serviceRevoked (BeanContextServiceRevokedEvent bcsre)
+ {
+ throw new Error ("Not implemented");
+ }
+ }
+
+ protected static class BCSSServiceProvider
+ implements Serializable
+ {
+ private static final long serialVersionUID = 861278251667444782L;
+
+ protected BeanContextServiceProvider serviceProvider;
+
+ protected BeanContextServiceProvider getServiceProvider()
+ {
+ return serviceProvider;
+ }
+ }
+
+ protected transient ArrayList bcsListeners;
+
+ protected transient BCSSProxyServiceProvider proxy;
+
+ protected transient int serializable;
+
+ protected transient HashMap services;
+
+ public BeanContextServicesSupport ()
+ {
+ super();
+ }
+
+ public BeanContextServicesSupport (BeanContextServices peer)
+ {
+ super(peer);
+ }
+
+ public BeanContextServicesSupport(BeanContextServices peer, Locale locale)
+ {
+ super(peer, locale);
+ }
+
+ public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
+ boolean dtime)
+ {
+ super(peer, locale, dtime);
+ }
+
+ public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
+ boolean dtime, boolean visible)
+ {
+ super(peer, locale, dtime, visible);
+ }
+
+ public void addBeanContextServicesListener
+ (BeanContextServicesListener listener)
+ {
+ if (! bcsListeners.contains(listener))
+ bcsListeners.add(listener);
+ }
+
+ public boolean addService (Class serviceClass, BeanContextServiceProvider bcsp)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected boolean addService (Class serviceClass,
+ BeanContextServiceProvider bcsp,
+ boolean fireEvent)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void bcsPreDeserializationHook (ObjectInputStream ois)
+ throws ClassNotFoundException, IOException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void bcsPreSerializationHook (ObjectOutputStream oos)
+ throws IOException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void childJustRemovedHook (Object child,
+ BeanContextSupport.BCSChild bcsc)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected BeanContextSupport.BCSChild createBCSChild (Object targetChild,
+ Object peer)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected BeanContextServicesSupport.BCSSServiceProvider
+ createBCSSServiceProvider (Class sc, BeanContextServiceProvider bcsp)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected final void fireServiceAdded (BeanContextServiceAvailableEvent bcssae)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected final void fireServiceAdded (Class serviceClass)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected final void fireServiceRevoked(BeanContextServiceRevokedEvent event)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected final void fireServiceRevoked (Class serviceClass,
+ boolean revokeNow)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public BeanContextServices getBeanContextServicesPeer ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected static final BeanContextServicesListener
+ getChildBeanContextServicesListener (Object child)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public Iterator getCurrentServiceClasses ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public Iterator getCurrentServiceSelectors (Class serviceClass)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public Object getService (BeanContextChild child, Object requestor,
+ Class serviceClass, Object serviceSelector,
+ BeanContextServiceRevokedListener bcsrl)
+ throws TooManyListenersException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public boolean hasService (Class serviceClass)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void initialize ()
+ {
+ super.initialize();
+
+ bcsListeners = new ArrayList();
+ services = new HashMap();
+ }
+
+ protected void initializeBeanContextResources ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void releaseBeanContextResources ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void releaseService (BeanContextChild child, Object requestor,
+ Object service)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void removeBeanContextServicesListener
+ (BeanContextServicesListener listener)
+ {
+ int index = bcsListeners.indexOf(listener);
+
+ if (index > -1)
+ bcsListeners.remove(index);
+ }
+
+ public void revokeService (Class serviceClass, BeanContextServiceProvider bcsp,
+ boolean revokeCurrentServicesNow)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void serviceAvailable (BeanContextServiceAvailableEvent bcssae)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void serviceRevoked (BeanContextServiceRevokedEvent bcssre)
+ {
+ throw new Error ("Not implemented");
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextSupport.java b/libjava/classpath/java/beans/beancontext/BeanContextSupport.java
new file mode 100644
index 00000000000..7e024e23a13
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextSupport.java
@@ -0,0 +1,460 @@
+/* BeanContextSupport.java --
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.beans.beancontext;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.Visibility;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+
+/**
+ * @author Michael Koch
+ * @since 1.2
+ */
+public class BeanContextSupport extends BeanContextChildSupport
+ implements BeanContext, Serializable, PropertyChangeListener,
+ VetoableChangeListener
+{
+ private static final long serialVersionUID = -4879613978649577204L;
+
+ private void readObject (ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ private void writeObject (ObjectOutputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected class BCSChild implements Serializable
+ {
+ private static final long serialVersionUID = 3289144128843950629L;
+ }
+
+ protected static final class BCSIterator implements Iterator
+ {
+ public boolean hasNext ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public Object next ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void remove ()
+ {
+ // This must be a noop remove operation.
+ }
+ }
+
+ protected transient ArrayList bcmListeners;
+
+ protected transient HashMap children;
+
+ protected transient boolean designTime;
+
+ protected transient Locale locale;
+
+ protected transient boolean okToUseGui;
+
+ /**
+ * Construct a BeanContextSupport instance.
+ */
+ public BeanContextSupport ()
+ {
+ this (null, null, true, true);
+ }
+
+ /**
+ * Construct a BeanContextSupport instance.
+ */
+ public BeanContextSupport (BeanContext peer)
+ {
+ this (peer, null, true, true);
+ }
+
+ /**
+ * Construct a BeanContextSupport instance.
+ */
+ public BeanContextSupport (BeanContext peer, Locale lcle)
+ {
+ this (peer, lcle, true, true);
+ }
+
+ /**
+ * Construct a BeanContextSupport instance.
+ */
+ public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime)
+ {
+ this (peer, lcle, dtime, true);
+ }
+
+ /**
+ * Construct a BeanContextSupport instance.
+ */
+ public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime,
+ boolean visible)
+ {
+ locale = lcle;
+ designTime = dtime;
+ okToUseGui = visible;
+
+ initialize ();
+ }
+
+ public boolean add (Object targetChild)
+ {
+ if (targetChild == null)
+ throw new IllegalArgumentException();
+
+ if (children.containsKey(targetChild))
+ return false;
+
+ // FIXME: The second argument is surely wrong.
+ children.put(targetChild, targetChild);
+ return true;
+ }
+
+ public boolean addAll (Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addBeanContextMembershipListener
+ (BeanContextMembershipListener listener)
+ {
+ if (! bcmListeners.contains(listener))
+ bcmListeners.add(listener);
+ }
+
+ public boolean avoidingGui ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected Iterator bcsChildren ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void bcsPreDeserializationHook (ObjectInputStream ois)
+ throws ClassNotFoundException, IOException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void bcsPreSerializationHook (ObjectOutputStream oos)
+ throws IOException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void childDeserializedHook (Object child, BeanContextSupport.BCSChild bcsc)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void childJustAddedHook (Object child, BeanContextSupport.BCSChild bcsc)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void childJustRemovedHook (Object child, BeanContextSupport.BCSChild bcsc)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected static final boolean classEquals (Class first, Class second)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void clear ()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean contains (Object o)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public boolean containsAll (Collection c)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public boolean containsKey (Object o)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected final Object[] copyChildren ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected BeanContextSupport.BCSChild createBCSChild (Object targetChild, Object peer)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected final void deserialize (ObjectInputStream ois, Collection coll)
+ throws ClassNotFoundException, IOException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void dontUseGui ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected final void fireChildrenAdded (BeanContextMembershipEvent bcme)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected final void fireChildrenRemoved (BeanContextMembershipEvent bcme)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public BeanContext getBeanContextPeer ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected static final BeanContextChild getChildBeanContextChild (Object child)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected static final BeanContextMembershipListener getChildBeanContextMembershipListener (Object child)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected static final PropertyChangeListener getChildPropertyChangeListener (Object child)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected static final Serializable getChildSerializable (Object child)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected static final VetoableChangeListener getChildVetoableChangeListener (Object child)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected static final Visibility getChildVisibility (Object child)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public Locale getLocale ()
+ {
+ return locale;
+ }
+
+ public URL getResource (String name, BeanContextChild bcc)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public InputStream getResourceAsStream (String name, BeanContextChild bcc)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected void initialize ()
+ {
+ bcmListeners = new ArrayList();
+ children = new HashMap();
+ }
+
+ public Object instantiateChild (String beanName)
+ throws IOException, ClassNotFoundException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public boolean isDesignTime ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public boolean isEmpty ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public boolean isSerializing ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public Iterator iterator ()
+ {
+ return children.keySet().iterator();
+ }
+
+ public boolean needsGui ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void okToUseGui ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void propertyChange (PropertyChangeEvent pce)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public final void readChildren (ObjectInputStream ois)
+ throws IOException, ClassNotFoundException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public boolean remove (Object targetChild)
+ {
+ return remove(targetChild, true);
+ }
+
+ protected boolean remove (Object targetChild, boolean callChildSetBC)
+ {
+ if (targetChild == null)
+ throw new IllegalArgumentException();
+
+ throw new Error ("Not implemented");
+ }
+
+ public boolean removeAll (Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeBeanContextMembershipListener (BeanContextMembershipListener bcml)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public boolean retainAll (Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ protected final void serialize (ObjectOutputStream oos, Collection coll)
+ throws IOException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void setDesignTime (boolean dtime)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void setLocale (Locale newLocale)
+ throws PropertyVetoException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public int size ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public Object[] toArray ()
+ {
+ return children.keySet().toArray();
+ }
+
+ public Object[] toArray(Object[] array)
+ {
+ return children.keySet().toArray(array);
+ }
+
+ protected boolean validatePendingAdd (Object targetChild)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ protected boolean validatePendingRemove (Object targetChild)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public void vetoableChange (PropertyChangeEvent pce)
+ throws PropertyVetoException
+ {
+ throw new Error ("Not implemented");
+ }
+
+ public final void writeChildren (ObjectOutputStream oos)
+ throws IOException
+ {
+ throw new Error ("Not implemented");
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/package.html b/libjava/classpath/java/beans/beancontext/package.html
new file mode 100644
index 00000000000..55e3bd723da
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.beans.beancontext package.
+ Copyright (C) 2002 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 - java.beans.beancontext</title></head>
+
+<body>
+<p>Containers and execution environments for beans.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/beans/package.html b/libjava/classpath/java/beans/package.html
new file mode 100644
index 00000000000..5ca8000371b
--- /dev/null
+++ b/libjava/classpath/java/beans/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.beans package.
+ Copyright (C) 2002 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 - java.beans</title></head>
+
+<body>
+<p>Listeners and descriptors for managing beans.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/io/BufferedInputStream.java b/libjava/classpath/java/io/BufferedInputStream.java
new file mode 100644
index 00000000000..6fb024614d2
--- /dev/null
+++ b/libjava/classpath/java/io/BufferedInputStream.java
@@ -0,0 +1,379 @@
+/* BufferedInputStream.java -- An input stream that implements buffering
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This subclass of <code>FilterInputStream</code> buffers input from an
+ * underlying implementation to provide a possibly more efficient read
+ * mechanism. It maintains the buffer and buffer state in instance
+ * variables that are available to subclasses. The default buffer size
+ * of 2048 bytes can be overridden by the creator of the stream.
+ * <p>
+ * This class also implements mark/reset functionality. It is capable
+ * of remembering any number of input bytes, to the limits of
+ * system memory or the size of <code>Integer.MAX_VALUE</code>
+ * <p>
+ * Please note that this class does not properly handle character
+ * encodings. Consider using the <code>BufferedReader</code> class which
+ * does.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ */
+public class BufferedInputStream extends FilterInputStream
+{
+
+ /**
+ * This is the default buffer size
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 2048;
+
+ /**
+ * The buffer used for storing data from the underlying stream.
+ */
+ protected byte[] buf;
+
+ /**
+ * The number of valid bytes currently in the buffer. It is also the index
+ * of the buffer position one byte past the end of the valid data.
+ */
+ protected int count;
+
+ /**
+ * The index of the next character that will by read from the buffer.
+ * When <code>pos == count</code>, the buffer is empty.
+ */
+ protected int pos;
+
+ /**
+ * The value of <code>pos</code> when the <code>mark()</code> method was
+ * called.
+ * This is set to -1 if there is no mark set.
+ */
+ protected int markpos = -1;
+
+ /**
+ * This is the maximum number of bytes than can be read after a
+ * call to <code>mark()</code> before the mark can be discarded.
+ * After this may bytes are read, the <code>reset()</code> method
+ * may not be called successfully.
+ */
+ protected int marklimit;
+
+ /**
+ * This is the initial buffer size. When the buffer is grown because
+ * of marking requirements, it will be grown by bufferSize increments.
+ * The underlying stream will be read in chunks of bufferSize.
+ */
+ private final int bufferSize;
+
+ /**
+ * This method initializes a new <code>BufferedInputStream</code> that will
+ * read from the specified subordinate stream with a default buffer size
+ * of 2048 bytes
+ *
+ * @param in The subordinate stream to read from
+ */
+ public BufferedInputStream(InputStream in)
+ {
+ this(in, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * This method initializes a new <code>BufferedInputStream</code> that will
+ * read from the specified subordinate stream with a buffer size that
+ * is specified by the caller.
+ *
+ * @param in The subordinate stream to read from
+ * @param size The buffer size to use
+ *
+ * @exception IllegalArgumentException when size is smaller then 1
+ */
+ public BufferedInputStream(InputStream in, int size)
+ {
+ super(in);
+ if (size <= 0)
+ throw new IllegalArgumentException();
+ buf = new byte[size];
+ // initialize pos & count to bufferSize, to prevent refill from
+ // allocating a new buffer (if the caller starts out by calling mark()).
+ pos = count = bufferSize = size;
+ }
+
+ /**
+ * This method returns the number of bytes that can be read from this
+ * stream before a read can block. A return of 0 indicates that blocking
+ * might (or might not) occur on the very next read attempt.
+ * <p>
+ * The number of available bytes will be the number of read ahead bytes
+ * stored in the internal buffer plus the number of available bytes in
+ * the underlying stream.
+ *
+ * @return The number of bytes that can be read before blocking could occur
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized int available() throws IOException
+ {
+ return count - pos + super.available();
+ }
+
+ /**
+ * This method closes the underlying input stream and frees any
+ * resources associated with it. Sets <code>buf</code> to <code>null</code>.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public void close() throws IOException
+ {
+ // Free up the array memory.
+ buf = null;
+ pos = count = 0;
+ markpos = -1;
+ super.close();
+ }
+
+ /**
+ * This method marks a position in the input to which the stream can be
+ * "reset" by calling the <code>reset()</code> method. The parameter
+ * <code>readlimit</code> is the number of bytes that can be read from the
+ * stream after setting the mark before the mark becomes invalid. For
+ * example, if <code>mark()</code> is called with a read limit of 10, then
+ * when 11 bytes of data are read from the stream before the
+ * <code>reset()</code> method is called, then the mark is invalid and the
+ * stream object instance is not required to remember the mark.
+ * <p>
+ * Note that the number of bytes that can be remembered by this method
+ * can be greater than the size of the internal read buffer. It is also
+ * not dependent on the subordinate stream supporting mark/reset
+ * functionality.
+ *
+ * @param readlimit The number of bytes that can be read before the mark
+ * becomes invalid
+ */
+ public synchronized void mark(int readlimit)
+ {
+ marklimit = readlimit;
+ markpos = pos;
+ }
+
+ /**
+ * This method returns <code>true</code> to indicate that this class
+ * supports mark/reset functionality.
+ *
+ * @return <code>true</code> to indicate that mark/reset functionality is
+ * supported
+ *
+ */
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ /**
+ * This method reads an unsigned byte from the input stream and returns it
+ * as an int in the range of 0-255. This method also will return -1 if
+ * the end of the stream has been reached.
+ * <p>
+ * This method will block until the byte can be read.
+ *
+ * @return The byte read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized int read() throws IOException
+ {
+ if (pos >= count && !refill())
+ return -1; // EOF
+
+ return buf[pos++] & 0xFF;
+ }
+
+ /**
+ * This method reads bytes from a stream and stores them into a caller
+ * supplied buffer. It starts storing the data at index <code>off</code>
+ * into the buffer and attempts to read <code>len</code> bytes. This method
+ * can return before reading the number of bytes requested, but it will try
+ * to read the requested number of bytes by repeatedly calling the underlying
+ * stream as long as available() for this stream continues to return a
+ * non-zero value (or until the requested number of bytes have been read).
+ * The actual number of bytes read is returned as an int. A -1 is returned
+ * to indicate the end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ *
+ * @param b The array into which the bytes read should be stored
+ * @param off The offset into the array to start storing bytes
+ * @param len The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ * @exception IndexOutOfBoundsException when <code>off</code> or
+ * <code>len</code> are negative, or when <code>off + len</code>
+ * is larger then the size of <code>b</code>,
+ */
+ public synchronized int read(byte[] b, int off, int len) throws IOException
+ {
+ if (off < 0 || len < 0 || b.length - off < len)
+ throw new IndexOutOfBoundsException();
+
+ if (len == 0)
+ return 0;
+
+ if (pos >= count && !refill())
+ return -1; // No bytes were read before EOF.
+
+ int totalBytesRead = Math.min(count - pos, len);
+ System.arraycopy(buf, pos, b, off, totalBytesRead);
+ pos += totalBytesRead;
+ off += totalBytesRead;
+ len -= totalBytesRead;
+
+ while (len > 0 && super.available() > 0 && refill())
+ {
+ int remain = Math.min(count - pos, len);
+ System.arraycopy(buf, pos, b, off, remain);
+ pos += remain;
+ off += remain;
+ len -= remain;
+ totalBytesRead += remain;
+ }
+
+ return totalBytesRead;
+ }
+
+ /**
+ * This method resets a stream to the point where the <code>mark()</code>
+ * method was called. Any bytes that were read after the mark point was
+ * set will be re-read during subsequent reads.
+ * <p>
+ * This method will throw an IOException if the number of bytes read from
+ * the stream since the call to <code>mark()</code> exceeds the mark limit
+ * passed when establishing the mark.
+ *
+ * @exception IOException If <code>mark()</code> was never called or more
+ * then <code>marklimit</code> bytes were read since the last
+ * call to <code>mark()</code>
+ */
+ public synchronized void reset() throws IOException
+ {
+ if (markpos == -1)
+ throw new IOException(buf == null ? "Stream closed." : "Invalid mark.");
+
+ pos = markpos;
+ }
+
+ /**
+ * This method skips the specified number of bytes in the stream. It
+ * returns the actual number of bytes skipped, which may be less than the
+ * requested amount.
+ *
+ * @param n The requested number of bytes to skip
+ *
+ * @return The actual number of bytes skipped.
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized long skip(long n) throws IOException
+ {
+ if (buf == null)
+ throw new IOException("Stream closed.");
+
+ final long origN = n;
+
+ while (n > 0L)
+ {
+ if (pos >= count && !refill())
+ break;
+
+ int numread = (int) Math.min((long) (count - pos), n);
+ pos += numread;
+ n -= numread;
+ }
+
+ return origN - n;
+ }
+
+ /**
+ * Called to refill the buffer (when count is equal to pos).
+ *
+ * @return <code>true</code> when at least one additional byte was read
+ * into <code>buf</code>, <code>false</code> otherwise (at EOF).
+ */
+ private boolean refill() throws IOException
+ {
+ if (buf == null)
+ throw new IOException("Stream closed.");
+
+ if (markpos == -1 || count - markpos >= marklimit)
+ {
+ markpos = -1;
+ pos = count = 0;
+ }
+ else
+ {
+ byte[] newbuf = buf;
+ if (markpos < bufferSize)
+ {
+ newbuf = new byte[count - markpos + bufferSize];
+ }
+ System.arraycopy(buf, markpos, newbuf, 0, count - markpos);
+ buf = newbuf;
+ count -= markpos;
+ pos -= markpos;
+ markpos = 0;
+ }
+
+ int numread = super.read(buf, count, bufferSize);
+
+ if (numread <= 0) // EOF
+ return false;
+
+ count += numread;
+ return true;
+ }
+}
diff --git a/libjava/classpath/java/io/BufferedOutputStream.java b/libjava/classpath/java/io/BufferedOutputStream.java
new file mode 100644
index 00000000000..ce7ebc7e938
--- /dev/null
+++ b/libjava/classpath/java/io/BufferedOutputStream.java
@@ -0,0 +1,192 @@
+/* BufferedOutputStream.java -- Buffer output into large blocks before writing
+ Copyright (C) 1998, 2000, 2003 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.io;
+
+/**
+ * This class accumulates bytes written in a buffer instead of immediately
+ * writing the data to the underlying output sink. The bytes are instead
+ * as one large block when the buffer is filled, or when the stream is
+ * closed or explicitly flushed. This mode operation can provide a more
+ * efficient mechanism for writing versus doing numerous small unbuffered
+ * writes.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class BufferedOutputStream extends FilterOutputStream
+{
+ /**
+ * This is the default buffer size
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 512;
+
+ /**
+ * This is the internal byte array used for buffering output before
+ * writing it.
+ */
+ protected byte[] buf;
+
+ /**
+ * This is the number of bytes that are currently in the buffer and
+ * are waiting to be written to the underlying stream. It always points to
+ * the index into the buffer where the next byte of data will be stored
+ */
+ protected int count;
+
+ /**
+ * This method initializes a new <code>BufferedOutputStream</code> instance
+ * that will write to the specified subordinate <code>OutputStream</code>
+ * and which will use a default buffer size of 512 bytes.
+ *
+ * @param out The underlying <code>OutputStream</code> to write data to
+ */
+ public BufferedOutputStream(OutputStream out)
+ {
+ this(out, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * This method initializes a new <code>BufferedOutputStream</code> instance
+ * that will write to the specified subordinate <code>OutputStream</code>
+ * and which will use the specified buffer size
+ *
+ * @param out The underlying <code>OutputStream</code> to write data to
+ * @param size The size of the internal buffer
+ */
+ public BufferedOutputStream(OutputStream out, int size)
+ {
+ super(out);
+
+ buf = new byte[size];
+ }
+
+ /**
+ * This method causes any currently buffered bytes to be immediately
+ * written to the underlying output stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized void flush() throws IOException
+ {
+ if (count == 0)
+ return;
+
+ out.write(buf, 0, count);
+ count = 0;
+ out.flush();
+ }
+
+ /**
+ * This method flushes any remaining buffered bytes then closes the
+ * underlying output stream. Any further attempts to write to this stream
+ * may throw an exception
+ *
+ public synchronized void close() throws IOException
+ {
+ flush();
+ out.close();
+ }
+ */
+
+ /**
+ * This method runs when the object is garbage collected. It is
+ * responsible for ensuring that all buffered bytes are written and
+ * for closing the underlying stream.
+ *
+ * @exception IOException If an error occurs (ignored by the Java runtime)
+ *
+ protected void finalize() throws IOException
+ {
+ close();
+ }
+ */
+
+ /**
+ * This method writes a single byte of data. This will be written to the
+ * buffer instead of the underlying data source. However, if the buffer
+ * is filled as a result of this write request, it will be flushed to the
+ * underlying output stream.
+ *
+ * @param b The byte of data to be written, passed as an int
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized void write(int b) throws IOException
+ {
+ if (count == buf.length)
+ flush();
+
+ buf[count] = (byte)(b & 0xFF);
+ ++count;
+ }
+
+ /**
+ * This method writes <code>len</code> bytes from the byte array
+ * <code>buf</code> starting at position <code>offset</code> in the buffer.
+ * These bytes will be written to the internal buffer. However, if this
+ * write operation fills the buffer, the buffer will be flushed to the
+ * underlying output stream.
+ *
+ * @param buf The array of bytes to write.
+ * @param offset The index into the byte array to start writing from.
+ * @param len The number of bytes to write.
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized void write(byte[] buf, int offset, int len)
+ throws IOException
+ {
+ // Buffer can hold everything. Note that the case where LEN < 0
+ // is automatically handled by the downstream write.
+ if (len < (this.buf.length - count))
+ {
+ System.arraycopy(buf, offset, this.buf, count, len);
+ count += len;
+ }
+ else
+ {
+ // The write was too big. So flush the buffer and write the new
+ // bytes directly to the underlying stream, per the JDK 1.2
+ // docs.
+ flush();
+ out.write (buf, offset, len);
+ }
+ }
+
+} // class BufferedOutputStream
+
diff --git a/libjava/classpath/java/io/BufferedReader.java b/libjava/classpath/java/io/BufferedReader.java
new file mode 100644
index 00000000000..4849949c989
--- /dev/null
+++ b/libjava/classpath/java/io/BufferedReader.java
@@ -0,0 +1,581 @@
+/* BufferedReader.java
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This subclass of <code>FilterReader</code> buffers input from an
+ * underlying implementation to provide a possibly more efficient read
+ * mechanism. It maintains the buffer and buffer state in instance
+ * variables that are available to subclasses. The default buffer size
+ * of 8192 chars can be overridden by the creator of the stream.
+ * <p>
+ * This class also implements mark/reset functionality. It is capable
+ * of remembering any number of input chars, to the limits of
+ * system memory or the size of <code>Integer.MAX_VALUE</code>
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class BufferedReader extends Reader
+{
+ Reader in;
+ char[] buffer;
+ /* Index of current read position. Must be >= 0 and <= limit. */
+ /* There is a special case where pos may be equal to limit+1; this
+ * is used as an indicator that a readLine was done with a '\r' was
+ * the very last char in the buffer. Since we don't want to read-ahead
+ * and potentially block, we set pos this way to indicate the situation
+ * and deal with it later. Doing it this way rather than having a
+ * separate boolean field to indicate the condition has the advantage
+ * that it is self-clearing on things like mark/reset.
+ */
+ int pos;
+ /* Limit of valid data in buffer. Must be >= pos and <= buffer.length. */
+ /* This can be < pos in the one special case described above. */
+ int limit;
+
+ /* The value -1 means there is no mark, or the mark has been invalidated.
+ Otherwise, markPos is the index in the buffer of the marked position.
+ Must be >= 0 and <= pos.
+ Note we do not explicitly store the read-limit.
+ The implicit read-limit is (buffer.length - markPos), which is
+ guaranteed to be >= the read-limit requested in the call to mark. */
+ int markPos = -1;
+
+ // The JCL book specifies the default buffer size as 8K characters.
+ // This is package-private because it is used by LineNumberReader.
+ static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ /**
+ * The line buffer for <code>readLine</code>.
+ */
+ private StringBuffer sbuf = null;
+
+ /**
+ * Create a new <code>BufferedReader</code> that will read from the
+ * specified subordinate stream with a default buffer size of 8192 chars.
+ *
+ * @param in The subordinate stream to read from
+ */
+ public BufferedReader(Reader in)
+ {
+ this(in, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * Create a new <code>BufferedReader</code> that will read from the
+ * specified subordinate stream with a buffer size that is specified by the
+ * caller.
+ *
+ * @param in The subordinate stream to read from
+ * @param size The buffer size to use
+ *
+ * @exception IllegalArgumentException if size &lt;= 0
+ */
+ public BufferedReader(Reader in, int size)
+ {
+ super(in.lock);
+ if (size <= 0)
+ throw new IllegalArgumentException("Illegal buffer size: " + size);
+ this.in = in;
+ buffer = new char[size];
+ }
+
+ /**
+ * This method closes the underlying stream and frees any associated
+ * resources.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (in != null)
+ in.close();
+ in = null;
+ buffer = null;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> to indicate that this class supports mark/reset
+ * functionality.
+ *
+ * @return <code>true</code>
+ */
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ /**
+ * Mark a position in the input to which the stream can be
+ * "reset" by calling the <code>reset()</code> method. The parameter
+ * <code>readLimit</code> is the number of chars that can be read from the
+ * stream after setting the mark before the mark becomes invalid. For
+ * example, if <code>mark()</code> is called with a read limit of 10, then
+ * when 11 chars of data are read from the stream before the
+ * <code>reset()</code> method is called, then the mark is invalid and the
+ * stream object instance is not required to remember the mark.
+ * <p>
+ * Note that the number of chars that can be remembered by this method
+ * can be greater than the size of the internal read buffer. It is also
+ * not dependent on the subordinate stream supporting mark/reset
+ * functionality.
+ *
+ * @param readLimit The number of chars that can be read before the mark
+ * becomes invalid
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException if readLimit is negative.
+ */
+ public void mark(int readLimit) throws IOException
+ {
+ if (readLimit < 0)
+ throw new IllegalArgumentException("Read-ahead limit is negative");
+
+ synchronized (lock)
+ {
+ checkStatus();
+ // In this method we need to be aware of the special case where
+ // pos + 1 == limit. This indicates that a '\r' was the last char
+ // in the buffer during a readLine. We'll want to maintain that
+ // condition after we shift things around and if a larger buffer is
+ // needed to track readLimit, we'll have to make it one element
+ // larger to ensure we don't invalidate the mark too early, if the
+ // char following the '\r' is NOT a '\n'. This is ok because, per
+ // the spec, we are not required to invalidate when passing readLimit.
+ //
+ // Note that if 'pos > limit', then doing 'limit -= pos' will cause
+ // limit to be negative. This is the only way limit will be < 0.
+
+ if (pos + readLimit > limit)
+ {
+ char[] old_buffer = buffer;
+ int extraBuffSpace = 0;
+ if (pos > limit)
+ extraBuffSpace = 1;
+ if (readLimit + extraBuffSpace > limit)
+ buffer = new char[readLimit + extraBuffSpace];
+ limit -= pos;
+ if (limit >= 0)
+ {
+ System.arraycopy(old_buffer, pos, buffer, 0, limit);
+ pos = 0;
+ }
+ }
+
+ if (limit < 0)
+ {
+ // Maintain the relationship of 'pos > limit'.
+ pos = 1;
+ limit = markPos = 0;
+ }
+ else
+ markPos = pos;
+ // Now pos + readLimit <= buffer.length. thus if we need to read
+ // beyond buffer.length, then we are allowed to invalidate markPos.
+ }
+ }
+
+ /**
+ * Reset the stream to the point where the <code>mark()</code> method
+ * was called. Any chars that were read after the mark point was set will
+ * be re-read during subsequent reads.
+ * <p>
+ * This method will throw an IOException if the number of chars read from
+ * the stream since the call to <code>mark()</code> exceeds the mark limit
+ * passed when establishing the mark.
+ *
+ * @exception IOException If an error occurs;
+ */
+ public void reset() throws IOException
+ {
+ synchronized (lock)
+ {
+ checkStatus();
+ if (markPos < 0)
+ throw new IOException("mark never set or invalidated");
+
+ // Need to handle the extremely unlikely case where a readLine was
+ // done with a '\r' as the last char in the buffer; which was then
+ // immediately followed by a mark and a reset with NO intervening
+ // read of any sort. In that case, setting pos to markPos would
+ // lose that info and a subsequent read would thus not skip a '\n'
+ // (if one exists). The value of limit in this rare case is zero.
+ // We can assume that if limit is zero for other reasons, then
+ // pos is already set to zero and doesn't need to be readjusted.
+ if (limit > 0)
+ pos = markPos;
+ }
+ }
+
+ /**
+ * This method determines whether or not a stream is ready to be read. If
+ * this method returns <code>false</code> then this stream could (but is
+ * not guaranteed to) block on the next read attempt.
+ *
+ * @return <code>true</code> if this stream is ready to be read,
+ * <code>false</code> otherwise
+ *
+ * @exception IOException If an error occurs
+ */
+ public boolean ready() throws IOException
+ {
+ synchronized (lock)
+ {
+ checkStatus();
+ return pos < limit || in.ready();
+ }
+ }
+
+ /**
+ * This method read chars from a stream and stores them into a caller
+ * supplied buffer. It starts storing the data at index
+ * <code>offset</code> into
+ * the buffer and attempts to read <code>len</code> chars. This method can
+ * return before reading the number of chars requested. The actual number
+ * of chars read is returned as an int. A -1 is returned to indicate the
+ * end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ *
+ * @param buf The array into which the chars read should be stored
+ * @param offset The offset into the array to start storing chars
+ * @param count The requested number of chars to read
+ *
+ * @return The actual number of chars read, or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ * @exception IndexOutOfBoundsException If offset and count are not
+ * valid regarding buf.
+ */
+ public int read(char[] buf, int offset, int count) throws IOException
+ {
+ if (offset < 0 || offset + count > buf.length || count < 0)
+ throw new IndexOutOfBoundsException();
+
+ synchronized (lock)
+ {
+ checkStatus();
+ // Once again, we need to handle the special case of a readLine
+ // that has a '\r' at the end of the buffer. In this case, we'll
+ // need to skip a '\n' if it is the next char to be read.
+ // This special case is indicated by 'pos > limit'.
+ boolean retAtEndOfBuffer = false;
+
+ int avail = limit - pos;
+ if (count > avail)
+ {
+ if (avail > 0)
+ count = avail;
+ else // pos >= limit
+ {
+ if (limit == buffer.length)
+ markPos = -1; // read too far - invalidate the mark.
+ if (pos > limit)
+ {
+ // Set a boolean and make pos == limit to simplify things.
+ retAtEndOfBuffer = true;
+ --pos;
+ }
+ if (markPos < 0)
+ {
+ // Optimization: can read directly into buf.
+ if (count >= buffer.length && !retAtEndOfBuffer)
+ return in.read(buf, offset, count);
+ pos = limit = 0;
+ }
+ avail = in.read(buffer, limit, buffer.length - limit);
+ if (retAtEndOfBuffer && avail > 0 && buffer[limit] == '\n')
+ {
+ --avail;
+ limit++;
+ }
+ if (avail < count)
+ {
+ if (avail <= 0)
+ return avail;
+ count = avail;
+ }
+ limit += avail;
+ }
+ }
+ System.arraycopy(buffer, pos, buf, offset, count);
+ pos += count;
+ return count;
+ }
+ }
+
+ /* Read more data into the buffer. Update pos and limit appropriately.
+ Assumes pos==limit initially. May invalidate the mark if read too much.
+ Return number of chars read (never 0), or -1 on eof. */
+ private int fill() throws IOException
+ {
+ checkStatus();
+ // Handle the special case of a readLine that has a '\r' at the end of
+ // the buffer. In this case, we'll need to skip a '\n' if it is the
+ // next char to be read. This special case is indicated by 'pos > limit'.
+ boolean retAtEndOfBuffer = false;
+ if (pos > limit)
+ {
+ retAtEndOfBuffer = true;
+ --pos;
+ }
+
+ if (markPos >= 0 && limit == buffer.length)
+ markPos = -1;
+ if (markPos < 0)
+ pos = limit = 0;
+ int count = in.read(buffer, limit, buffer.length - limit);
+ if (count > 0)
+ limit += count;
+
+ if (retAtEndOfBuffer && buffer[pos] == '\n')
+ {
+ --count;
+ // If the mark was set to the location of the \n, then we
+ // must change it to fully pretend that the \n does not
+ // exist.
+ if (markPos == pos)
+ ++markPos;
+ ++pos;
+ }
+
+ return count;
+ }
+
+ public int read() throws IOException
+ {
+ synchronized (lock)
+ {
+ checkStatus();
+ if (pos >= limit && fill () <= 0)
+ return -1;
+ return buffer[pos++];
+ }
+ }
+
+ /* Return the end of the line starting at this.pos and ending at limit.
+ * The index returns is *before* any line terminators, or limit
+ * if no line terminators were found.
+ */
+ private int lineEnd(int limit)
+ {
+ int i = pos;
+ for (; i < limit; i++)
+ {
+ char ch = buffer[i];
+ if (ch == '\n' || ch == '\r')
+ break;
+ }
+ return i;
+ }
+
+ /**
+ * This method reads a single line of text from the input stream, returning
+ * it as a <code>String</code>. A line is terminated by "\n", a "\r", or
+ * an "\r\n" sequence. The system dependent line separator is not used.
+ * The line termination characters are not returned in the resulting
+ * <code>String</code>.
+ *
+ * @return The line of text read, or <code>null</code> if end of stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public String readLine() throws IOException
+ {
+ checkStatus();
+ // Handle the special case where a previous readLine (with no intervening
+ // reads/skips) had a '\r' at the end of the buffer.
+ // In this case, we'll need to skip a '\n' if it's the next char to be read.
+ // This special case is indicated by 'pos > limit'.
+ if (pos > limit)
+ {
+ int ch = read();
+ if (ch < 0)
+ return null;
+ if (ch != '\n')
+ --pos;
+ }
+ int i = lineEnd(limit);
+ if (i < limit)
+ {
+ String str = String.valueOf(buffer, pos, i - pos);
+ pos = i + 1;
+ // If the last char in the buffer is a '\r', we must remember
+ // to check if the next char to be read after the buffer is refilled
+ // is a '\n'. If so, skip it. To indicate this condition, we set pos
+ // to be limit + 1, which normally is never possible.
+ if (buffer[i] == '\r')
+ if (pos == limit || buffer[pos] == '\n')
+ pos++;
+ return str;
+ }
+ if (sbuf == null)
+ sbuf = new StringBuffer(200);
+ else
+ sbuf.setLength(0);
+ sbuf.append(buffer, pos, i - pos);
+ pos = i;
+ // We only want to return null when no characters were read before
+ // EOF. So we must keep track of this separately. Otherwise we
+ // would treat an empty `sbuf' as an EOF condition, which is wrong
+ // when there is just a newline.
+ boolean eof = false;
+ for (;;)
+ {
+ // readLine should block. So we must not return until a -1 is reached.
+ if (pos >= limit)
+ {
+ // here count == 0 isn't sufficient to give a failure.
+ int count = fill();
+ if (count < 0)
+ {
+ eof = true;
+ break;
+ }
+ continue;
+ }
+ int ch = buffer[pos++];
+ if (ch == '\n' || ch == '\r')
+ {
+ // Check here if a '\r' was the last char in the buffer; if so,
+ // mark it as in the comment above to indicate future reads
+ // should skip a newline that is the next char read after
+ // refilling the buffer.
+ if (ch == '\r')
+ if (pos == limit || buffer[pos] == '\n')
+ pos++;
+ break;
+ }
+ i = lineEnd(limit);
+ sbuf.append(buffer, pos - 1, i - (pos - 1));
+ pos = i;
+ }
+ return (sbuf.length() == 0 && eof) ? null : sbuf.toString();
+ }
+
+ /**
+ * This method skips the specified number of chars in the stream. It
+ * returns the actual number of chars skipped, which may be less than the
+ * requested amount.
+ * <p>
+ * This method first discards chars in the buffer, then calls the
+ * <code>skip</code> method on the underlying stream to skip the
+ * remaining chars.
+ *
+ * @param count The requested number of chars to skip
+ *
+ * @return The actual number of chars skipped.
+ *
+ * @exception IOException If an error occurs.
+ * @exception IllegalArgumentException If count is negative.
+ */
+ public long skip(long count) throws IOException
+ {
+ synchronized (lock)
+ {
+ checkStatus();
+ if (count < 0)
+ throw new IllegalArgumentException("skip value is negative");
+ if (count == 0)
+ return 0;
+ // Yet again, we need to handle the special case of a readLine
+ // that has a '\r' at the end of the buffer. In this case, we need
+ // to ignore a '\n' if it is the next char to be read.
+ // This special case is indicated by 'pos > limit' (i.e. avail < 0).
+ // To simplify things, if we're dealing with the special case for
+ // readLine, just read the next char (since the fill method will
+ // skip the '\n' for us). By doing this, we'll have to back up pos.
+ // That's easier than trying to keep track of whether we've skipped
+ // one element or not.
+ if (pos > limit)
+ {
+ if (read() < 0)
+ return 0;
+ else
+ --pos;
+ }
+
+ int avail = limit - pos;
+
+ if (count < avail)
+ {
+ pos += count;
+ return count;
+ }
+
+ pos = limit;
+ long todo = count - avail;
+ if (todo > buffer.length)
+ {
+ markPos = -1;
+ todo -= in.skip(todo);
+ }
+ else
+ {
+ while (todo > 0)
+ {
+ avail = fill();
+ if (avail <= 0)
+ break;
+ if (avail > todo)
+ avail = (int) todo;
+ pos += avail;
+ todo -= avail;
+ }
+ }
+ return count - todo;
+ }
+ }
+
+ private void checkStatus() throws IOException
+ {
+ if (in == null)
+ throw new IOException("Stream closed");
+ }
+}
diff --git a/libjava/classpath/java/io/BufferedWriter.java b/libjava/classpath/java/io/BufferedWriter.java
new file mode 100644
index 00000000000..185a5344062
--- /dev/null
+++ b/libjava/classpath/java/io/BufferedWriter.java
@@ -0,0 +1,262 @@
+/* BufferedWriter.java -- Buffer output into large blocks before writing
+ Copyright (C) 1998, 1999, 2000, 2001 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.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.1.
+ */
+
+/**
+ * This class accumulates chars written in a buffer instead of immediately
+ * writing the data to the underlying output sink. The chars are instead
+ * as one large block when the buffer is filled, or when the stream is
+ * closed or explicitly flushed. This mode operation can provide a more
+ * efficient mechanism for writing versus doing numerous small unbuffered
+ * writes.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @date September 25, 1998
+ */
+public class BufferedWriter extends Writer
+{
+ /**
+ * This is the default buffer size
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ /**
+ * This is the underlying <code>Writer</code> to which this object
+ * sends its output.
+ */
+ private Writer out;
+
+ /**
+ * This is the internal char array used for buffering output before
+ * writing it.
+ */
+ char[] buffer;
+
+ /**
+ * This is the number of chars that are currently in the buffer and
+ * are waiting to be written to the underlying stream. It always points to
+ * the index into the buffer where the next char of data will be stored
+ */
+ int count;
+
+ /**
+ * This method initializes a new <code>BufferedWriter</code> instance
+ * that will write to the specified subordinate <code>Writer</code>
+ * and which will use a default buffer size of 8192 chars.
+ *
+ * @param out The underlying <code>Writer</code> to write data to
+ */
+ public BufferedWriter (Writer out)
+ {
+ this (out, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * This method initializes a new <code>BufferedWriter</code> instance
+ * that will write to the specified subordinate <code>Writer</code>
+ * and which will use the specified buffer size
+ *
+ * @param out The underlying <code>Writer</code> to write data to
+ * @param size The size of the internal buffer
+ */
+ public BufferedWriter (Writer out, int size)
+ {
+ super(out.lock);
+ this.out = out;
+ this.buffer = new char[size];
+ this.count = 0;
+ }
+
+ /**
+ * This method flushes any remaining buffered chars then closes the
+ * underlying output stream. Any further attempts to write to this stream
+ * may throw an exception
+ *
+ * @exception IOException If an error occurs.
+ */
+ public void close () throws IOException
+ {
+ synchronized (lock)
+ {
+ // It is safe to call localFlush even if the stream is already
+ // closed.
+ localFlush ();
+ out.close();
+ buffer = null;
+ }
+ }
+
+ /**
+ * This method causes any currently buffered chars to be immediately
+ * written to the underlying output stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void flush () throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buffer == null)
+ throw new IOException ("Stream closed");
+ localFlush ();
+ out.flush();
+ }
+ }
+
+ /**
+ * This method writes out a system depedent line separator sequence. The
+ * actual value written is detemined from the <xmp>line.separator</xmp>
+ * system property.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void newLine () throws IOException
+ {
+ write (System.getProperty("line.separator"));
+ }
+
+ /**
+ * This method writes a single char of data. This will be written to the
+ * buffer instead of the underlying data source. However, if the buffer
+ * is filled as a result of this write request, it will be flushed to the
+ * underlying output stream.
+ *
+ * @param oneChar The char of data to be written, passed as an int
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (int oneChar) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buffer == null)
+ throw new IOException ("Stream closed");
+ buffer[count++] = (char) oneChar;
+ if (count == buffer.length)
+ localFlush ();
+ }
+ }
+
+ /**
+ * This method writes <code>len</code> chars from the char array
+ * <code>buf</code> starting at position <code>offset</code> in the buffer.
+ * These chars will be written to the internal buffer. However, if this
+ * write operation fills the buffer, the buffer will be flushed to the
+ * underlying output stream.
+ *
+ * @param buf The array of chars to write.
+ * @param offset The index into the char array to start writing from.
+ * @param len The number of chars to write.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (char[] buf, int offset, int len) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buffer == null)
+ throw new IOException ("Stream closed");
+
+ // Bypass buffering if there is too much incoming data.
+ if (count + len > buffer.length)
+ {
+ localFlush ();
+ out.write(buf, offset, len);
+ }
+ else
+ {
+ System.arraycopy(buf, offset, buffer, count, len);
+ count += len;
+ if (count == buffer.length)
+ localFlush ();
+ }
+ }
+ }
+
+ /**
+ * This method writes <code>len</code> chars from the <code>String</code>
+ * <code>str</code> starting at position <code>offset</code> in the string.
+ * These chars will be written to the internal buffer. However, if this
+ * write operation fills the buffer, the buffer will be flushed to the
+ * underlying output stream.
+ *
+ * @param str The <code>String</code> to write.
+ * @param offset The index into the string to start writing from.
+ * @param len The number of chars to write.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (String str, int offset, int len) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buffer == null)
+ throw new IOException ("Stream closed");
+
+ if (count + len > buffer.length)
+ {
+ localFlush ();
+ out.write(str, offset, len);
+ }
+ else
+ {
+ str.getChars(offset, offset + len, buffer, count);
+ count += len;
+ if (count == buffer.length)
+ localFlush ();
+ }
+ }
+ }
+
+ // This should only be called with the lock held.
+ private void localFlush () throws IOException
+ {
+ if (count > 0)
+ {
+ out.write(buffer, 0, count);
+ count = 0;
+ }
+ }
+}
diff --git a/libjava/classpath/java/io/ByteArrayInputStream.java b/libjava/classpath/java/io/ByteArrayInputStream.java
new file mode 100644
index 00000000000..2bbde95b724
--- /dev/null
+++ b/libjava/classpath/java/io/ByteArrayInputStream.java
@@ -0,0 +1,251 @@
+/* ByteArrayInputStream.java -- Read an array as a stream
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This class permits an array of bytes to be read as an input stream.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class ByteArrayInputStream extends InputStream
+{
+ /**
+ * The array that contains the data supplied during read operations
+ */
+ protected byte[] buf;
+
+ /**
+ * The array index of the next byte to be read from the buffer
+ * <code>buf</code>
+ */
+ protected int pos;
+
+ /**
+ * The currently marked position in the stream. This defaults to 0, so a
+ * reset operation on the stream resets it to read from array index 0 in
+ * the buffer - even if the stream was initially created with an offset
+ * greater than 0
+ */
+ protected int mark;
+
+ /**
+ * This indicates the maximum number of bytes that can be read from this
+ * stream. It is the array index of the position after the last valid
+ * byte in the buffer <code>buf</code>
+ */
+ protected int count;
+
+ /**
+ * Create a new ByteArrayInputStream that will read bytes from the passed
+ * in byte array. This stream will read from the beginning to the end
+ * of the array. It is identical to calling an overloaded constructor
+ * as <code>ByteArrayInputStream(buf, 0, buf.length)</code>.
+ * <p>
+ * Note that this array is not copied. If its contents are changed
+ * while this stream is being read, those changes will be reflected in the
+ * bytes supplied to the reader. Please use caution in changing the
+ * contents of the buffer while this stream is open.
+ *
+ * @param buffer The byte array buffer this stream will read from.
+ */
+ public ByteArrayInputStream(byte[] buffer)
+ {
+ this(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Create a new ByteArrayInputStream that will read bytes from the
+ * passed in byte array. This stream will read from position
+ * <code>offset</code> in the array for a length of
+ * <code>length</code> bytes past <code>offset</code>. If the
+ * stream is reset to a position before <code>offset</code> then
+ * more than <code>length</code> bytes can be read from the stream.
+ * The <code>length</code> value should be viewed as the array index
+ * one greater than the last position in the buffer to read.
+ * <p>
+ * Note that this array is not copied. If its contents are changed
+ * while this stream is being read, those changes will be reflected in the
+ * bytes supplied to the reader. Please use caution in changing the
+ * contents of the buffer while this stream is open.
+ *
+ * @param buffer The byte array buffer this stream will read from.
+ * @param offset The index into the buffer to start reading bytes from
+ * @param length The number of bytes to read from the buffer
+ */
+ public ByteArrayInputStream(byte[] buffer, int offset, int length)
+ {
+ if (offset < 0 || length < 0 || offset > buffer.length)
+ throw new IllegalArgumentException();
+
+ buf = buffer;
+
+ count = offset + length;
+ if (count > buf.length)
+ count = buf.length;
+
+ pos = offset;
+ mark = pos;
+ }
+
+ /**
+ * This method returns the number of bytes available to be read from this
+ * stream. The value returned will be equal to <code>count - pos</code>.
+ *
+ * @return The number of bytes that can be read from this stream
+ * before blocking, which is all of them
+ */
+ public synchronized int available()
+ {
+ return count - pos;
+ }
+
+ /**
+ * This method sets the mark position in this stream to the current
+ * position. Note that the <code>readlimit</code> parameter in this
+ * method does nothing as this stream is always capable of
+ * remembering all the bytes int it.
+ * <p>
+ * Note that in this class the mark position is set by default to
+ * position 0 in the stream. This is in constrast to some other
+ * stream types where there is no default mark position.
+ *
+ * @param readLimit The number of bytes this stream must remember.
+ * This parameter is ignored.
+ */
+ public synchronized void mark(int readLimit)
+ {
+ // readLimit is ignored per Java Class Lib. book, p.220.
+ mark = pos;
+ }
+
+ /**
+ * This method overrides the <code>markSupported</code> method in
+ * <code>InputStream</code> in order to return <code>true</code> -
+ * indicating that this stream class supports mark/reset
+ * functionality.
+ *
+ * @return <code>true</code> to indicate that this class supports
+ * mark/reset.
+ */
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ /**
+ * This method reads one byte from the stream. The <code>pos</code>
+ * counter is advanced to the next byte to be read. The byte read is
+ * returned as an int in the range of 0-255. If the stream position
+ * is already at the end of the buffer, no byte is read and a -1 is
+ * returned in order to indicate the end of the stream.
+ *
+ * @return The byte read, or -1 if end of stream
+ */
+ public synchronized int read()
+ {
+ if (pos < count)
+ return ((int) buf[pos++]) & 0xFF;
+ return -1;
+ }
+
+ /**
+ * This method reads bytes from the stream and stores them into a
+ * caller supplied buffer. It starts storing the data at index
+ * <code>offset</code> into the buffer and attempts to read
+ * <code>len</code> bytes. This method can return before reading
+ * the number of bytes requested if the end of the stream is
+ * encountered first. The actual number of bytes read is returned.
+ * If no bytes can be read because the stream is already at the end
+ * of stream position, a -1 is returned.
+ * <p>
+ * This method does not block.
+ *
+ * @param buffer The array into which the bytes read should be stored.
+ * @param offset The offset into the array to start storing bytes
+ * @param length The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of stream.
+ */
+ public synchronized int read(byte[] buffer, int offset, int length)
+ {
+ if (pos >= count)
+ return -1;
+
+ int numBytes = Math.min(count - pos, length);
+ System.arraycopy(buf, pos, buffer, offset, numBytes);
+ pos += numBytes;
+ return numBytes;
+ }
+
+ /**
+ * This method sets the read position in the stream to the mark
+ * point by setting the <code>pos</code> variable equal to the
+ * <code>mark</code> variable. Since a mark can be set anywhere in
+ * the array, the mark/reset methods int this class can be used to
+ * provide random search capabilities for this type of stream.
+ */
+ public synchronized void reset()
+ {
+ pos = mark;
+ }
+
+ /**
+ * This method attempts to skip the requested number of bytes in the
+ * input stream. It does this by advancing the <code>pos</code>
+ * value by the specified number of bytes. It this would exceed the
+ * length of the buffer, then only enough bytes are skipped to
+ * position the stream at the end of the buffer. The actual number
+ * of bytes skipped is returned.
+ *
+ * @param num The requested number of bytes to skip
+ *
+ * @return The actual number of bytes skipped.
+ */
+ public synchronized long skip(long num)
+ {
+ // Even though the var numBytes is a long, in reality it can never
+ // be larger than an int since the result of subtracting 2 positive
+ // ints will always fit in an int. Since we have to return a long
+ // anyway, numBytes might as well just be a long.
+ long numBytes = Math.min((long) (count - pos), num < 0 ? 0L : num);
+ pos += numBytes;
+ return numBytes;
+ }
+}
diff --git a/libjava/classpath/java/io/ByteArrayOutputStream.java b/libjava/classpath/java/io/ByteArrayOutputStream.java
new file mode 100644
index 00000000000..e996ebbc70f
--- /dev/null
+++ b/libjava/classpath/java/io/ByteArrayOutputStream.java
@@ -0,0 +1,283 @@
+/* BufferedReader.java
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.1.
+ */
+
+/**
+ * This class allows data to be written to a byte array buffer and
+ * and then retrieved by an application. The internal byte array
+ * buffer is dynamically resized to hold all the data written. Please
+ * be aware that writing large amounts to data to this stream will
+ * cause large amounts of memory to be allocated.
+ * <p>
+ * The size of the internal buffer defaults to 32 and it is resized
+ * by doubling the size of the buffer. This default size can be
+ * overridden by using the
+ * <code>gnu.java.io.ByteArrayOutputStream.initialBufferSize</code>
+ * property.
+ * <p>
+ * There is a constructor that specified the initial buffer size and
+ * that is the preferred way to set that value because it it portable
+ * across all Java class library implementations.
+ * <p>
+ * Note that this class also has methods that convert the byte array
+ * buffer to a <code>String</code> using either the system default or an
+ * application specified character encoding. Thus it can handle
+ * multibyte character encodings.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @date September 24, 1998
+ */
+public class ByteArrayOutputStream extends OutputStream
+{
+ /**
+ * This method initializes a new <code>ByteArrayOutputStream</code>
+ * with the default buffer size of 32 bytes. If a different initial
+ * buffer size is desired, see the constructor
+ * <code>ByteArrayOutputStream(int size)</code>. For applications
+ * where the source code is not available, the default buffer size
+ * can be set using the system property
+ * <code>gnu.java.io.ByteArrayOutputStream.initialBufferSize</code>
+ */
+ public ByteArrayOutputStream ()
+ {
+ this (initial_buffer_size);
+ }
+
+ /**
+ * This method initializes a new <code>ByteArrayOutputStream</code> with
+ * a specified initial buffer size.
+ *
+ * @param size The initial buffer size in bytes
+ */
+ public ByteArrayOutputStream (int size)
+ {
+ buf = new byte[size];
+ count = 0;
+ }
+
+ /**
+ * This method discards all of the bytes that have been written to
+ * the internal buffer so far by setting the <code>count</code>
+ * variable to 0. The internal buffer remains at its currently
+ * allocated size.
+ */
+ public synchronized void reset ()
+ {
+ count = 0;
+ }
+
+ /**
+ * This method returns the number of bytes that have been written to
+ * the buffer so far. This is the same as the value of the protected
+ * <code>count</code> variable. If the <code>reset</code> method is
+ * called, then this value is reset as well. Note that this method does
+ * not return the length of the internal buffer, but only the number
+ * of bytes that have been written to it.
+ *
+ * @return The number of bytes in the internal buffer
+ *
+ * @see #reset()
+ */
+ public int size ()
+ {
+ return count;
+ }
+
+ /**
+ * This method returns a byte array containing the bytes that have been
+ * written to this stream so far. This array is a copy of the valid
+ * bytes in the internal buffer and its length is equal to the number of
+ * valid bytes, not necessarily to the the length of the current
+ * internal buffer. Note that since this method allocates a new array,
+ * it should be used with caution when the internal buffer is very large.
+ */
+ public synchronized byte[] toByteArray ()
+ {
+ byte[] ret = new byte[count];
+ System.arraycopy(buf, 0, ret, 0, count);
+ return ret;
+ }
+
+ /**
+ * Returns the bytes in the internal array as a <code>String</code>. The
+ * bytes in the buffer are converted to characters using the system default
+ * encoding. There is an overloaded <code>toString()</code> method that
+ * allows an application specified character encoding to be used.
+ *
+ * @return A <code>String</code> containing the data written to this
+ * stream so far
+ */
+ public String toString ()
+ {
+ return new String (buf, 0, count);
+ }
+
+ /**
+ * Returns the bytes in the internal array as a <code>String</code>. The
+ * bytes in the buffer are converted to characters using the specified
+ * encoding.
+ *
+ * @param enc The name of the character encoding to use
+ *
+ * @return A <code>String</code> containing the data written to this
+ * stream so far
+ *
+ * @exception UnsupportedEncodingException If the named encoding is
+ * not available
+ */
+ public String toString (String enc) throws UnsupportedEncodingException
+ {
+ return new String (buf, 0, count, enc);
+ }
+
+ /**
+ * This method returns the bytes in the internal array as a
+ * <code>String</code>. It uses each byte in the array as the low
+ * order eight bits of the Unicode character value and the passed in
+ * parameter as the high eight bits.
+ * <p>
+ * This method does not convert bytes to characters in the proper way and
+ * so is deprecated in favor of the other overloaded <code>toString</code>
+ * methods which use a true character encoding.
+ *
+ * @param hibyte The high eight bits to use for each character in
+ * the <code>String</code>
+ *
+ * @return A <code>String</code> containing the data written to this
+ * stream so far
+ *
+ * @deprecated
+ */
+ public String toString (int hibyte)
+ {
+ return new String (buf, 0, count, hibyte);
+ }
+
+ // Resize buffer to accommodate new bytes.
+ private void resize (int add)
+ {
+ if (count + add > buf.length)
+ {
+ int newlen = buf.length * 2;
+ if (count + add > newlen)
+ newlen = count + add;
+ byte[] newbuf = new byte[newlen];
+ System.arraycopy(buf, 0, newbuf, 0, count);
+ buf = newbuf;
+ }
+ }
+
+ /**
+ * This method writes the writes the specified byte into the internal
+ * buffer.
+ *
+ * @param oneByte The byte to be read passed as an int
+ */
+ public synchronized void write (int oneByte)
+ {
+ resize (1);
+ buf[count++] = (byte) oneByte;
+ }
+
+ /**
+ * This method writes <code>len</code> bytes from the passed in array
+ * <code>buf</code> starting at index <code>offset</code> into the
+ * internal buffer.
+ *
+ * @param buffer The byte array to write data from
+ * @param offset The index into the buffer to start writing data from
+ * @param add The number of bytes to write
+ */
+ public synchronized void write (byte[] buffer, int offset, int add)
+ {
+ // If ADD < 0 then arraycopy will throw the appropriate error for
+ // us.
+ if (add >= 0)
+ resize (add);
+ System.arraycopy(buffer, offset, buf, count, add);
+ count += add;
+ }
+
+ /**
+ * This method writes all the bytes that have been written to this stream
+ * from the internal buffer to the specified <code>OutputStream</code>.
+ *
+ * @param out The <code>OutputStream</code> to write to
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized void writeTo (OutputStream out) throws IOException
+ {
+ out.write(buf, 0, count);
+ }
+
+ /**
+ * The internal buffer where the data written is stored
+ */
+ protected byte[] buf;
+
+ /**
+ * The number of bytes that have been written to the buffer
+ */
+ protected int count;
+
+ /**
+ * The default initial buffer size. Specified by the JCL.
+ */
+ private static final int DEFAULT_INITIAL_BUFFER_SIZE = 32;
+
+ // The default buffer size which can be overridden by the user.
+ private static final int initial_buffer_size;
+
+ static
+ {
+ int r
+ = Integer.getInteger ("gnu.java.io.ByteArrayOutputStream.initialBufferSize",
+ DEFAULT_INITIAL_BUFFER_SIZE).intValue ();
+ if (r <= 0)
+ r = DEFAULT_INITIAL_BUFFER_SIZE;
+ initial_buffer_size = r;
+ }
+}
diff --git a/libjava/classpath/java/io/CharArrayReader.java b/libjava/classpath/java/io/CharArrayReader.java
new file mode 100644
index 00000000000..c14fa077592
--- /dev/null
+++ b/libjava/classpath/java/io/CharArrayReader.java
@@ -0,0 +1,305 @@
+/* CharArrayReader.java -- Read an array of characters as a stream
+ Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This class permits an array of chars to be read as an input stream.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class CharArrayReader extends Reader
+{
+ /**
+ * The array that contains the data supplied during read operations
+ */
+ protected char[] buf;
+
+ /**
+ * The array index of the next char to be read from the buffer
+ * <code>buf</code>
+ */
+ protected int pos;
+
+ /**
+ * The currently marked position in the stream. This defaults to 0, so a
+ * reset operation on the stream resets it to read from array index 0 in
+ * the buffer - even if the stream was initially created with an offset
+ * greater than 0
+ */
+ protected int markedPos;
+
+ /**
+ * This indicates the maximum number of chars that can be read from this
+ * stream. It is the array index of the position after the last valid
+ * char in the buffer <code>buf</code>
+ */
+ protected int count;
+
+ /**
+ * Create a new CharArrayReader that will read chars from the passed
+ * in char array. This stream will read from the beginning to the end
+ * of the array. It is identical to calling an overloaded constructor
+ * as <code>CharArrayReader(buf, 0, buf.length)</code>.
+ * <p>
+ * Note that this array is not copied. If its contents are changed
+ * while this stream is being read, those changes will be reflected in the
+ * chars supplied to the reader. Please use caution in changing the
+ * contents of the buffer while this stream is open.
+ *
+ * @param buffer The char array buffer this stream will read from.
+ */
+ public CharArrayReader(char[] buffer)
+ {
+ this(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Create a new CharArrayReader that will read chars from the passed
+ * in char array. This stream will read from position
+ * <code>offset</code> in the array for a length of
+ * <code>length</code> chars past <code>offset</code>. If the
+ * stream is reset to a position before <code>offset</code> then
+ * more than <code>length</code> chars can be read from the stream.
+ * The <code>length</code> value should be viewed as the array index
+ * one greater than the last position in the buffer to read.
+ * <p>
+ * Note that this array is not copied. If its contents are changed
+ * while this stream is being read, those changes will be reflected in the
+ * chars supplied to the reader. Please use caution in changing the
+ * contents of the buffer while this stream is open.
+ *
+ * @param buffer The char array buffer this stream will read from.
+ * @param offset The index into the buffer to start reading chars from
+ * @param length The number of chars to read from the buffer
+ */
+ public CharArrayReader(char[] buffer, int offset, int length)
+ {
+ super();
+ if (offset < 0 || length < 0 || offset > buffer.length)
+ throw new IllegalArgumentException();
+
+ buf = buffer;
+
+ count = offset + length;
+ if (count > buf.length)
+ count = buf.length;
+
+ pos = offset;
+ markedPos = pos;
+ }
+
+ /**
+ * This method closes the stream.
+ */
+ public void close()
+ {
+ synchronized (lock)
+ {
+ buf = null;
+ }
+ }
+
+ /**
+ * This method sets the mark position in this stream to the current
+ * position. Note that the <code>readlimit</code> parameter in this
+ * method does nothing as this stream is always capable of
+ * remembering all the chars int it.
+ * <p>
+ * Note that in this class the mark position is set by default to
+ * position 0 in the stream. This is in constrast to some other
+ * stream types where there is no default mark position.
+ *
+ * @param readAheadLimit The number of chars this stream must
+ * remember. This parameter is ignored.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void mark(int readAheadLimit) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+ // readAheadLimit is ignored per Java Class Lib. book, p. 318.
+ markedPos = pos;
+ }
+ }
+
+ /**
+ * This method overrides the <code>markSupported</code> method in
+ * <code>Reader</code> in order to return <code>true</code> -
+ * indicating that this stream class supports mark/reset
+ * functionality.
+ *
+ * @return <code>true</code> to indicate that this class supports
+ * mark/reset.
+ */
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ /**
+ * This method reads one char from the stream. The <code>pos</code>
+ * counter is advanced to the next char to be read. The char read
+ * is returned as an int in the range of 0-65535. If the stream
+ * position is already at the end of the buffer, no char is read and
+ * a -1 is returned in order to indicate the end of the stream.
+ *
+ * @return The char read, or -1 if end of stream
+ */
+ public int read() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ if (pos < 0)
+ throw new ArrayIndexOutOfBoundsException(pos);
+
+ if (pos < count)
+ return ((int) buf[pos++]) & 0xFFFF;
+ return -1;
+ }
+ }
+
+ /**
+ * This method reads chars from the stream and stores them into a
+ * caller supplied buffer. It starts storing the data at index
+ * <code>offset</code> into the buffer and attempts to read
+ * <code>len</code> chars. This method can return before reading
+ * the number of chars requested if the end of the stream is
+ * encountered first. The actual number of chars read is returned.
+ * If no chars can be read because the stream is already at the end
+ * of stream position, a -1 is returned.
+ * <p>
+ * This method does not block.
+ *
+ * @param b The array into which the chars read should be stored.
+ * @param off The offset into the array to start storing chars
+ * @param len The requested number of chars to read
+ *
+ * @return The actual number of chars read, or -1 if end of stream.
+ */
+ public int read(char[] b, int off, int len) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ /* Don't need to check pos value, arraycopy will check it. */
+ if (off < 0 || len < 0 || off + len > b.length)
+ throw new IndexOutOfBoundsException();
+
+ if (pos >= count)
+ return -1;
+
+ int numChars = Math.min(count - pos, len);
+ System.arraycopy(buf, pos, b, off, numChars);
+ pos += numChars;
+ return numChars;
+ }
+ }
+
+ /**
+ * Return true if more characters are available to be read.
+ *
+ * @return <code>true</code> to indicate that this stream is ready
+ * to be read.
+ *
+ * @specnote The JDK 1.3 API docs are wrong here. This method will
+ * return false if there are no more characters available.
+ */
+ public boolean ready() throws IOException
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ return (pos < count);
+ }
+
+ /**
+ * This method sets the read position in the stream to the mark
+ * point by setting the <code>pos</code> variable equal to the
+ * <code>mark</code> variable. Since a mark can be set anywhere in
+ * the array, the mark/reset methods int this class can be used to
+ * provide random search capabilities for this type of stream.
+ */
+ public void reset() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ pos = markedPos;
+ }
+ }
+
+ /**
+ * This method attempts to skip the requested number of chars in the
+ * input stream. It does this by advancing the <code>pos</code> value by the
+ * specified number of chars. It this would exceed the length of the
+ * buffer, then only enough chars are skipped to position the stream at
+ * the end of the buffer. The actual number of chars skipped is returned.
+ *
+ * @param n The requested number of chars to skip
+ *
+ * @return The actual number of chars skipped.
+ */
+ public long skip(long n) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ // Even though the var numChars is a long, in reality it can never
+ // be larger than an int since the result of subtracting 2 positive
+ // ints will always fit in an int. Since we have to return a long
+ // anyway, numChars might as well just be a long.
+ long numChars = Math.min((long) (count - pos), n < 0 ? 0L : n);
+ pos += numChars;
+ return numChars;
+ }
+ }
+}
diff --git a/libjava/classpath/java/io/CharArrayWriter.java b/libjava/classpath/java/io/CharArrayWriter.java
new file mode 100644
index 00000000000..f9b338fe0cc
--- /dev/null
+++ b/libjava/classpath/java/io/CharArrayWriter.java
@@ -0,0 +1,274 @@
+/* CharArrayWriter.java -- Write chars to a buffer
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This class allows data to be written to a char array buffer and
+ * and then retrieved by an application. The internal char array
+ * buffer is dynamically resized to hold all the data written. Please
+ * be aware that writing large amounts to data to this stream will
+ * cause large amounts of memory to be allocated.
+ * <p>
+ * The size of the internal buffer defaults to 32 and it is resized
+ * in increments of 1024 chars. This behavior can be over-ridden by using the
+ * following two properties:
+ * <p>
+ * <ul>
+ * <li><xmp>gnu.java.io.CharArrayWriter.initialBufferSize</xmp></li>
+ * <li><xmp>gnu.java.io.CharArrayWriter.bufferIncrementSize</xmp></li>
+ * </ul>
+ * <p>
+ * There is a constructor that specified the initial buffer size and
+ * that is the preferred way to set that value because it it portable
+ * across all Java class library implementations.
+ * <p>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class CharArrayWriter extends Writer
+{
+ /**
+ * The default initial buffer size
+ */
+ private static final int DEFAULT_INITIAL_BUFFER_SIZE = 32;
+
+ /**
+ * This method initializes a new <code>CharArrayWriter</code> with
+ * the default buffer size of 32 chars. If a different initial
+ * buffer size is desired, see the constructor
+ * <code>CharArrayWriter(int size)</code>.
+ */
+ public CharArrayWriter ()
+ {
+ this (DEFAULT_INITIAL_BUFFER_SIZE);
+ }
+
+ /**
+ * This method initializes a new <code>CharArrayWriter</code> with
+ * a specified initial buffer size.
+ *
+ * @param size The initial buffer size in chars
+ */
+ public CharArrayWriter (int size)
+ {
+ super ();
+ buf = new char[size];
+ }
+
+ /**
+ * Closes the stream. This method is guaranteed not to free the contents
+ * of the internal buffer, which can still be retrieved.
+ */
+ public void close ()
+ {
+ }
+
+ /**
+ * This method flushes all buffered chars to the stream.
+ */
+ public void flush ()
+ {
+ }
+
+ /**
+ * This method discards all of the chars that have been written to the
+ * internal buffer so far by setting the <code>count</code> variable to
+ * 0. The internal buffer remains at its currently allocated size.
+ */
+ public void reset ()
+ {
+ synchronized (lock)
+ {
+ count = 0;
+ }
+ }
+
+ /**
+ * This method returns the number of chars that have been written to
+ * the buffer so far. This is the same as the value of the protected
+ * <code>count</code> variable. If the <code>reset</code> method is
+ * called, then this value is reset as well. Note that this method does
+ * not return the length of the internal buffer, but only the number
+ * of chars that have been written to it.
+ *
+ * @return The number of chars in the internal buffer
+ *
+ * @see #reset()
+ */
+ public int size ()
+ {
+ return count;
+ }
+
+ /**
+ * This method returns a char array containing the chars that have been
+ * written to this stream so far. This array is a copy of the valid
+ * chars in the internal buffer and its length is equal to the number of
+ * valid chars, not necessarily to the the length of the current
+ * internal buffer. Note that since this method allocates a new array,
+ * it should be used with caution when the internal buffer is very large.
+ */
+ public char[] toCharArray ()
+ {
+ synchronized (lock)
+ {
+ char[] nc = new char[count];
+ System.arraycopy(buf, 0, nc, 0, count);
+ return nc;
+ }
+ }
+
+ /**
+ * Returns the chars in the internal array as a <code>String</code>. The
+ * chars in the buffer are converted to characters using the system default
+ * encoding. There is an overloaded <code>toString()</code> method that
+ * allows an application specified character encoding to be used.
+ *
+ * @return A <code>String</code> containing the data written to this
+ * stream so far
+ */
+ public String toString ()
+ {
+ synchronized (lock)
+ {
+ return new String (buf, 0, count);
+ }
+ }
+
+ /**
+ * This method writes the writes the specified char into the internal
+ * buffer.
+ *
+ * @param oneChar The char to be read passed as an int
+ */
+ public void write (int oneChar)
+ {
+ synchronized (lock)
+ {
+ resize (1);
+ buf[count++] = (char) oneChar;
+ }
+ }
+
+ /**
+ * This method writes <code>len</code> chars from the passed in array
+ * <code>buf</code> starting at index <code>offset</code> into that buffer
+ *
+ * @param buffer The char array to write data from
+ * @param offset The index into the buffer to start writing data from
+ * @param len The number of chars to write
+ */
+ public void write (char[] buffer, int offset, int len)
+ {
+ synchronized (lock)
+ {
+ if (len >= 0)
+ resize (len);
+ System.arraycopy(buffer, offset, buf, count, len);
+ count += len;
+ }
+ }
+
+ /**
+ * This method writes <code>len</code> chars from the passed in
+ * <code>String</code> <code>buf</code> starting at index
+ * <code>offset</code> into the internal buffer.
+ *
+ * @param str The <code>String</code> to write data from
+ * @param offset The index into the string to start writing data from
+ * @param len The number of chars to write
+ */
+ public void write (String str, int offset, int len)
+ {
+ synchronized (lock)
+ {
+ if (len >= 0)
+ resize (len);
+ str.getChars(offset, offset + len, buf, count);
+ count += len;
+ }
+ }
+
+ /**
+ * This method writes all the chars that have been written to this stream
+ * from the internal buffer to the specified <code>Writer</code>.
+ *
+ * @param out The <code>Writer</code> to write to
+ *
+ * @exception IOException If an error occurs
+ */
+ public void writeTo (Writer out) throws IOException
+ {
+ synchronized (lock)
+ {
+ out.write(buf, 0, count);
+ }
+ }
+
+ /**
+ * This private method makes the buffer bigger when we run out of room
+ * by allocating a larger buffer and copying the valid chars from the
+ * old array into it. This is obviously slow and should be avoided by
+ * application programmers by setting their initial buffer size big
+ * enough to hold everything if possible.
+ */
+ private void resize (int len)
+ {
+ if (count + len >= buf.length)
+ {
+ int newlen = buf.length * 2;
+ if (count + len > newlen)
+ newlen = count + len;
+ char[] newbuf = new char[newlen];
+ System.arraycopy(buf, 0, newbuf, 0, count);
+ buf = newbuf;
+ }
+ }
+
+ /**
+ * The internal buffer where the data written is stored
+ */
+ protected char[] buf;
+
+ /**
+ * The number of chars that have been written to the buffer
+ */
+ protected int count;
+}
diff --git a/libjava/classpath/java/io/CharConversionException.java b/libjava/classpath/java/io/CharConversionException.java
new file mode 100644
index 00000000000..a7a608429ef
--- /dev/null
+++ b/libjava/classpath/java/io/CharConversionException.java
@@ -0,0 +1,73 @@
+/* CharConversionException.java -- Character conversion exceptions
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown to indicate that a problem occurred with
+ * an attempted character conversion.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class CharConversionException extends IOException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -8680016352018427031L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ public CharConversionException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public CharConversionException(String message)
+ {
+ super(message);
+ }
+} // class CharConversionException
diff --git a/libjava/classpath/java/io/Closeable.java b/libjava/classpath/java/io/Closeable.java
new file mode 100644
index 00000000000..b8523d79e63
--- /dev/null
+++ b/libjava/classpath/java/io/Closeable.java
@@ -0,0 +1,63 @@
+/* Closeable.java -- Closeable object
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.io;
+
+/**
+ * A <code>Closeable</code> class represents a stream of
+ * data, which can be closed when it is no longer needed.
+ * Closing a stream allows the resources it uses to be
+ * freed for an alternate use.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface Closeable
+{
+
+ /**
+ * Closes the stream represented by this class, thus freeing
+ * system resources. In that case that the stream is already
+ * in the closed state, this method has no effect.
+ *
+ * @throws IOException if an I/O error occurs in closing.
+ */
+ void close()
+ throws IOException;
+
+}
diff --git a/libjava/classpath/java/io/DataInput.java b/libjava/classpath/java/io/DataInput.java
new file mode 100644
index 00000000000..45cb0c13025
--- /dev/null
+++ b/libjava/classpath/java/io/DataInput.java
@@ -0,0 +1,456 @@
+/* DataInput.java -- Interface for reading data from a stream
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct. */
+
+/**
+ * This interface is implemented by classes that can data from streams
+ * into Java primitive types.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public interface DataInput
+{
+
+ /**
+ * This method reads a Java boolean value from an input stream. It does
+ * so by reading a single byte of data. If that byte is zero, then the
+ * value returned is <code>false</code>. If the byte is non-zero, then
+ * the value returned is <code>true</code>.
+ * <p>
+ * This method can read a <code>boolean</code> written by an object
+ * implementing the <code>writeBoolean()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>boolean</code> value read
+ *
+ * @exception EOFException If end of file is reached before
+ * reading the boolean
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeBoolean
+ */
+ boolean readBoolean() throws EOFException, IOException;
+
+ /**
+ * This method reads a Java byte value from an input stream. The value
+ * is in the range of -128 to 127.
+ * <p>
+ * This method can read a <code>byte</code> written by an object
+ * implementing the
+ * <code>writeByte()</code> method in the <code>DataOutput</code> interface.
+ * <p>
+ * @return The <code>byte</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the byte
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeByte
+ */
+ byte readByte() throws EOFException, IOException;
+
+ /**
+ * This method reads 8 unsigned bits into a Java <code>int</code> value from
+ * the stream. The value returned is in the range of 0 to 255.
+ * <p>
+ * This method can read an unsigned byte written by an object
+ * implementing the
+ * <code>writeByte()</code> method in the <code>DataOutput</code>
+ * interface.
+ *
+ * @return The unsigned bytes value read as a Java <code>int</code>.
+ *
+ * @exception EOFException If end of file is reached before reading the value
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeByte
+ */
+ int readUnsignedByte() throws EOFException, IOException;
+
+ /**
+ * This method reads a Java <code>char</code> value from an input stream.
+ * It operates by reading two bytes from the stream and converting them to
+ * a single 16-bit Java <code>char</code>. The two bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code> represent the
+ * first and second byte read from the stream respectively, they will be
+ * transformed to a <code>char</code> in the following manner:
+ * <p>
+ * <code>(char)((byte1 << 8) + byte2)</code>
+ * <p>
+ * This method can read a <code>char</code> written by an object implementing
+ * the
+ * <code>writeChar()</code> method in the <code>DataOutput</code> interface.
+ *
+ * @return The <code>char</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the char
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeChar
+ */
+ char readChar() throws EOFException, IOException;
+
+ /**
+ * This method reads a signed 16-bit value into a Java in from the stream.
+ * It operates by reading two bytes from the stream and converting them to
+ * a single 16-bit Java <code>short</code>. The two bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code> represent the
+ * first and second byte read from the stream respectively, they will be
+ * transformed to a <code>short</code> in the following manner:
+ * <p>
+ * <code>(short)(((byte1 & 0xFF) << 8) + (byte2 & 0xFF))</code>
+ * <p>
+ * The value returned is in the range of -32768 to 32767.
+ * <p>
+ * This method can read a <code>short</code> written by an object
+ * implementing
+ * the <code>writeShort()</code> method in the <code>DataOutput</code>
+ * interface.
+ *
+ * @return The <code>short</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the value
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeShort
+ */
+ short readShort() throws EOFException, IOException;
+
+ /**
+ * This method reads 16 unsigned bits into a Java int value from the stream.
+ * It operates by reading two bytes from the stream and converting them to
+ * a single Java <code>int</code>. The two bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code> represent the
+ * first and second byte read from the stream respectively, they will be
+ * transformed to an <code>int</code> in the following manner:
+ * <p>
+ * <code>(int)(((byte1 0xFF) << 8) + (byte2 & 0xFF))</code>
+ * <p>
+ * The value returned is in the range of 0 to 65535.
+ * <p>
+ * This method can read an unsigned short written by an object implementing
+ * the <code>writeShort()</code> method in the
+ * <code>DataOutput</code>
+ * interface.
+ *
+ * @return The unsigned short value read as a Java <code>int</code>.
+ *
+ * @exception EOFException If end of file is reached before reading
+ * the value
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeShort
+ */
+ int readUnsignedShort() throws EOFException, IOException;
+
+ /**
+ * This method reads a Java <code>int</code> value from an input stream
+ * It operates by reading four bytes from the stream and converting them to
+ * a single Java <code>int</code>. The bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> through <code>byte4</code> represent
+ * the first four bytes read from the stream, they will be
+ * transformed to an <code>int</code> in the following manner:
+ * <p>
+ * <code>(int)(((byte1 & 0xFF) << 24) + ((byte2 & 0xFF) << 16) +
+ * ((byte3 & 0xFF)<< 8) + (byte4 & 0xFF)))</code>
+ * <p>
+ * The value returned is in the range of -2147483648 to 2147483647.
+ * <p>
+ * This method can read an <code>int</code> written by an object
+ * implementing the <code>writeInt()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>int</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the int
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeInt
+ */
+ int readInt() throws EOFException, IOException;
+
+ /**
+ * This method reads a Java <code>long</code> value from an input stream
+ * It operates by reading eight bytes from the stream and converting them to
+ * a single Java <code>long</code>. The bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> through <code>byte8</code> represent
+ * the first eight bytes read from the stream, they will be
+ * transformed to an <code>long</code> in the following manner:
+ * <p>
+ * <code>(long)(((byte1 & 0xFF) << 56) + ((byte2 & 0xFF) << 48) +
+ * ((byte3 & 0xFF) << 40) + ((byte4 & 0xFF) << 32) +
+ * ((byte5 & 0xFF) << 24) + ((byte6 & 0xFF) << 16) +
+ * ((byte7 & 0xFF) << 8) + (byte8 & 0xFF)))
+ * </code>
+ * <p>
+ * The value returned is in the range of -9223372036854775808 to
+ * 9223372036854775807.
+ * <p>
+ * This method can read an <code>long</code> written by an object
+ * implementing the <code>writeLong()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>long</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the long
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeLong
+ */
+ long readLong() throws EOFException, IOException;
+
+ /**
+ * This method reads a Java float value from an input stream. It operates
+ * by first reading an <code>int</code> value from the stream by calling the
+ * <code>readInt()</code> method in this interface, then converts that
+ * <code>int</code> to a <code>float</code> using the
+ * <code>intBitsToFloat</code> method in the class
+ * <code>java.lang.Float</code>.
+ * <p>
+ * This method can read a <code>float</code> written by an object
+ * implementing
+ * the <code>writeFloat()</code> method in the <code>DataOutput</code>
+ * interface.
+ *
+ * @return The <code>float</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the
+ * float
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeFloat
+ * @see java.lang.Float#intBitsToFloat
+ */
+ float readFloat() throws EOFException, IOException;
+
+ /**
+ * This method reads a Java double value from an input stream. It operates
+ * by first reading a <code>long</code> value from the stream by calling the
+ * <code>readLong()</code> method in this interface, then converts that
+ * <code>long</code> to a <code>double</code> using the
+ * <code>longBitsToDouble</code> method in the class
+ * <code>java.lang.Double</code>.
+ * <p>
+ * This method can read a <code>double</code> written by an object
+ * implementing the <code>writeDouble()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>double</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the
+ * double
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeDouble
+ * @see java.lang.Double#longBitsToDouble
+ */
+ double readDouble() throws EOFException, IOException;
+
+ /**
+ * This method reads the next line of text data from an input stream.
+ * It operates by reading bytes and converting those bytes to
+ * <code>char</code>
+ * values by treating the byte read as the low eight bits of the
+ * <code>char</code> and using 0 as the high eight bits. Because of this,
+ * it does not support the full 16-bit Unicode character set.
+ * <P>
+ * The reading of bytes ends when either the end of file or a line terminator
+ * is encountered. The bytes read are then returned as a
+ * <code>String</code>.
+ * A line terminator is a byte sequence consisting of either
+ * <code>\r</code>, <code>\n</code> or <code>\r\n</code>. These termination
+ * charaters are discarded and are not returned as part of the string.
+ * A line is also terminated by an end of file condition.
+ * <p>
+ *
+ * @return The line read as a <code>String</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ String readLine() throws IOException;
+
+ /**
+ * This method reads a <code>String</code> from an input stream that is
+ * encoded in a modified UTF-8 format. This format has a leading two byte
+ * sequence that contains the remaining number of bytes to read.
+ * This two byte
+ * sequence is read using the <code>readUnsignedShort()</code> method of this
+ * interface.
+ *
+ * After the number of remaining bytes have been determined, these bytes
+ * are read an transformed into <code>char</code> values. These
+ * <code>char</code> values are encoded in the stream using either a one,
+ * two, or three byte format.
+ * The particular format in use can be determined by examining the first
+ * byte read.
+ * <p>
+ * If the first byte has a high order bit of 0, then
+ * that character consists on only one byte. This character value consists
+ * of seven bits that are at positions 0 through 6 of the byte. As an
+ * example, if <code>byte1</code> is the byte read from the stream, it would
+ * be converted to a <code>char</code> like so:
+ * <p>
+ * <code>(char)byte1</code>
+ * <p>
+ * If the first byte has 110 as its high order bits, then the
+ * character consists of two bytes. The bits that make up the character
+ * value are in positions 0 through 4 of the first byte and bit positions
+ * 0 through 5 of the second byte. (The second byte should have
+ * 10 as its high order bits). These values are in most significant
+ * byte first (i.e., "big endian") order.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code> are the first
+ * two bytes read respectively, and the high order bits of them match the
+ * patterns which indicate a two byte character encoding, then they would be
+ * converted to a Java <code>char</code> like so:
+ * <p>
+ * <code>(char)(((byte1 &amp; 0x1F) &lt;&lt; 6) + (byte2 &amp; 0x3F))</code>
+ * <p>
+ * If the first byte has a 1110 as its high order bits, then the
+ * character consists of three bytes. The bits that make up the character
+ * value are in positions 0 through 3 of the first byte and bit positions
+ * 0 through 5 of the other two bytes. (The second and third bytes should
+ * have 10 as their high order bits). These values are in most
+ * significant byte first (i.e., "big endian") order.
+ * <p>
+ * As an example, if <code>byte1</code>, <code>byte2</code>, and
+ * <code>byte3</code> are the three bytes read, and the high order bits of
+ * them match the patterns which indicate a three byte character encoding,
+ * then they would be converted to a Java <code>char</code> like so:
+ *
+ * <code>
+ * (char)(((byte1 &amp; 0x0F) &lt;&lt; 12) + ((byte2 &amp; 0x3F) + (byte3 &amp; 0x3F))
+ * </code>
+ *
+ * Note that all characters are encoded in the method that requires the
+ * fewest number of bytes with the exception of the character with the
+ * value of <code>\&lt;llll&gt;u0000</code> which is encoded as two bytes.
+ * This is a modification of the UTF standard used to prevent C language
+ * style <code>NUL</code> values from appearing in the byte stream.
+ * <p>
+ * This method can read data that was written by an object implementing the
+ * <code>writeUTF()</code> method in <code>DataOutput</code>.
+ *
+ * @return The <code>String</code> read
+ *
+ * @exception EOFException If end of file is reached before reading the
+ * String
+ * @exception UTFDataFormatException If the data is not in UTF-8 format
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeUTF
+ */
+ String readUTF() throws EOFException, UTFDataFormatException, IOException;
+
+ /**
+ * This method reads raw bytes into the passed array until the array is
+ * full. Note that this method blocks until the data is available and
+ * throws an exception if there is not enough data left in the stream to
+ * fill the buffer. Note also that zero length buffers are permitted.
+ * In this case, the method will return immediately without reading any
+ * bytes from the stream.
+ *
+ * @param buf The buffer into which to read the data
+ *
+ * @exception EOFException If end of file is reached before filling the
+ * buffer
+ * @exception IOException If any other error occurs
+ */
+ void readFully(byte[] buf) throws EOFException, IOException;
+
+ /**
+ * This method reads raw bytes into the passed array <code>buf</code>
+ * starting
+ * <code>offset</code> bytes into the buffer. The number of bytes read
+ * will be
+ * exactly <code>len</code>. Note that this method blocks until the data is
+ * available and throws an exception if there is not enough data left in
+ * the stream to read <code>len</code> bytes. Note also that zero length
+ * buffers are permitted. In this case, the method will return immediately
+ * without reading any bytes from the stream.
+ *
+ * @param buf The buffer into which to read the data
+ * @param offset The offset into the buffer to start storing data
+ * @param len The number of bytes to read into the buffer
+ *
+ * @exception EOFException If end of file is reached before filling the
+ * buffer
+ * @exception IOException If any other error occurs
+ */
+ void readFully(byte[] buf, int offset, int len)
+ throws EOFException, IOException;
+
+ /**
+ * This method skips and discards the specified number of bytes in an
+ * input stream. Note that this method may skip less than the requested
+ * number of bytes. The actual number of bytes skipped is returned.
+ * No bytes are skipped if a negative number is passed to this method.
+ *
+ * @param numBytes The number of bytes to skip
+ *
+ * @return The number of bytes actually skipped, which will always be
+ * <code>numBytes</code>
+ *
+ * @exception EOFException If end of file is reached before all bytes can be
+ * skipped
+ * @exception IOException If any other error occurs
+ */
+ int skipBytes(int numBytes) throws EOFException, IOException;
+
+} // interface DataInput
diff --git a/libjava/classpath/java/io/DataInputStream.java b/libjava/classpath/java/io/DataInputStream.java
new file mode 100644
index 00000000000..d2604b51ffa
--- /dev/null
+++ b/libjava/classpath/java/io/DataInputStream.java
@@ -0,0 +1,739 @@
+/* DataInputStream.java -- FilteredInputStream that implements DataInput
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This subclass of <code>FilteredInputStream</code> implements the
+ * <code>DataInput</code> interface that provides method for reading primitive
+ * Java data types from a stream.
+ *
+ * @see DataInput
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @date October 20, 1998.
+ */
+public class DataInputStream extends FilterInputStream implements DataInput
+{
+ // Byte buffer, used to make primitive read calls more efficient.
+ byte[] buf = new byte [8];
+
+ /**
+ * This constructor initializes a new <code>DataInputStream</code>
+ * to read from the specified subordinate stream.
+ *
+ * @param in The subordinate <code>InputStream</code> to read from
+ */
+ public DataInputStream (InputStream in)
+ {
+ super (in);
+ }
+
+ /**
+ * This method reads bytes from the underlying stream into the specified
+ * byte array buffer. It will attempt to fill the buffer completely, but
+ * may return a short count if there is insufficient data remaining to be
+ * read to fill the buffer.
+ *
+ * @param b The buffer into which bytes will be read.
+ *
+ * @return The actual number of bytes read, or -1 if end of stream reached
+ * before reading any bytes.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public final int read (byte[] b) throws IOException
+ {
+ return in.read (b, 0, b.length);
+ }
+
+ /**
+ * This method reads bytes from the underlying stream into the specified
+ * byte array buffer. It will attempt to read <code>len</code> bytes and
+ * will start storing them at position <code>off</code> into the buffer.
+ * This method can return a short count if there is insufficient data
+ * remaining to be read to complete the desired read length.
+ *
+ * @param b The buffer into which bytes will be read.
+ * @param off The offset into the buffer to start storing bytes.
+ * @param len The requested number of bytes to read.
+ *
+ * @return The actual number of bytes read, or -1 if end of stream reached
+ * before reading any bytes.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public final int read (byte[] b, int off, int len) throws IOException
+ {
+ return in.read (b, off, len);
+ }
+
+ /**
+ * This method reads a Java boolean value from an input stream. It does
+ * so by reading a single byte of data. If that byte is zero, then the
+ * value returned is <code>false</code>. If the byte is non-zero, then
+ * the value returned is <code>true</code>.
+ * <p>
+ * This method can read a <code>boolean</code> written by an object
+ * implementing the <code>writeBoolean()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>boolean</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading
+ * the boolean
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeBoolean
+ */
+ public final boolean readBoolean () throws IOException
+ {
+ return convertToBoolean (in.read ());
+ }
+
+ /**
+ * This method reads a Java byte value from an input stream. The value
+ * is in the range of -128 to 127.
+ * <p>
+ * This method can read a <code>byte</code> written by an object
+ * implementing the <code>writeByte()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>byte</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the byte
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeByte
+ */
+ public final byte readByte () throws IOException
+ {
+ return convertToByte (in.read ());
+ }
+
+ /**
+ * This method reads a Java <code>char</code> value from an input stream.
+ * It operates by reading two bytes from the stream and converting them to
+ * a single 16-bit Java <code>char</code>. The two bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code>
+ * represent the first and second byte read from the stream
+ * respectively, they will be transformed to a <code>char</code> in
+ * the following manner:
+ * <p>
+ * <code>(char)(((byte1 &amp; 0xFF) &lt;&lt; 8) | (byte2 &amp; 0xFF)</code>
+ * <p>
+ * This method can read a <code>char</code> written by an object
+ * implementing the <code>writeChar()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>char</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the char
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeChar
+ */
+ public final char readChar () throws IOException
+ {
+ readFully (buf, 0, 2);
+ return convertToChar (buf);
+ }
+
+ /**
+ * This method reads a Java double value from an input stream. It operates
+ * by first reading a <code>long</code> value from the stream by calling the
+ * <code>readLong()</code> method in this interface, then converts
+ * that <code>long</code> to a <code>double</code> using the
+ * <code>longBitsToDouble</code> method in the class
+ * <code>java.lang.Double</code>
+ * <p>
+ * This method can read a <code>double</code> written by an object
+ * implementing the <code>writeDouble()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>double</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading
+ * the double
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeDouble
+ * @see java.lang.Double#longBitsToDouble
+ */
+ public final double readDouble () throws IOException
+ {
+ return Double.longBitsToDouble (readLong ());
+ }
+
+ /**
+ * This method reads a Java float value from an input stream. It
+ * operates by first reading an <code>int</code> value from the
+ * stream by calling the <code>readInt()</code> method in this
+ * interface, then converts that <code>int</code> to a
+ * <code>float</code> using the <code>intBitsToFloat</code> method
+ * in the class <code>java.lang.Float</code>
+ * <p>
+ * This method can read a <code>float</code> written by an object
+ * implementing the <code>writeFloat()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>float</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the float
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeFloat
+ * @see java.lang.Float#intBitsToFloat
+ */
+ public final float readFloat () throws IOException
+ {
+ return Float.intBitsToFloat (readInt ());
+ }
+
+ /**
+ * This method reads raw bytes into the passed array until the array is
+ * full. Note that this method blocks until the data is available and
+ * throws an exception if there is not enough data left in the stream to
+ * fill the buffer. Note also that zero length buffers are permitted.
+ * In this case, the method will return immediately without reading any
+ * bytes from the stream.
+ *
+ * @param b The buffer into which to read the data
+ *
+ * @exception EOFException If end of file is reached before filling the
+ * buffer
+ * @exception IOException If any other error occurs
+ */
+ public final void readFully (byte[] b) throws IOException
+ {
+ readFully (b, 0, b.length);
+ }
+
+ /**
+ * This method reads raw bytes into the passed array <code>buf</code>
+ * starting
+ * <code>offset</code> bytes into the buffer. The number of bytes read
+ * will be
+ * exactly <code>len</code>. Note that this method blocks until the data is
+ * available and throws an exception if there is not enough data left in
+ * the stream to read <code>len</code> bytes. Note also that zero length
+ * buffers are permitted. In this case, the method will return immediately
+ * without reading any bytes from the stream.
+ *
+ * @param buf The buffer into which to read the data
+ * @param offset The offset into the buffer to start storing data
+ * @param len The number of bytes to read into the buffer
+ *
+ * @exception EOFException If end of file is reached before filling the
+ * buffer
+ * @exception IOException If any other error occurs
+ */
+ public final void readFully (byte[] buf, int offset, int len) throws IOException
+ {
+ if (len < 0)
+ throw new IndexOutOfBoundsException("Negative length: " + len);
+
+ while (len > 0)
+ {
+ // in.read will block until some data is available.
+ int numread = in.read (buf, offset, len);
+ if (numread < 0)
+ throw new EOFException ();
+ len -= numread;
+ offset += numread;
+ }
+ }
+
+ /**
+ * This method reads a Java <code>int</code> value from an input stream
+ * It operates by reading four bytes from the stream and converting them to
+ * a single Java <code>int</code>. The bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> through <code>byte4</code> represent
+ * the first four bytes read from the stream, they will be
+ * transformed to an <code>int</code> in the following manner:
+ * <p>
+ * <code>(int)(((byte1 &amp; 0xFF) &lt;&lt; 24) + ((byte2 &amp; 0xFF) &lt;&lt; 16) +
+ * ((byte3 &amp; 0xFF)&lt;&lt; 8) + (byte4 &amp; 0xFF)))</code>
+ * <p>
+ * The value returned is in the range of -2147483648 to 2147483647.
+ * <p>
+ * This method can read an <code>int</code> written by an object
+ * implementing the <code>writeInt()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>int</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the int
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeInt
+ */
+ public final int readInt () throws IOException
+ {
+ readFully (buf, 0, 4);
+ return convertToInt (buf);
+ }
+
+ /**
+ * This method reads the next line of text data from an input
+ * stream. It operates by reading bytes and converting those bytes
+ * to <code>char</code> values by treating the byte read as the low
+ * eight bits of the <code>char</code> and using 0 as the high eight
+ * bits. Because of this, it does not support the full 16-bit
+ * Unicode character set.
+ * <p>
+ * The reading of bytes ends when either the end of file or a line
+ * terminator is encountered. The bytes read are then returned as a
+ * <code>String</code> A line terminator is a byte sequence
+ * consisting of either <code>\r</code>, <code>\n</code> or
+ * <code>\r\n</code>. These termination charaters are discarded and
+ * are not returned as part of the string.
+ * <p>
+ * This method can read data that was written by an object implementing the
+ * <code>writeLine()</code> method in <code>DataOutput</code>.
+ *
+ * @return The line read as a <code>String</code>
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataOutput
+ *
+ * @deprecated
+ */
+ public final String readLine() throws IOException
+ {
+ StringBuffer strb = new StringBuffer();
+
+ while (true)
+ {
+ int c = in.read();
+ if (c == -1) // got an EOF
+ return strb.length() > 0 ? strb.toString() : null;
+ if (c == '\r')
+ {
+ int next_c = in.read();
+ if (next_c != '\n' && next_c != -1)
+ {
+ if (!(in instanceof PushbackInputStream))
+ in = new PushbackInputStream(in);
+ ((PushbackInputStream) in).unread(next_c);
+ }
+ break;
+ }
+ if (c == '\n')
+ break;
+ strb.append((char) c);
+ }
+
+ return strb.length() > 0 ? strb.toString() : "";
+ }
+
+ /**
+ * This method reads a Java <code>long</code> value from an input stream
+ * It operates by reading eight bytes from the stream and converting them to
+ * a single Java <code>long</code>. The bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> through <code>byte8</code> represent
+ * the first eight bytes read from the stream, they will be
+ * transformed to an <code>long</code> in the following manner:
+ * <p>
+ * <code>(long)(((byte1 &amp; 0xFF) &lt;&lt; 56) + ((byte2 &amp; 0xFF) &lt;&lt; 48) +
+ * ((byte3 &amp; 0xFF) &lt;&lt; 40) + ((byte4 &amp; 0xFF) &lt;&lt; 32) +
+ * ((byte5 &amp; 0xFF) &lt;&lt; 24) + ((byte6 &amp; 0xFF) &lt;&lt; 16) +
+ * ((byte7 &amp; 0xFF) &lt;&lt; 8) + (byte8 &amp; 0xFF)))
+ * </code>
+ * <p>
+ * The value returned is in the range of -9223372036854775808 to
+ * 9223372036854775807.
+ * <p>
+ * This method can read an <code>long</code> written by an object
+ * implementing the <code>writeLong()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>long</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the long
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeLong
+ */
+ public final long readLong () throws IOException
+ {
+ readFully (buf, 0, 8);
+ return convertToLong (buf);
+ }
+
+ /**
+ * This method reads a signed 16-bit value into a Java in from the
+ * stream. It operates by reading two bytes from the stream and
+ * converting them to a single 16-bit Java <code>short</code>. The
+ * two bytes are stored most significant byte first (i.e., "big
+ * endian") regardless of the native host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code>
+ * represent the first and second byte read from the stream
+ * respectively, they will be transformed to a <code>short</code>. in
+ * the following manner:
+ * <p>
+ * <code>(short)(((byte1 &amp; 0xFF) &lt;&lt; 8) | (byte2 &amp; 0xFF))</code>
+ * <p>
+ * The value returned is in the range of -32768 to 32767.
+ * <p>
+ * This method can read a <code>short</code> written by an object
+ * implementing the <code>writeShort()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The <code>short</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the value
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeShort
+ */
+ public final short readShort () throws IOException
+ {
+ readFully (buf, 0, 2);
+ return convertToShort (buf);
+ }
+
+ /**
+ * This method reads 8 unsigned bits into a Java <code>int</code>
+ * value from the stream. The value returned is in the range of 0 to
+ * 255.
+ * <p>
+ * This method can read an unsigned byte written by an object
+ * implementing the <code>writeUnsignedByte()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The unsigned bytes value read as a Java <code>int</code>.
+ *
+ * @exception EOFException If end of file is reached before reading the value
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeByte
+ */
+ public final int readUnsignedByte () throws IOException
+ {
+ return convertToUnsignedByte (in.read ());
+ }
+
+ /**
+ * This method reads 16 unsigned bits into a Java int value from the stream.
+ * It operates by reading two bytes from the stream and converting them to
+ * a single Java <code>int</code> The two bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code>
+ * represent the first and second byte read from the stream
+ * respectively, they will be transformed to an <code>int</code> in
+ * the following manner:
+ * <p>
+ * <code>(int)(((byte1 &amp; 0xFF) &lt;&lt; 8) + (byte2 &amp; 0xFF))</code>
+ * <p>
+ * The value returned is in the range of 0 to 65535.
+ * <p>
+ * This method can read an unsigned short written by an object
+ * implementing the <code>writeUnsignedShort()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The unsigned short value read as a Java <code>int</code>
+ *
+ * @exception EOFException If end of file is reached before reading the value
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeShort
+ */
+ public final int readUnsignedShort () throws IOException
+ {
+ readFully (buf, 0, 2);
+ return convertToUnsignedShort (buf);
+ }
+
+ /**
+ * This method reads a <code>String</code> from an input stream that
+ * is encoded in a modified UTF-8 format. This format has a leading
+ * two byte sequence that contains the remaining number of bytes to
+ * read. This two byte sequence is read using the
+ * <code>readUnsignedShort()</code> method of this interface.
+ * <p>
+ * After the number of remaining bytes have been determined, these
+ * bytes are read an transformed into <code>char</code> values.
+ * These <code>char</code> values are encoded in the stream using
+ * either a one, two, or three byte format. The particular format
+ * in use can be determined by examining the first byte read.
+ * <p>
+ * If the first byte has a high order bit of 0, then that character
+ * consists on only one byte. This character value consists of
+ * seven bits that are at positions 0 through 6 of the byte. As an
+ * example, if <code>byte1</code> is the byte read from the stream,
+ * it would be converted to a <code>char</code> like so:
+ * <p>
+ * <code>(char)byte1</code>
+ * <p>
+ * If the first byte has 110 as its high order bits, then the
+ * character consists of two bytes. The bits that make up the character
+ * value are in positions 0 through 4 of the first byte and bit positions
+ * 0 through 5 of the second byte. (The second byte should have
+ * 10 as its high order bits). These values are in most significant
+ * byte first (i.e., "big endian") order.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code> are
+ * the first two bytes read respectively, and the high order bits of
+ * them match the patterns which indicate a two byte character
+ * encoding, then they would be converted to a Java
+ * <code>char</code> like so:
+ * <p>
+ * <code>(char)(((byte1 & 0x1F) << 6) | (byte2 & 0x3F))</code>
+ * <p>
+ * If the first byte has a 1110 as its high order bits, then the
+ * character consists of three bytes. The bits that make up the character
+ * value are in positions 0 through 3 of the first byte and bit positions
+ * 0 through 5 of the other two bytes. (The second and third bytes should
+ * have 10 as their high order bits). These values are in most
+ * significant byte first (i.e., "big endian") order.
+ * <p>
+ * As an example, if <code>byte1</code> <code>byte2</code> and
+ * <code>byte3</code> are the three bytes read, and the high order
+ * bits of them match the patterns which indicate a three byte
+ * character encoding, then they would be converted to a Java
+ * <code>char</code> like so:
+ * <p>
+ * <code>(char)(((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) |
+ * (byte3 & 0x3F))</code>
+ * <p>
+ * Note that all characters are encoded in the method that requires
+ * the fewest number of bytes with the exception of the character
+ * with the value of <code>&#92;u0000</code> which is encoded as two
+ * bytes. This is a modification of the UTF standard used to
+ * prevent C language style <code>NUL</code> values from appearing
+ * in the byte stream.
+ * <p>
+ * This method can read data that was written by an object implementing the
+ * <code>writeUTF()</code> method in <code>DataOutput</code>
+ *
+ * @return The <code>String</code> read
+ *
+ * @exception EOFException If end of file is reached before reading
+ * the String
+ * @exception UTFDataFormatException If the data is not in UTF-8 format
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput#writeUTF
+ */
+ public final String readUTF () throws IOException
+ {
+ return readUTF (this);
+ }
+
+ /**
+ * This method reads a String encoded in UTF-8 format from the
+ * specified <code>DataInput</code> source.
+ *
+ * @param in The <code>DataInput</code> source to read from
+ *
+ * @return The String read from the source
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readUTF
+ */
+ public static final String readUTF(DataInput in) throws IOException
+ {
+ final int UTFlen = in.readUnsignedShort ();
+ byte[] buf = new byte [UTFlen];
+
+ // This blocks until the entire string is available rather than
+ // doing partial processing on the bytes that are available and then
+ // blocking. An advantage of the latter is that Exceptions
+ // could be thrown earlier. The former is a bit cleaner.
+ in.readFully (buf, 0, UTFlen);
+
+ return convertFromUTF (buf);
+ }
+
+ /**
+ * This method attempts to skip and discard the specified number of bytes
+ * in the input stream. It may actually skip fewer bytes than requested.
+ * This method will not skip any bytes if passed a negative number of bytes
+ * to skip.
+ *
+ * @param n The requested number of bytes to skip.
+ *
+ * @return The requested number of bytes to skip.
+ *
+ * @exception IOException If an error occurs.
+ * @specnote The JDK docs claim that this returns the number of bytes
+ * actually skipped. The JCL claims that this method can throw an
+ * EOFException. Neither of these appear to be true in the JDK 1.3's
+ * implementation. This tries to implement the actual JDK behaviour.
+ */
+ public final int skipBytes (int n) throws IOException
+ {
+ if (n <= 0)
+ return 0;
+ try
+ {
+ return (int) in.skip (n);
+ }
+ catch (EOFException x)
+ {
+ // do nothing.
+ }
+ return n;
+ }
+
+ static boolean convertToBoolean (int b) throws EOFException
+ {
+ if (b < 0)
+ throw new EOFException ();
+
+ return (b != 0);
+ }
+
+ static byte convertToByte (int i) throws EOFException
+ {
+ if (i < 0)
+ throw new EOFException ();
+
+ return (byte) i;
+ }
+
+ static int convertToUnsignedByte (int i) throws EOFException
+ {
+ if (i < 0)
+ throw new EOFException ();
+
+ return (i & 0xFF);
+ }
+
+ static char convertToChar (byte[] buf)
+ {
+ return (char) ((buf [0] << 8)
+ | (buf [1] & 0xff));
+ }
+
+ static short convertToShort (byte[] buf)
+ {
+ return (short) ((buf [0] << 8)
+ | (buf [1] & 0xff));
+ }
+
+ static int convertToUnsignedShort (byte[] buf)
+ {
+ return (((buf [0] & 0xff) << 8)
+ | (buf [1] & 0xff));
+ }
+
+ static int convertToInt (byte[] buf)
+ {
+ return (((buf [0] & 0xff) << 24)
+ | ((buf [1] & 0xff) << 16)
+ | ((buf [2] & 0xff) << 8)
+ | (buf [3] & 0xff));
+ }
+
+ static long convertToLong (byte[] buf)
+ {
+ return (((long)(buf [0] & 0xff) << 56) |
+ ((long)(buf [1] & 0xff) << 48) |
+ ((long)(buf [2] & 0xff) << 40) |
+ ((long)(buf [3] & 0xff) << 32) |
+ ((long)(buf [4] & 0xff) << 24) |
+ ((long)(buf [5] & 0xff) << 16) |
+ ((long)(buf [6] & 0xff) << 8) |
+ ((long)(buf [7] & 0xff)));
+ }
+
+ // FIXME: This method should be re-thought. I suspect we have multiple
+ // UTF-8 decoders floating around. We should use the standard charset
+ // converters, maybe and adding a direct call into one of the new
+ // NIO converters for a super-fast UTF8 decode.
+ static String convertFromUTF (byte[] buf)
+ throws EOFException, UTFDataFormatException
+ {
+ // Give StringBuffer an initial estimated size to avoid
+ // enlarge buffer frequently
+ StringBuffer strbuf = new StringBuffer (buf.length / 2 + 2);
+
+ for (int i = 0; i < buf.length; )
+ {
+ if ((buf [i] & 0x80) == 0) // bit pattern 0xxxxxxx
+ strbuf.append ((char) (buf [i++] & 0xFF));
+ else if ((buf [i] & 0xE0) == 0xC0) // bit pattern 110xxxxx
+ {
+ if (i + 1 >= buf.length
+ || (buf [i + 1] & 0xC0) != 0x80)
+ throw new UTFDataFormatException ();
+
+ strbuf.append((char) (((buf [i++] & 0x1F) << 6)
+ | (buf [i++] & 0x3F)));
+ }
+ else if ((buf [i] & 0xF0) == 0xE0) // bit pattern 1110xxxx
+ {
+ if (i + 2 >= buf.length
+ || (buf [i + 1] & 0xC0) != 0x80
+ || (buf [i + 2] & 0xC0) != 0x80)
+ throw new UTFDataFormatException ();
+
+ strbuf.append ((char) (((buf [i++] & 0x0F) << 12)
+ | ((buf [i++] & 0x3F) << 6)
+ | (buf [i++] & 0x3F)));
+ }
+ else // must be ((buf [i] & 0xF0) == 0xF0 || (buf [i] & 0xC0) == 0x80)
+ throw new UTFDataFormatException (); // bit patterns 1111xxxx or
+ // 10xxxxxx
+ }
+
+ return strbuf.toString ();
+ }
+}
diff --git a/libjava/classpath/java/io/DataOutput.java b/libjava/classpath/java/io/DataOutput.java
new file mode 100644
index 00000000000..0d436233218
--- /dev/null
+++ b/libjava/classpath/java/io/DataOutput.java
@@ -0,0 +1,326 @@
+/* DataOutput.java -- Interface for writing data from a stream
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.1.
+ */
+
+/**
+ * This interface is implemented by classes that can wrte data to streams
+ * from Java primitive types. This data can subsequently be read back
+ * by classes implementing the <code>DataInput</code> interface.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ *
+ * @see DataInput
+ */
+public interface DataOutput
+{
+ /**
+ * This method writes a Java boolean value to an output stream. If
+ * <code>value</code> is <code>true</code>, a byte with the value of
+ * 1 will be written, otherwise a byte with the value of 0 will be
+ * written.
+ *
+ * The value written can be read using the <code>readBoolean</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The boolean value to write
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readBoolean
+ */
+ void writeBoolean(boolean value) throws IOException;
+
+ /**
+ * This method writes a Java byte value to an output stream. The
+ * byte to be written will be in the lowest 8 bits of the
+ * <code>int</code> value passed.
+ *
+ * The value written can be read using the <code>readByte</code> or
+ * <code>readUnsignedByte</code> methods in <code>DataInput</code>.
+ *
+ * @param value The int value to write
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readByte
+ * @see DataInput#readUnsignedByte
+ */
+ void writeByte(int value) throws IOException;
+
+ /**
+ * This method writes a Java char value to an output stream. The
+ * char to be written will be in the lowest 16 bits of the <code>int</code>
+ * value passed. These bytes will be written "big endian". That is,
+ * with the high byte written first in the following manner:
+ * <p>
+ * <code>byte0 = (byte)((value & 0xFF00) >> 8);<br>
+ * byte1 = (byte)(value & 0x00FF);</code>
+ * <p>
+ *
+ * The value written can be read using the <code>readChar</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The char value to write
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readChar
+ */
+ void writeChar(int value) throws IOException;
+
+ /**
+ * This method writes a Java short value to an output stream. The
+ * char to be written will be in the lowest 16 bits of the <code>int</code>
+ * value passed. These bytes will be written "big endian". That is,
+ * with the high byte written first in the following manner:
+ * <p>
+ * <code>byte0 = (byte)((value & 0xFF00) >> 8);<br>
+ * byte1 = (byte)(value & 0x00FF);</code>
+ * <p>
+ *
+ * The value written can be read using the <code>readShort</code> and
+ * <code>readUnsignedShort</code> methods in <code>DataInput</code>.
+ *
+ * @param value The int value to write as a 16-bit value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readShort
+ * @see DataInput#readUnsignedShort
+ */
+ void writeShort(int value) throws IOException;
+
+ /**
+ * This method writes a Java int value to an output stream. The 4 bytes
+ * of the passed value will be written "big endian". That is, with
+ * the high byte written first in the following manner:
+ * <p>
+ * <code>byte0 = (byte)((value & 0xFF000000) >> 24);<br>
+ * byte1 = (byte)((value & 0x00FF0000) >> 16);<br>
+ * byte2 = (byte)((value & 0x0000FF00) >> 8);<br>
+ * byte3 = (byte)(value & 0x000000FF);</code>
+ * <p>
+ *
+ * The value written can be read using the <code>readInt</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The int value to write
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readInt
+ */
+ void writeInt(int value) throws IOException;
+
+ /**
+ * This method writes a Java long value to an output stream. The 8 bytes
+ * of the passed value will be written "big endian". That is, with
+ * the high byte written first in the following manner:
+ * <p>
+ * <code>byte0 = (byte)((value & 0xFF00000000000000L) >> 56);<br>
+ * byte1 = (byte)((value & 0x00FF000000000000L) >> 48);<br>
+ * byte2 = (byte)((value & 0x0000FF0000000000L) >> 40);<br>
+ * byte3 = (byte)((value & 0x000000FF00000000L) >> 32);<br>
+ * byte4 = (byte)((value & 0x00000000FF000000L) >> 24);<br>
+ * byte5 = (byte)((value & 0x0000000000FF0000L) >> 16);<br>
+ * byte6 = (byte)((value & 0x000000000000FF00L) >> 8);<br>
+ * byte7 = (byte)(value & 0x00000000000000FFL);</code>
+ * <p>
+ *
+ * The value written can be read using the <code>readLong</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The long value to write
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readLong
+ */
+ void writeLong(long value) throws IOException;
+
+ /**
+ * This method writes a Java <code>float</code> value to the stream. This
+ * value is written by first calling the method
+ * <code>Float.floatToIntBits</code>
+ * to retrieve an <code>int</code> representing the floating point number,
+ * then writing this <code>int</code> value to the stream exactly the same
+ * as the <code>writeInt()</code> method does.
+ *
+ * The value written can be read using the <code>readFloat</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The float value to write
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see #writeInt
+ * @see DataInput#readFloat
+ * @see Float#floatToIntBits
+ */
+ void writeFloat(float value) throws IOException;
+
+ /**
+ * This method writes a Java <code>double</code> value to the stream. This
+ * value is written by first calling the method
+ * <code>Double.doubleToLongBits</code>
+ * to retrieve an <code>long</code> representing the floating point number,
+ * then writing this <code>long</code> value to the stream exactly the same
+ * as the <code>writeLong()</code> method does.
+ *
+ * The value written can be read using the <code>readDouble</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The double value to write
+ *
+ * @exception IOException If any other error occurs
+ *
+ * @see #writeLong
+ * @see DataInput#readDouble
+ * @see Double#doubleToLongBits
+ */
+ void writeDouble(double value) throws IOException;
+
+ /**
+ * This method writes all the bytes in a <code>String</code> out to the
+ * stream. One byte is written for each character in the
+ * <code>String</code>.
+ * The high eight bits of each character are discarded, thus this
+ * method is inappropriate for completely representing Unicode characters.
+ *
+ * @param value The <code>String</code> to write
+ *
+ * @exception IOException If an error occurs
+ */
+ void writeBytes(String value) throws IOException;
+
+ /**
+ * This method writes all the characters of a <code>String</code> to an
+ * output stream as an array of <code>char</code>'s. Each character
+ * is written using the method specified in the <code>writeChar</code>
+ * method.
+ *
+ * @param value The String to write
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see #writeChar(int)
+ */
+ void writeChars(String value) throws IOException;
+
+ /**
+ * This method writes a Java <code>String</code> to the stream in a modified
+ * UTF-8 format. First, two bytes are written to the stream indicating the
+ * number of bytes to follow. This is written in the form of a Java
+ * <code>short</code> value in the same manner used by the
+ * <code>writeShort</code> method. Note that this is the number of
+ * bytes in the
+ * encoded <code>String</code> not the <code>String</code> length. Next
+ * come the encoded characters. Each character in the <code>String</code>
+ * is encoded as either one, two or three bytes. For characters in the
+ * range of <code>\u0001</code> to <code>\u007F</code>, one byte is used.
+ * The character
+ * value goes into bits 0-7 and bit eight is 0. For characters in the range
+ * of <code>\u0080</code> to <code>\u007FF</code>, two bytes are used. Bits
+ * 6-10 of the character value are encoded bits 0-4 of the first byte, with
+ * the high bytes having a value of "110". Bits 0-5 of the character value
+ * are stored in bits 0-5 of the second byte, with the high bits set to
+ * "10". This type of encoding is also done for the null character
+ * <code>\u0000</code>. This eliminates any C style NUL character values
+ * in the output. All remaining characters are stored as three bytes.
+ * Bits 12-15 of the character value are stored in bits 0-3 of the first
+ * byte. The high bits of the first bytes are set to "1110". Bits 6-11
+ * of the character value are stored in bits 0-5 of the second byte. The
+ * high bits of the second byte are set to "10". And bits 0-5 of the
+ * character value are stored in bits 0-5 of byte three, with the high bits
+ * of that byte set to "10".
+ *
+ * The value written can be read using the <code>readUTF</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The <code>String</code> to write
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readUTF
+ */
+ void writeUTF(String value) throws IOException;
+
+ /**
+ * This method writes an 8-bit value (passed into the method as a Java
+ * <code>int</code>) to an output stream. The low 8 bits of the
+ * passed value are written.
+ *
+ * @param value The <code>byte</code> to write to the output stream
+ *
+ * @exception IOException If an error occurs
+ */
+ void write(int value) throws IOException;
+
+ /**
+ * This method writes the raw byte array passed in to the output stream.
+ *
+ * @param buf The byte array to write
+ *
+ * @exception IOException If an error occurs
+ */
+ void write(byte[] buf) throws IOException;
+
+ /**
+ * This method writes raw bytes from the passed array <code>buf</code>
+ * starting
+ * <code>offset</code> bytes into the buffer. The number of bytes
+ * written will be exactly <code>len</code>.
+ *
+ * @param buf The buffer from which to write the data
+ * @param offset The offset into the buffer to start writing data from
+ * @param len The number of bytes to write from the buffer to the output
+ * stream
+ *
+ * @exception IOException If any other error occurs
+ */
+ void write(byte[] buf, int offset, int len) throws IOException;
+
+} // interface DataOutput
+
diff --git a/libjava/classpath/java/io/DataOutputStream.java b/libjava/classpath/java/io/DataOutputStream.java
new file mode 100644
index 00000000000..39f7ed1ff24
--- /dev/null
+++ b/libjava/classpath/java/io/DataOutputStream.java
@@ -0,0 +1,455 @@
+/* DataOutputStream.java -- Writes primitive Java datatypes to streams
+ Copyright (C) 1998, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.1.
+ */
+
+/**
+ * This class provides a mechanism for writing primitive Java datatypes
+ * to an <code>OutputStream</code> in a portable way. Data written to
+ * a stream using this class can be read back in using the
+ * <code>DataInputStream</code> class on any platform.
+ *
+ * @see DataInputStream
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class DataOutputStream extends FilterOutputStream implements DataOutput
+{
+ /**
+ * This is the total number of bytes that have been written to the
+ * stream by this object instance.
+ */
+ protected int written;
+
+ /**
+ * This method initializes an instance of <code>DataOutputStream</code> to
+ * write its data to the specified underlying <code>OutputStream</code>
+ *
+ * @param out The subordinate <code>OutputStream</code> to which this
+ * object will write
+ */
+ public DataOutputStream (OutputStream out)
+ {
+ super (out);
+ written = 0;
+ }
+
+ /**
+ * This method flushes any unwritten bytes to the underlying stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public void flush () throws IOException
+ {
+ out.flush();
+ }
+
+ /**
+ * This method returns the total number of bytes that have been written to
+ * the underlying output stream so far. This is the value of the
+ * <code>written</code> instance variable
+ *
+ * @return The number of bytes written to the stream.
+ */
+ public final int size ()
+ {
+ return written;
+ }
+
+ /**
+ * This method writes the specified byte (passed as an <code>int</code>)
+ * to the underlying output stream.
+ *
+ * @param value The <code>byte</code> to write, passed as an <code>int</code>.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public synchronized void write (int value) throws IOException
+ {
+ out.write (value);
+ ++written;
+ }
+
+ /**
+ * This method writes <code>len</code> bytes from the specified byte array
+ * <code>buf</code> starting at position <code>offset</code> into the
+ * buffer to the underlying output stream.
+ *
+ * @param buf The byte array to write from.
+ * @param offset The index into the byte array to start writing from.
+ * @param len The number of bytes to write.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public synchronized void write (byte[] buf, int offset, int len)
+ throws IOException
+ {
+ out.write(buf, offset, len);
+ written += len;
+ }
+
+ /**
+ * This method writes a Java boolean value to an output stream. If
+ * <code>value</code> is <code>true</code>, a byte with the value of
+ * 1 will be written, otherwise a byte with the value of 0 will be
+ * written.
+ *
+ * The value written can be read using the <code>readBoolean</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The <code>boolean</code> value to write to the stream
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readBoolean
+ */
+ public final void writeBoolean (boolean value) throws IOException
+ {
+ write (value ? 1 : 0);
+ }
+
+ /**
+ * This method writes a Java byte value to an output stream. The
+ * byte to be written will be in the lowest 8 bits of the
+ * <code>int</code> value passed.
+ *
+ * The value written can be read using the <code>readByte</code> or
+ * <code>readUnsignedByte</code> methods in <code>DataInput</code>.
+ *
+ * @param value The <code>byte</code> to write to the stream, passed as
+ * the low eight bits of an <code>int</code>.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readByte
+ * @see DataInput#readUnsignedByte
+ */
+ public final void writeByte (int value) throws IOException
+ {
+ write (value & 0xff);
+ }
+
+ /**
+ * This method writes a Java short value to an output stream. The
+ * char to be written will be in the lowest 16 bits of the <code>int</code>
+ * value passed. These bytes will be written "big endian". That is,
+ * with the high byte written first in the following manner:
+ * <p>
+ * <code>byte0 = (byte)((value & 0xFF00) >> 8);<br>
+ * byte1 = (byte)(value & 0x00FF);</code>
+ * <p>
+ *
+ * The value written can be read using the <code>readShort</code> and
+ * <code>readUnsignedShort</code> methods in <code>DataInput</code>.
+ *
+ * @param value The <code>short</code> value to write to the stream,
+ * passed as an <code>int</code>.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readShort
+ * @see DataInput#readUnsignedShort
+ */
+ public final synchronized void writeShort (int value) throws IOException
+ {
+ write ((byte) (0xff & (value >> 8)));
+ write ((byte) (0xff & value));
+ }
+
+ /**
+ * This method writes a Java char value to an output stream. The
+ * char to be written will be in the lowest 16 bits of the <code>int</code>
+ * value passed. These bytes will be written "big endian". That is,
+ * with the high byte written first in the following manner:
+ * <p>
+ * <code>byte0 = (byte)((value & 0xFF00) >> 8);<br>
+ * byte1 = (byte)(value & 0x00FF);</code>
+ * <p>
+ *
+ * The value written can be read using the <code>readChar</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The <code>char</code> value to write,
+ * passed as an <code>int</code>.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readChar
+ */
+ public final synchronized void writeChar (int value) throws IOException
+ {
+ write ((byte) (0xff & (value >> 8)));
+ write ((byte) (0xff & value));
+ }
+
+ /**
+ * This method writes a Java int value to an output stream. The 4 bytes
+ * of the passed value will be written "big endian". That is, with
+ * the high byte written first in the following manner:
+ * <p>
+ * <code>byte0 = (byte)((value & 0xFF000000) >> 24);<br>
+ * byte1 = (byte)((value & 0x00FF0000) >> 16);<br>
+ * byte2 = (byte)((value & 0x0000FF00) >> 8);<br>
+ * byte3 = (byte)(value & 0x000000FF);</code>
+ * <p>
+ *
+ * The value written can be read using the <code>readInt</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The <code>int</code> value to write to the stream
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readInt
+ */
+ public final synchronized void writeInt (int value) throws IOException
+ {
+ write ((byte) (0xff & (value >> 24)));
+ write ((byte) (0xff & (value >> 16)));
+ write ((byte) (0xff & (value >> 8)));
+ write ((byte) (0xff & value));
+ }
+
+ /**
+ * This method writes a Java long value to an output stream. The 8 bytes
+ * of the passed value will be written "big endian". That is, with
+ * the high byte written first in the following manner:
+ * <p>
+ * <code>byte0 = (byte)((value & 0xFF00000000000000L) >> 56);<br>
+ * byte1 = (byte)((value & 0x00FF000000000000L) >> 48);<br>
+ * byte2 = (byte)((value & 0x0000FF0000000000L) >> 40);<br>
+ * byte3 = (byte)((value & 0x000000FF00000000L) >> 32);<br>
+ * byte4 = (byte)((value & 0x00000000FF000000L) >> 24);<br>
+ * byte5 = (byte)((value & 0x0000000000FF0000L) >> 16);<br>
+ * byte6 = (byte)((value & 0x000000000000FF00L) >> 8);<br>
+ * byte7 = (byte)(value & 0x00000000000000FFL);</code>
+ * <p>
+ *
+ * The value written can be read using the <code>readLong</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The <code>long</code> value to write to the stream
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readLong
+ */
+ public final synchronized void writeLong (long value) throws IOException
+ {
+ write ((byte) (0xff & (value >> 56)));
+ write ((byte) (0xff & (value>> 48)));
+ write ((byte) (0xff & (value>> 40)));
+ write ((byte) (0xff & (value>> 32)));
+ write ((byte) (0xff & (value>> 24)));
+ write ((byte) (0xff & (value>> 16)));
+ write ((byte) (0xff & (value>> 8)));
+ write ((byte) (0xff & value));
+ }
+
+ /**
+ * This method writes a Java <code>float</code> value to the stream. This
+ * value is written by first calling the method
+ * <code>Float.floatToIntBits</code>
+ * to retrieve an <code>int</code> representing the floating point number,
+ * then writing this <code>int</code> value to the stream exactly the same
+ * as the <code>writeInt()</code> method does.
+ *
+ * The value written can be read using the <code>readFloat</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The <code>float</code> value to write to the stream
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see writeInt
+ * @see DataInput#readFloat
+ * @see Float#floatToIntBits
+ */
+ public final void writeFloat (float value) throws IOException
+ {
+ writeInt (Float.floatToIntBits (value));
+ }
+
+ /**
+ * This method writes a Java <code>double</code> value to the stream. This
+ * value is written by first calling the method
+ * <code>Double.doubleToLongBits</code>
+ * to retrieve an <code>long</code> representing the floating point number,
+ * then writing this <code>long</code> value to the stream exactly the same
+ * as the <code>writeLong()</code> method does.
+ *
+ * The value written can be read using the <code>readDouble</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The <code>double</code> value to write to the stream
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see writeLong
+ * @see DataInput#readDouble
+ * @see Double#doubleToLongBits
+ */
+ public final void writeDouble (double value) throws IOException
+ {
+ writeLong (Double.doubleToLongBits (value));
+ }
+
+ /**
+ * This method writes all the bytes in a <code>String</code> out to the
+ * stream. One byte is written for each character in the
+ * <code>String</code>.
+ * The high eight bits of each character are discarded, thus this
+ * method is inappropriate for completely representing Unicode characters.
+ *
+ * @param value The <code>String</code> to write to the stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeBytes (String value) throws IOException
+ {
+ int len = value.length();
+ for (int i = 0; i < len; ++i)
+ writeByte (value.charAt(i));
+ }
+
+ /**
+ * This method writes all the characters of a <code>String</code> to an
+ * output stream as an array of <code>char</code>'s. Each character
+ * is written using the method specified in the <code>writeChar</code>
+ * method.
+ *
+ * @param value The <code>String</code> to write to the stream
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see writeChar
+ */
+ public final void writeChars (String value) throws IOException
+ {
+ int len = value.length();
+ for (int i = 0; i < len; ++i)
+ writeChar (value.charAt(i));
+ }
+
+ /**
+ * This method writes a Java <code>String</code> to the stream in a modified
+ * UTF-8 format. First, two bytes are written to the stream indicating the
+ * number of bytes to follow. Note that this is the number of bytes in the
+ * encoded <code>String</code> not the <code>String</code> length. Next
+ * come the encoded characters. Each character in the <code>String</code>
+ * is encoded as either one, two or three bytes. For characters in the
+ * range of <code>\u0001</code> to <\u007F>, one byte is used. The character
+ * value goes into bits 0-7 and bit eight is 0. For characters in the range
+ * of <code>\u0080</code> to <code>\u007FF</code>, two bytes are used. Bits
+ * 6-10 of the character value are encoded bits 0-4 of the first byte, with
+ * the high bytes having a value of "110". Bits 0-5 of the character value
+ * are stored in bits 0-5 of the second byte, with the high bits set to
+ * "10". This type of encoding is also done for the null character
+ * <code>\u0000</code>. This eliminates any C style NUL character values
+ * in the output. All remaining characters are stored as three bytes.
+ * Bits 12-15 of the character value are stored in bits 0-3 of the first
+ * byte. The high bits of the first bytes are set to "1110". Bits 6-11
+ * of the character value are stored in bits 0-5 of the second byte. The
+ * high bits of the second byte are set to "10". And bits 0-5 of the
+ * character value are stored in bits 0-5 of byte three, with the high bits
+ * of that byte set to "10".
+ *
+ * The value written can be read using the <code>readUTF</code>
+ * method in <code>DataInput</code>.
+ *
+ * @param value The <code>String</code> to write to the output in UTF format
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataInput#readUTF
+ */
+ public final synchronized void writeUTF(String value) throws IOException
+ {
+ int len = value.length();
+ int sum = 0;
+
+ for (int i = 0; i < len && sum <= 65535; ++i)
+ {
+ char c = value.charAt(i);
+ if (c >= '\u0001' && c <= '\u007f')
+ sum += 1;
+ else if (c == '\u0000' || (c >= '\u0080' && c <= '\u07ff'))
+ sum += 2;
+ else
+ sum += 3;
+ }
+
+ if (sum > 65535)
+ throw new UTFDataFormatException ();
+
+ int pos = 0;
+ byte[] buf = new byte[sum];
+
+ for (int i = 0; i < len; ++i)
+ {
+ char c = value.charAt(i);
+ if (c >= '\u0001' && c <= '\u007f')
+ buf[pos++] = (byte) c;
+ else if (c == '\u0000' || (c >= '\u0080' && c <= '\u07ff'))
+ {
+ buf[pos++] = (byte) (0xc0 | (0x1f & (c >> 6)));
+ buf[pos++] = (byte) (0x80 | (0x3f & c));
+ }
+ else
+ {
+ // JSL says the first byte should be or'd with 0xc0, but
+ // that is a typo. Unicode says 0xe0, and that is what is
+ // consistent with DataInputStream.
+ buf[pos++] = (byte) (0xe0 | (0x0f & (c >> 12)));
+ buf[pos++] = (byte) (0x80 | (0x3f & (c >> 6)));
+ buf[pos++] = (byte) (0x80 | (0x3f & c));
+ }
+ }
+
+ writeShort (sum);
+ write(buf, 0, sum);
+ }
+
+} // class DataOutputStream
+
diff --git a/libjava/classpath/java/io/DeleteFileHelper.java b/libjava/classpath/java/io/DeleteFileHelper.java
new file mode 100644
index 00000000000..d73628c4973
--- /dev/null
+++ b/libjava/classpath/java/io/DeleteFileHelper.java
@@ -0,0 +1,109 @@
+/* DeleteFileHelper.java -- Helper class to delete files on VM exit
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.io;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Jeroen Frijters (jeroen@sumatra.nl)
+ * @author Michael Koch (konqueror@gmx.de)
+ */
+final class DeleteFileHelper extends Thread
+{
+ private static ArrayList filesToDelete;
+
+ static synchronized void add(File file)
+ {
+ if (filesToDelete == null)
+ {
+ filesToDelete = new ArrayList();
+
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ try
+ {
+ Runtime.getRuntime().addShutdownHook(new DeleteFileHelper());
+ }
+ catch (IllegalStateException e)
+ {
+ // Shutdown is already in progress, so we can't
+ // register ours.
+ }
+
+ return null;
+ }
+ });
+ }
+
+ filesToDelete.add(file);
+ }
+
+ private static synchronized void deleteFiles()
+ {
+ Iterator it = filesToDelete.iterator();
+
+ while (it.hasNext())
+ {
+ try
+ {
+ File file = (File) it.next();
+ file.delete();
+ }
+ catch (Exception e)
+ {
+ // Do nothing here.
+ }
+ }
+ }
+
+ // Package-private to avoid a trampoline constructor.
+ DeleteFileHelper()
+ {
+ }
+
+ public void run()
+ {
+ deleteFiles();
+ }
+}
diff --git a/libjava/classpath/java/io/EOFException.java b/libjava/classpath/java/io/EOFException.java
new file mode 100644
index 00000000000..cfedb7d9eb0
--- /dev/null
+++ b/libjava/classpath/java/io/EOFException.java
@@ -0,0 +1,76 @@
+/* EOFException.java -- unexpected end of file exception
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown when the end of the file or stream was
+ * encountered unexpectedly. This is not the normal way that an EOF
+ * condition is reported; such as a special value like -1 being returned.
+ * However, certain types of streams expecting certain data in a certain
+ * format might reach EOF before reading their expected data pattern and
+ * thus throw this exception.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class EOFException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 6433858223774886977L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ public EOFException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public EOFException(String message)
+ {
+ super(message);
+ }
+} // class EOFException
diff --git a/libjava/classpath/java/io/Externalizable.java b/libjava/classpath/java/io/Externalizable.java
new file mode 100644
index 00000000000..113c19ff60f
--- /dev/null
+++ b/libjava/classpath/java/io/Externalizable.java
@@ -0,0 +1,107 @@
+/* Externalizable.java -- Interface for saving and restoring object data
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This interface provides a way that classes can completely control how
+ * the data of their object instances are written and read to and from
+ * streams. It has two methods which are used to write the data to a stream
+ * and to read the data from a stream. The read method must read the data
+ * in exactly the way it was written by the write method.
+ * <p>
+ * Note that classes which implement this interface must take into account
+ * that all superclass data must also be written to the stream as well.
+ * The class implementing this interface must figure out how to make that
+ * happen.
+ * <p>
+ * This interface can be used to provide object persistence. When an
+ * object is to be stored externally, the <code>writeExternal</code> method is
+ * called to save state. When the object is restored, an instance is
+ * created using the default no-argument constructor and the
+ * <code>readExternal</code> method is used to restore the state.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Externalizable extends Serializable
+{
+ /**
+ * This method restores an object's state by reading in the instance data
+ * for the object from the passed in stream. Note that this stream is not
+ * a subclass of <code>InputStream</code>, but rather is a class that
+ * implements
+ * the <code>ObjectInput</code> interface. That interface provides a
+ * mechanism for
+ * reading in Java data types from a stream.
+ * <p>
+ * Note that this method must be compatible with <code>writeExternal</code>.
+ * It must read back the exact same types that were written by that
+ * method in the exact order they were written.
+ * <p>
+ * If this method needs to read back an object instance, then the class
+ * for that object must be found and loaded. If that operation fails,
+ * then this method throws a <code>ClassNotFoundException</code>
+ *
+ * @param in An <code>ObjectInput</code> instance for reading in the object
+ * state
+ *
+ * @exception ClassNotFoundException If the class of an object being
+ * restored cannot be found
+ * @exception IOException If any other error occurs
+ */
+ void readExternal(ObjectInput in)
+ throws ClassNotFoundException, IOException;
+
+ /**
+ * This method is responsible for writing the instance data of an object
+ * to the passed in stream. Note that this stream is not a subclass of
+ * <code>OutputStream</code>, but rather is a class that implements the
+ * <code>ObjectOutput</code> interface. That interface provides a
+ * number of methods
+ * for writing Java data values to a stream.
+ * <p>
+ * Not that the implementation of this method must be coordinated with
+ * the implementation of <code>readExternal</code>.
+ *
+ * @param out An <code>ObjectOutput</code> instance for writing the
+ * object state
+ *
+ * @exception IOException If an error occurs
+ */
+ void writeExternal(ObjectOutput out) throws IOException;
+}
diff --git a/libjava/classpath/java/io/File.java b/libjava/classpath/java/io/File.java
new file mode 100644
index 00000000000..3b747e6bd03
--- /dev/null
+++ b/libjava/classpath/java/io/File.java
@@ -0,0 +1,1357 @@
+/* File.java -- Class representing a file on disk
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.classpath.SystemProperties;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.3.
+ */
+
+/**
+ * This class represents a file or directory on a local disk. It provides
+ * facilities for dealing with a variety of systems that use various
+ * types of path separators ("/" versus "\", for example). It also
+ * contains method useful for creating and deleting files and directories.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class File implements Serializable, Comparable
+{
+ private static final long serialVersionUID = 301077366599181567L;
+
+ /**
+ * This is the path separator string for the current host. This field
+ * contains the value of the <code>file.separator</code> system property.
+ * An example separator string would be "/" on the GNU system.
+ */
+ public static final String separator = SystemProperties.getProperty("file.separator");
+ private static final String dupSeparator = separator + separator;
+
+ /**
+ * This is the first character of the file separator string. On many
+ * hosts (for example, on the GNU system), this represents the entire
+ * separator string. The complete separator string is obtained from the
+ * <code>file.separator</code>system property.
+ */
+ public static final char separatorChar = separator.charAt(0);
+
+ /**
+ * This is the string that is used to separate the host name from the
+ * path name in paths than include the host name. It is the value of
+ * the <code>path.separator</code> system property.
+ */
+ public static final String pathSeparator
+ = SystemProperties.getProperty("path.separator");
+
+ /**
+ * This is the first character of the string used to separate the host name
+ * from the path name in paths that include a host. The separator string
+ * is taken from the <code>path.separator</code> system property.
+ */
+ public static final char pathSeparatorChar = pathSeparator.charAt(0);
+
+ /**
+ * This is the path to the file set when the object is created. It
+ * may be an absolute or relative path name.
+ */
+ private String path;
+
+ /**
+ * This method tests whether or not the current thread is allowed to
+ * to read the file pointed to by this object. This will be true if and
+ * and only if 1) the file exists and 2) the <code>SecurityManager</code>
+ * (if any) allows access to the file via it's <code>checkRead</code>
+ * method 3) the file is readable.
+ *
+ * @return <code>true</code> if reading is allowed,
+ * <code>false</code> otherwise
+ *
+ * @exception SecurityException If the <code>SecurityManager</code>
+ * does not allow access to the file
+ */
+ public boolean canRead()
+ {
+ // Test for existence. This also does the SecurityManager check
+ if (!exists())
+ return false;
+
+ return VMFile.canRead(path);
+ }
+
+ /**
+ * This method test whether or not the current thread is allowed to
+ * write to this object. This will be true if and only if 1) The
+ * <code>SecurityManager</code> (if any) allows write access to the
+ * file and 2) The file exists and 3) The file is writable. To determine
+ * whether or not a non-existent file can be created, check the parent
+ * directory for write access.
+ *
+ * @return <code>true</code> if writing is allowed, <code>false</code>
+ * otherwise
+ *
+ * @exception SecurityException If the <code>SecurityManager</code>
+ * does not allow access to the file
+ */
+ public boolean canWrite()
+ {
+ // First do a SecurityCheck before doing anything else.
+ checkWrite();
+
+ // Test for existence. This is required by the spec
+ if (! VMFile.exists(path))
+ return false;
+
+ if (VMFile.isDirectory(path))
+ return VMFile.canWriteDirectory(this);
+ else
+ return VMFile.canWrite(path);
+ }
+
+ /**
+ * This method creates a new file of zero length with the same name as
+ * the path of this <code>File</code> object if an only if that file
+ * does not already exist.
+ * <p>
+ * A <code>SecurityManager.checkWrite</code> check is done prior
+ * to performing this action.
+ *
+ * @return <code>true</code> if the file was created, <code>false</code> if
+ * the file alread existed.
+ *
+ * @exception IOException If an I/O error occurs
+ * @exception SecurityException If the <code>SecurityManager</code> will
+ * not allow this operation to be performed.
+ *
+ * @since 1.2
+ */
+ public boolean createNewFile() throws IOException
+ {
+ checkWrite();
+ return VMFile.create(path);
+ }
+ /**
+ * This method deletes the file represented by this object. If this file
+ * is a directory, it must be empty in order for the delete to succeed.
+ *
+ * @return <code>true</code> if the file was deleted, <code>false</code>
+ * otherwise
+ *
+ * @exception SecurityException If deleting of the file is not allowed
+ */
+ public synchronized boolean delete()
+ {
+ SecurityManager s = System.getSecurityManager();
+
+ if (s != null)
+ s.checkDelete(path);
+
+ return VMFile.delete(path);
+ }
+
+ /**
+ * This method tests two <code>File</code> objects for equality by
+ * comparing the path of the specified <code>File</code> against the path
+ * of this object. The two objects are equal if an only if 1) The
+ * argument is not null 2) The argument is a <code>File</code> object and
+ * 3) The path of the <code>File</code>argument is equal to the path
+ * of this object.
+ * <p>
+ * The paths of the files are determined by calling the
+ * <code>getPath()</code>
+ * method on each object.
+ *
+ * @return <code>true</code> if the two objects are equal,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof File))
+ return false;
+
+ File other = (File) obj;
+
+ if (VMFile.IS_CASE_SENSITIVE)
+ return path.equals(other.path);
+ else
+ return path.equalsIgnoreCase(other.path);
+ }
+
+ /**
+ * This method tests whether or not the file represented by the object
+ * actually exists on the filesystem.
+ *
+ * @return <code>true</code> if the file exists, <code>false</code>otherwise.
+ *
+ * @exception SecurityException If reading of the file is not permitted
+ */
+ public boolean exists()
+ {
+ checkRead();
+ return VMFile.exists(path);
+ }
+
+ /**
+ * This method initializes a new <code>File</code> object to represent
+ * a file with the specified path.
+ *
+ * @param name The path name of the file
+ */
+ public File(String name)
+ {
+ path = normalizePath (name);
+ }
+
+ // Remove duplicate and redundant separator characters.
+ private String normalizePath(String p)
+ {
+ // On Windows, convert any '/' to '\'. This appears to be the same logic
+ // that Sun's Win32 Java performs.
+ if (separatorChar == '\\')
+ {
+ p = p.replace ('/', '\\');
+ // We have to special case the "\c:" prefix.
+ if (p.length() > 2 && p.charAt(0) == '\\' &&
+ ((p.charAt(1) >= 'a' && p.charAt(1) <= 'z') ||
+ (p.charAt(1) >= 'A' && p.charAt(1) <= 'Z')) &&
+ p.charAt(2) == ':')
+ p = p.substring(1);
+ }
+
+ int dupIndex = p.indexOf(dupSeparator);
+ int plen = p.length();
+
+ // Special case: permit Windows UNC path prefix.
+ if (dupSeparator.equals("\\\\") && dupIndex == 0)
+ dupIndex = p.indexOf(dupSeparator, 1);
+
+ if (dupIndex == -1)
+ {
+ // Ignore trailing separator (though on Windows "a:\", for
+ // example, is a valid and minimal path).
+ if (plen > 1 && p.charAt (plen - 1) == separatorChar)
+ {
+ if (! (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':'))
+ return p.substring (0, plen - 1);
+ }
+ else
+ return p;
+ }
+
+ StringBuffer newpath = new StringBuffer(plen);
+ int last = 0;
+ while (dupIndex != -1)
+ {
+ newpath.append(p.substring(last, dupIndex));
+ // Ignore the duplicate path characters.
+ while (p.charAt(dupIndex) == separatorChar)
+ {
+ dupIndex++;
+ if (dupIndex == plen)
+ return newpath.toString();
+ }
+ newpath.append(separatorChar);
+ last = dupIndex;
+ dupIndex = p.indexOf(dupSeparator, last);
+ }
+
+ // Again, ignore possible trailing separator (except special cases
+ // like "a:\" on Windows).
+ int end;
+ if (plen > 1 && p.charAt (plen - 1) == separatorChar)
+ {
+ if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')
+ end = plen;
+ else
+ end = plen - 1;
+ }
+ else
+ end = plen;
+ newpath.append(p.substring(last, end));
+
+ return newpath.toString();
+ }
+
+ /**
+ * This method initializes a new <code>File</code> object to represent
+ * a file in the specified named directory. The path name to the file
+ * will be the directory name plus the separator string plus the file
+ * name. If the directory path name ends in the separator string, another
+ * separator string will still be appended.
+ *
+ * @param dirPath The path to the directory the file resides in
+ * @param name The name of the file
+ */
+ public File(String dirPath, String name)
+ {
+ if (name == null)
+ throw new NullPointerException();
+ if (dirPath != null)
+ {
+ if (dirPath.length() > 0)
+ {
+ // Try to be smart about the number of separator characters.
+ if (dirPath.charAt(dirPath.length() - 1) == separatorChar
+ || name.length() == 0)
+ path = normalizePath(dirPath + name);
+ else
+ path = normalizePath(dirPath + separatorChar + name);
+ }
+ else
+ {
+ // If dirPath is empty, use a system dependant
+ // default prefix.
+ // Note that the leading separators in name have
+ // to be chopped off, to prevent them forming
+ // a UNC prefix on Windows.
+ if (separatorChar == '\\' /* TODO use ON_WINDOWS */)
+ {
+ int skip = 0;
+ while(name.length() > skip
+ && (name.charAt(skip) == separatorChar
+ || name.charAt(skip) == '/'))
+ {
+ skip++;
+ }
+ name = name.substring(skip);
+ }
+ path = normalizePath(separatorChar + name);
+ }
+ }
+ else
+ path = normalizePath(name);
+ }
+
+ /**
+ * This method initializes a new <code>File</code> object to represent
+ * a file in the specified directory. If the <code>directory</code>
+ * argument is <code>null</code>, the file is assumed to be in the
+ * current directory as specified by the <code>user.dir</code> system
+ * property
+ *
+ * @param directory The directory this file resides in
+ * @param name The name of the file
+ */
+ public File(File directory, String name)
+ {
+ this (directory == null ? null : directory.path, name);
+ }
+
+ /**
+ * This method initializes a new <code>File</code> object to represent
+ * a file corresponding to the specified <code>file:</code> protocol URI.
+ *
+ * @param uri The uri.
+ */
+ public File(URI uri)
+ {
+ if (uri == null)
+ throw new NullPointerException("uri is null");
+
+ if (!uri.getScheme().equals("file"))
+ throw new IllegalArgumentException("invalid uri protocol");
+
+ path = normalizePath(uri.getPath());
+ }
+
+ /**
+ * This method returns the path of this file as an absolute path name.
+ * If the path name is already absolute, then it is returned. Otherwise
+ * the value returned is the current directory plus the separatory
+ * string plus the path of the file. The current directory is determined
+ * from the <code>user.dir</code> system property.
+ *
+ * @return The absolute path of this file
+ */
+ public String getAbsolutePath()
+ {
+ if (isAbsolute())
+ return path;
+ else if (separatorChar == '\\'
+ && path.length() > 0 && path.charAt (0) == '\\')
+ {
+ // On Windows, even if the path starts with a '\\' it is not
+ // really absolute until we prefix the drive specifier from
+ // the current working directory to it.
+ return System.getProperty ("user.dir").substring (0, 2) + path;
+ }
+ else if (separatorChar == '\\'
+ && path.length() > 1 && path.charAt (1) == ':'
+ && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
+ || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')))
+ {
+ // On Windows, a process has a current working directory for
+ // each drive and a path like "G:foo\bar" would mean the
+ // absolute path "G:\wombat\foo\bar" if "\wombat" is the
+ // working directory on the G drive.
+ String drvDir = null;
+ try
+ {
+ drvDir = new File (path.substring (0, 2)).getCanonicalPath();
+ }
+ catch (IOException e)
+ {
+ drvDir = path.substring (0, 2) + "\\";
+ }
+
+ // Note: this would return "C:\\." for the path "C:.", if "\"
+ // is the working folder on the C drive, but this is
+ // consistent with what Sun's JRE 1.4.1.01 actually returns!
+ if (path.length() > 2)
+ return drvDir + '\\' + path.substring (2, path.length());
+ else
+ return drvDir;
+ }
+ else
+ return System.getProperty ("user.dir") + separatorChar + path;
+ }
+
+ /**
+ * This method returns a <code>File</code> object representing the
+ * absolute path of this object.
+ *
+ * @return A <code>File</code> with the absolute path of the object.
+ *
+ * @since 1.2
+ */
+ public File getAbsoluteFile()
+ {
+ return new File(getAbsolutePath());
+ }
+
+ /**
+ * This method returns a canonical representation of the pathname of
+ * this file. The actual form of the canonical representation is
+ * different. On the GNU system, the canonical form differs from the
+ * absolute form in that all relative file references to "." and ".."
+ * are resolved and removed.
+ * <p>
+ * Note that this method, unlike the other methods which return path
+ * names, can throw an IOException. This is because native method
+ * might be required in order to resolve the canonical path
+ *
+ * @exception IOException If an error occurs
+ */
+ public String getCanonicalPath() throws IOException
+ {
+ // On Windows, getAbsolutePath might end up calling us, so we
+ // have to special case that call to avoid infinite recursion.
+ if (separatorChar == '\\' && path.length() == 2 &&
+ ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') ||
+ (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) &&
+ path.charAt(1) == ':')
+ {
+ return VMFile.toCanonicalForm(path);
+ }
+ // Call getAbsolutePath first to make sure that we do the
+ // current directory handling, because the native code
+ // may have a different idea of the current directory.
+ return VMFile.toCanonicalForm(getAbsolutePath());
+ }
+
+ /**
+ * This method returns a <code>File</code> object representing the
+ * canonical path of this object.
+ *
+ * @return A <code>File</code> instance representing the canonical path of
+ * this object.
+ *
+ * @exception IOException If an error occurs.
+ *
+ * @since 1.2
+ */
+ public File getCanonicalFile() throws IOException
+ {
+ return new File(getCanonicalPath());
+ }
+
+ /**
+ * This method returns the name of the file. This is everything in the
+ * complete path of the file after the last instance of the separator
+ * string.
+ *
+ * @return The file name
+ */
+ public String getName()
+ {
+ return VMFile.getName(path);
+ }
+
+ /**
+ * This method returns a <code>String</code> the represents this file's
+ * parent. <code>null</code> is returned if the file has no parent. The
+ * parent is determined via a simple operation which removes the
+ *
+ * @return The parent directory of this file
+ */
+ public String getParent()
+ {
+ String prefix = null;
+ int nameSeqIndex = 0;
+
+ // The "prefix", if present, is the leading "/" on UNIX and
+ // either the drive specifier (e.g. "C:") or the leading "\\"
+ // of a UNC network path on Windows.
+ if (separatorChar == '/' && path.charAt (0) == '/')
+ {
+ prefix = "/";
+ nameSeqIndex = 1;
+ }
+ else if (separatorChar == '\\' && path.length() > 1)
+ {
+ if ((path.charAt (0) == '\\' && path.charAt (1) == '\\')
+ || (((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
+ || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))
+ && path.charAt (1) == ':'))
+ {
+ prefix = path.substring (0, 2);
+ nameSeqIndex = 2;
+ }
+ }
+
+ // According to the JDK docs, the returned parent path is the
+ // portion of the name sequence before the last separator
+ // character, if found, prefixed by the prefix, otherwise null.
+ if (nameSeqIndex < path.length())
+ {
+ String nameSeq = path.substring (nameSeqIndex, path.length());
+ int last = nameSeq.lastIndexOf (separatorChar);
+ if (last == -1)
+ return prefix;
+ else if (last == (nameSeq.length() - 1))
+ // Note: The path would not have a trailing separator
+ // except for cases like "C:\" on Windows (see
+ // normalizePath( )), where Sun's JRE 1.4 returns null.
+ return null;
+ else if (last == 0)
+ last++;
+
+ if (prefix != null)
+ return prefix + nameSeq.substring (0, last);
+ else
+ return nameSeq.substring (0, last);
+ }
+ else
+ // Sun's JRE 1.4 returns null if the prefix is the only
+ // component of the path - so "/" gives null on UNIX and
+ // "C:", "\\", etc. return null on Windows.
+ return null;
+ }
+
+ /**
+ * This method returns a <code>File</code> object representing the parent
+ * file of this one.
+ *
+ * @return a <code>File</code> for the parent of this object.
+ * <code>null</code>
+ * will be returned if this object does not have a parent.
+ *
+ * @since 1.2
+ */
+ public File getParentFile()
+ {
+ String parent = getParent();
+ return parent != null ? new File(parent) : null;
+ }
+
+ /**
+ * Returns the path name that represents this file. May be a relative
+ * or an absolute path name
+ *
+ * @return The pathname of this file
+ */
+ public String getPath()
+ {
+ return path;
+ }
+
+ /**
+ * This method returns a hash code representing this file. It is the
+ * hash code of the path of this file (as returned by <code>getPath()</code>)
+ * exclusived or-ed with the value 1234321.
+ *
+ * @return The hash code for this object
+ */
+ public int hashCode()
+ {
+ if (VMFile.IS_CASE_SENSITIVE)
+ return path.hashCode() ^ 1234321;
+ else
+ return path.toLowerCase().hashCode() ^ 1234321;
+ }
+
+ /**
+ * This method returns true if this object represents an absolute file
+ * path and false if it does not. The definition of an absolute path varies
+ * by system. As an example, on GNU systems, a path is absolute if it starts
+ * with a "/".
+ *
+ * @return <code>true</code> if this object represents an absolute
+ * file name, <code>false</code> otherwise.
+ */
+ public boolean isAbsolute()
+ {
+ if (separatorChar == '\\')
+ return path.startsWith(dupSeparator) ||
+ (path.length() > 2 &&
+ ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') ||
+ (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) &&
+ path.charAt(1) == ':' &&
+ path.charAt(2) == '\\');
+ else
+ return path.startsWith(separator);
+ }
+
+ /**
+ * This method tests whether or not the file represented by this object
+ * is a directory. In order for this method to return <code>true</code>,
+ * the file represented by this object must exist and be a directory.
+ *
+ * @return <code>true</code> if this file is a directory, <code>false</code>
+ * otherwise
+ *
+ * @exception SecurityException If reading of the file is not permitted
+ */
+ public boolean isDirectory()
+ {
+ checkRead();
+ return VMFile.isDirectory(path);
+ }
+
+ /**
+ * This method tests whether or not the file represented by this object
+ * is a "plain" file. A file is a plain file if and only if it 1) Exists,
+ * 2) Is not a directory or other type of special file.
+ *
+ * @return <code>true</code> if this is a plain file, <code>false</code>
+ * otherwise
+ *
+ * @exception SecurityException If reading of the file is not permitted
+ */
+ public boolean isFile()
+ {
+ checkRead();
+ return VMFile.isFile(path);
+ }
+
+ /**
+ * This method tests whether or not this file represents a "hidden" file.
+ * On GNU systems, a file is hidden if its name begins with a "."
+ * character. Files with these names are traditionally not shown with
+ * directory listing tools.
+ *
+ * @return <code>true</code> if the file is hidden, <code>false</code>
+ * otherwise.
+ *
+ * @since 1.2
+ */
+ public boolean isHidden()
+ {
+ return VMFile.isHidden(path);
+ }
+
+ /**
+ * This method returns the last modification time of this file. The
+ * time value returned is an abstract value that should not be interpreted
+ * as a specified time value. It is only useful for comparing to other
+ * such time values returned on the same system. In that case, the larger
+ * value indicates a more recent modification time.
+ * <p>
+ * If the file does not exist, then a value of 0 is returned.
+ *
+ * @return The last modification time of the file
+ *
+ * @exception SecurityException If reading of the file is not permitted
+ */
+ public long lastModified()
+ {
+ checkRead();
+ return VMFile.lastModified(path);
+ }
+
+ /**
+ * This method returns the length of the file represented by this object,
+ * or 0 if the specified file does not exist.
+ *
+ * @return The length of the file
+ *
+ * @exception SecurityException If reading of the file is not permitted
+ */
+ public long length()
+ {
+ checkRead();
+ return VMFile.length(path);
+ }
+
+ /**
+ * This method returns a array of <code>String</code>'s representing the
+ * list of files is then directory represented by this object. If this
+ * object represents a non-directory file or a non-existent file, then
+ * <code>null</code> is returned. The list of files will not contain
+ * any names such as "." or ".." which indicate the current or parent
+ * directory. Also, the names are not guaranteed to be sorted.
+ * <p>
+ * In this form of the <code>list()</code> method, a filter is specified
+ * that allows the caller to control which files are returned in the
+ * list. The <code>FilenameFilter</code> specified is called for each
+ * file returned to determine whether or not that file should be included
+ * in the list.
+ * <p>
+ * A <code>SecurityManager</code> check is made prior to reading the
+ * directory. If read access to the directory is denied, an exception
+ * will be thrown.
+ *
+ * @param filter An object which will identify files to exclude from
+ * the directory listing.
+ *
+ * @return An array of files in the directory, or <code>null</code>
+ * if this object does not represent a valid directory.
+ *
+ * @exception SecurityException If read access is not allowed to the
+ * directory by the <code>SecurityManager</code>
+ */
+ public String[] list(FilenameFilter filter)
+ {
+ checkRead();
+
+ if (!exists() || !isDirectory())
+ return null;
+
+ // Get the list of files
+ String files[] = VMFile.list(path);
+
+ // Check if an error occured in listInternal().
+ if (files == null)
+ return null;
+
+ if (filter == null)
+ return files;
+
+ // Apply the filter
+ int count = 0;
+ for (int i = 0; i < files.length; i++)
+ {
+ if (filter.accept(this, files[i]))
+ ++count;
+ else
+ files[i] = null;
+ }
+
+ String[] retfiles = new String[count];
+ count = 0;
+ for (int i = 0; i < files.length; i++)
+ if (files[i] != null)
+ retfiles[count++] = files[i];
+
+ return retfiles;
+ }
+
+ /**
+ * This method returns a array of <code>String</code>'s representing the
+ * list of files is then directory represented by this object. If this
+ * object represents a non-directory file or a non-existent file, then
+ * <code>null</code> is returned. The list of files will not contain
+ * any names such as "." or ".." which indicate the current or parent
+ * directory. Also, the names are not guaranteed to be sorted.
+ * <p>
+ * A <code>SecurityManager</code> check is made prior to reading the
+ * directory. If read access to the directory is denied, an exception
+ * will be thrown.
+ *
+ * @return An array of files in the directory, or <code>null</code> if
+ * this object does not represent a valid directory.
+ *
+ * @exception SecurityException If read access is not allowed to the
+ * directory by the <code>SecurityManager</code>
+ */
+ public String[] list()
+ {
+ return list(null);
+ }
+
+ /**
+ * This method returns an array of <code>File</code> objects representing
+ * all the files in the directory represented by this object. If this
+ * object does not represent a directory, <code>null</code> is returned.
+ * Each of the returned <code>File</code> object is constructed with this
+ * object as its parent.
+ * <p>
+ * A <code>SecurityManager</code> check is made prior to reading the
+ * directory. If read access to the directory is denied, an exception
+ * will be thrown.
+ *
+ * @return An array of <code>File</code> objects for this directory.
+ *
+ * @exception SecurityException If the <code>SecurityManager</code> denies
+ * access to this directory.
+ *
+ * @since 1.2
+ */
+ public File[] listFiles()
+ {
+ return listFiles((FilenameFilter) null);
+ }
+
+ /**
+ * This method returns an array of <code>File</code> objects representing
+ * all the files in the directory represented by this object. If this
+ * object does not represent a directory, <code>null</code> is returned.
+ * Each of the returned <code>File</code> object is constructed with this
+ * object as its parent.
+ * <p>
+ * In this form of the <code>listFiles()</code> method, a filter is specified
+ * that allows the caller to control which files are returned in the
+ * list. The <code>FilenameFilter</code> specified is called for each
+ * file returned to determine whether or not that file should be included
+ * in the list.
+ * <p>
+ * A <code>SecurityManager</code> check is made prior to reading the
+ * directory. If read access to the directory is denied, an exception
+ * will be thrown.
+ *
+ * @return An array of <code>File</code> objects for this directory.
+ *
+ * @exception SecurityException If the <code>SecurityManager</code> denies
+ * access to this directory.
+ *
+ * @since 1.2
+ */
+ public File[] listFiles(FilenameFilter filter)
+ {
+ String[] filelist = list(filter);
+
+ if (filelist == null)
+ return null;
+
+ File[] fobjlist = new File [filelist.length];
+
+ for (int i = 0; i < filelist.length; i++)
+ fobjlist [i] = new File(this, filelist [i]);
+
+ return fobjlist;
+ }
+
+ /**
+ * This method returns an array of <code>File</code> objects representing
+ * all the files in the directory represented by this object. If this
+ * object does not represent a directory, <code>null</code> is returned.
+ * Each of the returned <code>File</code> object is constructed with this
+ * object as its parent.
+ * <p>
+ * In this form of the <code>listFiles()</code> method, a filter is specified
+ * that allows the caller to control which files are returned in the
+ * list. The <code>FileFilter</code> specified is called for each
+ * file returned to determine whether or not that file should be included
+ * in the list.
+ * <p>
+ * A <code>SecurityManager</code> check is made prior to reading the
+ * directory. If read access to the directory is denied, an exception
+ * will be thrown.
+ *
+ * @return An array of <code>File</code> objects for this directory.
+ *
+ * @exception SecurityException If the <code>SecurityManager</code> denies
+ * access to this directory.
+ *
+ * @since 1.2
+ */
+ public File[] listFiles(FileFilter filter)
+ {
+ File[] fobjlist = listFiles((FilenameFilter) null);
+
+ if (fobjlist == null)
+ return null;
+
+ if (filter == null)
+ return fobjlist;
+
+ int count = 0;
+ for (int i = 0; i < fobjlist.length; i++)
+ if (filter.accept(fobjlist[i]) == true)
+ ++count;
+
+ File[] final_list = new File[count];
+ count = 0;
+ for (int i = 0; i < fobjlist.length; i++)
+ if (filter.accept(fobjlist[i]) == true)
+ {
+ final_list[count] = fobjlist[i];
+ ++count;
+ }
+
+ return final_list;
+ }
+
+ /**
+ * This method returns a <code>String</code> that is the path name of the
+ * file as returned by <code>getPath</code>.
+ *
+ * @return A <code>String</code> representation of this file
+ */
+ public String toString()
+ {
+ return path;
+ }
+
+ /**
+ * @return A <code>URI</code> for this object.
+ */
+ public URI toURI()
+ {
+ String abspath = getAbsolutePath();
+
+ if (isDirectory())
+ abspath = abspath + separatorChar;
+
+ if (separatorChar == '\\')
+ abspath = separatorChar + abspath;
+
+ try
+ {
+ return new URI("file", null, null, -1,
+ abspath.replace(separatorChar, '/'),
+ null, null);
+ }
+ catch (URISyntaxException use)
+ {
+ // Can't happen.
+ throw (InternalError) new InternalError("Unconvertible file: "
+ + this).initCause(use);
+ }
+ }
+
+ /**
+ * This method returns a <code>URL</code> with the <code>file:</code>
+ * protocol that represents this file. The exact form of this URL is
+ * system dependent.
+ *
+ * @return A <code>URL</code> for this object.
+ *
+ * @exception MalformedURLException If the URL cannot be created
+ * successfully.
+ */
+ public URL toURL() throws MalformedURLException
+ {
+ // On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt",
+ // while on UNIX, it returns URLs of the form "file:/foo/bar.txt".
+ if (separatorChar == '\\')
+ return new URL ("file:/" + getAbsolutePath().replace ('\\', '/')
+ + (isDirectory() ? "/" : ""));
+ else
+ return new URL ("file:" + getAbsolutePath()
+ + (isDirectory() ? "/" : ""));
+ }
+
+
+ /**
+ * This method creates a directory for the path represented by this object.
+ *
+ * @return <code>true</code> if the directory was created,
+ * <code>false</code> otherwise
+ *
+ * @exception SecurityException If write access is not allowed to this file
+ */
+ public boolean mkdir()
+ {
+ checkWrite();
+ return VMFile.mkdir(path);
+ }
+
+ /**
+ * This method creates a directory for the path represented by this file.
+ * It will also create any intervening parent directories if necessary.
+ *
+ * @return <code>true</code> if the directory was created,
+ * <code>false</code> otherwise
+ *
+ * @exception SecurityException If write access is not allowed to this file
+ */
+ public boolean mkdirs()
+ {
+ String parent = getParent();
+ if (parent == null)
+ {
+ return mkdir();
+ }
+
+ File f = new File(parent);
+ if (!f.exists())
+ {
+ boolean rc = f.mkdirs();
+ if (rc == false)
+ return false;
+ }
+
+ return mkdir();
+ }
+
+ /**
+ * This method creates a temporary file in the specified directory. If
+ * the directory name is null, then this method uses the system temporary
+ * directory. The files created are guaranteed not to currently exist and
+ * the same file name will never be used twice in the same virtual
+ * machine instance.
+ * The system temporary directory is determined by examinging the
+ * <code>java.io.tmpdir</code> system property.
+ * <p>
+ * The <code>prefix</code> parameter is a sequence of at least three
+ * characters that are used as the start of the generated filename. The
+ * <code>suffix</code> parameter is a sequence of characters that is used
+ * to terminate the file name. This parameter may be <code>null</code>
+ * and if it is, the suffix defaults to ".tmp".
+ * <p>
+ * If a <code>SecurityManager</code> exists, then its <code>checkWrite</code>
+ * method is used to verify that this operation is permitted.
+ *
+ * @param prefix The character prefix to use in generating the path name.
+ * @param suffix The character suffix to use in generating the path name.
+ * @param directory The directory to create the file in, or
+ * <code>null</code> for the default temporary directory
+ *
+ * @exception IllegalArgumentException If the patterns is not valid
+ * @exception SecurityException If there is no permission to perform
+ * this operation
+ * @exception IOException If an error occurs
+ *
+ * @since 1.2
+ */
+ public static File createTempFile(String prefix, String suffix,
+ File directory)
+ throws IOException
+ {
+ // Grab the system temp directory if necessary
+ if (directory == null)
+ {
+ String dirname = System.getProperty("java.io.tmpdir");
+ if (dirname == null)
+ throw new IOException("Cannot determine system temporary directory");
+
+ directory = new File(dirname);
+ if (! VMFile.exists(directory.path))
+ throw new IOException("System temporary directory "
+ + directory.getName() + " does not exist.");
+ if (! VMFile.isDirectory(directory.path))
+ throw new IOException("System temporary directory "
+ + directory.getName()
+ + " is not really a directory.");
+ }
+
+ // Check if prefix is at least 3 characters long
+ if (prefix.length() < 3)
+ throw new IllegalArgumentException("Prefix too short: " + prefix);
+
+ // Set default value of suffix
+ if (suffix == null)
+ suffix = ".tmp";
+
+ // Now identify a file name and make sure it doesn't exist.
+ File file;
+ if (!VMFile.IS_DOS_8_3)
+ {
+ do
+ {
+ String filename = prefix + System.currentTimeMillis() + suffix;
+ file = new File(directory, filename);
+ }
+ while (VMFile.exists(file.path));
+ }
+ else
+ {
+ // make sure prefix is not longer than 7 characters
+ if (prefix.length() >= 8)
+ throw new IllegalArgumentException("Prefix too long: " + prefix + "(valid length 3..7)");
+
+ long mask = 0x000000ffffFFFFL >> (prefix.length() * 4);
+ do
+ {
+ int n = (int) (System.currentTimeMillis() & mask);
+ String filename = prefix + java.lang.Integer.toHexString(n) + suffix;
+ file = new File(directory, filename);
+ }
+ while (VMFile.exists(file.path));
+ }
+
+ // Verify that we are allowed to create this file
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkWrite(file.getAbsolutePath());
+
+ // Now create the file and return our file object
+ // XXX - FIXME race condition.
+ VMFile.create(file.getAbsolutePath());
+ return file;
+ }
+
+ /**
+ * This method sets the file represented by this object to be read only.
+ * A read only file or directory cannot be modified. Please note that
+ * GNU systems allow read only files to be deleted if the directory it
+ * is contained in is writable.
+ *
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * otherwise.
+ *
+ * @exception SecurityException If the <code>SecurityManager</code> does
+ * not allow this operation.
+ *
+ * @since 1.2
+ */
+ public boolean setReadOnly()
+ {
+ // Do a security check before trying to do anything else.
+ checkWrite();
+
+ // Test for existence.
+ if (! VMFile.exists(path))
+ return false;
+
+ return VMFile.setReadOnly(path);
+ }
+
+ /**
+ * This method returns an array of filesystem roots. Some operating systems
+ * have volume oriented filesystem. This method provides a mechanism for
+ * determining which volumes exist. GNU systems use a single hierarchical
+ * filesystem, so will have only one "/" filesystem root.
+ *
+ * @return An array of <code>File</code> objects for each filesystem root
+ * available.
+ *
+ * @since 1.2
+ */
+ public static File[] listRoots()
+ {
+ return VMFile.listRoots();
+ }
+
+ /**
+ * This method creates a temporary file in the system temporary directory.
+ * The files created are guaranteed not to currently exist and the same file
+ * name will never be used twice in the same virtual machine instance. The
+ * system temporary directory is determined by examinging the
+ * <code>java.io.tmpdir</code> system property.
+ * <p>
+ * The <code>prefix</code> parameter is a sequence of at least three
+ * characters that are used as the start of the generated filename. The
+ * <code>suffix</code> parameter is a sequence of characters that is used
+ * to terminate the file name. This parameter may be <code>null</code>
+ * and if it is, the suffix defaults to ".tmp".
+ * <p>
+ * If a <code>SecurityManager</code> exists, then its <code>checkWrite</code>
+ * method is used to verify that this operation is permitted.
+ * <p>
+ * This method is identical to calling
+ * <code>createTempFile(prefix, suffix, null)</code>.
+ *
+ * @param prefix The character prefix to use in generating the path name.
+ * @param suffix The character suffix to use in generating the path name.
+ *
+ * @exception IllegalArgumentException If the prefix or suffix are not valid.
+ * @exception SecurityException If there is no permission to perform
+ * this operation
+ * @exception IOException If an error occurs
+ */
+ public static File createTempFile(String prefix, String suffix)
+ throws IOException
+ {
+ return createTempFile(prefix, suffix, null);
+ }
+
+ /**
+ * This method compares the specified <code>File</code> to this one
+ * to test for equality. It does this by comparing the canonical path names
+ * of the files.
+ * <p>
+ * The canonical paths of the files are determined by calling the
+ * <code>getCanonicalPath</code> method on each object.
+ * <p>
+ * This method returns a 0 if the specified <code>Object</code> is equal
+ * to this one, a negative value if it is less than this one
+ * a positive value if it is greater than this one.
+ *
+ * @return An integer as described above
+ *
+ * @since 1.2
+ */
+ public int compareTo(File other)
+ {
+ if (VMFile.IS_CASE_SENSITIVE)
+ return path.compareTo (other.path);
+ else
+ return path.compareToIgnoreCase (other.path);
+ }
+
+ /**
+ * This method compares the specified <code>Object</code> to this one
+ * to test for equality. It does this by comparing the canonical path names
+ * of the files. This method is identical to <code>compareTo(File)</code>
+ * except that if the <code>Object</code> passed to it is not a
+ * <code>File</code>, it throws a <code>ClassCastException</code>
+ * <p>
+ * The canonical paths of the files are determined by calling the
+ * <code>getCanonicalPath</code> method on each object.
+ * <p>
+ * This method returns a 0 if the specified <code>Object</code> is equal
+ * to this one, a negative value if it is less than this one
+ * a positive value if it is greater than this one.
+ *
+ * @return An integer as described above
+ *
+ * @exception ClassCastException If the passed <code>Object</code> is
+ * not a <code>File</code>
+ *
+ * @since 1.2
+ */
+ public int compareTo(Object obj)
+ {
+ return compareTo((File) obj);
+ }
+
+ /**
+ * This method renames the file represented by this object to the path
+ * of the file represented by the argument <code>File</code>.
+ *
+ * @param dest The <code>File</code> object representing the target name
+ *
+ * @return <code>true</code> if the rename succeeds, <code>false</code>
+ * otherwise.
+ *
+ * @exception SecurityException If write access is not allowed to the
+ * file by the <code>SecurityMananger</code>.
+ */
+ public synchronized boolean renameTo(File dest)
+ {
+ checkWrite();
+ dest.checkWrite();
+ // Call our native rename method
+ return VMFile.renameTo(path, dest.path);
+ }
+
+ /**
+ * This method sets the modification time on the file to the specified
+ * value. This is specified as the number of seconds since midnight
+ * on January 1, 1970 GMT.
+ *
+ * @param time The desired modification time.
+ *
+ * @return <code>true</code> if the operation succeeded, <code>false</code>
+ * otherwise.
+ *
+ * @exception IllegalArgumentException If the specified time is negative.
+ * @exception SecurityException If the <code>SecurityManager</code> will
+ * not allow this operation.
+ *
+ * @since 1.2
+ */
+ public boolean setLastModified(long time)
+ {
+ if (time < 0)
+ throw new IllegalArgumentException("Negative modification time: " + time);
+
+ checkWrite();
+ return VMFile.setLastModified(path, time);
+ }
+
+ private void checkWrite()
+ {
+ // Check the SecurityManager
+ SecurityManager s = System.getSecurityManager();
+
+ if (s != null)
+ s.checkWrite(path);
+ }
+
+ private void checkRead()
+ {
+ // Check the SecurityManager
+ SecurityManager s = System.getSecurityManager();
+
+ if (s != null)
+ s.checkRead(path);
+ }
+
+ /**
+ * Calling this method requests that the file represented by this object
+ * be deleted when the virtual machine exits. Note that this request cannot
+ * be cancelled. Also, it will only be carried out if the virtual machine
+ * exits normally.
+ *
+ * @exception SecurityException If deleting of the file is not allowed
+ *
+ * @since 1.2
+ */
+ public void deleteOnExit()
+ {
+ // Check the SecurityManager
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkDelete(path);
+
+ DeleteFileHelper.add(this);
+ }
+
+ private void writeObject(ObjectOutputStream oos) throws IOException
+ {
+ oos.defaultWriteObject();
+ oos.writeChar(separatorChar);
+ }
+
+ private void readObject(ObjectInputStream ois)
+ throws ClassNotFoundException, IOException
+ {
+ ois.defaultReadObject();
+
+ // If the file was from an OS with a different dir separator,
+ // fixup the path to use the separator on this OS.
+ char oldSeparatorChar = ois.readChar();
+
+ if (oldSeparatorChar != separatorChar)
+ path = path.replace(oldSeparatorChar, separatorChar);
+ }
+
+} // class File
+
diff --git a/libjava/classpath/java/io/FileDescriptor.java b/libjava/classpath/java/io/FileDescriptor.java
new file mode 100644
index 00000000000..d300c9cb617
--- /dev/null
+++ b/libjava/classpath/java/io/FileDescriptor.java
@@ -0,0 +1,139 @@
+/* FileDescriptor.java -- Opaque file handle class
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.java.nio.channels.FileChannelImpl;
+
+import java.nio.channels.ByteChannel;
+import java.nio.channels.FileChannel;
+
+/**
+ * This class represents an opaque file handle as a Java class. It should
+ * be used only to pass to other methods that expect an object of this
+ * type. No system specific information can be obtained from this object.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @date September 24, 1998
+ */
+public final class FileDescriptor
+{
+ /**
+ * A <code>FileDescriptor</code> representing the system standard input
+ * stream. This will usually be accessed through the
+ * <code>System.in</code>variable.
+ */
+ public static final FileDescriptor in
+ = new FileDescriptor (FileChannelImpl.in);
+
+ /**
+ * A <code>FileDescriptor</code> representing the system standard output
+ * stream. This will usually be accessed through the
+ * <code>System.out</code>variable.
+ */
+ public static final FileDescriptor out
+ = new FileDescriptor (FileChannelImpl.out);
+
+ /**
+ * A <code>FileDescriptor</code> representing the system standard error
+ * stream. This will usually be accessed through the
+ * <code>System.err</code>variable.
+ */
+ public static final FileDescriptor err
+ = new FileDescriptor (FileChannelImpl.err);
+
+ final ByteChannel channel;
+
+ /**
+ * This method is used to initialize an invalid FileDescriptor object.
+ */
+ public FileDescriptor()
+ {
+ channel = null;
+ }
+
+ /**
+ * This method is used to initialize a FileDescriptor object.
+ */
+ FileDescriptor(ByteChannel channel)
+ {
+ this.channel = channel;
+ }
+
+
+ /**
+ * This method forces all data that has not yet been physically written to
+ * the underlying storage medium associated with this
+ * <code>FileDescriptor</code>
+ * to be written out. This method will not return until all data has
+ * been fully written to the underlying device. If the device does not
+ * support this functionality or if an error occurs, then an exception
+ * will be thrown.
+ */
+ public void sync () throws SyncFailedException
+ {
+ if (channel instanceof FileChannel)
+ {
+ try
+ {
+ ((FileChannel) channel).force(true);
+ }
+ catch (IOException ex)
+ {
+ if (ex instanceof SyncFailedException)
+ throw (SyncFailedException) ex;
+ else
+ throw new SyncFailedException(ex.toString());
+ }
+ }
+ }
+
+ /**
+ * This methods tests whether or not this object represents a valid open
+ * native file handle.
+ *
+ * @return <code>true</code> if this object represents a valid
+ * native file handle, <code>false</code> otherwise
+ */
+ public boolean valid ()
+ {
+ return channel != null && channel.isOpen();
+ }
+}
diff --git a/libjava/classpath/java/io/FileFilter.java b/libjava/classpath/java/io/FileFilter.java
new file mode 100644
index 00000000000..e57ac9fd060
--- /dev/null
+++ b/libjava/classpath/java/io/FileFilter.java
@@ -0,0 +1,65 @@
+/* FileFilter.java -- Filter a list of pathnames
+ Copyright (C) 1998,2003 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.io;
+
+/**
+ * This interface has one method which is used for filtering pathnames
+ * returned in a pathname listing. It is currently used by the
+ * <code>File.listFiles(FileFilter)</code> method.
+ * <p>
+ * The method in this interface determines if a particular pathname should
+ * or should not be included in the pathname listing.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ *
+ * @see File#listFiles(java.io.FileFilter)
+ */
+public interface FileFilter
+{
+ /**
+ * This method determines whether or not a given pathname should be included
+ * in a pathname listing.
+ *
+ * @param pathname The pathname to test
+ *
+ * @return <code>true</code> if the path should be included in the list,
+ * <code>false</code> otherwise.
+ */
+ boolean accept(File pathname);
+}
diff --git a/libjava/classpath/java/io/FileInputStream.java b/libjava/classpath/java/io/FileInputStream.java
new file mode 100644
index 00000000000..8ca38b02fc4
--- /dev/null
+++ b/libjava/classpath/java/io/FileInputStream.java
@@ -0,0 +1,309 @@
+/* FileInputStream.java -- An input stream that reads from disk files.
+ Copyright (C) 1998, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.java.nio.channels.FileChannelImpl;
+
+import java.nio.channels.FileChannel;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This class is a stream that reads its bytes from a file.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class FileInputStream extends InputStream
+{
+ /**
+ * This is the native file handle for the file this stream is reading from
+ */
+ private FileDescriptor fd;
+
+ private FileChannelImpl ch;
+
+ /**
+ * This method initializes a <code>FileInputStream</code> to read from the
+ * specified named file. A security check is first made to determine
+ * whether or not access to this file is allowed. This is done by
+ * calling the <code>checkRead()</code> method of the
+ * <code>SecurityManager</code>
+ * (if one exists) with the name of this file. An exception is thrown
+ * if reading is not allowed. If the file does not exist, an exception
+ * is also thrown.
+ *
+ * @param name The name of the file this stream should read from
+ *
+ * @exception SecurityException If read access to the file is not allowed
+ * @exception FileNotFoundException If the file does not exist
+ * or if it is a directory
+ */
+ public FileInputStream(String name) throws FileNotFoundException
+ {
+ this(new File(name));
+ }
+
+ /**
+ * This method initializes a <code>FileInputStream</code> to read from the
+ * specified <code>File</code> object. A security check is first
+ * made to determine
+ * whether or not access to this file is allowed. This is done by
+ * calling the <code>checkRead()</code> method of the
+ * <code>SecurityManager</code>
+ * (if one exists) with the name of this file. An exception is thrown
+ * if reading is not allowed. If the file does not exist, an exception
+ * is also thrown.
+ *
+ * @param file The <code>File</code> object this stream should read from
+ *
+ * @exception SecurityException If read access to the file is not allowed
+ * @exception FileNotFoundException If the file does not exist
+ * or if it is a directory.
+ */
+ public FileInputStream(File file) throws FileNotFoundException
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkRead(file.getPath());
+
+ ch = FileChannelImpl.create(file, FileChannelImpl.READ);
+ }
+
+ /**
+ * This method initializes a <code>FileInputStream</code> to read from the
+ * specified <code>FileDescriptor</code> object. A security
+ * check is first made to
+ * determine whether or not access to this file is allowed. This is done by
+ * calling the <code>checkRead()</code> method of the
+ * <code>SecurityManager</code>
+ * (if one exists) with the specified <code>FileDescriptor</code>
+ * An exception is
+ * thrown if reading is not allowed.
+ *
+ * @param fdObj The <code>FileDescriptor</code> object this stream
+ * should read from
+ *
+ * @exception SecurityException If read access to the file is not allowed
+ */
+ public FileInputStream(FileDescriptor fdObj)
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkRead(fdObj);
+
+ fd = fdObj;
+ ch = (FileChannelImpl) fdObj.channel;
+ }
+
+ FileInputStream(FileChannelImpl ch)
+ {
+ this.ch = ch;
+ }
+
+ /**
+ * This method returns the number of bytes that can be read from this
+ * stream before a read can block. A return of 0 indicates that blocking
+ * might (or might not) occur on the very next read attempt.
+ * <p>
+ * This method returns the number of unread bytes remaining in the file if
+ * the descriptor being read from is an actual file. If this method is
+ * reading from a ''special'' file such a the standard input, this method
+ * will return the appropriate value for the stream being read.
+ * <p>
+ * Be aware that reads on plain files that do not reside locally might
+ * possibly block even if this method says they should not. For example,
+ * a remote server might crash, preventing an NFS mounted file from being
+ * read.
+ *
+ * @return The number of bytes that can be read before blocking could occur
+ *
+ * @exception IOException If an error occurs
+ */
+ public int available() throws IOException
+ {
+ return ch.available();
+ }
+
+ /**
+ * This method closes the stream. Any futher attempts to read from the
+ * stream will likely generate an IOException since the underlying file
+ * will be closed.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public void close() throws IOException
+ {
+ ch.close();
+ }
+
+ protected void finalize() throws IOException
+ {
+ // We don't actually need this, but we include it because it is
+ // mentioned in the JCL.
+ }
+
+ /**
+ * This method returns a <code>FileDescriptor</code> object representing the
+ * underlying native file handle of the file this stream is reading
+ * from
+ *
+ * @return A <code>FileDescriptor</code> for this stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public final FileDescriptor getFD() throws IOException
+ {
+ synchronized (this)
+ {
+ if (fd == null)
+ fd = new FileDescriptor (ch);
+ return fd;
+ }
+ }
+
+ /**
+ * This method reads an unsigned byte from the input stream and returns it
+ * as an int in the range of 0-255. This method also will return -1 if
+ * the end of the stream has been reached.
+ * <p>
+ * This method will block until the byte can be read.
+ *
+ * @return The byte read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ return ch.read();
+ }
+
+ /**
+ * This method reads bytes from a stream and stores them into a caller
+ * supplied buffer. This method attempts to completely fill the buffer,
+ * but can return before doing so. The actual number of bytes read is
+ * returned as an int. A -1 is returned to indicate the end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * This method operates by calling an overloaded read method like so:
+ * <code>read(buf, 0, buf.length)</code>
+ *
+ * @param buf The buffer into which the bytes read will be stored.
+ *
+ * @return The number of bytes read or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public int read(byte[] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ /**
+ * This method read bytes from a stream and stores them into a caller
+ * supplied buffer. It starts storing the data at index
+ * <code>offset</code> into
+ * the buffer and attempts to read <code>len</code> bytes. This method can
+ * return before reading the number of bytes requested. The actual number
+ * of bytes read is returned as an int. A -1 is returned to indicate the
+ * end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ *
+ * @param buf The array into which the bytes read should be stored
+ * @param offset The offset into the array to start storing bytes
+ * @param len The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public int read(byte[] buf, int offset, int len) throws IOException
+ {
+ if (offset < 0
+ || len < 0
+ || offset + len > buf.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ return ch.read(buf, offset, len);
+ }
+
+ /**
+ * This method skips the specified number of bytes in the stream. It
+ * returns the actual number of bytes skipped, which may be less than the
+ * requested amount.
+ * <p>
+ * @param numBytes The requested number of bytes to skip
+ *
+ * @return The actual number of bytes skipped.
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized long skip (long numBytes) throws IOException
+ {
+ if (numBytes < 0)
+ throw new IllegalArgumentException ("Can't skip negative bytes: " +
+ numBytes);
+
+ if (numBytes == 0)
+ return 0;
+
+ long oldPos = ch.position ();
+ ch.position(oldPos + numBytes);
+ return ch.position() - oldPos;
+ }
+
+ /**
+ * This method creates a java.nio.channels.FileChannel.
+ * Nio does not allow one to create a file channel directly.
+ * A file channel must be created by first creating an instance of
+ * Input/Output/RandomAccessFile and invoking the getChannel() method on it.
+ */
+ public synchronized FileChannel getChannel ()
+ {
+ return ch;
+ }
+
+} // class FileInputStream
+
diff --git a/libjava/classpath/java/io/FileNotFoundException.java b/libjava/classpath/java/io/FileNotFoundException.java
new file mode 100644
index 00000000000..3c11e296072
--- /dev/null
+++ b/libjava/classpath/java/io/FileNotFoundException.java
@@ -0,0 +1,73 @@
+/* FileNotFoundException.java -- the requested file could not be found
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown when an attempt is made to access a file that
+ * does not exist, or is inaccessible for some other reason (such as writing
+ * a read-only file).
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class FileNotFoundException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -897856973823710492L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ public FileNotFoundException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public FileNotFoundException(String message)
+ {
+ super(message);
+ }
+} // class FileNotFoundException
diff --git a/libjava/classpath/java/io/FileOutputStream.java b/libjava/classpath/java/io/FileOutputStream.java
new file mode 100644
index 00000000000..10ea6b536cb
--- /dev/null
+++ b/libjava/classpath/java/io/FileOutputStream.java
@@ -0,0 +1,296 @@
+/* FileOutputStream.java -- Writes to a file on disk.
+ Copyright (C) 1998, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.java.nio.channels.FileChannelImpl;
+
+import java.nio.channels.FileChannel;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.1.
+ */
+
+/**
+ * This classes allows a stream of data to be written to a disk file or
+ * any open <code>FileDescriptor</code>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class FileOutputStream extends OutputStream
+{
+ private FileDescriptor fd;
+
+ private FileChannelImpl ch;
+
+ /**
+ * This method initializes a <code>FileOutputStream</code> object to write
+ * to the named file. The file is created if it does not exist, and
+ * the bytes written are written starting at the beginning of the file if
+ * the <code>append</code> argument is <code>false</code> or at the end
+ * of the file if the <code>append</code> argument is true.
+ * <p>
+ * Before opening a file, a security check is performed by calling the
+ * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
+ * one exists) with the name of the file to be opened. An exception is
+ * thrown if writing is not allowed.
+ *
+ * @param path The name of the file this stream should write to
+ * @param append <code>true</code> to append bytes to the end of the file,
+ * or <code>false</code> to write bytes to the beginning
+ *
+ * @exception SecurityException If write access to the file is not allowed
+ * @exception FileNotFoundException If a non-security error occurs
+ */
+ public FileOutputStream (String path, boolean append)
+ throws SecurityException, FileNotFoundException
+ {
+ this (new File(path), append);
+ }
+
+ /**
+ * This method initializes a <code>FileOutputStream</code> object to write
+ * to the named file. The file is created if it does not exist, and
+ * the bytes written are written starting at the beginning of the file.
+ * <p>
+ * Before opening a file, a security check is performed by calling the
+ * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
+ * one exists) with the name of the file to be opened. An exception is
+ * thrown if writing is not allowed.
+ *
+ * @param path The name of the file this stream should write to
+ *
+ * @exception SecurityException If write access to the file is not allowed
+ * @exception FileNotFoundException If a non-security error occurs
+ */
+ public FileOutputStream (String path)
+ throws SecurityException, FileNotFoundException
+ {
+ this (path, false);
+ }
+
+ /**
+ * This method initializes a <code>FileOutputStream</code> object to write
+ * to the specified <code>File</code> object. The file is created if it
+ * does not exist, and the bytes written are written starting at the
+ * beginning of the file.
+ * <p>
+ * Before opening a file, a security check is performed by calling the
+ * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
+ * one exists) with the name of the file to be opened. An exception is
+ * thrown if writing is not allowed.
+ *
+ * @param file The <code>File</code> object this stream should write to
+ *
+ * @exception SecurityException If write access to the file is not allowed
+ * @exception FileNotFoundException If a non-security error occurs
+ */
+ public FileOutputStream (File file)
+ throws SecurityException, FileNotFoundException
+ {
+ this (file, false);
+ }
+
+ /**
+ * This method initializes a <code>FileOutputStream</code> object to write
+ * to the specified <code>File</code> object. The file is created if it
+ * does not exist, and the bytes written are written starting at the
+ * beginning of the file if the <code>append</code> parameter is
+ * <code>false</code>. Otherwise bytes are written at the end of the
+ * file.
+ * <p>
+ * Before opening a file, a security check is performed by calling the
+ * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
+ * one exists) with the name of the file to be opened. An exception is
+ * thrown if writing is not allowed.
+ *
+ * @param file The <code>File</code> object this stream should write to
+ * @param append <code>true</code> to append bytes to the end of the file,
+ * or <code>false</code> to write bytes to the beginning
+ *
+ * @exception SecurityException If write access to the file is not allowed
+ * @exception FileNotFoundException If a non-security error occurs
+ */
+ public FileOutputStream (File file, boolean append)
+ throws FileNotFoundException
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkWrite(file.getPath());
+
+ ch = FileChannelImpl.create(file, (append
+ ? FileChannelImpl.WRITE
+ | FileChannelImpl.APPEND
+ : FileChannelImpl.WRITE));
+ }
+
+ /**
+ * This method initializes a <code>FileOutputStream</code> object to write
+ * to the file represented by the specified <code>FileDescriptor</code>
+ * object. This method does not create any underlying disk file or
+ * reposition the file pointer of the given descriptor. It assumes that
+ * this descriptor is ready for writing as is.
+ * <p>
+ * Before opening a file, a security check is performed by calling the
+ * <code>checkWrite</code> method of the <code>SecurityManager</code> (if
+ * one exists) with the specified <code>FileDescriptor</code> as an argument.
+ * An exception is thrown if writing is not allowed.
+ *
+ * @param fdObj The <code>FileDescriptor</code> this stream should write to
+ *
+ * @exception SecurityException If write access to the file is not allowed
+ */
+ public FileOutputStream (FileDescriptor fdObj)
+ throws SecurityException
+ {
+ // Hmm, no other exception but this one to throw, but if the descriptor
+ // isn't valid, we surely don't have "permission" to write to it.
+ if (!fdObj.valid())
+ throw new SecurityException("Invalid FileDescriptor");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkWrite(fdObj);
+
+ fd = fdObj;
+ ch = (FileChannelImpl) fdObj.channel;
+ }
+
+ FileOutputStream(FileChannelImpl ch)
+ {
+ this.ch = ch;
+ }
+
+ protected void finalize () throws IOException
+ {
+ // We don't actually need this, but we include it because it is
+ // mentioned in the JCL.
+ }
+
+ /**
+ * This method returns a <code>FileDescriptor</code> object representing
+ * the file that is currently being written to
+ *
+ * @return A <code>FileDescriptor</code> object for this stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public final FileDescriptor getFD () throws IOException
+ {
+ synchronized (this)
+ {
+ if (fd == null)
+ fd = new FileDescriptor (ch);
+ return fd;
+ }
+ }
+
+ /**
+ * This method writes a single byte of data to the file.
+ *
+ * @param b The byte of data to write, passed as an <code>int</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (int b) throws IOException
+ {
+ ch.write (b);
+ }
+
+ /**
+ * This method writes all the bytes in the specified array to the
+ * file.
+ *
+ * @param buf The array of bytes to write to the file
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (byte[] buf)
+ throws IOException
+ {
+ write (buf, 0, buf.length);
+ }
+
+ /**
+ * This method writes <code>len</code> bytes from the byte array
+ * <code>buf</code> to the file starting at index <code>offset</code>.
+ *
+ * @param buf The array of bytes to write to the file
+ * @param offset The offset into the array to start writing bytes from
+ * @param len The number of bytes to write to the file
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (byte[] buf, int offset, int len)
+ throws IOException
+ {
+ if (offset < 0
+ || len < 0
+ || offset + len > buf.length)
+ throw new ArrayIndexOutOfBoundsException ();
+
+ ch.write (buf, offset, len);
+ }
+
+ /**
+ * This method closes the underlying file. Any further attempts to
+ * write to this stream will likely generate an exception since the
+ * file is closed.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close () throws IOException
+ {
+ ch.close();
+ }
+
+ /**
+ * This method creates a java.nio.channels.FileChannel.
+ * Nio does not allow one to create a file channel directly.
+ * A file channel must be created by first creating an instance of
+ * Input/Output/RandomAccessFile and invoking the getChannel() method on it.
+ */
+ public synchronized FileChannel getChannel()
+ {
+ return ch;
+ }
+
+} // class FileOutputStream
+
diff --git a/libjava/classpath/java/io/FilePermission.java b/libjava/classpath/java/io/FilePermission.java
new file mode 100644
index 00000000000..356787bfa72
--- /dev/null
+++ b/libjava/classpath/java/io/FilePermission.java
@@ -0,0 +1,292 @@
+/* FilePermission.java --
+ Copyright (C) 1998, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import java.security.Permission;
+
+public final class FilePermission extends Permission implements Serializable
+{
+ private static final long serialVersionUID = 7930732926638008763L;
+
+ private static final String CURRENT_DIRECTORY =
+ System.getProperty("user.dir");
+
+ private static final String ALL_FILES = "<<ALL FILES>>";
+
+ private boolean readPerm = false;
+ private boolean writePerm = false;
+ private boolean executePerm = false;
+ private boolean deletePerm = false;
+ private final String actionsString;
+
+ // Checks and caches the actions
+ private void checkPerms() throws IllegalArgumentException
+ {
+ String action;
+ int i = actionsString.indexOf(',');
+ int startI = 0;
+ while (i != -1)
+ {
+ action = actionsString.substring(startI, i).trim().toLowerCase();
+ if (action.equals("read"))
+ readPerm = true;
+ else if (action.equals("write"))
+ writePerm = true;
+ else if (action.equals("execute"))
+ executePerm = true;
+ else if (action.equals("delete"))
+ deletePerm = true;
+ else
+ throw new IllegalArgumentException("Unknown action: " + action);
+
+ startI = i + 1;
+ i = actionsString.indexOf(',', startI);
+ }
+
+ action = actionsString.substring(startI).trim().toLowerCase();
+ if (action.equals("read"))
+ readPerm = true;
+ else if (action.equals("write"))
+ writePerm = true;
+ else if (action.equals("execute"))
+ executePerm = true;
+ else if (action.equals("delete"))
+ deletePerm = true;
+ else
+ throw new IllegalArgumentException("Unknown action: " + action);
+ }
+
+ /**
+ * Create a new FilePermission.
+ *
+ * @param pathExpression an expression specifying the paths this
+ * permission represents.
+ * @param actionsString a comma-separated list of the actions this
+ * permission represents. The actions must be "read", "write",
+ * "execute" and/or "delete".
+ */
+ public FilePermission(String pathExpression, String actionsString)
+ {
+ // FIXME: what to do when the file string is malformed?
+ super(pathExpression);
+ if (pathExpression == null)
+ throw new NullPointerException("pathExpression");
+ if (actionsString == null)
+ throw new IllegalArgumentException("actionsString");
+ this.actionsString = actionsString;
+ checkPerms();
+ }
+
+ /**
+ * Get the actions this FilePermission supports.
+ * @return the String representing the actions this FilePermission supports.
+ */
+ public String getActions()
+ {
+ return actionsString;
+ }
+
+ /**
+ * Get the hash code for this Object.<P>
+ * FilePermission's hash code is calculated as the exclusive or of the
+ * target
+ * String's hash code and the action String's hash code.
+ * @specnote Sun did not specify how to calculate the hash code;
+ * I made this up.
+ * @return the hash code for this Object.
+ */
+ public int hashCode()
+ {
+ return getName().hashCode() ^ actionsString.hashCode();
+ }
+
+ /**
+ * Check two FilePermissions for semantic equality.
+ * Two FilePermissions are exactly equivalent if they have identical path
+ * expressions and have exactly the same access permissions.
+ * @param o the Object to compare to.
+ * @return whether the Objects are semantically equivalent.
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof FilePermission))
+ return false;
+ FilePermission p = (FilePermission) o;
+
+ String f1 = getName();
+ String f2 = p.getName();
+
+ // Compare names, taking into account if they refer to a directory
+ // and one has a separator and the other does not.
+ if (f1.length() > 0 && f1.charAt(f1.length() - 1) == File.separatorChar)
+ {
+ if (f2.length() > 0
+ && f2.charAt(f2.length() - 1) == File.separatorChar)
+ {
+ if (! f2.equals(f1))
+ return false;
+ }
+ else
+ {
+ if (! f2.equals(f1.substring(0, f1.length() - 1)))
+ return false;
+ }
+ }
+ else
+ {
+ if (f2.length() > 0
+ && f2.charAt(f2.length() - 1) == File.separatorChar)
+ {
+ if (! f1.equals(f2.substring(0, f2.length() - 1)))
+ return false;
+ }
+ else
+ {
+ if (! f1.equals(f2))
+ return false;
+ }
+ }
+ return (readPerm == p.readPerm
+ && writePerm == p.writePerm
+ && executePerm == p.executePerm
+ && deletePerm == p.deletePerm);
+ }
+
+ /**
+ * Check to see if this permission implies another.
+ * Permission A implies permission B if these things are all true:
+ * <OL>
+ * <LI>A and B are both FilePermissions.</LI>
+ * <LI>All possible files in B are included in A
+ * (possibly more are in A).</LI>
+ * <LI>All actions B supports, A also supports.</LI>
+ * </OL>
+ * @param p the Permission to compare against.
+ * @return whether this Permission implies p
+ */
+ public boolean implies(Permission p)
+ {
+ if (! (p instanceof FilePermission))
+ return false;
+
+ String f1 = getName();
+
+ if (f1.equals(ALL_FILES))
+ return true;
+
+ FilePermission fp = (FilePermission) p;
+ String f2 = fp.getName();
+
+ if (f1.charAt(0) != File.separatorChar)
+ f1 = CURRENT_DIRECTORY + f1;
+ if (f2.charAt(0) != File.separatorChar)
+ f2 = CURRENT_DIRECTORY + f2;
+
+ String sub1;
+
+ switch (f1.charAt(f1.length() - 1))
+ {
+ case '*':
+ sub1 = f1.substring(0, f1.length() - 1); // chop off "*"
+ if (f2.length() <= sub1.length())
+ {
+ // If it's smaller, there is no way it could be part of
+ // this directory. If it's the same (or length - 1), it
+ // could be the same directory but specifies access to
+ // the directory rather than the files in it.
+ return false;
+ }
+ else if (f2.charAt(sub1.length() - 1) == File.separatorChar)
+ {
+ // Make sure the part before the "/" is the same.
+ if (! f2.substring(0, sub1.length()).equals(sub1))
+ return false;
+ // Make sure there are no subdirectories specified
+ // underneath this one.
+ if (f2.substring(sub1.length() + 1).indexOf(File.separatorChar)
+ != -1)
+ return false;
+ }
+ else
+ {
+ // Obviously not equal: f2 is either not a directory or
+ // is not the same directory (its name continues further
+ // than we want).
+ return false;
+ }
+ break;
+ case '-':
+ // Chop off "/-".
+ sub1 = f1.substring(0, f1.length() - 2);
+ if (f2.length() < sub1.length())
+ {
+ // If it's smaller, there is no way it could be part of
+ // this directory.
+ return false;
+ }
+ else if (f2.length() > sub1.length()
+ && f2.charAt(sub1.length()) != File.separatorChar)
+ return false;
+ else if (! f2.substring(0, sub1.length()).equals(sub1))
+ return false;
+ break;
+
+ default:
+ if (f2.charAt(f2.length() - 1) == File.separatorChar)
+ {
+ if (! f1.equals(f2.substring(0, f2.length() - 1)))
+ return false;
+ }
+ else if (!f1.equals(f2))
+ return false;
+ break;
+ }
+
+ if (readPerm && ! fp.readPerm)
+ return false;
+ if (writePerm && ! fp.writePerm)
+ return false;
+ if (executePerm && ! fp.executePerm)
+ return false;
+ if (deletePerm && ! fp.deletePerm)
+ return false;
+
+ return true;
+ }
+}
diff --git a/libjava/classpath/java/io/FileReader.java b/libjava/classpath/java/io/FileReader.java
new file mode 100644
index 00000000000..4a1dd5ff4ce
--- /dev/null
+++ b/libjava/classpath/java/io/FileReader.java
@@ -0,0 +1,92 @@
+/* FileReader.java -- Convenience class for reading characters from a file
+ Copyright (C) 1998, 2000, 2003 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.io;
+
+/**
+ * This class provides a convenient way to set up a <code>Reader</code>
+ * to read from a file. It opens the specified file for reading and creates
+ * the <code>InputStreamReader</code> to read from the
+ * resulting <code>FileInputStream</code>. This class can only be used
+ * to read from files using the default character encoding. Use
+ * <code>InputStreamReader</code> directly to use a non-default encoding.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class FileReader extends InputStreamReader
+{
+ /**
+ * This method initializes a <code>FileReader</code> instance to read from
+ * the specified <code>File</code> object.
+ *
+ * @param file The <code>File</code> object representing the file to read from
+ *
+ * @exception FileNotFoundException If the file is not found or some other
+ * error occurs
+ */
+ public FileReader(File file) throws FileNotFoundException
+ {
+ super(new FileInputStream(file));
+ }
+
+ /**
+ * This method initializes a <code>FileReader</code> instance to read from
+ * this specified <code>FileDescriptor</code> object.
+ *
+ * @param fd The <code>FileDescriptor</code> to read from.
+ */
+ public FileReader(FileDescriptor fd)
+ {
+ super(new FileInputStream(fd));
+ }
+
+ /**
+ * This method initializes a <code>FileReader</code> instance to read from
+ * the specified named file.
+ *
+ * @param name The name of the file to read from
+ *
+ * @exception FileNotFoundException If the file is not found or some other
+ * error occurs
+ */
+ public FileReader(String name) throws FileNotFoundException
+ {
+ super(new FileInputStream(name));
+ }
+} // class FileReader
+
diff --git a/libjava/classpath/java/io/FileWriter.java b/libjava/classpath/java/io/FileWriter.java
new file mode 100644
index 00000000000..b34db83231e
--- /dev/null
+++ b/libjava/classpath/java/io/FileWriter.java
@@ -0,0 +1,137 @@
+/* FileWriter.java -- Convenience class for writing to files.
+ Copyright (C) 1998, 1999, 2001, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.1.
+ */
+
+/**
+ * This is a convenience class for writing to files. It creates an
+ * <code>FileOutputStream</code> and initializes an
+ * <code>OutputStreamWriter</code> to write to it.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class FileWriter extends OutputStreamWriter
+{
+ /**
+ * This method initializes a new <code>FileWriter</code> object to write
+ * to the specified <code>File</code> object.
+ *
+ * @param file The <code>File</code> object to write to.
+ *
+ * @throws SecurityException If writing to this file is forbidden by the
+ * <code>SecurityManager</code>.
+ * @throws IOException If any other error occurs
+ */
+ public FileWriter(File file) throws SecurityException, IOException
+ {
+ super(new FileOutputStream(file));
+ }
+
+ /**
+ * This method initializes a new <code>FileWriter</code> object to write
+ * to the specified <code>File</code> object.
+ *
+ * @param file The <code>File</code> object to write to.
+ * @param append <code>true</code> to start adding data at the end of the
+ * file, <code>false</code> otherwise.
+ *
+ * @throws SecurityException If writing to this file is forbidden by the
+ * <code>SecurityManager</code>.
+ * @throws IOException If any other error occurs
+ */
+ public FileWriter(File file, boolean append) throws IOException
+ {
+ super(new FileOutputStream(file, append));
+ }
+
+ /**
+ * This method initializes a new <code>FileWriter</code> object to write
+ * to the specified <code>FileDescriptor</code> object.
+ *
+ * @param fd The <code>FileDescriptor</code> object to write to
+ *
+ * @throws SecurityException If writing to this file is forbidden by the
+ * <code>SecurityManager</code>.
+ */
+ public FileWriter(FileDescriptor fd) throws SecurityException
+ {
+ super(new FileOutputStream(fd));
+ }
+
+ /**
+ * This method intializes a new <code>FileWriter</code> object to
+ * write to the
+ * specified named file.
+ *
+ * @param name The name of the file to write to
+ *
+ * @throws SecurityException If writing to this file is forbidden by the
+ * <code>SecurityManager</code>.
+ * @throws IOException If any other error occurs
+ */
+ public FileWriter(String name) throws IOException
+ {
+ super(new FileOutputStream(name));
+ }
+
+ /**
+ * This method intializes a new <code>FileWriter</code> object to
+ * write to the
+ * specified named file. This form of the constructor allows the caller
+ * to determin whether data should be written starting at the beginning or
+ * the end of the file.
+ *
+ * @param name The name of the file to write to
+ * @param append <code>true</code> to start adding data at the end of the
+ * file, <code>false</code> otherwise.
+ *
+ * @throws SecurityException If writing to this file is forbidden by the
+ * <code>SecurityManager</code>.
+ * @throws IOException If any other error occurs
+ */
+ public FileWriter(String name, boolean append) throws IOException
+ {
+ super(new FileOutputStream(name, append));
+ }
+}
diff --git a/libjava/classpath/java/io/FilenameFilter.java b/libjava/classpath/java/io/FilenameFilter.java
new file mode 100644
index 00000000000..57b4d3b182c
--- /dev/null
+++ b/libjava/classpath/java/io/FilenameFilter.java
@@ -0,0 +1,76 @@
+/* FilenameFilter.java -- Filter a list of filenames
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to 1.1.
+ */
+
+/**
+ * This interface has one method which is used for filtering filenames
+ * returned in a directory listing. It is currently used by the
+ * <code>File.list(FilenameFilter)</code> method and by the filename
+ * dialog in AWT.
+ * <p>
+ * The method in this interface determines if a particular file should
+ * or should not be included in the file listing.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ *
+ * @see File#listFiles(java.io.FilenameFilter)
+ * @see java.awt.FileDialog#setFilenameFilter(java.io.FilenameFilter)
+ */
+public interface FilenameFilter
+{
+ /**
+ * This method determines whether or not a given file should be included
+ * in a directory listing.
+ *
+ * @param dir The <code>File</code> instance for the directory being read
+ * @param name The name of the file to test
+ *
+ * @return <code>true</code> if the file should be included in the list,
+ * <code>false</code> otherwise.
+ */
+ boolean accept(File dir, String name);
+
+} // interface FilenameFilter
+
diff --git a/libjava/classpath/java/io/FilterInputStream.java b/libjava/classpath/java/io/FilterInputStream.java
new file mode 100644
index 00000000000..d3cb9e4f71f
--- /dev/null
+++ b/libjava/classpath/java/io/FilterInputStream.java
@@ -0,0 +1,203 @@
+/* FilterInputStream.java -- Base class for classes that filter input
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This is the common superclass of all standard classes that filter
+ * input. It acts as a layer on top of an underlying <code>InputStream</code>
+ * and simply redirects calls made to it to the subordinate InputStream
+ * instead. Subclasses of this class perform additional filtering
+ * functions in addition to simply redirecting the call.
+ * <p>
+ * This class is not abstract. However, since it only redirects calls
+ * to a subordinate <code>InputStream</code> without adding any functionality
+ * on top of it, this class should not be used directly. Instead, various
+ * subclasses of this class should be used. This is enforced with a
+ * protected constructor. Do not try to hack around it.
+ * <p>
+ * When creating a subclass of <code>FilterInputStream</code>, override the
+ * appropriate methods to implement the desired filtering. However, note
+ * that the <code>read(byte[])</code> method does not need to be overridden
+ * as this class redirects calls to that method to
+ * <code>read(byte[], int, int)</code> instead of to the subordinate
+ * <code>InputStream read(byte[])</code> method.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class FilterInputStream extends InputStream
+{
+ /**
+ * This is the subordinate <code>InputStream</code> to which method calls
+ * are redirected
+ */
+ protected InputStream in;
+
+ /**
+ * Create a <code>FilterInputStream</code> with the specified subordinate
+ * <code>InputStream</code>.
+ *
+ * @param in The subordinate <code>InputStream</code>
+ */
+ protected FilterInputStream(InputStream in)
+ {
+ this.in = in;
+ }
+
+ /**
+ * Calls the <code>in.mark(int)</code> method.
+ *
+ * @param readlimit The parameter passed to <code>in.mark(int)</code>
+ */
+ public void mark(int readlimit)
+ {
+ in.mark(readlimit);
+ }
+
+ /**
+ * Calls the <code>in.markSupported()</code> method.
+ *
+ * @return <code>true</code> if mark/reset is supported, <code>false</code>
+ * otherwise
+ */
+ public boolean markSupported()
+ {
+ return in.markSupported();
+ }
+
+ /**
+ * Calls the <code>in.reset()</code> method.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void reset() throws IOException
+ {
+ in.reset();
+ }
+
+ /**
+ * Calls the <code>in.available()</code> method.
+ *
+ * @return The value returned from <code>in.available()</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public int available() throws IOException
+ {
+ return in.available();
+ }
+
+ /**
+ * Calls the <code>in.skip(long)</code> method
+ *
+ * @param numBytes The requested number of bytes to skip.
+ *
+ * @return The value returned from <code>in.skip(long)</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public long skip(long numBytes) throws IOException
+ {
+ return in.skip(numBytes);
+ }
+
+ /**
+ * Calls the <code>in.read()</code> method
+ *
+ * @return The value returned from <code>in.read()</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ return in.read();
+ }
+
+ /**
+ * Calls the <code>read(byte[], int, int)</code> overloaded method.
+ * Note that
+ * this method does not redirect its call directly to a corresponding
+ * method in <code>in</code>. This allows subclasses to override only the
+ * three argument version of <code>read</code>.
+ *
+ * @param buf The buffer to read bytes into
+ *
+ * @return The value retured from <code>in.read(byte[], int, int)</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read(byte[] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ /**
+ * Calls the <code>in.read(byte[], int, int)</code> method.
+ *
+ * @param buf The buffer to read bytes into
+ * @param offset The index into the buffer to start storing bytes
+ * @param len The maximum number of bytes to read.
+ *
+ * @return The value retured from <code>in.read(byte[], int, int)</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read(byte[] buf, int offset, int len) throws IOException
+ {
+ return in.read(buf, offset, len);
+ }
+
+ /**
+ * This method closes the input stream by closing the input stream that
+ * this object is filtering. Future attempts to access this stream may
+ * throw an exception.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ in.close();
+ }
+}
diff --git a/libjava/classpath/java/io/FilterOutputStream.java b/libjava/classpath/java/io/FilterOutputStream.java
new file mode 100644
index 00000000000..4c2dfc04a65
--- /dev/null
+++ b/libjava/classpath/java/io/FilterOutputStream.java
@@ -0,0 +1,150 @@
+/* FilterOutputStream.java -- Parent class for output streams that filter
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.1.
+ */
+
+/**
+ * This class is the common superclass of output stream classes that
+ * filter the output they write. These classes typically transform the
+ * data in some way prior to writing it out to another underlying
+ * <code>OutputStream</code>. This class simply overrides all the
+ * methods in <code>OutputStream</code> to redirect them to the
+ * underlying stream. Subclasses provide actual filtering.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class FilterOutputStream extends OutputStream
+{
+ /**
+ * This is the subordinate <code>OutputStream</code> that this class
+ * redirects its method calls to.
+ */
+ protected OutputStream out;
+
+ /**
+ * This method initializes an instance of <code>FilterOutputStream</code>
+ * to write to the specified subordinate <code>OutputStream</code>.
+ *
+ * @param out The <code>OutputStream</code> to write to
+ */
+ public FilterOutputStream(OutputStream out)
+ {
+ this.out = out;
+ }
+
+ /**
+ * This method closes the underlying <code>OutputStream</code>. Any
+ * further attempts to write to this stream may throw an exception.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ flush();
+ out.close();
+ }
+
+ /**
+ * This method attempt to flush all buffered output to be written to the
+ * underlying output sink.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void flush() throws IOException
+ {
+ out.flush();
+ }
+
+ /**
+ * This method writes a single byte of output to the underlying
+ * <code>OutputStream</code>.
+ *
+ * @param b The byte to write, passed as an int.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(int b) throws IOException
+ {
+ out.write(b);
+ }
+
+ /**
+ * This method writes all the bytes in the specified array to the underlying
+ * <code>OutputStream</code>. It does this by calling the three parameter
+ * version of this method - <code>write(byte[], int, int)</code> in this
+ * class instead of writing to the underlying <code>OutputStream</code>
+ * directly. This allows most subclasses to avoid overriding this method.
+ *
+ * @param buf The byte array to write bytes from
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(byte[] buf) throws IOException
+ {
+ // Don't do checking here, per Java Lang Spec.
+ write(buf, 0, buf.length);
+ }
+
+ /**
+ * This method calls the <code>write(int)</code> method <code>len</code>
+ * times for all bytes from the array <code>buf</code> starting at index
+ * <code>offset</code>. Subclasses should overwrite this method to get a
+ * more efficient implementation.
+ *
+ * @param buf The byte array to write bytes from
+ * @param offset The index into the array to start writing bytes from
+ * @param len The number of bytes to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(byte[] buf, int offset, int len) throws IOException
+ {
+ // Don't do checking here, per Java Lang Spec.
+ for (int i=0; i < len; i++)
+ write(buf[offset + i]);
+
+ }
+
+} // class FilterOutputStream
+
diff --git a/libjava/classpath/java/io/FilterReader.java b/libjava/classpath/java/io/FilterReader.java
new file mode 100644
index 00000000000..2bd040a7f72
--- /dev/null
+++ b/libjava/classpath/java/io/FilterReader.java
@@ -0,0 +1,185 @@
+/* FilterReader.java -- Base class for char stream classes that filter input
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This is the common superclass of all standard classes that filter
+ * input. It acts as a layer on top of an underlying <code>Reader</code>
+ * and simply redirects calls made to it to the subordinate Reader
+ * instead. Subclasses of this class perform additional filtering
+ * functions in addition to simply redirecting the call.
+ * <p>
+ * When creating a subclass of <code>FilterReader</code>, override the
+ * appropriate methods to implement the desired filtering. However, note
+ * that the <code>read(char[])</code> method does not need to be overridden
+ * as this class redirects calls to that method to
+ * <code>read(yte[], int, int)</code> instead of to the subordinate
+ * <code>Reader} read(yte[])</code> method.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public abstract class FilterReader extends Reader
+{
+ /**
+ * This is the subordinate <code>Reader</code> to which method calls
+ * are redirected
+ */
+ protected Reader in;
+
+ /**
+ * Create a <code>FilterReader</code> with the specified subordinate
+ * <code>Reader</code>.
+ * The <code>lock</code> of the new <code>FilterReader</code> will be set
+ * to <code>in.lock</code>.
+ *
+ * @param in The subordinate <code>Reader</code>
+ */
+ protected FilterReader(Reader in)
+ {
+ super(in.lock);
+ this.in = in;
+ }
+
+ /**
+ * Calls the <code>in.mark(int)</code> method.
+ *
+ * @param readlimit The parameter passed to <code>in.mark(int)</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public void mark(int readlimit) throws IOException
+ {
+ in.mark(readlimit);
+ }
+
+ /**
+ * Calls the <code>in.markSupported()</code> method.
+ *
+ * @return <code>true</code> if mark/reset is supported,
+ * <code>false</code> otherwise
+ */
+ public boolean markSupported()
+ {
+ return(in.markSupported());
+ }
+
+ /**
+ * Calls the <code>in.reset()</code> method.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void reset() throws IOException
+ {
+ in.reset();
+ }
+
+ /**
+ * Calls the <code>in.read()</code> method.
+ *
+ * @return The value returned from <code>in.available()</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public boolean ready() throws IOException
+ {
+ return(in.ready());
+ }
+
+ /**
+ * Calls the <code>in.skip(long)</code> method
+ *
+ * @param numBytes The requested number of chars to skip.
+ *
+ * @return The value returned from <code>in.skip(long)</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public long skip(long num_chars) throws IOException
+ {
+ return(in.skip(num_chars));
+ }
+
+ /**
+ * Calls the <code>in.read()</code> method
+ *
+ * @return The value returned from <code>in.read()</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ return(in.read());
+ }
+
+ /**
+ * Calls the <code>in.read(char[], int, int)</code> method.
+ *
+ * @param buf The buffer to read chars into
+ * @param offset The index into the buffer to start storing chars
+ * @param len The maximum number of chars to read.
+ *
+ * @return The value retured from <code>in.read(char[], int, int)</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read(char[] buf, int offset, int len) throws IOException
+ {
+ return(in.read(buf, offset, len));
+ }
+
+ /**
+ * This method closes the stream by calling the <code>close()</code> method
+ * of the underlying stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ in.close();
+ }
+
+} // class FilterReader
+
diff --git a/libjava/classpath/java/io/FilterWriter.java b/libjava/classpath/java/io/FilterWriter.java
new file mode 100644
index 00000000000..9b9ce33f9f6
--- /dev/null
+++ b/libjava/classpath/java/io/FilterWriter.java
@@ -0,0 +1,147 @@
+/* FilterWriter.java -- Parent class for output streams that filter
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to version 1.1.
+ */
+
+/**
+ * This class is the common superclass of output character stream classes
+ * that filter the output they write. These classes typically transform the
+ * data in some way prior to writing it out to another underlying
+ * <code>Writer</code>. This class simply overrides all the
+ * methods in <code>Writer</code> to redirect them to the
+ * underlying stream. Subclasses provide actual filtering.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public abstract class FilterWriter extends Writer
+{
+ /**
+ * This is the subordinate <code>Writer</code> that this class
+ * redirects its method calls to.
+ */
+ protected Writer out;
+
+ /**
+ * This method initializes an instance of <code>FilterWriter</code>
+ * to write to the specified subordinate <code>Writer</code>.
+ * The given <code>Writer</code> will be used as <code>lock</code> for
+ * the newly created <code>FilterWriter</code>.
+ *
+ * @param out The <code>Writer</code> to write to
+ */
+ protected FilterWriter(Writer out)
+ {
+ super(out.lock);
+ this.out = out;
+ }
+
+ /**
+ * This method closes the underlying <code>Writer</code>. Any
+ * further attempts to write to this stream may throw an exception.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ out.close();
+ }
+
+ /**
+ * This method attempt to flush all buffered output to be written to the
+ * underlying output sink.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void flush() throws IOException
+ {
+ out.flush();
+ }
+
+ /**
+ * This method writes a single char of output to the underlying
+ * <code>Writer</code>.
+ *
+ * @param b The char to write, passed as an int.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(int b) throws IOException
+ {
+ out.write(b);
+ }
+
+ /**
+ * This method writes <code>len</code> chars from the array <code>buf</code>
+ * starting at index <code>offset</code> to the underlying
+ * <code>Writer</code>.
+ *
+ * @param buf The char array to write chars from
+ * @param offset The index into the array to start writing chars from
+ * @param len The number of chars to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(char[] buf, int offset, int len) throws IOException
+ {
+ out.write(buf, offset, len);
+ }
+
+ /**
+ * This method writes <code>len</code> chars from the <code>String</code>
+ * starting at position <code>offset</code>.
+ *
+ * @param str The <code>String</code> that is to be written
+ * @param offset The character offset into the <code>String</code>
+ * to start writing from
+ * @param len The number of chars to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(String str, int offset, int len) throws IOException
+ {
+ out.write(str, offset, len);
+ }
+
+} // class FilterWriter
+
diff --git a/libjava/classpath/java/io/Flushable.java b/libjava/classpath/java/io/Flushable.java
new file mode 100644
index 00000000000..e9718d60a9b
--- /dev/null
+++ b/libjava/classpath/java/io/Flushable.java
@@ -0,0 +1,62 @@
+/* Flushable.java -- Flushable object
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.io;
+
+/**
+ * A <code>Flushable</code> class represents a stream of
+ * data, for which internally buffered data can be `flushed'.
+ * Flushing such a stream causes the buffered data to be
+ * written to the stream.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface Flushable
+{
+
+ /**
+ * Flushes the stream represented by this class,
+ * so that any buffered data is written to the stream.
+ *
+ * @throws IOException if an I/O error occurs in flushing.
+ */
+ void flush()
+ throws IOException;
+
+}
diff --git a/libjava/classpath/java/io/IOException.java b/libjava/classpath/java/io/IOException.java
new file mode 100644
index 00000000000..cf3ad194633
--- /dev/null
+++ b/libjava/classpath/java/io/IOException.java
@@ -0,0 +1,74 @@
+/* IOException.java -- Generic input/output exception
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown to indicate an I/O problem of some sort
+ * occurred. Since this is a fairly generic exception, often a subclass
+ * of IOException will actually be thrown in order to provide a more
+ * detailed indication of what happened.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class IOException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 7818375828146090155L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ public IOException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public IOException(String message)
+ {
+ super(message);
+ }
+} // class IOException
diff --git a/libjava/classpath/java/io/InputStream.java b/libjava/classpath/java/io/InputStream.java
new file mode 100644
index 00000000000..86d1cd74914
--- /dev/null
+++ b/libjava/classpath/java/io/InputStream.java
@@ -0,0 +1,272 @@
+/* InputStream.java -- Base class for input
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This abstract class forms the base of the hierarchy of classes that read
+ * input as a stream of bytes. It provides a common set of methods for
+ * reading bytes from streams. Subclasses implement and extend these
+ * methods to read bytes from a particular input source such as a file
+ * or network connection.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public abstract class InputStream
+{
+ /**
+ * Default, no-arg, public constructor
+ */
+ public InputStream()
+ {
+ }
+
+ /**
+ * This method returns the number of bytes that can be read from this
+ * stream before a read can block. A return of 0 indicates that blocking
+ * might (or might not) occur on the very next read attempt.
+ * <p>
+ * This method always returns 0 in this class
+ *
+ * @return The number of bytes that can be read before blocking could occur
+ *
+ * @exception IOException If an error occurs
+ */
+ public int available() throws IOException
+ {
+ return 0;
+ }
+
+ /**
+ * This method closes the stream. Any futher attempts to read from the
+ * stream may generate an <code>IOException</code>
+ * <p>
+ * This method does nothing in this class, but subclasses may override
+ * this method in order to provide additional functionality.
+ *
+ * @exception IOException If an error occurs, which can only happen
+ * in a subclass
+ */
+ public void close() throws IOException
+ {
+ // Do nothing
+ }
+
+ /**
+ * This method marks a position in the input to which the stream can
+ * be "reset" by calling the <code>reset()</code> method. The
+ * parameter @code{readlimit} is the number of bytes that can be read
+ * from the stream after setting the mark before the mark becomes
+ * invalid. For example, if <code>mark()</code> is called with a
+ * read limit of 10, then when 11 bytes of data are read from the
+ * stream before the <code>reset()</code> method is called, then the
+ * mark is invalid and the stream object instance is not required to
+ * remember the mark.
+ * <p>
+ * This method does nothing in this class, but subclasses may override it
+ * to provide mark/reset functionality.
+ *
+ * @param readLimit The number of bytes that can be read before the
+ * mark becomes invalid
+ */
+ public void mark(int readLimit)
+ {
+ // Do nothing
+ }
+
+ /**
+ * This method returns a boolean that indicates whether the mark/reset
+ * methods are supported in this class. Those methods can be used to
+ * remember a specific point in the stream and reset the stream to that
+ * point.
+ * <p>
+ * This method always returns <code>false</code> in this class, but
+ * subclasses can override this method to return <code>true</code>
+ * if they support mark/reset functionality.
+ *
+ * @return <code>true</code> if mark/reset functionality is
+ * supported, <code>false</code> otherwise
+ */
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ /**
+ * This method reads an unsigned byte from the input stream and returns it
+ * as an int in the range of 0-255. This method also will return -1 if
+ * the end of the stream has been reached.
+ * <p>
+ * This method will block until the byte can be read.
+ *
+ * @return The byte read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract int read() throws IOException;
+
+ /**
+ * This method reads bytes from a stream and stores them into a caller
+ * supplied buffer. This method attempts to completely fill the buffer,
+ * but can return before doing so. The actual number of bytes read is
+ * returned as an int. A -1 is returned to indicate the end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * This method operates by calling an overloaded read method like so:
+ * <code>read(b, 0, b.length)</code>
+ *
+ * @param b The buffer into which the bytes read will be stored.
+ *
+ * @return The number of bytes read or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public int read(byte[] b) throws IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * This method read bytes from a stream and stores them into a
+ * caller supplied buffer. It starts storing the data at index
+ * <code>off</code> into the buffer and attempts to read
+ * <code>len</code> bytes. This method can return before reading the
+ * number of bytes requested. The actual number of bytes read is
+ * returned as an int. A -1 is returned to indicate the end of the
+ * stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * This method operates by calling the single byte <code>read()</code> method
+ * in a loop until the desired number of bytes are read. The read loop
+ * stops short if the end of the stream is encountered or if an IOException
+ * is encountered on any read operation except the first. If the first
+ * attempt to read a bytes fails, the IOException is allowed to propagate
+ * upward. And subsequent IOException is caught and treated identically
+ * to an end of stream condition. Subclasses can (and should if possible)
+ * override this method to provide a more efficient implementation.
+ *
+ * @param b The array into which the bytes read should be stored
+ * @param off The offset into the array to start storing bytes
+ * @param len The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (off < 0 || len < 0 || off + len > b.length)
+ throw new IndexOutOfBoundsException();
+ if (b.length == 0)
+ return 0;
+
+ int i, ch;
+
+ for (i = 0; i < len; ++i)
+ try
+ {
+ if ((ch = read()) < 0)
+ return i == 0 ? -1 : i; // EOF
+ b[off + i] = (byte) ch;
+ }
+ catch (IOException ex)
+ {
+ // Only reading the first byte should cause an IOException.
+ if (i == 0)
+ throw ex;
+ return i;
+ }
+
+ return i;
+ }
+
+ /**
+ * This method resets a stream to the point where the
+ * <code>mark()</code> method was called. Any bytes that were read
+ * after the mark point was set will be re-read during subsequent
+ * reads.
+ * <p>
+ * This method always throws an IOException in this class, but subclasses
+ * can override this method if they provide mark/reset functionality.
+ *
+ * @exception IOException Always thrown for this class
+ */
+ public void reset() throws IOException
+ {
+ throw new IOException("mark/reset not supported");
+ }
+
+ /**
+ * This method skips the specified number of bytes in the stream. It
+ * returns the actual number of bytes skipped, which may be less than the
+ * requested amount.
+ * <p>
+ * This method reads and discards bytes into a byte array until the
+ * specified number of bytes were skipped or until either the end of stream
+ * is reached or a read attempt returns a short count. Subclasses can
+ * override this metho to provide a more efficient implementation where
+ * one exists.
+ *
+ * @param n The requested number of bytes to skip
+ *
+ * @return The actual number of bytes skipped.
+ *
+ * @exception IOException If an error occurs
+ */
+ public long skip(long n) throws IOException
+ {
+ // Throw away n bytes by reading them into a temp byte[].
+ // Limit the temp array to 2Kb so we don't grab too much memory.
+ final int buflen = n > 2048 ? 2048 : (int) n;
+ byte[] tmpbuf = new byte[buflen];
+ final long origN = n;
+
+ while (n > 0L)
+ {
+ int numread = read(tmpbuf, 0, n > buflen ? buflen : (int) n);
+ if (numread <= 0)
+ break;
+ n -= numread;
+ }
+
+ return origN - n;
+ }
+}
diff --git a/libjava/classpath/java/io/InputStreamReader.java b/libjava/classpath/java/io/InputStreamReader.java
new file mode 100644
index 00000000000..315af83e1a4
--- /dev/null
+++ b/libjava/classpath/java/io/InputStreamReader.java
@@ -0,0 +1,438 @@
+/* InputStreamReader.java -- Reader than transforms bytes to chars
+ Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.CharBuffer;
+import java.nio.ByteBuffer;
+import gnu.java.nio.charset.EncodingHelper;
+
+/**
+ * This class reads characters from a byte input stream. The characters
+ * read are converted from bytes in the underlying stream by a
+ * decoding layer. The decoding layer transforms bytes to chars according
+ * to an encoding standard. There are many available encodings to choose
+ * from. The desired encoding can either be specified by name, or if no
+ * encoding is selected, the system default encoding will be used. The
+ * system default encoding name is determined from the system property
+ * <code>file.encoding</code>. The only encodings that are guaranteed to
+ * be availalbe are "8859_1" (the Latin-1 character set) and "UTF8".
+ * Unforunately, Java does not provide a mechanism for listing the
+ * ecodings that are supported in a given implementation.
+ * <p>
+ * Here is a list of standard encoding names that may be available:
+ * <p>
+ * <ul>
+ * <li>8859_1 (ISO-8859-1/Latin-1)</li>
+ * <li>8859_2 (ISO-8859-2/Latin-2)</li>
+ * <li>8859_3 (ISO-8859-3/Latin-3)</li>
+ * <li>8859_4 (ISO-8859-4/Latin-4)</li>
+ * <li>8859_5 (ISO-8859-5/Latin-5)</li>
+ * <li>8859_6 (ISO-8859-6/Latin-6)</li>
+ * <li>8859_7 (ISO-8859-7/Latin-7)</li>
+ * <li>8859_8 (ISO-8859-8/Latin-8)</li>
+ * <li>8859_9 (ISO-8859-9/Latin-9)</li>
+ * <li>ASCII (7-bit ASCII)</li>
+ * <li>UTF8 (UCS Transformation Format-8)</li>
+ * <li>More later</li>
+ * </ul>
+ * <p>
+ * It is recommended that applications do not use
+ * <code>InputStreamReader</code>'s
+ * directly. Rather, for efficiency purposes, an object of this class
+ * should be wrapped by a <code>BufferedReader</code>.
+ * <p>
+ * Due to a deficiency the Java class library design, there is no standard
+ * way for an application to install its own byte-character encoding.
+ *
+ * @see BufferedReader
+ * @see InputStream
+ *
+ * @author Robert Schuster
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ * @date April 22, 1998.
+ */
+public class InputStreamReader extends Reader
+{
+ /**
+ * The input stream.
+ */
+ private InputStream in;
+
+ /**
+ * The charset decoder.
+ */
+ private CharsetDecoder decoder;
+
+ /**
+ * End of stream reached.
+ */
+ private boolean isDone = false;
+
+ /**
+ * Need this.
+ */
+ private float maxBytesPerChar;
+
+ /**
+ * Buffer holding surplus loaded bytes (if any)
+ */
+ private ByteBuffer byteBuffer;
+
+ /**
+ * java.io canonical name of the encoding.
+ */
+ private String encoding;
+
+ /**
+ * We might decode to a 2-char UTF-16 surrogate, which won't fit in the
+ * output buffer. In this case we need to save the surrogate char.
+ */
+ private char savedSurrogate;
+ private boolean hasSavedSurrogate = false;
+
+ /**
+ * This method initializes a new instance of <code>InputStreamReader</code>
+ * to read from the specified stream using the default encoding.
+ *
+ * @param in The <code>InputStream</code> to read from
+ */
+ public InputStreamReader(InputStream in)
+ {
+ if (in == null)
+ throw new NullPointerException();
+ this.in = in;
+ try
+ {
+ encoding = System.getProperty("file.encoding");
+ // Don't use NIO if avoidable
+ if(EncodingHelper.isISOLatin1(encoding))
+ {
+ encoding = "ISO8859_1";
+ maxBytesPerChar = 1f;
+ decoder = null;
+ return;
+ }
+ Charset cs = EncodingHelper.getCharset(encoding);
+ decoder = cs.newDecoder();
+ encoding = EncodingHelper.getOldCanonical(cs.name());
+ try {
+ maxBytesPerChar = cs.newEncoder().maxBytesPerChar();
+ } catch(UnsupportedOperationException _){
+ maxBytesPerChar = 1f;
+ }
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ decoder.reset();
+ } catch(RuntimeException e) {
+ encoding = "ISO8859_1";
+ maxBytesPerChar = 1f;
+ decoder = null;
+ } catch(UnsupportedEncodingException e) {
+ encoding = "ISO8859_1";
+ maxBytesPerChar = 1f;
+ decoder = null;
+ }
+ }
+
+ /**
+ * This method initializes a new instance of <code>InputStreamReader</code>
+ * to read from the specified stream using a caller supplied character
+ * encoding scheme. Note that due to a deficiency in the Java language
+ * design, there is no way to determine which encodings are supported.
+ *
+ * @param in The <code>InputStream</code> to read from
+ * @param encoding_name The name of the encoding scheme to use
+ *
+ * @exception UnsupportedEncodingException If the encoding scheme
+ * requested is not available.
+ */
+ public InputStreamReader(InputStream in, String encoding_name)
+ throws UnsupportedEncodingException
+ {
+ if (in == null
+ || encoding_name == null)
+ throw new NullPointerException();
+
+ this.in = in;
+ // Don't use NIO if avoidable
+ if(EncodingHelper.isISOLatin1(encoding_name))
+ {
+ encoding = "ISO8859_1";
+ maxBytesPerChar = 1f;
+ decoder = null;
+ return;
+ }
+ try {
+ Charset cs = EncodingHelper.getCharset(encoding_name);
+ try {
+ maxBytesPerChar = cs.newEncoder().maxBytesPerChar();
+ } catch(UnsupportedOperationException _){
+ maxBytesPerChar = 1f;
+ }
+
+ decoder = cs.newDecoder();
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ decoder.reset();
+
+ // The encoding should be the old name, if such exists.
+ encoding = EncodingHelper.getOldCanonical(cs.name());
+ } catch(RuntimeException e) {
+ encoding = "ISO8859_1";
+ maxBytesPerChar = 1f;
+ decoder = null;
+ }
+ }
+
+ /**
+ * Creates an InputStreamReader that uses a decoder of the given
+ * charset to decode the bytes in the InputStream into
+ * characters.
+ */
+ public InputStreamReader(InputStream in, Charset charset) {
+ this.in = in;
+ decoder = charset.newDecoder();
+
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ decoder.reset();
+ encoding = EncodingHelper.getOldCanonical(charset.name());
+ }
+
+ /**
+ * Creates an InputStreamReader that uses the given charset decoder
+ * to decode the bytes in the InputStream into characters.
+ */
+ public InputStreamReader(InputStream in, CharsetDecoder decoder) {
+ this.in = in;
+ this.decoder = decoder;
+
+ try {
+ maxBytesPerChar = decoder.charset().newEncoder().maxBytesPerChar();
+ } catch(UnsupportedOperationException _){
+ maxBytesPerChar = 1f;
+ }
+
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ decoder.reset();
+ encoding = EncodingHelper.getOldCanonical(decoder.charset().name());
+ }
+
+ /**
+ * This method closes this stream, as well as the underlying
+ * <code>InputStream</code>.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ synchronized (lock)
+ {
+ // Makes sure all intermediate data is released by the decoder.
+ if (decoder != null)
+ decoder.reset();
+ if (in != null)
+ in.close();
+ in = null;
+ isDone = true;
+ decoder = null;
+ }
+ }
+
+ /**
+ * This method returns the name of the encoding that is currently in use
+ * by this object. If the stream has been closed, this method is allowed
+ * to return <code>null</code>.
+ *
+ * @return The current encoding name
+ */
+ public String getEncoding()
+ {
+ return in != null ? encoding : null;
+ }
+
+ /**
+ * This method checks to see if the stream is ready to be read. It
+ * will return <code>true</code> if is, or <code>false</code> if it is not.
+ * If the stream is not ready to be read, it could (although is not required
+ * to) block on the next read attempt.
+ *
+ * @return <code>true</code> if the stream is ready to be read,
+ * <code>false</code> otherwise
+ *
+ * @exception IOException If an error occurs
+ */
+ public boolean ready() throws IOException
+ {
+ if (in == null)
+ throw new IOException("Reader has been closed");
+
+ return in.available() != 0;
+ }
+
+ /**
+ * This method reads up to <code>length</code> characters from the stream into
+ * the specified array starting at index <code>offset</code> into the
+ * array.
+ *
+ * @param buf The character array to recieve the data read
+ * @param offset The offset into the array to start storing characters
+ * @param length The requested number of characters to read.
+ *
+ * @return The actual number of characters read, or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read(char[] buf, int offset, int length) throws IOException
+ {
+ if (in == null)
+ throw new IOException("Reader has been closed");
+ if (isDone)
+ return -1;
+ if(decoder != null){
+ int totalBytes = (int)((double)length * maxBytesPerChar);
+ byte[] bytes = new byte[totalBytes];
+
+ int remaining = 0;
+ if(byteBuffer != null)
+ {
+ remaining = byteBuffer.remaining();
+ byteBuffer.get(bytes, 0, remaining);
+ }
+ int read;
+ if(totalBytes - remaining > 0)
+ {
+ read = in.read(bytes, remaining, totalBytes - remaining);
+ if(read == -1){
+ read = remaining;
+ isDone = true;
+ } else
+ read += remaining;
+ } else
+ read = remaining;
+ byteBuffer = ByteBuffer.wrap(bytes, 0, read);
+ CharBuffer cb = CharBuffer.wrap(buf, offset, length);
+ int startPos = cb.position();
+
+ if(hasSavedSurrogate){
+ hasSavedSurrogate = false;
+ cb.put(savedSurrogate);
+ read++;
+ }
+
+ CoderResult cr = decoder.decode(byteBuffer, cb, isDone);
+ decoder.reset();
+ // 1 char remains which is the first half of a surrogate pair.
+ if(cr.isOverflow() && cb.hasRemaining()){
+ CharBuffer overflowbuf = CharBuffer.allocate(2);
+ cr = decoder.decode(byteBuffer, overflowbuf, isDone);
+ overflowbuf.flip();
+ if(overflowbuf.hasRemaining())
+ {
+ cb.put(overflowbuf.get());
+ savedSurrogate = overflowbuf.get();
+ hasSavedSurrogate = true;
+ isDone = false;
+ }
+ }
+
+ if(byteBuffer.hasRemaining()) {
+ byteBuffer.compact();
+ byteBuffer.flip();
+ isDone = false;
+ } else
+ byteBuffer = null;
+
+ read = cb.position() - startPos;
+ return (read <= 0) ? -1 : read;
+ } else {
+ byte[] bytes = new byte[length];
+ int read = in.read(bytes);
+ for(int i=0;i<read;i++)
+ buf[offset+i] = (char)(bytes[i]&0xFF);
+ return read;
+ }
+ }
+
+ /**
+ * Reads an char from the input stream and returns it
+ * as an int in the range of 0-65535. This method also will return -1 if
+ * the end of the stream has been reached.
+ * <p>
+ * This method will block until the char can be read.
+ *
+ * @return The char read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ char[] buf = new char[1];
+ int count = read(buf, 0, 1);
+ return count > 0 ? buf[0] : -1;
+ }
+
+ /**
+ * Skips the specified number of chars in the stream. It
+ * returns the actual number of chars skipped, which may be less than the
+ * requested amount.
+ *
+ * @param count The requested number of chars to skip
+ *
+ * @return The actual number of chars skipped.
+ *
+ * @exception IOException If an error occurs
+ */
+ public long skip(long count) throws IOException
+ {
+ if (in == null)
+ throw new IOException("Reader has been closed");
+
+ return super.skip(count);
+ }
+}
diff --git a/libjava/classpath/java/io/InterruptedIOException.java b/libjava/classpath/java/io/InterruptedIOException.java
new file mode 100644
index 00000000000..96ec83649f8
--- /dev/null
+++ b/libjava/classpath/java/io/InterruptedIOException.java
@@ -0,0 +1,94 @@
+/* InterruptedIOException.java -- an I/O operation was interrupted
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown when a in process I/O operation is interrupted
+ * for some reason. The field bytesTransferred will contain the number of
+ * bytes that were read/written prior to the interruption.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see Thread#interrupt()
+ * @status updated to 1.4
+ */
+public class InterruptedIOException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 4020568460727500567L;
+
+ /**
+ * The number of bytes read/written prior to the interruption.
+ *
+ * @serial count of bytes successfully transferred
+ */
+ public int bytesTransferred;
+
+ /**
+ * Create an extends without a descriptive error message.
+ */
+ public InterruptedIOException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public InterruptedIOException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Create an exception with a descriptive error message and count of
+ * bytes transferred.
+ *
+ * @param message the descriptive error message
+ * @param bytesTransferred number of bytes tranferred before interruption
+ */
+ InterruptedIOException(String message, int bytesTransferred)
+ {
+ super(message);
+ this.bytesTransferred = bytesTransferred;
+ }
+} // class InterruptedIOException
diff --git a/libjava/classpath/java/io/InvalidClassException.java b/libjava/classpath/java/io/InvalidClassException.java
new file mode 100644
index 00000000000..c71b0c67fc7
--- /dev/null
+++ b/libjava/classpath/java/io/InvalidClassException.java
@@ -0,0 +1,111 @@
+/* InvalidClassException.java -- deserializing a class failed
+ Copyright (C) 1998, 2002 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.io;
+
+/**
+ * This exception is thrown when there is some sort of problem with a
+ * class during a serialization operation. This could be:<br><ul>
+ * <li>the serial version of the class doesn't match</li>
+ * <li>the class contains unknown datatypes</li>
+ * <li>the class does not have an accessible no-arg constructor</li>
+ * </ul>.
+ *
+ * <p>The field <code>classname</code> will contain the name of the
+ * class that caused the problem if known. The getMessage() method
+ * for this exception will always include the name of that class
+ * if known.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class InvalidClassException extends ObjectStreamException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -4333316296251054416L;
+
+ /**
+ * The name of the class which encountered the error.
+ *
+ * @serial the classname causing the error
+ */
+ public String classname;
+
+ /**
+ * Create an exception with a descriptive error message, but a null
+ * classname.
+ *
+ * @param message the descriptive error message
+ */
+ public InvalidClassException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Create an exception with a descriptive error message, and the name of
+ * the class that caused the problem.
+ *
+ * @param classname the name of the faulty class
+ * @param message the descriptive error message
+ */
+ public InvalidClassException(String classname, String message)
+ {
+ super(message);
+ this.classname = classname;
+ }
+
+ /**
+ * Returns the descriptive error message for this exception. It will
+ * include the class name that caused the problem if known, in the format:
+ * <code>[classname][; ][super.getMessage()]</code>.
+ *
+ * @return A descriptive error message, may be null
+ */
+ public String getMessage()
+ {
+ String msg = super.getMessage();
+ if (msg == null)
+ return classname;
+ return (classname == null ? "" : classname + "; ") + msg;
+ }
+}
+
diff --git a/libjava/classpath/java/io/InvalidObjectException.java b/libjava/classpath/java/io/InvalidObjectException.java
new file mode 100644
index 00000000000..deee876db27
--- /dev/null
+++ b/libjava/classpath/java/io/InvalidObjectException.java
@@ -0,0 +1,66 @@
+/* InvalidObjectException.java -- deserialization failed verification
+ Copyright (C) 1998, 2002 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.io;
+
+/**
+ * This exception is thrown when an object fails a validation test
+ * during serialization.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class InvalidObjectException extends ObjectStreamException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 3233174318281839583L;
+
+ /**
+ * Create an exception with a descriptive error message String. This should
+ * be the cause of the verification failure.
+ *
+ * @param message the descriptive error message
+ */
+ public InvalidObjectException(String message)
+ {
+ super(message);
+ }
+} // class InvalidObjectException
diff --git a/libjava/classpath/java/io/LineNumberInputStream.java b/libjava/classpath/java/io/LineNumberInputStream.java
new file mode 100644
index 00000000000..da43097f28c
--- /dev/null
+++ b/libjava/classpath/java/io/LineNumberInputStream.java
@@ -0,0 +1,315 @@
+/* LineNumberInputStream.java -- An input stream which counts line numbers
+ Copyright (C) 1998, 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This class functions like a standard <code>InputStream</code>
+ * except that it counts line numbers, and canonicalizes newline
+ * characters. As data is read, whenever the byte sequences "\r",
+ * "\n", or "\r\n" are encountered, the running line count is
+ * incremeted by one. Additionally, the whatever line termination
+ * sequence was encountered will be converted to a "\n" byte. Note
+ * that this class numbers lines from 0. When the first line
+ * terminator is encountered, the line number is incremented to 1, and
+ * so on.
+ * <p>
+ * This class counts only line termination characters. If the last line
+ * read from the stream does not end in a line termination sequence, it
+ * will not be counted as a line.
+ * <p>
+ * Note that since this class operates as a filter on an underlying
+ * stream, it has the same mark/reset functionality as the underlying
+ * stream. The <code>mark()</code> and <code>reset()</code> methods
+ * in this class handle line numbers correctly. Calling
+ * <code>reset()</code> resets the line number to the point at which
+ * <code>mark()</code> was called if the subordinate stream supports
+ * that functionality.
+ * <p>
+ * @deprecated This class is deprecated in favor if
+ * <code>LineNumberReader</code> because it operates on ASCII bytes
+ * instead of an encoded character stream. This class is for backward
+ * compatibility only and should not be used in new applications.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class LineNumberInputStream extends FilterInputStream
+{
+ /** The current line number. */
+ private int lineNumber = 0;
+
+ /** The line number when the stream was marked. */
+ private int markLineNumber = 0;
+
+ /** Flag to indicate a '\r' was just read so that an immediately
+ * subsequent '\n' can be ignored. */
+ private boolean justReadReturnChar = false;
+
+ /**
+ * Create a new <code>LineNumberInputStream</code> that reads from the
+ * specified subordinate <code>InputStream</code>
+ *
+ * @param in The subordinate <code>InputStream</code> to read from
+ */
+ public LineNumberInputStream(InputStream in)
+ {
+ super(in);
+ }
+
+ /**
+ * This method returns the number of bytes that can be read from the
+ * stream before the stream can block. This method is tricky
+ * because the subordinate <code>InputStream</code> might return
+ * only "\r\n" characters, which are replaced by a single "\n"
+ * character by the <code>read()</code> method of this class. So
+ * this method can only guarantee that <code>in.available() /
+ * 2</code> bytes can actually be read before blocking. In
+ * practice, considerably more bytes might be read before blocking
+ * <p>
+ * Note that the stream may not block if additional bytes beyond the count
+ * returned by this method are read.
+ *
+ * @return The number of bytes that can be read before blocking could occur
+ *
+ * @exception IOException If an error occurs
+ */
+ public int available() throws IOException
+ {
+ // We can only guarantee half the characters that might be available
+ // without blocking because "\r\n" is treated as a single character.
+ return in.available() / 2;
+ }
+
+ /**
+ * This method returns the current line number
+ *
+ * @return The current line number
+ */
+ public int getLineNumber()
+ {
+ return lineNumber;
+ }
+
+ /**
+ * This method marks a position in the input to which the stream can
+ * be "reset" byte calling the <code>reset()</code> method. The
+ * parameter <code>readlimit</code> is the number of bytes that can
+ * be read from the stream after setting the mark before the mark
+ * becomes invalid. For example, if <code>mark()</code> is called
+ * with a read limit of 10, then when 11 bytes of data are read from
+ * the stream before the <code>reset()</code> method is called, then
+ * the mark is invalid and the stream object instance is not
+ * required to remember the mark.
+ * <p>
+ * In this class, this method will remember the current line number
+ * as well as the current position in the stream. When the
+ * <code>reset()</code> method is called, the line number will be
+ * restored to the saved line number in addition to the stream
+ * position.
+ * <p>
+ * This method only works if the subordinate stream supports mark/reset
+ * functionality.
+ *
+ * @param readlimit The number of bytes that can be read before the
+ * mark becomes invalid
+ */
+ public void mark(int readlimit)
+ {
+ in.mark(readlimit);
+ markLineNumber = lineNumber;
+ }
+
+ /**
+ * This method reads an unsigned byte from the input stream and returns it
+ * as an int in the range of 0-255. This method will return -1 if the
+ * end of the stream has been reached.
+ * <p>
+ * Note that if a line termination sequence is encountered (ie, "\r",
+ * "\n", or "\r\n") then that line termination sequence is converted to
+ * a single "\n" value which is returned from this method. This means
+ * that it is possible this method reads two bytes from the subordinate
+ * stream instead of just one.
+ * <p>
+ * Note that this method will block until a byte of data is available
+ * to be read.
+ *
+ * @return The byte read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ // Treat "\r\n" as a single character. A '\r' may have been read by
+ // a previous call to read so we keep an internal flag to avoid having
+ // to read ahead.
+
+ int ch = in.read();
+
+ if (ch == '\n')
+ if (justReadReturnChar)
+ {
+ ch = in.read();
+ justReadReturnChar = false;
+ }
+ else
+ lineNumber++;
+ else if (ch == '\r')
+ {
+ ch = '\n';
+ justReadReturnChar = true;
+ lineNumber++;
+ }
+ else
+ justReadReturnChar = false;
+
+ return ch;
+ }
+
+ /**
+ * This method reads bytes from a stream and stores them into a caller
+ * supplied buffer. It starts storing data at index <code>offset</code> into
+ * the buffer and attemps to read <code>len</code> bytes. This method can
+ * return before reading the number of bytes requested. The actual number
+ * of bytes read is returned as an int. A -1 is returned to indicated the
+ * end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * Note that if a line termination sequence is encountered (ie, "\r",
+ * "\n", or "\r\n") then that line termination sequence is converted to
+ * a single "\n" value which is stored in the buffer. Only a single
+ * byte is counted towards the number of bytes read in this case.
+ *
+ * @param b The array into which the bytes read should be stored
+ * @param off The offset into the array to start storing bytes
+ * @param len The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of stream
+ *
+ * @exception IOException If an error occurs.
+ */
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (off < 0 || len < 0 || off + len > b.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ // This case always succeeds.
+ if (len == 0)
+ return 0;
+
+ // The simplest, though not necessarily the most time efficient thing
+ // to do is simply call read(void) len times. Since this is a deprecated
+ // class, that should be ok.
+ final int origOff = off;
+ while (len-- > 0)
+ {
+ int ch = read();
+ if (ch < 0)
+ break;
+
+ b[off++] = (byte) ch;
+ }
+
+ // This is safe since we already know that some bytes were
+ // actually requested.
+ return off == origOff ? -1 : off - origOff;
+ }
+
+ /**
+ * This method resets a stream to the point where the
+ * <code>mark()</code> method was called. Any bytes that were read
+ * after the mark point was set will be re-read during subsequent
+ * reads.
+ * <p>
+ * In this class, this method will also restore the line number that was
+ * current when the <code>mark()</code> method was called.
+ * <p>
+ * This method only works if the subordinate stream supports mark/reset
+ * functionality.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void reset() throws IOException
+ {
+ in.reset();
+ lineNumber = markLineNumber;
+ justReadReturnChar = false;
+ }
+
+ /**
+ * This method sets the current line number to the specified value.
+ *
+ * @param lineNumber The new line number
+ */
+ public void setLineNumber(int lineNumber)
+ {
+ this.lineNumber = lineNumber;
+ }
+
+ /**
+ * This method skips up to the requested number of bytes in the
+ * input stream. The actual number of bytes skipped is returned. If the
+ * desired number of bytes to skip is negative, no bytes are skipped.
+ *
+ * @param n requested number of bytes to skip.
+ *
+ * @return The actual number of bytes skipped.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public long skip(long n) throws IOException
+ {
+ if (n <= 0)
+ return 0L;
+
+ final long origN = n;
+
+ do
+ {
+ int ch = read();
+ if (ch < 0)
+ break;
+ if (ch == '\n' || ch == '\r')
+ lineNumber++;
+ }
+ while (--n > 0);
+
+ return origN - n;
+ }
+}
diff --git a/libjava/classpath/java/io/LineNumberReader.java b/libjava/classpath/java/io/LineNumberReader.java
new file mode 100644
index 00000000000..ea418a5e4d6
--- /dev/null
+++ b/libjava/classpath/java/io/LineNumberReader.java
@@ -0,0 +1,417 @@
+/* LineNumberReader.java -- A character input stream which counts line numbers
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.io;
+
+/**
+ * This class functions like a standard <code>Reader</code> except that it
+ * counts line numbers, and canonicalizes newline characters. As data
+ * is read, whenever the char sequences "\r", "\n", or "\r\n" are encountered,
+ * the running line count is incremeted by one. Additionally, the whatever
+ * line termination sequence was encountered will be converted to a "\n"
+ * char. Note that this class numbers lines from 0. When the first
+ * line terminator is encountered, the line number is incremented to 1, and
+ * so on. Also note that actual "\r" and "\n" characters are looked for.
+ * The system dependent line separator sequence is ignored.
+ * <p>
+ * This class counts only line termination characters. If the last line
+ * read from the stream does not end in a line termination sequence, it
+ * will not be counted as a line.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @date December 28, 2003.
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ *
+ * This implementation has the feature that if '\r' is read, it
+ * does not look for a '\n', but immediately returns '\n'.
+ * On the next read(), if a '\n' is read, it is skipped.
+ * This has the advantage that we do not read (and hang) unnecessarily.
+ *
+ * This implementation is also minimal in the number of fields it uses.
+ */
+public class LineNumberReader extends BufferedReader
+{
+ /** The current line number. */
+ private int lineNumber;
+ /** Whether we already found a new line in the former call. */
+ private boolean matchedNewLine;
+ /** The saved line number when calling mark() */
+ private int savedLineNumber;
+
+ /**
+ * Create a new <code>LineNumberReader</code> that reads from the
+ * specified subordinate <code>Reader</code>. A default 8K char sized
+ * buffer will be used for reads.
+ *
+ * @param in The subordinate <code>Reader</code> to read from
+ */
+ public LineNumberReader(Reader in)
+ {
+ super(in, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * This method initializes a new <code>LineNumberReader</code> to read
+ * from the specified subordinate <code>Reader</code> using the specified
+ * read buffer size.
+ *
+ * @param in The subordinate <code>Reader</code> to read from
+ * @param size The buffer size to use for reading
+ */
+ public LineNumberReader(Reader in, int size)
+ {
+ super(in, size);
+ }
+
+ /**
+ * This method returns the current line number
+ *
+ * @return The current line number
+ */
+ public int getLineNumber()
+ {
+ return lineNumber;
+ }
+
+ /**
+ * This method sets the current line number to the specified value.
+ *
+ * @param line_number The new line number
+ */
+ public void setLineNumber(int lineNumber)
+ {
+ this.lineNumber = lineNumber;
+ }
+
+ /**
+ * This method marks a position in the input to which the stream can be
+ * "reset" char calling the <code>reset()</code> method. The parameter
+ * <code>readlimit</code> is the number of chars that can be read from the
+ * stream after setting the mark before the mark becomes invalid. For
+ * example, if <code>mark()</code> is called with a read limit of 10,
+ * then when
+ * 11 chars of data are read from the stream before the <code>reset()</code>
+ * method is called, then the mark is invalid and the stream object
+ * instance is not required to remember the mark.
+ * <p>
+ * In this class, this method will remember the current line number as well
+ * as the current position in the stream. When the <code>reset()</code>
+ * method
+ * is called, the line number will be restored to the saved line number in
+ * addition to the stream position.
+ *
+ * @param readlimit The number of chars that can be read before the
+ * mark becomes invalid
+ *
+ * @exception IOException If an error occurs
+ */
+ public void mark(int readLimit) throws IOException
+ {
+ if (readLimit < 0)
+ throw new IllegalArgumentException("Read-ahead limit is negative");
+
+ synchronized (lock)
+ {
+ // This is basically the same as BufferedReader.mark.
+ // However, if the previous character was a '\r', we need to
+ // save that 'r', in case the next character is a '\n'.
+ if (pos + readLimit > limit)
+ {
+ int saveCR = matchedNewLine ? 1 : 0;
+ char[] old_buffer = buffer;
+ if (readLimit > limit)
+ buffer = new char[saveCR + readLimit];
+ int copy_start = pos - saveCR;
+ savedLineNumber = lineNumber;
+ limit -= copy_start;
+ System.arraycopy(old_buffer, copy_start, buffer, 0, limit);
+ pos = saveCR;
+ }
+ markPos = pos;
+ }
+ }
+
+ /**
+ * This method resets a stream to the point where the <code>mark()</code>
+ * method
+ * was called. Any chars that were read after the mark point was set will
+ * be re-read during subsequent reads.
+ * <p>
+ * In this class, this method will also restore the line number that was
+ * current when the <code>mark()</code> method was called.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void reset() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (markPos < 0)
+ throw new IOException("mark never set or invalidated");
+ lineNumber = savedLineNumber;
+ pos = markPos;
+ matchedNewLine = (markPos > 0 && buffer[markPos-1] == '\r');
+ }
+ }
+
+ /**
+ * This private method fills the input buffer whatever pos is.
+ * Consequently pos should be checked before calling this method.
+ *
+ * @return the number of bytes actually read from the input stream or
+ * -1 if end of stream.
+ * @exception IOException If an error occurs.
+ */
+ private int fill() throws IOException
+ {
+ if (markPos >= 0 && limit == buffer.length)
+ markPos = -1;
+ if (markPos < 0)
+ pos = limit = 0;
+ int count = in.read(buffer, limit, buffer.length - limit);
+ if (count <= 0)
+ return -1;
+ limit += count;
+
+ return count;
+ }
+
+ /**
+ * This method reads an unsigned char from the input stream and returns it
+ * as an int in the range of 0-65535. This method will return -1 if the
+ * end of the stream has been reached.
+ * <p>
+ * Note that if a line termination sequence is encountered (ie, "\r",
+ * "\n", or "\r\n") then that line termination sequence is converted to
+ * a single "\n" value which is returned from this method. This means
+ * that it is possible this method reads two chars from the subordinate
+ * stream instead of just one.
+ * <p>
+ * Note that this method will block until a char of data is available
+ * to be read.
+ *
+ * @return The char read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ synchronized (lock)
+ {
+ skipRedundantLF();
+ if (pos >= limit && fill() < 0)
+ return -1;
+ char ch = buffer[pos++];
+
+ if ((matchedNewLine = (ch == '\r')) || ch == '\n')
+ {
+ lineNumber++;
+ return '\n';
+ }
+ matchedNewLine = false;
+ return (int) ch;
+ }
+ }
+
+ /**
+ * This method reads chars from a stream and stores them into a caller
+ * supplied buffer. It starts storing data at index <code>offset</code> into
+ * the buffer and attemps to read <code>len</code> chars. This method can
+ * return before reading the number of chars requested. The actual number
+ * of chars read is returned as an int. A -1 is returned to indicated the
+ * end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * Note that if a line termination sequence is encountered (ie, "\r",
+ * "\n", or "\r\n") then that line termination sequence is converted to
+ * a single "\n" value which is stored in the buffer. Only a single
+ * char is counted towards the number of chars read in this case.
+ *
+ * @param buf The array into which the chars read should be stored
+ * @param offset The offset into the array to start storing chars
+ * @param len The requested number of chars to read
+ *
+ * @return The actual number of chars read, or -1 if end of stream
+ *
+ * @exception IOException If an error occurs.
+ * @exception NullPointerException If buf is null (in any case).
+ * @exception IndexOutOfBoundsException If buffer parameters (offset and
+ * count) lies outside of the buffer capacity.
+ */
+ public int read(char[] buf, int offset, int count) throws IOException
+ {
+ if (buf == null)
+ throw new NullPointerException();
+
+ if (offset + count > buf.length || offset < 0)
+ throw new IndexOutOfBoundsException();
+
+ if (count <= 0)
+ {
+ if (count < 0)
+ throw new IndexOutOfBoundsException();
+ return 0;
+ }
+
+ synchronized (lock)
+ {
+ if (pos >= limit && fill() < 0)
+ return -1;
+
+ int start_offset = offset;
+ boolean matched = matchedNewLine;
+
+ while (count-- > 0 && pos < limit)
+ {
+ char ch = buffer[pos++];
+ if (ch == '\r')
+ {
+ lineNumber++;
+ matched = true;
+ }
+ else if (ch == '\n' && !matched)
+ lineNumber++;
+ else
+ matched = false;
+
+ buf[offset++] = ch;
+ }
+
+ matchedNewLine = matched;
+ return offset - start_offset;
+ }
+ }
+
+ private void skipRedundantLF() throws IOException
+ {
+ if (pos > 0 && matchedNewLine)
+ {
+ if (pos < limit)
+ { // fast case
+ if (buffer[pos] == '\n')
+ pos++;
+ }
+ else
+ { // check whether the next buffer begins with '\n'.
+ // in that case kill the '\n'.
+ if (fill() <= 0)
+ return;
+ if (buffer[pos] == '\n')
+ pos++;
+ }
+ matchedNewLine = true;
+ }
+ }
+
+ /**
+ * This method reads a line of text from the input stream and returns
+ * it as a <code>String</code>. A line is considered to be terminated
+ * by a "\r", "\n", or "\r\n" sequence, not by the system dependent line
+ * separator.
+ *
+ * @return The line read as a <code>String</code> or <code>null</code>
+ * if end of stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public String readLine() throws IOException
+ {
+ // BufferedReader.readLine already does this. Shouldn't need to keep
+ // track of newlines (since the read method deals with this for us).
+ // But if the buffer is large, we may not call the read method at all
+ // and super.readLine can't increment lineNumber itself.
+ // Though it may seem kludgy, the safest thing to do is to save off
+ // lineNumber and increment it explicitly when we're done (iff we
+ // ended with a '\n' or '\r' as opposed to EOF).
+ //
+ // Also, we need to undo the special casing done by BufferedReader.readLine
+ // when a '\r' is the last char in the buffer. That situation is marked
+ // by 'pos > limit'.
+ int tmpLineNumber = lineNumber;
+ skipRedundantLF();
+ String str = super.readLine();
+ if (pos > limit)
+ --pos;
+
+ // The only case where you mustn't increment the line number is you are
+ // at the EOS.
+ if (str != null)
+ lineNumber = tmpLineNumber + 1;
+
+ return str;
+ }
+
+ /**
+ * This method skips over characters in the stream. This method will
+ * skip the specified number of characters if possible, but is not required
+ * to skip them all. The actual number of characters skipped is returned.
+ * This method returns 0 if the specified number of chars is less than 1.
+ *
+ * @param count The specified number of chars to skip.
+ *
+ * @return The actual number of chars skipped.
+ *
+ * @exception IOException If an error occurs
+ */
+ public long skip (long count) throws IOException
+ {
+ if (count < 0)
+ throw new IllegalArgumentException("skip() value is negative");
+ if (count == 0)
+ return 0;
+
+ int skipped;
+ char[] buf = new char[1];
+
+ for (skipped = 0; skipped < count; skipped++)
+ {
+ int ch = read(buf, 0, 1);
+
+ if (ch < 0)
+ break;
+ }
+
+ return skipped;
+ }
+}
+
diff --git a/libjava/classpath/java/io/NotActiveException.java b/libjava/classpath/java/io/NotActiveException.java
new file mode 100644
index 00000000000..949ba8eca52
--- /dev/null
+++ b/libjava/classpath/java/io/NotActiveException.java
@@ -0,0 +1,72 @@
+/* NotActiveException.java -- thrown when serialization is not active
+ Copyright (C) 1998, 2002 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.io;
+
+/**
+ * This exception is thrown when a problem occurs due to the fact that
+ * serialization is not active.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class NotActiveException extends ObjectStreamException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -3893467273049808895L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ public NotActiveException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public NotActiveException(String message)
+ {
+ super(message);
+ }
+} // class NotActiveException
diff --git a/libjava/classpath/java/io/NotSerializableException.java b/libjava/classpath/java/io/NotSerializableException.java
new file mode 100644
index 00000000000..d49c939e31d
--- /dev/null
+++ b/libjava/classpath/java/io/NotSerializableException.java
@@ -0,0 +1,74 @@
+/* NotSerializableException.java -- a Serializable class that isn't
+ Copyright (C) 1998, 2002 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.io;
+
+/**
+ * This exception is thrown when a class implements Serializable because
+ * of a superclass, but should not be serialized. The descriptive message
+ * will consist of the name of the class in question.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class NotSerializableException extends ObjectStreamException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 2906642554793891381L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ public NotSerializableException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message, which should
+ * be the name of the class.
+ *
+ * @param message the descriptive error message
+ */
+ public NotSerializableException(String message)
+ {
+ super(message);
+ }
+} // class NotSerializableException
diff --git a/libjava/classpath/java/io/ObjectInput.java b/libjava/classpath/java/io/ObjectInput.java
new file mode 100644
index 00000000000..175b60f9dc0
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectInput.java
@@ -0,0 +1,140 @@
+/* ObjectInput.java -- Read object data from a stream
+ Copyright (C) 1998,2003 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.io;
+
+/**
+ * This interface extends the <code>DataInput</code> interface to provide a
+ * facility to read objects as well as primitive types from a stream. It
+ * also has methods that allow input to be done in a manner similar to
+ * <code>InputStream</code>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ *
+ * @see DataInput
+ */
+public interface ObjectInput extends DataInput
+{
+ /**
+ * This method returns the number of bytes that can be read without
+ * blocking.
+ *
+ * @return The number of bytes available before blocking
+ *
+ * @exception IOException If an error occurs
+ */
+ int available() throws IOException;
+
+ /**
+ * This method reading a byte of data from a stream. It returns that byte
+ * as an <code>int</code>. This method blocks if no data is available
+ * to be read.
+ *
+ * @return The byte of data read
+ *
+ * @exception IOException If an error occurs
+ */
+ int read() throws IOException;
+
+ /**
+ * This method reads raw bytes and stores them them a byte array buffer.
+ * Note that this method will block if no data is available. However,
+ * it will not necessarily block until it fills the entire buffer. That is,
+ * a "short count" is possible.
+ *
+ * @param buf The byte array to receive the data read
+ *
+ * @return The actual number of bytes read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ int read(byte[] buf) throws IOException;
+
+ /**
+ * This method reads raw bytes and stores them in a byte array buffer
+ * <code>buf</code> starting at position <code>offset</code> into the
+ * buffer. A
+ * maximum of <code>len</code> bytes will be read. Note that this method
+ * blocks if no data is available, but will not necessarily block until
+ * it can read <code>len</code> bytes of data. That is, a "short count" is
+ * possible.
+ *
+ * @param buf The byte array to receive the data read
+ * @param offset The offset into <code>buf</code> to start storing data
+ * @param len The maximum number of bytes to read
+ *
+ * @return The actual number of bytes read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ int read(byte[] buf, int offset, int len) throws IOException;
+
+ /**
+ * Reads an object instance and returns it. If the class for the object
+ * being read cannot be found, then a <code>ClassNotFoundException</code>
+ * will be thrown.
+ *
+ * @return The object instance that was read
+ *
+ * @exception ClassNotFoundException If a class for the object cannot be
+ * found
+ * @exception IOException If any other error occurs
+ */
+ Object readObject()
+ throws ClassNotFoundException, IOException;
+
+ /**
+ * This method causes the specified number of bytes to be read and
+ * discarded. It is possible that fewer than the requested number of bytes
+ * will actually be skipped.
+ *
+ * @param numBytes The number of bytes to skip
+ *
+ * @return The actual number of bytes skipped
+ *
+ * @exception IOException If an error occurs
+ */
+ long skip(long numBytes) throws IOException;
+
+ /**
+ * This method closes the input source
+ *
+ * @exception IOException If an error occurs
+ */
+ void close() throws IOException;
+}
diff --git a/libjava/classpath/java/io/ObjectInputStream.java b/libjava/classpath/java/io/ObjectInputStream.java
new file mode 100644
index 00000000000..05776a7fcdd
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectInputStream.java
@@ -0,0 +1,1956 @@
+/* ObjectInputStream.java -- Class used to read serialized objects
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.classpath.Configuration;
+import gnu.java.io.ObjectIdentityWrapper;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class ObjectInputStream extends InputStream
+ implements ObjectInput, ObjectStreamConstants
+{
+ /**
+ * Creates a new <code>ObjectInputStream</code> that will do all of
+ * its reading from <code>in</code>. This method also checks
+ * the stream by reading the header information (stream magic number
+ * and stream version).
+ *
+ * @exception IOException Reading stream header from underlying
+ * stream cannot be completed.
+ *
+ * @exception StreamCorruptedException An invalid stream magic
+ * number or stream version was read from the stream.
+ *
+ * @see #readStreamHeader()
+ */
+ public ObjectInputStream(InputStream in)
+ throws IOException, StreamCorruptedException
+ {
+ if (DEBUG)
+ {
+ String val = System.getProperty("gcj.dumpobjects");
+ if (dump == false && val != null && !val.equals(""))
+ {
+ dump = true;
+ System.out.println ("Serialization debugging enabled");
+ }
+ else if (dump == true && (val == null || val.equals("")))
+ {
+ dump = false;
+ System.out.println ("Serialization debugging disabled");
+ }
+ }
+
+ this.resolveEnabled = false;
+ this.isDeserializing = false;
+ this.blockDataPosition = 0;
+ this.blockDataBytes = 0;
+ this.blockData = new byte[BUFFER_SIZE];
+ this.blockDataInput = new DataInputStream(this);
+ this.realInputStream = new DataInputStream(in);
+ this.nextOID = baseWireHandle;
+ this.objectLookupTable = new Hashtable();
+ this.validators = new Vector();
+ this.classLookupTable = new Hashtable();
+ setBlockDataMode(true);
+ readStreamHeader();
+ }
+
+
+ /**
+ * Returns the next deserialized object read from the underlying stream.
+ *
+ * This method can be overriden by a class by implementing
+ * <code>private void readObject (ObjectInputStream)</code>.
+ *
+ * If an exception is thrown from this method, the stream is left in
+ * an undefined state.
+ *
+ * @exception ClassNotFoundException The class that an object being
+ * read in belongs to cannot be found.
+ *
+ * @exception IOException Exception from underlying
+ * <code>InputStream</code>.
+ */
+ public final Object readObject() throws ClassNotFoundException, IOException
+ {
+ if (this.useSubclassMethod)
+ return readObjectOverride();
+
+ boolean was_deserializing;
+
+ Object ret_val;
+ was_deserializing = this.isDeserializing;
+
+ boolean is_consumed = false;
+ boolean old_mode = setBlockDataMode(false);
+
+ this.isDeserializing = true;
+
+ byte marker = this.realInputStream.readByte();
+
+ depth += 2;
+
+ if(dump) dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");
+
+ try
+ {
+ switch (marker)
+ {
+ case TC_ENDBLOCKDATA:
+ {
+ ret_val = null;
+ is_consumed = true;
+ break;
+ }
+
+ case TC_BLOCKDATA:
+ case TC_BLOCKDATALONG:
+ {
+ if (marker == TC_BLOCKDATALONG)
+ { if(dump) dumpElementln("BLOCKDATALONG"); }
+ else
+ { if(dump) dumpElementln("BLOCKDATA"); }
+ readNextBlock(marker);
+ throw new StreamCorruptedException("Unexpected blockData");
+ }
+
+ case TC_NULL:
+ {
+ if(dump) dumpElementln("NULL");
+ ret_val = null;
+ break;
+ }
+
+ case TC_REFERENCE:
+ {
+ if(dump) dumpElement("REFERENCE ");
+ Integer oid = new Integer(this.realInputStream.readInt());
+ if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
+ ret_val = ((ObjectIdentityWrapper)
+ this.objectLookupTable.get(oid)).object;
+ break;
+ }
+
+ case TC_CLASS:
+ {
+ if(dump) dumpElementln("CLASS");
+ ObjectStreamClass osc = (ObjectStreamClass)readObject();
+ Class clazz = osc.forClass();
+ assignNewHandle(clazz);
+ ret_val = clazz;
+ break;
+ }
+
+ case TC_PROXYCLASSDESC:
+ {
+ if(dump) dumpElementln("PROXYCLASS");
+ int n_intf = this.realInputStream.readInt();
+ String[] intfs = new String[n_intf];
+ for (int i = 0; i < n_intf; i++)
+ {
+ intfs[i] = this.realInputStream.readUTF();
+ System.out.println(intfs[i]);
+ }
+
+ boolean oldmode = setBlockDataMode(true);
+ Class cl = resolveProxyClass(intfs);
+ setBlockDataMode(oldmode);
+
+ ObjectStreamClass osc = lookupClass(cl);
+ assignNewHandle(osc);
+
+ if (!is_consumed)
+ {
+ byte b = this.realInputStream.readByte();
+ if (b != TC_ENDBLOCKDATA)
+ throw new IOException("Data annotated to class was not consumed." + b);
+ }
+ else
+ is_consumed = false;
+ ObjectStreamClass superosc = (ObjectStreamClass)readObject();
+ osc.setSuperclass(superosc);
+ ret_val = osc;
+ break;
+ }
+
+ case TC_CLASSDESC:
+ {
+ ObjectStreamClass osc = readClassDescriptor();
+
+ if (!is_consumed)
+ {
+ byte b = this.realInputStream.readByte();
+ if (b != TC_ENDBLOCKDATA)
+ throw new IOException("Data annotated to class was not consumed." + b);
+ }
+ else
+ is_consumed = false;
+
+ osc.setSuperclass ((ObjectStreamClass)readObject());
+ ret_val = osc;
+ break;
+ }
+
+ case TC_STRING:
+ case TC_LONGSTRING:
+ {
+ if(dump) dumpElement("STRING=");
+ String s = this.realInputStream.readUTF();
+ if(dump) dumpElementln(s);
+ ret_val = processResolution(null, s, assignNewHandle(s));
+ break;
+ }
+
+ case TC_ARRAY:
+ {
+ if(dump) dumpElementln("ARRAY");
+ ObjectStreamClass osc = (ObjectStreamClass)readObject();
+ Class componentType = osc.forClass().getComponentType();
+ if(dump) dumpElement("ARRAY LENGTH=");
+ int length = this.realInputStream.readInt();
+ if(dump) dumpElementln (length + "; COMPONENT TYPE=" + componentType);
+ Object array = Array.newInstance(componentType, length);
+ int handle = assignNewHandle(array);
+ readArrayElements(array, componentType);
+ if(dump)
+ for (int i = 0, len = Array.getLength(array); i < len; i++)
+ dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i));
+ ret_val = processResolution(null, array, handle);
+ break;
+ }
+
+ case TC_OBJECT:
+ {
+ if(dump) dumpElementln("OBJECT");
+ ObjectStreamClass osc = (ObjectStreamClass)readObject();
+ Class clazz = osc.forClass();
+
+ if (!osc.realClassIsSerializable)
+ throw new NotSerializableException
+ (clazz + " is not Serializable, and thus cannot be deserialized.");
+
+ if (osc.realClassIsExternalizable)
+ {
+ Externalizable obj = osc.newInstance();
+
+ int handle = assignNewHandle(obj);
+
+ boolean read_from_blocks = ((osc.getFlags() & SC_BLOCK_DATA) != 0);
+
+ boolean oldmode = this.readDataFromBlock;
+ if (read_from_blocks)
+ setBlockDataMode(true);
+
+ obj.readExternal(this);
+
+ if (read_from_blocks)
+ {
+ setBlockDataMode(oldmode);
+ if (!oldmode)
+ if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
+ throw new IOException("No end of block data seen for class with readExternal (ObjectInputStream) method.");
+ }
+
+ ret_val = processResolution(osc, obj, handle);
+ break;
+ } // end if (osc.realClassIsExternalizable)
+
+ Object obj = newObject(clazz, osc.firstNonSerializableParentConstructor);
+
+ int handle = assignNewHandle(obj);
+ Object prevObject = this.currentObject;
+ ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
+
+ this.currentObject = obj;
+ ObjectStreamClass[] hierarchy =
+ inputGetObjectStreamClasses(clazz);
+
+ for (int i = 0; i < hierarchy.length; i++)
+ {
+ this.currentObjectStreamClass = hierarchy[i];
+
+ if(dump) dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ());
+
+ // XXX: should initialize fields in classes in the hierarchy
+ // that aren't in the stream
+ // should skip over classes in the stream that aren't in the
+ // real classes hierarchy
+
+ Method readObjectMethod = this.currentObjectStreamClass.readObjectMethod;
+ if (readObjectMethod != null)
+ {
+ fieldsAlreadyRead = false;
+ boolean oldmode = setBlockDataMode(true);
+ callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
+ setBlockDataMode(oldmode);
+ }
+ else
+ {
+ readFields(obj, currentObjectStreamClass);
+ }
+
+ if (this.currentObjectStreamClass.hasWriteMethod())
+ {
+ if(dump) dumpElement("ENDBLOCKDATA? ");
+ try
+ {
+ // FIXME: XXX: This try block is to
+ // catch EOF which is thrown for some
+ // objects. That indicates a bug in
+ // the logic.
+
+ if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
+ throw new IOException
+ ("No end of block data seen for class with readObject (ObjectInputStream) method.");
+ if(dump) dumpElementln("yes");
+ }
+// catch (EOFException e)
+// {
+// if(dump) dumpElementln("no, got EOFException");
+// }
+ catch (IOException e)
+ {
+ if(dump) dumpElementln("no, got IOException");
+ }
+ }
+ }
+
+ this.currentObject = prevObject;
+ this.currentObjectStreamClass = prevObjectStreamClass;
+ ret_val = processResolution(osc, obj, handle);
+
+ break;
+ }
+
+ case TC_RESET:
+ if(dump) dumpElementln("RESET");
+ clearHandles();
+ ret_val = readObject();
+ break;
+
+ case TC_EXCEPTION:
+ {
+ if(dump) dumpElement("EXCEPTION=");
+ Exception e = (Exception)readObject();
+ if(dump) dumpElementln(e.toString());
+ clearHandles();
+ throw new WriteAbortedException("Exception thrown during writing of stream", e);
+ }
+
+ default:
+ throw new IOException("Unknown marker on stream: " + marker);
+ }
+ }
+ finally
+ {
+ setBlockDataMode(old_mode);
+
+ this.isDeserializing = was_deserializing;
+
+ depth -= 2;
+
+ if (! was_deserializing)
+ {
+ if (validators.size() > 0)
+ invokeValidators();
+ }
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * This method makes a partial check of types for the fields
+ * contained given in arguments. It checks primitive types of
+ * fields1 against non primitive types of fields2. This method
+ * assumes the two lists has already been sorted according to
+ * the Java specification.
+ *
+ * @param name Name of the class owning the given fields.
+ * @param fields1 First list to check.
+ * @param fields2 Second list to check.
+ * @throws InvalidClassException if a field in fields1, which has a primitive type, is a present
+ * in the non primitive part in fields2.
+ */
+ private void checkTypeConsistency(String name, ObjectStreamField[] fields1, ObjectStreamField[] fields2)
+ throws InvalidClassException
+ {
+ int nonPrimitive = 0;
+
+ for (nonPrimitive = 0;
+ nonPrimitive < fields1.length
+ && fields1[nonPrimitive].isPrimitive(); nonPrimitive++)
+ {
+ }
+
+ if (nonPrimitive == fields1.length)
+ return;
+
+ int i = 0;
+ ObjectStreamField f1;
+ ObjectStreamField f2;
+
+ while (i < fields2.length
+ && nonPrimitive < fields1.length)
+ {
+ f1 = fields1[nonPrimitive];
+ f2 = fields2[i];
+
+ if (!f2.isPrimitive())
+ break;
+
+ int compVal = f1.getName().compareTo (f2.getName());
+
+ if (compVal < 0)
+ {
+ nonPrimitive++;
+ }
+ else if (compVal > 0)
+ {
+ i++;
+ }
+ else
+ {
+ throw new InvalidClassException
+ ("invalid field type for " + f2.getName() +
+ " in class " + name);
+ }
+ }
+ }
+
+ /**
+ * This method reads a class descriptor from the real input stream
+ * and use these data to create a new instance of ObjectStreamClass.
+ * Fields are sorted and ordered for the real read which occurs for
+ * each instance of the described class. Be aware that if you call that
+ * method you must ensure that the stream is synchronized, in the other
+ * case it may be completely desynchronized.
+ *
+ * @return A new instance of ObjectStreamClass containing the freshly
+ * created descriptor.
+ * @throws ClassNotFoundException if the required class to build the
+ * descriptor has not been found in the system.
+ * @throws IOException An input/output error occured.
+ * @throws InvalidClassException If there was a compatibility problem
+ * between the class present in the system and the serialized class.
+ */
+ protected ObjectStreamClass readClassDescriptor()
+ throws ClassNotFoundException, IOException
+ {
+ if(dump) dumpElement("CLASSDESC NAME=");
+ String name = this.realInputStream.readUTF();
+ if(dump) dumpElement(name + "; UID=");
+ long uid = this.realInputStream.readLong ();
+ if(dump) dumpElement(Long.toHexString(uid) + "; FLAGS=");
+ byte flags = this.realInputStream.readByte ();
+ if(dump) dumpElement(Integer.toHexString(flags) + "; FIELD COUNT=");
+ short field_count = this.realInputStream.readShort();
+ if(dump) dumpElementln(Short.toString(field_count));
+ ObjectStreamField[] fields = new ObjectStreamField[field_count];
+ ObjectStreamClass osc = new ObjectStreamClass(name, uid,
+ flags, fields);
+ assignNewHandle(osc);
+
+ if (callersClassLoader == null)
+ callersClassLoader = currentLoader();
+
+ for (int i = 0; i < field_count; i++)
+ {
+ if(dump) dumpElement(" TYPE CODE=");
+ char type_code = (char)this.realInputStream.readByte();
+ if(dump) dumpElement(type_code + "; FIELD NAME=");
+ String field_name = this.realInputStream.readUTF();
+ if(dump) dumpElementln(field_name);
+ String class_name;
+
+ // If the type code is an array or an object we must
+ // decode a String here. In the other case we convert
+ // the type code and pass it to ObjectStreamField.
+ // Type codes are decoded by gnu.java.lang.reflect.TypeSignature.
+ if (type_code == 'L' || type_code == '[')
+ class_name = (String)readObject();
+ else
+ class_name = String.valueOf(type_code);
+
+ fields[i] =
+ new ObjectStreamField(field_name, class_name, callersClassLoader);
+ }
+
+ /* Now that fields have been read we may resolve the class
+ * (and read annotation if needed). */
+ Class clazz;
+ try
+ {
+ clazz = resolveClass(osc);
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ // Maybe it was an primitive class?
+ if (name.equals("void"))
+ clazz = Void.TYPE;
+ else if (name.equals("boolean"))
+ clazz = Boolean.TYPE;
+ else if (name.equals("byte"))
+ clazz = Byte.TYPE;
+ else if (name.equals("short"))
+ clazz = Short.TYPE;
+ else if (name.equals("char"))
+ clazz = Character.TYPE;
+ else if (name.equals("int"))
+ clazz = Integer.TYPE;
+ else if (name.equals("long"))
+ clazz = Long.TYPE;
+ else if (name.equals("float"))
+ clazz = Float.TYPE;
+ else if (name.equals("double"))
+ clazz = Double.TYPE;
+ else
+ throw cnfe;
+ }
+
+ boolean oldmode = setBlockDataMode(true);
+ osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
+ classLookupTable.put(clazz, osc);
+ setBlockDataMode(oldmode);
+
+ // find the first non-serializable, non-abstract
+ // class in clazz's inheritance hierarchy
+ Class first_nonserial = clazz.getSuperclass();
+ // Maybe it is a primitive class, those don't have a super class,
+ // or Object itself. Otherwise we can keep getting the superclass
+ // till we hit the Object class, or some other non-serializable class.
+
+ if (first_nonserial == null)
+ first_nonserial = clazz;
+ else
+ while (Serializable.class.isAssignableFrom(first_nonserial)
+ || Modifier.isAbstract(first_nonserial.getModifiers()))
+ first_nonserial = first_nonserial.getSuperclass();
+
+ final Class local_constructor_class = first_nonserial;
+
+ osc.firstNonSerializableParentConstructor =
+ (Constructor)AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ try
+ {
+ Constructor c = local_constructor_class.
+ getDeclaredConstructor(new Class[0]);
+ if (Modifier.isPrivate(c.getModifiers()))
+ return null;
+ return c;
+ }
+ catch (NoSuchMethodException e)
+ {
+ // error will be reported later, in newObject()
+ return null;
+ }
+ }
+ });
+
+ osc.realClassIsSerializable = Serializable.class.isAssignableFrom(clazz);
+ osc.realClassIsExternalizable = Externalizable.class.isAssignableFrom(clazz);
+
+ ObjectStreamField[] stream_fields = osc.fields;
+ ObjectStreamField[] real_fields = ObjectStreamClass.lookupForClassObject(clazz).fields;
+ ObjectStreamField[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)];
+
+ int stream_idx = 0;
+ int real_idx = 0;
+ int map_idx = 0;
+
+ /*
+ * Check that there is no type inconsistencies between the lists.
+ * A special checking must be done for the two groups: primitive types and
+ * not primitive types.
+ */
+ checkTypeConsistency(name, real_fields, stream_fields);
+ checkTypeConsistency(name, stream_fields, real_fields);
+
+
+ while (stream_idx < stream_fields.length
+ || real_idx < real_fields.length)
+ {
+ ObjectStreamField stream_field = null;
+ ObjectStreamField real_field = null;
+
+ if (stream_idx == stream_fields.length)
+ {
+ real_field = real_fields[real_idx++];
+ }
+ else if (real_idx == real_fields.length)
+ {
+ stream_field = stream_fields[stream_idx++];
+ }
+ else
+ {
+ int comp_val =
+ real_fields[real_idx].compareTo (stream_fields[stream_idx]);
+
+ if (comp_val < 0)
+ {
+ real_field = real_fields[real_idx++];
+ }
+ else if (comp_val > 0)
+ {
+ stream_field = stream_fields[stream_idx++];
+ }
+ else
+ {
+ stream_field = stream_fields[stream_idx++];
+ real_field = real_fields[real_idx++];
+ if (stream_field.getType() != real_field.getType())
+ throw new InvalidClassException
+ ("invalid field type for " + real_field.getName() +
+ " in class " + name);
+ }
+ }
+
+ /* If some of stream_fields does not correspond to any of real_fields,
+ * or the opposite, then fieldmapping will go short.
+ */
+ if (map_idx == fieldmapping.length)
+ {
+ ObjectStreamField[] newfieldmapping =
+ new ObjectStreamField[fieldmapping.length + 2];
+ System.arraycopy(fieldmapping, 0,
+ newfieldmapping, 0, fieldmapping.length);
+ fieldmapping = newfieldmapping;
+ }
+ fieldmapping[map_idx++] = stream_field;
+ fieldmapping[map_idx++] = real_field;
+ }
+ osc.fieldMapping = fieldmapping;
+
+ return osc;
+ }
+
+ /**
+ * Reads the current objects non-transient, non-static fields from
+ * the current class from the underlying output stream.
+ *
+ * This method is intended to be called from within a object's
+ * <code>private void readObject (ObjectInputStream)</code>
+ * method.
+ *
+ * @exception ClassNotFoundException The class that an object being
+ * read in belongs to cannot be found.
+ *
+ * @exception NotActiveException This method was called from a
+ * context other than from the current object's and current class's
+ * <code>private void readObject (ObjectInputStream)</code>
+ * method.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ */
+ public void defaultReadObject()
+ throws ClassNotFoundException, IOException, NotActiveException
+ {
+ if (this.currentObject == null || this.currentObjectStreamClass == null)
+ throw new NotActiveException("defaultReadObject called by non-active"
+ + " class and/or object");
+
+ if (fieldsAlreadyRead)
+ throw new NotActiveException("defaultReadObject called but fields "
+ + "already read from stream (by "
+ + "defaultReadObject or readFields)");
+
+ boolean oldmode = setBlockDataMode(false);
+ readFields(this.currentObject, this.currentObjectStreamClass);
+ setBlockDataMode(oldmode);
+
+ fieldsAlreadyRead = true;
+ }
+
+
+ /**
+ * Registers a <code>ObjectInputValidation</code> to be carried out
+ * on the object graph currently being deserialized before it is
+ * returned to the original caller of <code>readObject ()</code>.
+ * The order of validation for multiple
+ * <code>ObjectInputValidation</code>s can be controled using
+ * <code>priority</code>. Validators with higher priorities are
+ * called first.
+ *
+ * @see java.io.ObjectInputValidation
+ *
+ * @exception InvalidObjectException <code>validator</code> is
+ * <code>null</code>
+ *
+ * @exception NotActiveException an attempt was made to add a
+ * validator outside of the <code>readObject</code> method of the
+ * object currently being deserialized
+ */
+ public void registerValidation(ObjectInputValidation validator,
+ int priority)
+ throws InvalidObjectException, NotActiveException
+ {
+ if (this.currentObject == null || this.currentObjectStreamClass == null)
+ throw new NotActiveException("registerValidation called by non-active "
+ + "class and/or object");
+
+ if (validator == null)
+ throw new InvalidObjectException("attempt to add a null "
+ + "ObjectInputValidation object");
+
+ this.validators.addElement(new ValidatorAndPriority (validator,
+ priority));
+ }
+
+
+ /**
+ * Called when a class is being deserialized. This is a hook to
+ * allow subclasses to read in information written by the
+ * <code>annotateClass (Class)</code> method of an
+ * <code>ObjectOutputStream</code>.
+ *
+ * This implementation looks up the active call stack for a
+ * <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,
+ * it is used to load the class associated with <code>osc</code>,
+ * otherwise, the default system <code>ClassLoader</code> is used.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ *
+ * @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
+ */
+ protected Class resolveClass(ObjectStreamClass osc)
+ throws ClassNotFoundException, IOException
+ {
+ if (callersClassLoader == null)
+ {
+ callersClassLoader = currentLoader ();
+ if (DEBUG && dump)
+ {
+ dumpElementln ("CallersClassLoader = " + callersClassLoader);
+ }
+ }
+
+ return Class.forName(osc.getName(), true, callersClassLoader);
+ }
+
+ /**
+ * Returns the most recent user defined ClassLoader on the execution stack
+ * or null if none is found.
+ */
+ private ClassLoader currentLoader()
+ {
+ return VMObjectInputStream.currentClassLoader();
+ }
+
+ /**
+ * Lookup a class stored in the local hashtable. If it is not
+ * use the global lookup function in ObjectStreamClass to build
+ * the ObjectStreamClass. This method is requested according to
+ * the behaviour detected in the JDK by Kaffe's team.
+ *
+ * @param clazz Class to lookup in the hash table or for which
+ * we must build a descriptor.
+ * @return A valid instance of ObjectStreamClass corresponding
+ * to the specified class.
+ */
+ private ObjectStreamClass lookupClass(Class clazz)
+ {
+ if (clazz == null)
+ return null;
+
+ ObjectStreamClass oclazz;
+ oclazz = (ObjectStreamClass)classLookupTable.get(clazz);
+ if (oclazz == null)
+ return ObjectStreamClass.lookup(clazz);
+ else
+ return oclazz;
+ }
+
+ /**
+ * Reconstruct class hierarchy the same way
+ * {@link java.io.ObjectStreamClass.getObjectStreamClasses(java.lang.Class)} does
+ * but using lookupClass instead of ObjectStreamClass.lookup. This
+ * dup is necessary localize the lookup table. Hopefully some future
+ * rewritings will be able to prevent this.
+ *
+ * @param clazz This is the class for which we want the hierarchy.
+ *
+ * @return An array of valid {@link java.io.ObjectStreamClass} instances which
+ * represent the class hierarchy for clazz.
+ */
+ private ObjectStreamClass[] inputGetObjectStreamClasses(Class clazz)
+ {
+ ObjectStreamClass osc = lookupClass(clazz);
+
+ if (osc == null)
+ return new ObjectStreamClass[0];
+ else
+ {
+ Vector oscs = new Vector();
+
+ while (osc != null)
+ {
+ oscs.addElement(osc);
+ osc = osc.getSuper();
+ }
+
+ int count = oscs.size();
+ ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[count];
+
+ for (int i = count - 1; i >= 0; i--)
+ sorted_oscs[count - i - 1] = (ObjectStreamClass) oscs.elementAt(i);
+
+ return sorted_oscs;
+ }
+ }
+
+ /**
+ * Allows subclasses to resolve objects that are read from the
+ * stream with other objects to be returned in their place. This
+ * method is called the first time each object is encountered.
+ *
+ * This method must be enabled before it will be called in the
+ * serialization process.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ *
+ * @see #enableResolveObject(boolean)
+ */
+ protected Object resolveObject(Object obj) throws IOException
+ {
+ return obj;
+ }
+
+
+ protected Class resolveProxyClass(String[] intfs)
+ throws IOException, ClassNotFoundException
+ {
+ ClassLoader cl = currentLoader();
+
+ Class[] clss = new Class[intfs.length];
+ if(cl == null)
+ {
+ for (int i = 0; i < intfs.length; i++)
+ clss[i] = Class.forName(intfs[i]);
+ cl = ClassLoader.getSystemClassLoader();
+ }
+ else
+ for (int i = 0; i < intfs.length; i++)
+ clss[i] = cl.loadClass(intfs[i]);
+ try
+ {
+ return Proxy.getProxyClass(cl, clss);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ClassNotFoundException(null, e);
+ }
+ }
+
+ /**
+ * If <code>enable</code> is <code>true</code> and this object is
+ * trusted, then <code>resolveObject (Object)</code> will be called
+ * in subsequent calls to <code>readObject (Object)</code>.
+ * Otherwise, <code>resolveObject (Object)</code> will not be called.
+ *
+ * @exception SecurityException This class is not trusted.
+ */
+ protected boolean enableResolveObject (boolean enable)
+ throws SecurityException
+ {
+ if (enable)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new SerializablePermission("enableSubstitution"));
+ }
+
+ boolean old_val = this.resolveEnabled;
+ this.resolveEnabled = enable;
+ return old_val;
+ }
+
+ /**
+ * Reads stream magic and stream version information from the
+ * underlying stream.
+ *
+ * @exception IOException Exception from underlying stream.
+ *
+ * @exception StreamCorruptedException An invalid stream magic
+ * number or stream version was read from the stream.
+ */
+ protected void readStreamHeader()
+ throws IOException, StreamCorruptedException
+ {
+ if(dump) dumpElement("STREAM MAGIC ");
+ if (this.realInputStream.readShort() != STREAM_MAGIC)
+ throw new StreamCorruptedException("Invalid stream magic number");
+
+ if(dump) dumpElementln("STREAM VERSION ");
+ if (this.realInputStream.readShort() != STREAM_VERSION)
+ throw new StreamCorruptedException("Invalid stream version number");
+ }
+
+ public int read() throws IOException
+ {
+ if (this.readDataFromBlock)
+ {
+ if (this.blockDataPosition >= this.blockDataBytes)
+ readNextBlock();
+ return (this.blockData[this.blockDataPosition++] & 0xff);
+ }
+ else
+ return this.realInputStream.read();
+ }
+
+ public int read(byte[] data, int offset, int length) throws IOException
+ {
+ if (this.readDataFromBlock)
+ {
+ if (this.blockDataPosition + length > this.blockDataBytes)
+ {
+ int remain = this.blockDataBytes - this.blockDataPosition;
+ if (remain != 0)
+ {
+ System.arraycopy(this.blockData, this.blockDataPosition,
+ data, offset, remain);
+ offset += remain;
+ length -= remain;
+ }
+ readNextBlock ();
+ }
+
+ System.arraycopy(this.blockData, this.blockDataPosition,
+ data, offset, length);
+ this.blockDataPosition += length;
+
+ return length;
+ }
+ else
+ return this.realInputStream.read(data, offset, length);
+ }
+
+ public int available() throws IOException
+ {
+ if (this.readDataFromBlock)
+ {
+ if (this.blockDataPosition >= this.blockDataBytes)
+ readNextBlock ();
+
+ return this.blockDataBytes - this.blockDataPosition;
+ }
+ else
+ return this.realInputStream.available();
+ }
+
+ public void close() throws IOException
+ {
+ this.realInputStream.close();
+ }
+
+ public boolean readBoolean() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode (true);
+ boolean value = this.dataInputStream.readBoolean ();
+ if (switchmode)
+ setBlockDataMode (oldmode);
+ return value;
+ }
+
+ public byte readByte() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ byte value = this.dataInputStream.readByte();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public int readUnsignedByte() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ int value = this.dataInputStream.readUnsignedByte();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public short readShort() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ short value = this.dataInputStream.readShort();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public int readUnsignedShort() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ int value = this.dataInputStream.readUnsignedShort();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public char readChar() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ char value = this.dataInputStream.readChar();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public int readInt() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ int value = this.dataInputStream.readInt();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public long readLong() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ long value = this.dataInputStream.readLong();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public float readFloat() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ float value = this.dataInputStream.readFloat();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public double readDouble() throws IOException
+ {
+ boolean switchmode = true;
+ boolean oldmode = this.readDataFromBlock;
+ if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
+ switchmode = false;
+ if (switchmode)
+ oldmode = setBlockDataMode(true);
+ double value = this.dataInputStream.readDouble();
+ if (switchmode)
+ setBlockDataMode(oldmode);
+ return value;
+ }
+
+ public void readFully(byte data[]) throws IOException
+ {
+ this.dataInputStream.readFully(data);
+ }
+
+ public void readFully(byte data[], int offset, int size)
+ throws IOException
+ {
+ this.dataInputStream.readFully(data, offset, size);
+ }
+
+ public int skipBytes(int len) throws IOException
+ {
+ return this.dataInputStream.skipBytes(len);
+ }
+
+ /**
+ * @deprecated
+ * @see java.io.DataInputStream#readLine ()
+ */
+ public String readLine() throws IOException
+ {
+ return this.dataInputStream.readLine();
+ }
+
+ public String readUTF() throws IOException
+ {
+ return this.dataInputStream.readUTF();
+ }
+
+ /**
+ * This class allows a class to specify exactly which fields should
+ * be read, and what values should be read for these fields.
+ *
+ * XXX: finish up comments
+ */
+ public abstract static class GetField
+ {
+ public abstract ObjectStreamClass getObjectStreamClass();
+
+ public abstract boolean defaulted(String name)
+ throws IOException, IllegalArgumentException;
+
+ public abstract boolean get(String name, boolean defvalue)
+ throws IOException, IllegalArgumentException;
+
+ public abstract char get(String name, char defvalue)
+ throws IOException, IllegalArgumentException;
+
+ public abstract byte get(String name, byte defvalue)
+ throws IOException, IllegalArgumentException;
+
+ public abstract short get(String name, short defvalue)
+ throws IOException, IllegalArgumentException;
+
+ public abstract int get(String name, int defvalue)
+ throws IOException, IllegalArgumentException;
+
+ public abstract long get(String name, long defvalue)
+ throws IOException, IllegalArgumentException;
+
+ public abstract float get(String name, float defvalue)
+ throws IOException, IllegalArgumentException;
+
+ public abstract double get(String name, double defvalue)
+ throws IOException, IllegalArgumentException;
+
+ public abstract Object get(String name, Object defvalue)
+ throws IOException, IllegalArgumentException;
+ }
+
+ /**
+ * This method should be called by a method called 'readObject' in the
+ * deserializing class (if present). It cannot (and should not)be called
+ * outside of it. Its goal is to read all fields in the real input stream
+ * and keep them accessible through the {@link #GetField} class. Calling
+ * this method will not alter the deserializing object.
+ *
+ * @return A valid freshly created 'GetField' instance to get access to
+ * the deserialized stream.
+ * @throws IOException An input/output exception occured.
+ * @throws ClassNotFoundException
+ * @throws NotActiveException
+ */
+ public GetField readFields()
+ throws IOException, ClassNotFoundException, NotActiveException
+ {
+ if (this.currentObject == null || this.currentObjectStreamClass == null)
+ throw new NotActiveException("readFields called by non-active class and/or object");
+
+ if (prereadFields != null)
+ return prereadFields;
+
+ if (fieldsAlreadyRead)
+ throw new NotActiveException("readFields called but fields already read from"
+ + " stream (by defaultReadObject or readFields)");
+
+ final ObjectStreamClass clazz = this.currentObjectStreamClass;
+ final byte[] prim_field_data = new byte[clazz.primFieldSize];
+ final Object[] objs = new Object[clazz.objectFieldCount];
+
+ // Apparently Block data is not used with GetField as per
+ // empirical evidence against JDK 1.2. Also see Mauve test
+ // java.io.ObjectInputOutput.Test.GetPutField.
+ boolean oldmode = setBlockDataMode(false);
+ readFully(prim_field_data);
+ for (int i = 0; i < objs.length; ++ i)
+ objs[i] = readObject();
+ setBlockDataMode(oldmode);
+
+ prereadFields = new GetField()
+ {
+ public ObjectStreamClass getObjectStreamClass()
+ {
+ return clazz;
+ }
+
+ public boolean defaulted(String name)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField f = clazz.getField(name);
+
+ /* First if we have a serialized field use the descriptor */
+ if (f != null)
+ {
+ /* It is in serialPersistentFields but setClass tells us
+ * it should not be set. This value is defaulted.
+ */
+ if (f.isPersistent() && !f.isToSet())
+ return true;
+
+ return false;
+ }
+
+ /* This is not a serialized field. There should be
+ * a default value only if the field really exists.
+ */
+ try
+ {
+ return (clazz.forClass().getDeclaredField (name) != null);
+ }
+ catch (NoSuchFieldException e)
+ {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+
+ public boolean get(String name, boolean defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field = getField(name, Boolean.TYPE);
+
+ if (field == null)
+ return defvalue;
+
+ return prim_field_data[field.getOffset()] == 0 ? false : true;
+ }
+
+ public char get(String name, char defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field = getField(name, Character.TYPE);
+
+ if (field == null)
+ return defvalue;
+
+ int off = field.getOffset();
+
+ return (char)(((prim_field_data[off++] & 0xFF) << 8)
+ | (prim_field_data[off] & 0xFF));
+ }
+
+ public byte get(String name, byte defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field = getField(name, Byte.TYPE);
+
+ if (field == null)
+ return defvalue;
+
+ return prim_field_data[field.getOffset()];
+ }
+
+ public short get(String name, short defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field = getField(name, Short.TYPE);
+
+ if (field == null)
+ return defvalue;
+
+ int off = field.getOffset();
+
+ return (short)(((prim_field_data[off++] & 0xFF) << 8)
+ | (prim_field_data[off] & 0xFF));
+ }
+
+ public int get(String name, int defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field = getField(name, Integer.TYPE);
+
+ if (field == null)
+ return defvalue;
+
+ int off = field.getOffset();
+
+ return ((prim_field_data[off++] & 0xFF) << 24)
+ | ((prim_field_data[off++] & 0xFF) << 16)
+ | ((prim_field_data[off++] & 0xFF) << 8)
+ | (prim_field_data[off] & 0xFF);
+ }
+
+ public long get(String name, long defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field = getField(name, Long.TYPE);
+
+ if (field == null)
+ return defvalue;
+
+ int off = field.getOffset();
+
+ return (long)(((prim_field_data[off++] & 0xFFL) << 56)
+ | ((prim_field_data[off++] & 0xFFL) << 48)
+ | ((prim_field_data[off++] & 0xFFL) << 40)
+ | ((prim_field_data[off++] & 0xFFL) << 32)
+ | ((prim_field_data[off++] & 0xFF) << 24)
+ | ((prim_field_data[off++] & 0xFF) << 16)
+ | ((prim_field_data[off++] & 0xFF) << 8)
+ | (prim_field_data[off] & 0xFF));
+ }
+
+ public float get(String name, float defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field = getField(name, Float.TYPE);
+
+ if (field == null)
+ return defvalue;
+
+ int off = field.getOffset();
+
+ return Float.intBitsToFloat(((prim_field_data[off++] & 0xFF) << 24)
+ | ((prim_field_data[off++] & 0xFF) << 16)
+ | ((prim_field_data[off++] & 0xFF) << 8)
+ | (prim_field_data[off] & 0xFF));
+ }
+
+ public double get(String name, double defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field = getField(name, Double.TYPE);
+
+ if (field == null)
+ return defvalue;
+
+ int off = field.getOffset();
+
+ return Double.longBitsToDouble
+ ( (long) (((prim_field_data[off++] & 0xFFL) << 56)
+ | ((prim_field_data[off++] & 0xFFL) << 48)
+ | ((prim_field_data[off++] & 0xFFL) << 40)
+ | ((prim_field_data[off++] & 0xFFL) << 32)
+ | ((prim_field_data[off++] & 0xFF) << 24)
+ | ((prim_field_data[off++] & 0xFF) << 16)
+ | ((prim_field_data[off++] & 0xFF) << 8)
+ | (prim_field_data[off] & 0xFF)));
+ }
+
+ public Object get(String name, Object defvalue)
+ throws IOException, IllegalArgumentException
+ {
+ ObjectStreamField field =
+ getField(name, defvalue == null ? null : defvalue.getClass ());
+
+ if (field == null)
+ return defvalue;
+
+ return objs[field.getOffset()];
+ }
+
+ private ObjectStreamField getField(String name, Class type)
+ throws IllegalArgumentException
+ {
+ ObjectStreamField field = clazz.getField(name);
+ boolean illegal = false;
+
+ try
+ {
+ try
+ {
+ Class field_type = field.getType();
+
+ if (type == field_type ||
+ (type == null && !field_type.isPrimitive()))
+ {
+ /* See defaulted */
+ return field;
+ }
+
+ illegal = true;
+ throw new IllegalArgumentException
+ ("Field requested is of type "
+ + field_type.getName()
+ + ", but requested type was "
+ + (type == null ? "Object" : type.getName()));
+ }
+ catch (NullPointerException _)
+ {
+ /* Here we catch NullPointerException, because it may
+ only come from the call 'field.getType()'. If field
+ is null, we have to return null and classpath ethic
+ say we must try to avoid 'if (xxx == null)'.
+ */
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw e;
+ }
+
+ return null;
+ }
+ finally
+ {
+ /* If this is an unassigned field we should return
+ * the default value.
+ */
+ if (!illegal && field != null && !field.isToSet() && field.isPersistent())
+ return null;
+
+ /* We do not want to modify transient fields. They should
+ * be left to 0.
+ */
+ try
+ {
+ Field f = clazz.forClass().getDeclaredField(name);
+ if (Modifier.isTransient(f.getModifiers()))
+ throw new IllegalArgumentException
+ ("no such field (non transient) " + name);
+ if (field == null && f.getType() != type)
+ throw new IllegalArgumentException
+ ("Invalid requested type for field " + name);
+ }
+ catch (NoSuchFieldException e)
+ {
+ if (field == null)
+ throw new IllegalArgumentException(e.getMessage());
+ }
+
+ }
+ }
+ };
+
+ fieldsAlreadyRead = true;
+ return prereadFields;
+ }
+
+ /**
+ * Protected constructor that allows subclasses to override
+ * deserialization. This constructor should be called by subclasses
+ * that wish to override <code>readObject (Object)</code>. This
+ * method does a security check <i>NOTE: currently not
+ * implemented</i>, then sets a flag that informs
+ * <code>readObject (Object)</code> to call the subclasses
+ * <code>readObjectOverride (Object)</code> method.
+ *
+ * @see #readObjectOverride()
+ */
+ protected ObjectInputStream()
+ throws IOException, SecurityException
+ {
+ SecurityManager sec_man = System.getSecurityManager();
+ if (sec_man != null)
+ sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
+ this.useSubclassMethod = true;
+ }
+
+ /**
+ * This method allows subclasses to override the default
+ * de serialization mechanism provided by
+ * <code>ObjectInputStream</code>. To make this method be used for
+ * writing objects, subclasses must invoke the 0-argument
+ * constructor on this class from their constructor.
+ *
+ * @see #ObjectInputStream()
+ */
+ protected Object readObjectOverride()
+ throws ClassNotFoundException, IOException, OptionalDataException
+ {
+ throw new IOException("Subclass of ObjectInputStream must implement readObjectOverride");
+ }
+
+ /**
+ * Assigns the next available handle to <code>obj</code>.
+ *
+ * @param obj The object for which we want a new handle.
+ * @return A valid handle for the specified object.
+ */
+ private int assignNewHandle(Object obj)
+ {
+ this.objectLookupTable.put(new Integer(this.nextOID),
+ new ObjectIdentityWrapper(obj));
+ return this.nextOID++;
+ }
+
+ private Object processResolution(ObjectStreamClass osc, Object obj, int handle)
+ throws IOException
+ {
+ if (osc != null && obj instanceof Serializable)
+ {
+ try
+ {
+ Method m = osc.readResolveMethod;
+ if(m != null)
+ {
+ obj = m.invoke(obj, new Object[] {});
+ }
+ }
+ catch (IllegalAccessException ignore)
+ {
+ }
+ catch (InvocationTargetException ignore)
+ {
+ }
+ }
+
+ if (this.resolveEnabled)
+ obj = resolveObject(obj);
+
+ this.objectLookupTable.put(new Integer(handle),
+ new ObjectIdentityWrapper(obj));
+
+ return obj;
+ }
+
+ private void clearHandles()
+ {
+ this.objectLookupTable.clear();
+ this.nextOID = baseWireHandle;
+ }
+
+ private void readNextBlock() throws IOException
+ {
+ readNextBlock(this.realInputStream.readByte());
+ }
+
+ private void readNextBlock(byte marker) throws IOException
+ {
+ if (marker == TC_BLOCKDATA)
+ {
+ if(dump) dumpElement("BLOCK DATA SIZE=");
+ this.blockDataBytes = this.realInputStream.readUnsignedByte();
+ if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
+ }
+ else if (marker == TC_BLOCKDATALONG)
+ {
+ if(dump) dumpElement("BLOCK DATA LONG SIZE=");
+ this.blockDataBytes = this.realInputStream.readInt();
+ if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
+ }
+ else
+ {
+ throw new EOFException("Attempt to read primitive data, but no data block is active.");
+ }
+
+ if (this.blockData.length < this.blockDataBytes)
+ this.blockData = new byte[this.blockDataBytes];
+
+ this.realInputStream.readFully (this.blockData, 0, this.blockDataBytes);
+ this.blockDataPosition = 0;
+ }
+
+ private void readArrayElements (Object array, Class clazz)
+ throws ClassNotFoundException, IOException
+ {
+ if (clazz.isPrimitive())
+ {
+ if (clazz == Boolean.TYPE)
+ {
+ boolean[] cast_array = (boolean[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = this.realInputStream.readBoolean();
+ return;
+ }
+ if (clazz == Byte.TYPE)
+ {
+ byte[] cast_array = (byte[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = this.realInputStream.readByte();
+ return;
+ }
+ if (clazz == Character.TYPE)
+ {
+ char[] cast_array = (char[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = this.realInputStream.readChar();
+ return;
+ }
+ if (clazz == Double.TYPE)
+ {
+ double[] cast_array = (double[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = this.realInputStream.readDouble();
+ return;
+ }
+ if (clazz == Float.TYPE)
+ {
+ float[] cast_array = (float[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = this.realInputStream.readFloat();
+ return;
+ }
+ if (clazz == Integer.TYPE)
+ {
+ int[] cast_array = (int[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = this.realInputStream.readInt();
+ return;
+ }
+ if (clazz == Long.TYPE)
+ {
+ long[] cast_array = (long[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = this.realInputStream.readLong();
+ return;
+ }
+ if (clazz == Short.TYPE)
+ {
+ short[] cast_array = (short[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = this.realInputStream.readShort();
+ return;
+ }
+ }
+ else
+ {
+ Object[] cast_array = (Object[])array;
+ for (int i=0; i < cast_array.length; i++)
+ cast_array[i] = readObject();
+ }
+ }
+
+ private void readFields (Object obj, ObjectStreamClass stream_osc)
+ throws ClassNotFoundException, IOException
+ {
+ ObjectStreamField[] fields = stream_osc.fieldMapping;
+
+ for (int i = 0; i < fields.length; i += 2)
+ {
+ ObjectStreamField stream_field = fields[i];
+ ObjectStreamField real_field = fields[i + 1];
+ boolean read_value = (stream_field != null && stream_field.getOffset() >= 0 && stream_field.isToSet());
+ boolean set_value = (real_field != null && real_field.isToSet());
+ String field_name;
+ char type;
+
+ if (stream_field != null)
+ {
+ field_name = stream_field.getName();
+ type = stream_field.getTypeCode();
+ }
+ else
+ {
+ field_name = real_field.getName();
+ type = real_field.getTypeCode();
+ }
+
+ switch(type)
+ {
+ case 'Z':
+ {
+ boolean value =
+ read_value ? this.realInputStream.readBoolean() : false;
+ if (dump && read_value && set_value)
+ dumpElementln(" " + field_name + ": " + value);
+ if (set_value)
+ real_field.setBooleanField(obj, value);
+ break;
+ }
+ case 'B':
+ {
+ byte value =
+ read_value ? this.realInputStream.readByte() : 0;
+ if (dump && read_value && set_value)
+ dumpElementln(" " + field_name + ": " + value);
+ if (set_value)
+ real_field.setByteField(obj, value);
+ break;
+ }
+ case 'C':
+ {
+ char value =
+ read_value ? this.realInputStream.readChar(): 0;
+ if (dump && read_value && set_value)
+ dumpElementln(" " + field_name + ": " + value);
+ if (set_value)
+ real_field.setCharField(obj, value);
+ break;
+ }
+ case 'D':
+ {
+ double value =
+ read_value ? this.realInputStream.readDouble() : 0;
+ if (dump && read_value && set_value)
+ dumpElementln(" " + field_name + ": " + value);
+ if (set_value)
+ real_field.setDoubleField(obj, value);
+ break;
+ }
+ case 'F':
+ {
+ float value =
+ read_value ? this.realInputStream.readFloat() : 0;
+ if (dump && read_value && set_value)
+ dumpElementln(" " + field_name + ": " + value);
+ if (set_value)
+ real_field.setFloatField(obj, value);
+ break;
+ }
+ case 'I':
+ {
+ int value =
+ read_value ? this.realInputStream.readInt() : 0;
+ if (dump && read_value && set_value)
+ dumpElementln(" " + field_name + ": " + value);
+ if (set_value)
+ real_field.setIntField(obj, value);
+ break;
+ }
+ case 'J':
+ {
+ long value =
+ read_value ? this.realInputStream.readLong() : 0;
+ if (dump && read_value && set_value)
+ dumpElementln(" " + field_name + ": " + value);
+ if (set_value)
+ real_field.setLongField(obj, value);
+ break;
+ }
+ case 'S':
+ {
+ short value =
+ read_value ? this.realInputStream.readShort() : 0;
+ if (dump && read_value && set_value)
+ dumpElementln(" " + field_name + ": " + value);
+ if (set_value)
+ real_field.setShortField(obj, value);
+ break;
+ }
+ case 'L':
+ case '[':
+ {
+ Object value =
+ read_value ? readObject() : null;
+ if (set_value)
+ real_field.setObjectField(obj, value);
+ break;
+ }
+ default:
+ throw new InternalError("Invalid type code: " + type);
+ }
+ }
+ }
+
+ // Toggles writing primitive data to block-data buffer.
+ private boolean setBlockDataMode (boolean on)
+ {
+ boolean oldmode = this.readDataFromBlock;
+ this.readDataFromBlock = on;
+
+ if (on)
+ this.dataInputStream = this.blockDataInput;
+ else
+ this.dataInputStream = this.realInputStream;
+ return oldmode;
+ }
+
+ // returns a new instance of REAL_CLASS that has been constructed
+ // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
+ private Object newObject (Class real_class, Constructor constructor)
+ throws ClassNotFoundException, IOException
+ {
+ if (constructor == null)
+ throw new InvalidClassException("Missing accessible no-arg base class constructor for " + real_class.getName());
+ try
+ {
+ return VMObjectInputStream.allocateObject(real_class, constructor.getDeclaringClass(), constructor);
+ }
+ catch (InstantiationException e)
+ {
+ throw new ClassNotFoundException
+ ("Instance of " + real_class + " could not be created");
+ }
+ }
+
+ // runs all registered ObjectInputValidations in prioritized order
+ // on OBJ
+ private void invokeValidators() throws InvalidObjectException
+ {
+ Object[] validators = new Object[this.validators.size()];
+ this.validators.copyInto (validators);
+ Arrays.sort (validators);
+
+ try
+ {
+ for (int i=0; i < validators.length; i++)
+ ((ObjectInputValidation)validators[i]).validateObject();
+ }
+ finally
+ {
+ this.validators.removeAllElements();
+ }
+ }
+
+ private void callReadMethod (Method readObject, Class klass, Object obj)
+ throws ClassNotFoundException, IOException
+ {
+ try
+ {
+ readObject.invoke(obj, new Object[] { this });
+ }
+ catch (InvocationTargetException x)
+ {
+ /* Rethrow if possible. */
+ Throwable exception = x.getTargetException();
+ if (exception instanceof RuntimeException)
+ throw (RuntimeException) exception;
+ if (exception instanceof IOException)
+ throw (IOException) exception;
+ if (exception instanceof ClassNotFoundException)
+ throw (ClassNotFoundException) exception;
+
+ throw new IOException("Exception thrown from readObject() on " +
+ klass + ": " + exception.getClass().getName());
+ }
+ catch (Exception x)
+ {
+ throw new IOException("Failure invoking readObject() on " +
+ klass + ": " + x.getClass().getName());
+ }
+
+ // Invalidate fields which has been read through readFields.
+ prereadFields = null;
+ }
+
+ private static final int BUFFER_SIZE = 1024;
+
+ private DataInputStream realInputStream;
+ private DataInputStream dataInputStream;
+ private DataInputStream blockDataInput;
+ private int blockDataPosition;
+ private int blockDataBytes;
+ private byte[] blockData;
+ private boolean useSubclassMethod;
+ private int nextOID;
+ private boolean resolveEnabled;
+ private Hashtable objectLookupTable;
+ private Object currentObject;
+ private ObjectStreamClass currentObjectStreamClass;
+ private boolean readDataFromBlock;
+ private boolean isDeserializing;
+ private boolean fieldsAlreadyRead;
+ private Vector validators;
+ private Hashtable classLookupTable;
+ private GetField prereadFields;
+
+ private ClassLoader callersClassLoader;
+ private static boolean dump;
+
+ // The nesting depth for debugging output
+ private int depth = 0;
+
+ private static final boolean DEBUG = false;
+
+ private void dumpElement (String msg)
+ {
+ System.out.print(msg);
+ }
+
+ private void dumpElementln (String msg)
+ {
+ System.out.println(msg);
+ for (int i = 0; i < depth; i++)
+ System.out.print (" ");
+ System.out.print (Thread.currentThread() + ": ");
+ }
+
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary ("javaio");
+ }
+ }
+
+ // used to keep a prioritized list of object validators
+ private static final class ValidatorAndPriority implements Comparable
+ {
+ int priority;
+ ObjectInputValidation validator;
+
+ ValidatorAndPriority (ObjectInputValidation validator, int priority)
+ {
+ this.priority = priority;
+ this.validator = validator;
+ }
+
+ public int compareTo (Object o)
+ {
+ ValidatorAndPriority vap = (ValidatorAndPriority)o;
+ return this.priority - vap.priority;
+ }
+ }
+}
+
diff --git a/libjava/classpath/java/io/ObjectInputValidation.java b/libjava/classpath/java/io/ObjectInputValidation.java
new file mode 100644
index 00000000000..4fdb8414f63
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectInputValidation.java
@@ -0,0 +1,67 @@
+/* ObjectInputValidation.java -- Validate an object
+ Copyright (C) 1998, 2003 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.io;
+
+/**
+ * This class allows an object to validate that it is valid after
+ * deserialization has run completely for it and all dependent objects.
+ * This allows an object to determine if it is invalid even if all
+ * state data was correctly deserialized from the stream. It can also
+ * be used to perform re-initialization type activities on an object
+ * after it has been completely deserialized.
+ *
+ * Since this method functions as a type of callback, it must be
+ * registered through <code>ObjectInputStream.registerValidation</code>
+ * in order to be invoked. This is typically done in the
+ * <code>readObject</code> method.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ *
+ * @see ObjectInputStream#registerValidation
+ */
+public interface ObjectInputValidation
+{
+ /**
+ * This method is called to validate an object after serialization
+ * is complete. If the object is invalid an exception is thrown.
+ *
+ * @exception InvalidObjectException If the object is invalid
+ */
+ void validateObject() throws InvalidObjectException;
+}
diff --git a/libjava/classpath/java/io/ObjectOutput.java b/libjava/classpath/java/io/ObjectOutput.java
new file mode 100644
index 00000000000..d35a09c3acb
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectOutput.java
@@ -0,0 +1,111 @@
+/* ObjectOutput.java -- Interface for writing objects to a stream
+ Copyright (C) 1998, 2003 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.io;
+
+/**
+ * This interface extends <code>DataOutput</code> to provide the additional
+ * facility of writing object instances to a stream. It also adds some
+ * additional methods to make the interface more
+ * <code>OutputStream</code> like.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ *
+ * @see DataOutput
+ */
+public interface ObjectOutput extends DataOutput
+{
+ /**
+ * This method writes the specified byte to the output stream.
+ *
+ * @param b The byte to write.
+ *
+ * @exception IOException If an error occurs.
+ */
+ void write(int b) throws IOException;
+
+ /**
+ * This method writes all the bytes in the specified byte array to the
+ * output stream.
+ *
+ * @param buf The array of bytes to write.
+ *
+ * @exception IOException If an error occurs.
+ */
+ void write(byte[] buf) throws IOException;
+
+ /**
+ * This method writes <code>len</code> bytes from the specified array
+ * starting at index <code>offset</code> into that array.
+ *
+ * @param buf The byte array to write from.
+ * @param offset The index into the byte array to start writing from.
+ * @param len The number of bytes to write.
+ *
+ * @exception IOException If an error occurs.
+ */
+ void write(byte[] buf, int offset, int len)
+ throws IOException;
+
+ /**
+ * This method writes a object instance to a stream. The format of the
+ * data written is determined by the actual implementation of this method
+ *
+ * @param obj The object to write
+ *
+ * @exception IOException If an error occurs
+ */
+ void writeObject(Object obj) throws IOException;
+
+ /**
+ * This method causes any buffered data to be flushed out to the underlying
+ * stream
+ *
+ * @exception IOException If an error occurs
+ */
+ void flush() throws IOException;
+
+ /**
+ * This method closes the underlying stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ void close() throws IOException;
+
+} // interface ObjectOutput
+
diff --git a/libjava/classpath/java/io/ObjectOutputStream.java b/libjava/classpath/java/io/ObjectOutputStream.java
new file mode 100644
index 00000000000..5e754c5ec7a
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectOutputStream.java
@@ -0,0 +1,1578 @@
+/* ObjectOutputStream.java -- Class used to write serialized objects
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.classpath.Configuration;
+import gnu.java.io.ObjectIdentityWrapper;
+import gnu.java.lang.reflect.TypeSignature;
+import gnu.java.security.action.SetAccessibleAction;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.util.Hashtable;
+
+/**
+ * An <code>ObjectOutputStream</code> can be used to write objects
+ * as well as primitive data in a platform-independent manner to an
+ * <code>OutputStream</code>.
+ *
+ * The data produced by an <code>ObjectOutputStream</code> can be read
+ * and reconstituted by an <code>ObjectInputStream</code>.
+ *
+ * <code>writeObject (Object)</code> is used to write Objects, the
+ * <code>write&lt;type&gt;</code> methods are used to write primitive
+ * data (as in <code>DataOutputStream</code>). Strings can be written
+ * as objects or as primitive data.
+ *
+ * Not all objects can be written out using an
+ * <code>ObjectOutputStream</code>. Only those objects that are an
+ * instance of <code>java.io.Serializable</code> can be written.
+ *
+ * Using default serialization, information about the class of an
+ * object is written, all of the non-transient, non-static fields of
+ * the object are written, if any of these fields are objects, they are
+ * written out in the same manner.
+ *
+ * An object is only written out the first time it is encountered. If
+ * the object is encountered later, a reference to it is written to
+ * the underlying stream. Thus writing circular object graphs
+ * does not present a problem, nor are relationships between objects
+ * in a graph lost.
+ *
+ * Example usage:
+ * <pre>
+ * Hashtable map = new Hashtable ();
+ * map.put ("one", new Integer (1));
+ * map.put ("two", new Integer (2));
+ *
+ * ObjectOutputStream oos =
+ * new ObjectOutputStream (new FileOutputStream ("numbers"));
+ * oos.writeObject (map);
+ * oos.close ();
+ *
+ * ObjectInputStream ois =
+ * new ObjectInputStream (new FileInputStream ("numbers"));
+ * Hashtable newmap = (Hashtable)ois.readObject ();
+ *
+ * System.out.println (newmap);
+ * </pre>
+ *
+ * The default serialization can be overriden in two ways.
+ *
+ * By defining a method <code>private void
+ * writeObject (ObjectOutputStream)</code>, a class can dictate exactly
+ * how information about itself is written.
+ * <code>defaultWriteObject ()</code> may be called from this method to
+ * carry out default serialization. This method is not
+ * responsible for dealing with fields of super-classes or subclasses.
+ *
+ * By implementing <code>java.io.Externalizable</code>. This gives
+ * the class complete control over the way it is written to the
+ * stream. If this approach is used the burden of writing superclass
+ * and subclass data is transfered to the class implementing
+ * <code>java.io.Externalizable</code>.
+ *
+ * @see java.io.DataOutputStream
+ * @see java.io.Externalizable
+ * @see java.io.ObjectInputStream
+ * @see java.io.Serializable
+ */
+public class ObjectOutputStream extends OutputStream
+ implements ObjectOutput, ObjectStreamConstants
+{
+ /**
+ * Creates a new <code>ObjectOutputStream</code> that will do all of
+ * its writing onto <code>out</code>. This method also initializes
+ * the stream by writing the header information (stream magic number
+ * and stream version).
+ *
+ * @exception IOException Writing stream header to underlying
+ * stream cannot be completed.
+ *
+ * @see #writeStreamHeader()
+ */
+ public ObjectOutputStream (OutputStream out) throws IOException
+ {
+ realOutput = new DataOutputStream(out);
+ blockData = new byte[ BUFFER_SIZE ];
+ blockDataCount = 0;
+ blockDataOutput = new DataOutputStream(this);
+ setBlockDataMode(true);
+ replacementEnabled = false;
+ isSerializing = false;
+ nextOID = baseWireHandle;
+ OIDLookupTable = new Hashtable();
+ protocolVersion = defaultProtocolVersion;
+ useSubclassMethod = false;
+ writeStreamHeader();
+
+ if (DEBUG)
+ {
+ String val = System.getProperty("gcj.dumpobjects");
+ if (val != null && !val.equals(""))
+ dump = true;
+ }
+ }
+
+ /**
+ * Writes a representation of <code>obj</code> to the underlying
+ * output stream by writing out information about its class, then
+ * writing out each of the objects non-transient, non-static
+ * fields. If any of these fields are other objects,
+ * they are written out in the same manner.
+ *
+ * This method can be overriden by a class by implementing
+ * <code>private void writeObject (ObjectOutputStream)</code>.
+ *
+ * If an exception is thrown from this method, the stream is left in
+ * an undefined state.
+ *
+ * @exception NotSerializableException An attempt was made to
+ * serialize an <code>Object</code> that is not serializable.
+ *
+ * @exception InvalidClassException Somebody tried to serialize
+ * an object which is wrongly formatted.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ */
+ public final void writeObject(Object obj) throws IOException
+ {
+ if (useSubclassMethod)
+ {
+ if (dump)
+ dumpElementln ("WRITE OVERRIDE: " + obj);
+
+ writeObjectOverride(obj);
+ return;
+ }
+
+ if (dump)
+ dumpElementln ("WRITE: " + obj);
+
+ depth += 2;
+
+ boolean was_serializing = isSerializing;
+ boolean old_mode = setBlockDataMode(false);
+ try
+ {
+ isSerializing = true;
+ boolean replaceDone = false;
+ Object replacedObject = null;
+
+ while (true)
+ {
+ if (obj == null)
+ {
+ realOutput.writeByte(TC_NULL);
+ break;
+ }
+
+ Integer handle = findHandle(obj);
+ if (handle != null)
+ {
+ realOutput.writeByte(TC_REFERENCE);
+ realOutput.writeInt(handle.intValue());
+ break;
+ }
+
+ if (obj instanceof Class)
+ {
+ Class cl = (Class)obj;
+ ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(cl);
+ realOutput.writeByte(TC_CLASS);
+ if (!osc.isProxyClass)
+ {
+ writeObject (osc);
+ }
+ else
+ {
+ realOutput.writeByte(TC_PROXYCLASSDESC);
+ Class[] intfs = cl.getInterfaces();
+ realOutput.writeInt(intfs.length);
+ for (int i = 0; i < intfs.length; i++)
+ realOutput.writeUTF(intfs[i].getName());
+
+ boolean oldmode = setBlockDataMode(true);
+ annotateProxyClass(cl);
+ setBlockDataMode(oldmode);
+ realOutput.writeByte(TC_ENDBLOCKDATA);
+
+ writeObject(osc.getSuper());
+ }
+ assignNewHandle(obj);
+ break;
+ }
+
+ if (obj instanceof ObjectStreamClass)
+ {
+ writeClassDescriptor((ObjectStreamClass) obj);
+ break;
+ }
+
+ Class clazz = obj.getClass();
+ ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz);
+ if (osc == null)
+ throw new NotSerializableException(clazz.getName());
+
+ if ((replacementEnabled || obj instanceof Serializable)
+ && ! replaceDone)
+ {
+ replacedObject = obj;
+
+ if (obj instanceof Serializable)
+ {
+ try
+ {
+ Method m = osc.writeReplaceMethod;
+ if (m != null)
+ obj = m.invoke(obj, new Object[0]);
+ }
+ catch (IllegalAccessException ignore)
+ {
+ }
+ catch (InvocationTargetException ignore)
+ {
+ }
+ }
+
+ if (replacementEnabled)
+ obj = replaceObject(obj);
+
+ replaceDone = true;
+ continue;
+ }
+
+ if (obj instanceof String)
+ {
+ realOutput.writeByte(TC_STRING);
+ assignNewHandle(obj);
+ realOutput.writeUTF((String)obj);
+ break;
+ }
+
+ if (clazz.isArray ())
+ {
+ realOutput.writeByte(TC_ARRAY);
+ writeObject(osc);
+ assignNewHandle(obj);
+ writeArraySizeAndElements(obj, clazz.getComponentType());
+ break;
+ }
+
+ realOutput.writeByte(TC_OBJECT);
+ writeObject(osc);
+
+ if (replaceDone)
+ assignNewHandle(replacedObject);
+ else
+ assignNewHandle(obj);
+
+ if (obj instanceof Externalizable)
+ {
+ if (protocolVersion == PROTOCOL_VERSION_2)
+ setBlockDataMode(true);
+
+ ((Externalizable)obj).writeExternal(this);
+
+ if (protocolVersion == PROTOCOL_VERSION_2)
+ {
+ setBlockDataMode(false);
+ realOutput.writeByte(TC_ENDBLOCKDATA);
+ }
+
+ break;
+ }
+
+ if (obj instanceof Serializable)
+ {
+ Object prevObject = this.currentObject;
+ ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
+ currentObject = obj;
+ ObjectStreamClass[] hierarchy =
+ ObjectStreamClass.getObjectStreamClasses(clazz);
+
+ for (int i = 0; i < hierarchy.length; i++)
+ {
+ currentObjectStreamClass = hierarchy[i];
+
+ fieldsAlreadyWritten = false;
+ if (currentObjectStreamClass.hasWriteMethod())
+ {
+ if (dump)
+ dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
+ setBlockDataMode(true);
+ callWriteMethod(obj, currentObjectStreamClass);
+ setBlockDataMode(false);
+ realOutput.writeByte(TC_ENDBLOCKDATA);
+ if (dump)
+ dumpElementln ("WRITE ENDBLOCKDATA FOR: " + obj);
+ }
+ else
+ {
+ if (dump)
+ dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
+ writeFields(obj, currentObjectStreamClass);
+ }
+ }
+
+ this.currentObject = prevObject;
+ this.currentObjectStreamClass = prevObjectStreamClass;
+ currentPutField = null;
+ break;
+ }
+
+ throw new NotSerializableException(clazz.getName ());
+ } // end pseudo-loop
+ }
+ catch (ObjectStreamException ose)
+ {
+ // Rethrow these are fatal.
+ throw ose;
+ }
+ catch (IOException e)
+ {
+ realOutput.writeByte(TC_EXCEPTION);
+ reset(true);
+
+ setBlockDataMode(false);
+ try
+ {
+ if (DEBUG)
+ {
+ e.printStackTrace(System.out);
+ }
+ writeObject(e);
+ }
+ catch (IOException ioe)
+ {
+ StreamCorruptedException ex =
+ new StreamCorruptedException
+ (ioe + " thrown while exception was being written to stream.");
+ if (DEBUG)
+ {
+ ex.printStackTrace(System.out);
+ }
+ throw ex;
+ }
+
+ reset (true);
+
+ }
+ finally
+ {
+ isSerializing = was_serializing;
+ setBlockDataMode(old_mode);
+ depth -= 2;
+
+ if (dump)
+ dumpElementln ("END: " + obj);
+ }
+ }
+
+ protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException
+ {
+ realOutput.writeByte(TC_CLASSDESC);
+ realOutput.writeUTF(osc.getName());
+ realOutput.writeLong(osc.getSerialVersionUID());
+ assignNewHandle(osc);
+
+ int flags = osc.getFlags();
+
+ if (protocolVersion == PROTOCOL_VERSION_2
+ && osc.isExternalizable())
+ flags |= SC_BLOCK_DATA;
+
+ realOutput.writeByte(flags);
+
+ ObjectStreamField[] fields = osc.fields;
+ realOutput.writeShort(fields.length);
+
+ ObjectStreamField field;
+ for (int i = 0; i < fields.length; i++)
+ {
+ field = fields[i];
+ realOutput.writeByte(field.getTypeCode ());
+ realOutput.writeUTF(field.getName ());
+
+ if (! field.isPrimitive())
+ writeObject(field.getTypeString());
+ }
+
+ boolean oldmode = setBlockDataMode(true);
+ annotateClass(osc.forClass());
+ setBlockDataMode(oldmode);
+ realOutput.writeByte(TC_ENDBLOCKDATA);
+
+ if (osc.isSerializable() || osc.isExternalizable())
+ writeObject(osc.getSuper());
+ else
+ writeObject(null);
+ }
+
+ /**
+ * Writes the current objects non-transient, non-static fields from
+ * the current class to the underlying output stream.
+ *
+ * This method is intended to be called from within a object's
+ * <code>private void writeObject (ObjectOutputStream)</code>
+ * method.
+ *
+ * @exception NotActiveException This method was called from a
+ * context other than from the current object's and current class's
+ * <code>private void writeObject (ObjectOutputStream)</code>
+ * method.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ */
+ public void defaultWriteObject()
+ throws IOException, NotActiveException
+ {
+ markFieldsWritten();
+ writeFields(currentObject, currentObjectStreamClass);
+ }
+
+
+ private void markFieldsWritten() throws IOException
+ {
+ if (currentObject == null || currentObjectStreamClass == null)
+ throw new NotActiveException
+ ("defaultWriteObject called by non-active class and/or object");
+
+ if (fieldsAlreadyWritten)
+ throw new IOException
+ ("Only one of writeFields and defaultWriteObject may be called, and it may only be called once");
+
+ fieldsAlreadyWritten = true;
+ }
+
+ /**
+ * Resets stream to state equivalent to the state just after it was
+ * constructed.
+ *
+ * Causes all objects previously written to the stream to be
+ * forgotten. A notification of this reset is also written to the
+ * underlying stream.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code> or reset called while serialization is
+ * in progress.
+ */
+ public void reset() throws IOException
+ {
+ reset(false);
+ }
+
+
+ private void reset(boolean internal) throws IOException
+ {
+ if (!internal)
+ {
+ if (isSerializing)
+ throw new IOException("Reset called while serialization in progress");
+
+ realOutput.writeByte(TC_RESET);
+ }
+
+ clearHandles();
+ }
+
+
+ /**
+ * Informs this <code>ObjectOutputStream</code> to write data
+ * according to the specified protocol. There are currently two
+ * different protocols, specified by <code>PROTOCOL_VERSION_1</code>
+ * and <code>PROTOCOL_VERSION_2</code>. This implementation writes
+ * data using <code>PROTOCOL_VERSION_2</code> by default, as is done
+ * by the JDK 1.2.
+ *
+ * A non-portable method, <code>setDefaultProtocolVersion (int
+ * version)</code> is provided to change the default protocol
+ * version.
+ *
+ * For an explination of the differences beween the two protocols
+ * see XXX: the Java ObjectSerialization Specification.
+ *
+ * @exception IOException if <code>version</code> is not a valid
+ * protocol
+ *
+ * @see #setDefaultProtocolVersion(int)
+ */
+ public void useProtocolVersion(int version) throws IOException
+ {
+ if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
+ throw new IOException("Invalid protocol version requested.");
+
+ protocolVersion = version;
+ }
+
+
+ /**
+ * <em>GNU $classpath specific</em>
+ *
+ * Changes the default stream protocol used by all
+ * <code>ObjectOutputStream</code>s. There are currently two
+ * different protocols, specified by <code>PROTOCOL_VERSION_1</code>
+ * and <code>PROTOCOL_VERSION_2</code>. The default default is
+ * <code>PROTOCOL_VERSION_1</code>.
+ *
+ * @exception IOException if <code>version</code> is not a valid
+ * protocol
+ *
+ * @see #useProtocolVersion(int)
+ */
+ public static void setDefaultProtocolVersion(int version)
+ throws IOException
+ {
+ if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
+ throw new IOException("Invalid protocol version requested.");
+
+ defaultProtocolVersion = version;
+ }
+
+
+ /**
+ * An empty hook that allows subclasses to write extra information
+ * about classes to the stream. This method is called the first
+ * time each class is seen, and after all of the standard
+ * information about the class has been written.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ *
+ * @see ObjectInputStream#resolveClass(java.io.ObjectStreamClass)
+ */
+ protected void annotateClass(Class cl) throws IOException
+ {
+ }
+
+ protected void annotateProxyClass(Class cl) throws IOException
+ {
+ }
+
+ /**
+ * Allows subclasses to replace objects that are written to the
+ * stream with other objects to be written in their place. This
+ * method is called the first time each object is encountered
+ * (modulo reseting of the stream).
+ *
+ * This method must be enabled before it will be called in the
+ * serialization process.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ *
+ * @see #enableReplaceObject(boolean)
+ */
+ protected Object replaceObject(Object obj) throws IOException
+ {
+ return obj;
+ }
+
+
+ /**
+ * If <code>enable</code> is <code>true</code> and this object is
+ * trusted, then <code>replaceObject (Object)</code> will be called
+ * in subsequent calls to <code>writeObject (Object)</code>.
+ * Otherwise, <code>replaceObject (Object)</code> will not be called.
+ *
+ * @exception SecurityException This class is not trusted.
+ */
+ protected boolean enableReplaceObject(boolean enable)
+ throws SecurityException
+ {
+ if (enable)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new SerializablePermission("enableSubstitution"));
+ }
+
+ boolean old_val = replacementEnabled;
+ replacementEnabled = enable;
+ return old_val;
+ }
+
+
+ /**
+ * Writes stream magic and stream version information to the
+ * underlying stream.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ */
+ protected void writeStreamHeader() throws IOException
+ {
+ realOutput.writeShort(STREAM_MAGIC);
+ realOutput.writeShort(STREAM_VERSION);
+ }
+
+ /**
+ * Protected constructor that allows subclasses to override
+ * serialization. This constructor should be called by subclasses
+ * that wish to override <code>writeObject (Object)</code>. This
+ * method does a security check <i>NOTE: currently not
+ * implemented</i>, then sets a flag that informs
+ * <code>writeObject (Object)</code> to call the subclasses
+ * <code>writeObjectOverride (Object)</code> method.
+ *
+ * @see #writeObjectOverride(Object)
+ */
+ protected ObjectOutputStream() throws IOException, SecurityException
+ {
+ SecurityManager sec_man = System.getSecurityManager ();
+ if (sec_man != null)
+ sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
+ useSubclassMethod = true;
+ }
+
+
+ /**
+ * This method allows subclasses to override the default
+ * serialization mechanism provided by
+ * <code>ObjectOutputStream</code>. To make this method be used for
+ * writing objects, subclasses must invoke the 0-argument
+ * constructor on this class from there constructor.
+ *
+ * @see #ObjectOutputStream()
+ *
+ * @exception NotActiveException Subclass has arranged for this
+ * method to be called, but did not implement this method.
+ */
+ protected void writeObjectOverride(Object obj) throws NotActiveException,
+ IOException
+ {
+ throw new NotActiveException
+ ("Subclass of ObjectOutputStream must implement writeObjectOverride");
+ }
+
+
+ /**
+ * @see DataOutputStream#write(int)
+ */
+ public void write (int data) throws IOException
+ {
+ if (writeDataAsBlocks)
+ {
+ if (blockDataCount == BUFFER_SIZE)
+ drain();
+
+ blockData[ blockDataCount++ ] = (byte)data;
+ }
+ else
+ realOutput.write(data);
+ }
+
+
+ /**
+ * @see DataOutputStream#write(byte[])
+ */
+ public void write(byte[] b) throws IOException
+ {
+ write(b, 0, b.length);
+ }
+
+
+ /**
+ * @see DataOutputStream#write(byte[],int,int)
+ */
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ if (writeDataAsBlocks)
+ {
+ if (len < 0)
+ throw new IndexOutOfBoundsException();
+
+ if (blockDataCount + len < BUFFER_SIZE)
+ {
+ System.arraycopy(b, off, blockData, blockDataCount, len);
+ blockDataCount += len;
+ }
+ else
+ {
+ drain();
+ writeBlockDataHeader(len);
+ realOutput.write(b, off, len);
+ }
+ }
+ else
+ realOutput.write(b, off, len);
+ }
+
+
+ /**
+ * @see DataOutputStream#flush()
+ */
+ public void flush () throws IOException
+ {
+ drain();
+ realOutput.flush();
+ }
+
+
+ /**
+ * Causes the block-data buffer to be written to the underlying
+ * stream, but does not flush underlying stream.
+ *
+ * @exception IOException Exception from underlying
+ * <code>OutputStream</code>.
+ */
+ protected void drain() throws IOException
+ {
+ if (blockDataCount == 0)
+ return;
+
+ if (writeDataAsBlocks)
+ writeBlockDataHeader(blockDataCount);
+ realOutput.write(blockData, 0, blockDataCount);
+ blockDataCount = 0;
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#close ()
+ */
+ public void close() throws IOException
+ {
+ flush();
+ realOutput.close();
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeBoolean (boolean)
+ */
+ public void writeBoolean(boolean data) throws IOException
+ {
+ blockDataOutput.writeBoolean(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeByte (int)
+ */
+ public void writeByte(int data) throws IOException
+ {
+ blockDataOutput.writeByte(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeShort (int)
+ */
+ public void writeShort (int data) throws IOException
+ {
+ blockDataOutput.writeShort(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeChar (int)
+ */
+ public void writeChar(int data) throws IOException
+ {
+ blockDataOutput.writeChar(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeInt (int)
+ */
+ public void writeInt(int data) throws IOException
+ {
+ blockDataOutput.writeInt(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeLong (long)
+ */
+ public void writeLong(long data) throws IOException
+ {
+ blockDataOutput.writeLong(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeFloat (float)
+ */
+ public void writeFloat(float data) throws IOException
+ {
+ blockDataOutput.writeFloat(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeDouble (double)
+ */
+ public void writeDouble(double data) throws IOException
+ {
+ blockDataOutput.writeDouble(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeBytes (java.lang.String)
+ */
+ public void writeBytes(String data) throws IOException
+ {
+ blockDataOutput.writeBytes(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeChars (java.lang.String)
+ */
+ public void writeChars(String data) throws IOException
+ {
+ dataOutput.writeChars(data);
+ }
+
+
+ /**
+ * @see java.io.DataOutputStream#writeUTF (java.lang.String)
+ */
+ public void writeUTF(String data) throws IOException
+ {
+ dataOutput.writeUTF(data);
+ }
+
+
+ /**
+ * This class allows a class to specify exactly which fields should
+ * be written, and what values should be written for these fields.
+ *
+ * XXX: finish up comments
+ */
+ public abstract static class PutField
+ {
+ public abstract void put (String name, boolean value);
+ public abstract void put (String name, byte value);
+ public abstract void put (String name, char value);
+ public abstract void put (String name, double value);
+ public abstract void put (String name, float value);
+ public abstract void put (String name, int value);
+ public abstract void put (String name, long value);
+ public abstract void put (String name, short value);
+ public abstract void put (String name, Object value);
+
+ /**
+ * @deprecated
+ */
+ public abstract void write (ObjectOutput out) throws IOException;
+ }
+
+ public PutField putFields() throws IOException
+ {
+ if (currentPutField != null)
+ return currentPutField;
+
+ currentPutField = new PutField()
+ {
+ private byte[] prim_field_data
+ = new byte[currentObjectStreamClass.primFieldSize];
+ private Object[] objs
+ = new Object[currentObjectStreamClass.objectFieldCount];
+
+ private ObjectStreamField getField (String name)
+ {
+ ObjectStreamField field
+ = currentObjectStreamClass.getField(name);
+
+ if (field == null)
+ throw new IllegalArgumentException("no such serializable field " + name);
+
+ return field;
+ }
+
+ public void put(String name, boolean value)
+ {
+ ObjectStreamField field = getField(name);
+
+ checkType(field, 'Z');
+ prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
+ }
+
+ public void put(String name, byte value)
+ {
+ ObjectStreamField field = getField(name);
+
+ checkType(field, 'B');
+ prim_field_data[field.getOffset()] = value;
+ }
+
+ public void put(String name, char value)
+ {
+ ObjectStreamField field = getField(name);
+
+ checkType(field, 'C');
+ int off = field.getOffset();
+ prim_field_data[off++] = (byte)(value >>> 8);
+ prim_field_data[off] = (byte)value;
+ }
+
+ public void put(String name, double value)
+ {
+ ObjectStreamField field = getField (name);
+
+ checkType(field, 'D');
+ int off = field.getOffset();
+ long l_value = Double.doubleToLongBits (value);
+ prim_field_data[off++] = (byte)(l_value >>> 52);
+ prim_field_data[off++] = (byte)(l_value >>> 48);
+ prim_field_data[off++] = (byte)(l_value >>> 40);
+ prim_field_data[off++] = (byte)(l_value >>> 32);
+ prim_field_data[off++] = (byte)(l_value >>> 24);
+ prim_field_data[off++] = (byte)(l_value >>> 16);
+ prim_field_data[off++] = (byte)(l_value >>> 8);
+ prim_field_data[off] = (byte)l_value;
+ }
+
+ public void put(String name, float value)
+ {
+ ObjectStreamField field = getField(name);
+
+ checkType(field, 'F');
+ int off = field.getOffset();
+ int i_value = Float.floatToIntBits(value);
+ prim_field_data[off++] = (byte)(i_value >>> 24);
+ prim_field_data[off++] = (byte)(i_value >>> 16);
+ prim_field_data[off++] = (byte)(i_value >>> 8);
+ prim_field_data[off] = (byte)i_value;
+ }
+
+ public void put(String name, int value)
+ {
+ ObjectStreamField field = getField(name);
+ checkType(field, 'I');
+ int off = field.getOffset();
+ prim_field_data[off++] = (byte)(value >>> 24);
+ prim_field_data[off++] = (byte)(value >>> 16);
+ prim_field_data[off++] = (byte)(value >>> 8);
+ prim_field_data[off] = (byte)value;
+ }
+
+ public void put(String name, long value)
+ {
+ ObjectStreamField field = getField(name);
+ checkType(field, 'J');
+ int off = field.getOffset();
+ prim_field_data[off++] = (byte)(value >>> 52);
+ prim_field_data[off++] = (byte)(value >>> 48);
+ prim_field_data[off++] = (byte)(value >>> 40);
+ prim_field_data[off++] = (byte)(value >>> 32);
+ prim_field_data[off++] = (byte)(value >>> 24);
+ prim_field_data[off++] = (byte)(value >>> 16);
+ prim_field_data[off++] = (byte)(value >>> 8);
+ prim_field_data[off] = (byte)value;
+ }
+
+ public void put(String name, short value)
+ {
+ ObjectStreamField field = getField(name);
+ checkType(field, 'S');
+ int off = field.getOffset();
+ prim_field_data[off++] = (byte)(value >>> 8);
+ prim_field_data[off] = (byte)value;
+ }
+
+ public void put(String name, Object value)
+ {
+ ObjectStreamField field = getField(name);
+
+ if (value != null &&
+ ! field.getType().isAssignableFrom(value.getClass ()))
+ throw new IllegalArgumentException("Class " + value.getClass() +
+ " cannot be cast to " + field.getType());
+ objs[field.getOffset()] = value;
+ }
+
+ public void write(ObjectOutput out) throws IOException
+ {
+ // Apparently Block data is not used with PutField as per
+ // empirical evidence against JDK 1.2. Also see Mauve test
+ // java.io.ObjectInputOutput.Test.GetPutField.
+ boolean oldmode = setBlockDataMode(false);
+ out.write(prim_field_data);
+ for (int i = 0; i < objs.length; ++ i)
+ out.writeObject(objs[i]);
+ setBlockDataMode(oldmode);
+ }
+
+ private void checkType(ObjectStreamField field, char type)
+ throws IllegalArgumentException
+ {
+ if (TypeSignature.getEncodingOfClass(field.getType()).charAt(0)
+ != type)
+ throw new IllegalArgumentException();
+ }
+ };
+ // end PutFieldImpl
+
+ return currentPutField;
+ }
+
+
+ public void writeFields() throws IOException
+ {
+ if (currentPutField == null)
+ throw new NotActiveException("writeFields can only be called after putFields has been called");
+
+ markFieldsWritten();
+ currentPutField.write(this);
+ }
+
+
+ // write out the block-data buffer, picking the correct header
+ // depending on the size of the buffer
+ private void writeBlockDataHeader(int size) throws IOException
+ {
+ if (size < 256)
+ {
+ realOutput.writeByte(TC_BLOCKDATA);
+ realOutput.write(size);
+ }
+ else
+ {
+ realOutput.writeByte(TC_BLOCKDATALONG);
+ realOutput.writeInt(size);
+ }
+ }
+
+
+ // lookup the handle for OBJ, return null if OBJ doesn't have a
+ // handle yet
+ private Integer findHandle(Object obj)
+ {
+ return (Integer)OIDLookupTable.get(new ObjectIdentityWrapper(obj));
+ }
+
+
+ // assigns the next availible handle to OBJ
+ private int assignNewHandle(Object obj)
+ {
+ OIDLookupTable.put(new ObjectIdentityWrapper(obj),
+ new Integer(nextOID));
+ return nextOID++;
+ }
+
+
+ // resets mapping from objects to handles
+ private void clearHandles()
+ {
+ nextOID = baseWireHandle;
+ OIDLookupTable.clear();
+ }
+
+
+ // write out array size followed by each element of the array
+ private void writeArraySizeAndElements(Object array, Class clazz)
+ throws IOException
+ {
+ int length = Array.getLength(array);
+
+ if (clazz.isPrimitive())
+ {
+ if (clazz == Boolean.TYPE)
+ {
+ boolean[] cast_array = (boolean[])array;
+ realOutput.writeInt (length);
+ for (int i = 0; i < length; i++)
+ realOutput.writeBoolean(cast_array[i]);
+ return;
+ }
+ if (clazz == Byte.TYPE)
+ {
+ byte[] cast_array = (byte[])array;
+ realOutput.writeInt(length);
+ realOutput.write(cast_array, 0, length);
+ return;
+ }
+ if (clazz == Character.TYPE)
+ {
+ char[] cast_array = (char[])array;
+ realOutput.writeInt(length);
+ for (int i = 0; i < length; i++)
+ realOutput.writeChar(cast_array[i]);
+ return;
+ }
+ if (clazz == Double.TYPE)
+ {
+ double[] cast_array = (double[])array;
+ realOutput.writeInt(length);
+ for (int i = 0; i < length; i++)
+ realOutput.writeDouble(cast_array[i]);
+ return;
+ }
+ if (clazz == Float.TYPE)
+ {
+ float[] cast_array = (float[])array;
+ realOutput.writeInt(length);
+ for (int i = 0; i < length; i++)
+ realOutput.writeFloat(cast_array[i]);
+ return;
+ }
+ if (clazz == Integer.TYPE)
+ {
+ int[] cast_array = (int[])array;
+ realOutput.writeInt(length);
+ for (int i = 0; i < length; i++)
+ realOutput.writeInt(cast_array[i]);
+ return;
+ }
+ if (clazz == Long.TYPE)
+ {
+ long[] cast_array = (long[])array;
+ realOutput.writeInt (length);
+ for (int i = 0; i < length; i++)
+ realOutput.writeLong(cast_array[i]);
+ return;
+ }
+ if (clazz == Short.TYPE)
+ {
+ short[] cast_array = (short[])array;
+ realOutput.writeInt (length);
+ for (int i = 0; i < length; i++)
+ realOutput.writeShort(cast_array[i]);
+ return;
+ }
+ }
+ else
+ {
+ Object[] cast_array = (Object[])array;
+ realOutput.writeInt(length);
+ for (int i = 0; i < length; i++)
+ writeObject(cast_array[i]);
+ }
+ }
+
+
+ // writes out FIELDS of OBJECT for the specified ObjectStreamClass.
+ // FIELDS are already in canonical order.
+ private void writeFields(Object obj, ObjectStreamClass osc)
+ throws IOException
+ {
+ ObjectStreamField[] fields = osc.fields;
+ boolean oldmode = setBlockDataMode(false);
+ String field_name;
+ Class type;
+
+ for (int i = 0; i < fields.length; i++)
+ {
+ field_name = fields[i].getName();
+ type = fields[i].getType();
+
+ if (dump)
+ dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);
+
+ if (type == Boolean.TYPE)
+ realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
+ else if (type == Byte.TYPE)
+ realOutput.writeByte(getByteField(obj, osc.forClass(), field_name));
+ else if (type == Character.TYPE)
+ realOutput.writeChar(getCharField(obj, osc.forClass(), field_name));
+ else if (type == Double.TYPE)
+ realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name));
+ else if (type == Float.TYPE)
+ realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name));
+ else if (type == Integer.TYPE)
+ realOutput.writeInt(getIntField(obj, osc.forClass(), field_name));
+ else if (type == Long.TYPE)
+ realOutput.writeLong(getLongField(obj, osc.forClass(), field_name));
+ else if (type == Short.TYPE)
+ realOutput.writeShort(getShortField(obj, osc.forClass(), field_name));
+ else
+ writeObject(getObjectField(obj, osc.forClass(), field_name,
+ fields[i].getTypeString ()));
+ }
+ setBlockDataMode(oldmode);
+ }
+
+
+ // Toggles writing primitive data to block-data buffer.
+ // Package-private to avoid a trampoline constructor.
+ boolean setBlockDataMode(boolean on) throws IOException
+ {
+ if (on == writeDataAsBlocks)
+ return on;
+
+ drain();
+ boolean oldmode = writeDataAsBlocks;
+ writeDataAsBlocks = on;
+
+ if (on)
+ dataOutput = blockDataOutput;
+ else
+ dataOutput = realOutput;
+
+ return oldmode;
+ }
+
+
+ private void callWriteMethod(Object obj, ObjectStreamClass osc)
+ throws IOException
+ {
+ currentPutField = null;
+ try
+ {
+ Object args[] = {this};
+ osc.writeObjectMethod.invoke(obj, args);
+ }
+ catch (InvocationTargetException x)
+ {
+ /* Rethrow if possible. */
+ Throwable exception = x.getTargetException();
+ if (exception instanceof RuntimeException)
+ throw (RuntimeException) exception;
+ if (exception instanceof IOException)
+ throw (IOException) exception;
+
+ IOException ioe
+ = new IOException("Exception thrown from writeObject() on " +
+ osc.forClass().getName() + ": " +
+ exception.getClass().getName());
+ ioe.initCause(exception);
+ throw ioe;
+ }
+ catch (Exception x)
+ {
+ IOException ioe
+ = new IOException("Failure invoking writeObject() on " +
+ osc.forClass().getName() + ": " +
+ x.getClass().getName());
+ ioe.initCause(x);
+ throw ioe;
+ }
+ }
+
+ private boolean getBooleanField(Object obj, Class klass, String field_name)
+ throws IOException
+ {
+ try
+ {
+ Field f = getField(klass, field_name);
+ boolean b = f.getBoolean(obj);
+ return b;
+ }
+ catch (IllegalArgumentException _)
+ {
+ throw new InvalidClassException
+ ("invalid requested type for field " + field_name + " in class " + klass.getName());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ throw new IOException("Unexpected exception " + _);
+ }
+ }
+
+ private byte getByteField (Object obj, Class klass, String field_name)
+ throws IOException
+ {
+ try
+ {
+ Field f = getField (klass, field_name);
+ byte b = f.getByte (obj);
+ return b;
+ }
+ catch (IllegalArgumentException _)
+ {
+ throw new InvalidClassException
+ ("invalid requested type for field " + field_name + " in class " + klass.getName());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ throw new IOException("Unexpected exception " + _);
+ }
+ }
+
+ private char getCharField (Object obj, Class klass, String field_name)
+ throws IOException
+ {
+ try
+ {
+ Field f = getField (klass, field_name);
+ char b = f.getChar (obj);
+ return b;
+ }
+ catch (IllegalArgumentException _)
+ {
+ throw new InvalidClassException
+ ("invalid requested type for field " + field_name + " in class " + klass.getName());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ throw new IOException("Unexpected exception " + _);
+ }
+ }
+
+ private double getDoubleField (Object obj, Class klass, String field_name)
+ throws IOException
+ {
+ try
+ {
+ Field f = getField (klass, field_name);
+ double b = f.getDouble (obj);
+ return b;
+ }
+ catch (IllegalArgumentException _)
+ {
+ throw new InvalidClassException
+ ("invalid requested type for field " + field_name + " in class " + klass.getName());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ throw new IOException("Unexpected exception " + _);
+ }
+ }
+
+ private float getFloatField (Object obj, Class klass, String field_name)
+ throws IOException
+ {
+ try
+ {
+ Field f = getField (klass, field_name);
+ float b = f.getFloat (obj);
+ return b;
+ }
+ catch (IllegalArgumentException _)
+ {
+ throw new InvalidClassException
+ ("invalid requested type for field " + field_name + " in class " + klass.getName());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ throw new IOException("Unexpected exception " + _);
+ }
+ }
+
+ private int getIntField (Object obj, Class klass, String field_name)
+ throws IOException
+ {
+ try
+ {
+ Field f = getField (klass, field_name);
+ int b = f.getInt (obj);
+ return b;
+ }
+ catch (IllegalArgumentException _)
+ {
+ throw new InvalidClassException
+ ("invalid requested type for field " + field_name + " in class " + klass.getName());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ throw new IOException("Unexpected exception " + _);
+ }
+ }
+
+ private long getLongField (Object obj, Class klass, String field_name)
+ throws IOException
+ {
+ try
+ {
+ Field f = getField (klass, field_name);
+ long b = f.getLong (obj);
+ return b;
+ }
+ catch (IllegalArgumentException _)
+ {
+ throw new InvalidClassException
+ ("invalid requested type for field " + field_name + " in class " + klass.getName());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ throw new IOException("Unexpected exception " + _);
+ }
+ }
+
+ private short getShortField (Object obj, Class klass, String field_name)
+ throws IOException
+ {
+ try
+ {
+ Field f = getField (klass, field_name);
+ short b = f.getShort (obj);
+ return b;
+ }
+ catch (IllegalArgumentException _)
+ {
+ throw new InvalidClassException
+ ("invalid requested type for field " + field_name + " in class " + klass.getName());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ throw new IOException("Unexpected exception " + _);
+ }
+ }
+
+ private Object getObjectField (Object obj, Class klass, String field_name,
+ String type_code) throws IOException
+ {
+ try
+ {
+ Field f = getField (klass, field_name);
+ ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType());
+
+ /* if of is primitive something went wrong
+ * in the check for primitive classes in writeFields.
+ */
+ if (of.isPrimitive())
+ throw new InvalidClassException
+ ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field is primitive");
+
+ if (!of.getTypeString().equals(type_code))
+ throw new InvalidClassException
+ ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field " + of + " has type string " + of.getTypeString() + " instead of " + type_code);
+
+ Object o = f.get (obj);
+ // FIXME: We should check the type_code here
+ return o;
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new IOException ();
+ }
+ }
+
+ private Field getField (Class klass, String name)
+ throws java.io.InvalidClassException
+ {
+ try
+ {
+ final Field f = klass.getDeclaredField(name);
+ setAccessible.setMember(f);
+ AccessController.doPrivileged(setAccessible);
+ return f;
+ }
+ catch (java.lang.NoSuchFieldException e)
+ {
+ throw new InvalidClassException
+ ("no field called " + name + " in class " + klass.getName());
+ }
+ }
+
+ private void dumpElementln (String msg)
+ {
+ for (int i = 0; i < depth; i++)
+ System.out.print (" ");
+ System.out.print (Thread.currentThread() + ": ");
+ System.out.println(msg);
+ }
+
+ // this value comes from 1.2 spec, but is used in 1.1 as well
+ private static final int BUFFER_SIZE = 1024;
+
+ private static int defaultProtocolVersion = PROTOCOL_VERSION_2;
+
+ private DataOutputStream dataOutput;
+ private boolean writeDataAsBlocks;
+ private DataOutputStream realOutput;
+ private DataOutputStream blockDataOutput;
+ private byte[] blockData;
+ private int blockDataCount;
+ private Object currentObject;
+ // Package-private to avoid a trampoline.
+ ObjectStreamClass currentObjectStreamClass;
+ private PutField currentPutField;
+ private boolean fieldsAlreadyWritten;
+ private boolean replacementEnabled;
+ private boolean isSerializing;
+ private int nextOID;
+ private Hashtable OIDLookupTable;
+ private int protocolVersion;
+ private boolean useSubclassMethod;
+ private SetAccessibleAction setAccessible = new SetAccessibleAction();
+
+ // The nesting depth for debugging output
+ private int depth = 0;
+
+ // Set if we're generating debugging dumps
+ private boolean dump = false;
+
+ private static final boolean DEBUG = false;
+
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("javaio");
+ }
+ }
+}
diff --git a/libjava/classpath/java/io/ObjectStreamClass.java b/libjava/classpath/java/io/ObjectStreamClass.java
new file mode 100644
index 00000000000..b7bd1271324
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectStreamClass.java
@@ -0,0 +1,976 @@
+/* ObjectStreamClass.java -- Class used to write class information
+ about serialized objects.
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 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.io;
+
+import gnu.java.io.NullOutputStream;
+import gnu.java.lang.reflect.TypeSignature;
+import gnu.java.security.action.SetAccessibleAction;
+import gnu.java.security.provider.Gnu;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.DigestOutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class ObjectStreamClass implements Serializable
+{
+ /**
+ * Returns the <code>ObjectStreamClass</code> for <code>cl</code>.
+ * If <code>cl</code> is null, or is not <code>Serializable</code>,
+ * null is returned. <code>ObjectStreamClass</code>'s are memorized;
+ * later calls to this method with the same class will return the
+ * same <code>ObjectStreamClass</code> object and no recalculation
+ * will be done.
+ *
+ * @see java.io.Serializable
+ */
+ public static ObjectStreamClass lookup(Class cl)
+ {
+ if (cl == null)
+ return null;
+ if (! (Serializable.class).isAssignableFrom(cl))
+ return null;
+
+ return lookupForClassObject(cl);
+ }
+
+ /**
+ * This lookup for internal use by ObjectOutputStream. Suppose
+ * we have a java.lang.Class object C for class A, though A is not
+ * serializable, but it's okay to serialize C.
+ */
+ static ObjectStreamClass lookupForClassObject(Class cl)
+ {
+ if (cl == null)
+ return null;
+
+ ObjectStreamClass osc = (ObjectStreamClass) classLookupTable.get(cl);
+
+ if (osc != null)
+ return osc;
+ else
+ {
+ osc = new ObjectStreamClass(cl);
+ classLookupTable.put(cl, osc);
+ return osc;
+ }
+ }
+
+ /**
+ * Returns the name of the class that this
+ * <code>ObjectStreamClass</code> represents.
+ *
+ * @return the name of the class.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns the class that this <code>ObjectStreamClass</code>
+ * represents. Null could be returned if this
+ * <code>ObjectStreamClass</code> was read from an
+ * <code>ObjectInputStream</code> and the class it represents cannot
+ * be found or loaded.
+ *
+ * @see java.io.ObjectInputStream
+ */
+ public Class forClass()
+ {
+ return clazz;
+ }
+
+ /**
+ * Returns the serial version stream-unique identifier for the class
+ * represented by this <code>ObjectStreamClass</code>. This SUID is
+ * either defined by the class as <code>static final long
+ * serialVersionUID</code> or is calculated as specified in
+ * Javasoft's "Object Serialization Specification" XXX: add reference
+ *
+ * @return the serial version UID.
+ */
+ public long getSerialVersionUID()
+ {
+ return uid;
+ }
+
+ /**
+ * Returns the serializable (non-static and non-transient) Fields
+ * of the class represented by this ObjectStreamClass. The Fields
+ * are sorted by name.
+ *
+ * @return the fields.
+ */
+ public ObjectStreamField[] getFields()
+ {
+ ObjectStreamField[] copy = new ObjectStreamField[ fields.length ];
+ System.arraycopy(fields, 0, copy, 0, fields.length);
+ return copy;
+ }
+
+ // XXX doc
+ // Can't do binary search since fields is sorted by name and
+ // primitiveness.
+ public ObjectStreamField getField (String name)
+ {
+ for (int i = 0; i < fields.length; i++)
+ if (fields[i].getName().equals(name))
+ return fields[i];
+ return null;
+ }
+
+ /**
+ * Returns a textual representation of this
+ * <code>ObjectStreamClass</code> object including the name of the
+ * class it represents as well as that class's serial version
+ * stream-unique identifier.
+ *
+ * @see #getSerialVersionUID()
+ * @see #getName()
+ */
+ public String toString()
+ {
+ return "java.io.ObjectStreamClass< " + name + ", " + uid + " >";
+ }
+
+ // Returns true iff the class that this ObjectStreamClass represents
+ // has the following method:
+ //
+ // private void writeObject (ObjectOutputStream)
+ //
+ // This method is used by the class to override default
+ // serialization behavior.
+ boolean hasWriteMethod()
+ {
+ return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0;
+ }
+
+ // Returns true iff the class that this ObjectStreamClass represents
+ // implements Serializable but does *not* implement Externalizable.
+ boolean isSerializable()
+ {
+ return (flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0;
+ }
+
+
+ // Returns true iff the class that this ObjectStreamClass represents
+ // implements Externalizable.
+ boolean isExternalizable()
+ {
+ return (flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0;
+ }
+
+
+ // Returns the <code>ObjectStreamClass</code> that represents the
+ // class that is the superclass of the class this
+ // <code>ObjectStreamClass</code> represents. If the superclass is
+ // not Serializable, null is returned.
+ ObjectStreamClass getSuper()
+ {
+ return superClass;
+ }
+
+
+ // returns an array of ObjectStreamClasses that represent the super
+ // classes of CLAZZ and CLAZZ itself in order from most super to
+ // CLAZZ. ObjectStreamClass[0] is the highest superclass of CLAZZ
+ // that is serializable.
+ static ObjectStreamClass[] getObjectStreamClasses(Class clazz)
+ {
+ ObjectStreamClass osc = ObjectStreamClass.lookup(clazz);
+
+ if (osc == null)
+ return new ObjectStreamClass[0];
+ else
+ {
+ Vector oscs = new Vector();
+
+ while (osc != null)
+ {
+ oscs.addElement (osc);
+ osc = osc.getSuper();
+ }
+
+ int count = oscs.size();
+ ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[ count ];
+
+ for (int i = count - 1; i >= 0; i--)
+ sorted_oscs[ count - i - 1 ] = (ObjectStreamClass) oscs.elementAt(i);
+
+ return sorted_oscs;
+ }
+ }
+
+
+ // Returns an integer that consists of bit-flags that indicate
+ // properties of the class represented by this ObjectStreamClass.
+ // The bit-flags that could be present are those defined in
+ // ObjectStreamConstants that begin with `SC_'
+ int getFlags()
+ {
+ return flags;
+ }
+
+
+ ObjectStreamClass(String name, long uid, byte flags,
+ ObjectStreamField[] fields)
+ {
+ this.name = name;
+ this.uid = uid;
+ this.flags = flags;
+ this.fields = fields;
+ }
+
+ /**
+ * This method builds the internal description corresponding to a Java Class.
+ * As the constructor only assign a name to the current ObjectStreamClass instance,
+ * that method sets the serial UID, chose the fields which will be serialized,
+ * and compute the position of the fields in the serialized stream.
+ *
+ * @param cl The Java class which is used as a reference for building the descriptor.
+ * @param superClass The descriptor of the super class for this class descriptor.
+ * @throws InvalidClassException if an incompatibility between computed UID and
+ * already set UID is found.
+ */
+ void setClass(Class cl, ObjectStreamClass superClass) throws InvalidClassException
+ {
+ this.clazz = cl;
+
+ cacheMethods();
+
+ long class_uid = getClassUID(cl);
+ if (uid == 0)
+ uid = class_uid;
+ else
+ {
+ // Check that the actual UID of the resolved class matches the UID from
+ // the stream.
+ if (uid != class_uid)
+ {
+ String msg = cl +
+ ": Local class not compatible: stream serialVersionUID="
+ + uid + ", local serialVersionUID=" + class_uid;
+ throw new InvalidClassException (msg);
+ }
+ }
+
+ isProxyClass = clazz != null && Proxy.isProxyClass(clazz);
+ this.superClass = superClass;
+ calculateOffsets();
+
+ try
+ {
+ ObjectStreamField[] exportedFields = getSerialPersistentFields (clazz);
+
+ if (exportedFields == null)
+ return;
+
+ ObjectStreamField[] newFieldList = new ObjectStreamField[exportedFields.length + fields.length];
+ int i, j, k;
+
+ /* We now check the import fields against the exported fields.
+ * There should not be contradiction (e.g. int x and String x)
+ * but extra virtual fields can be added to the class.
+ */
+
+ Arrays.sort(exportedFields);
+
+ i = 0; j = 0; k = 0;
+ while (i < fields.length && j < exportedFields.length)
+ {
+ int comp = fields[i].compareTo(exportedFields[j]);
+
+ if (comp < 0)
+ {
+ newFieldList[k] = fields[i];
+ fields[i].setPersistent(false);
+ fields[i].setToSet(false);
+ i++;
+ }
+ else if (comp > 0)
+ {
+ /* field not found in imported fields. We add it
+ * in the list of supported fields.
+ */
+ newFieldList[k] = exportedFields[j];
+ newFieldList[k].setPersistent(true);
+ newFieldList[k].setToSet(false);
+ try
+ {
+ newFieldList[k].lookupField(clazz);
+ newFieldList[k].checkFieldType();
+ }
+ catch (NoSuchFieldException _)
+ {
+ }
+ j++;
+ }
+ else
+ {
+ try
+ {
+ exportedFields[j].lookupField(clazz);
+ exportedFields[j].checkFieldType();
+ }
+ catch (NoSuchFieldException _)
+ {
+ }
+
+ if (!fields[i].getType().equals(exportedFields[j].getType()))
+ throw new InvalidClassException
+ ("serialPersistentFields must be compatible with" +
+ " imported fields (about " + fields[i].getName() + ")");
+ newFieldList[k] = fields[i];
+ fields[i].setPersistent(true);
+ i++;
+ j++;
+ }
+ k++;
+ }
+
+ if (i < fields.length)
+ for (;i<fields.length;i++,k++)
+ {
+ fields[i].setPersistent(false);
+ fields[i].setToSet(false);
+ newFieldList[k] = fields[i];
+ }
+ else
+ if (j < exportedFields.length)
+ for (;j<exportedFields.length;j++,k++)
+ {
+ exportedFields[j].setPersistent(true);
+ exportedFields[j].setToSet(false);
+ newFieldList[k] = exportedFields[j];
+ }
+
+ fields = new ObjectStreamField[k];
+ System.arraycopy(newFieldList, 0, fields, 0, k);
+ }
+ catch (NoSuchFieldException ignore)
+ {
+ return;
+ }
+ catch (IllegalAccessException ignore)
+ {
+ return;
+ }
+ }
+
+ void setSuperclass (ObjectStreamClass osc)
+ {
+ superClass = osc;
+ }
+
+ void calculateOffsets()
+ {
+ int i;
+ ObjectStreamField field;
+ primFieldSize = 0;
+ int fcount = fields.length;
+ for (i = 0; i < fcount; ++ i)
+ {
+ field = fields[i];
+
+ if (! field.isPrimitive())
+ break;
+
+ field.setOffset(primFieldSize);
+ switch (field.getTypeCode())
+ {
+ case 'B':
+ case 'Z':
+ ++ primFieldSize;
+ break;
+ case 'C':
+ case 'S':
+ primFieldSize += 2;
+ break;
+ case 'I':
+ case 'F':
+ primFieldSize += 4;
+ break;
+ case 'D':
+ case 'J':
+ primFieldSize += 8;
+ break;
+ }
+ }
+
+ for (objectFieldCount = 0; i < fcount; ++ i)
+ fields[i].setOffset(objectFieldCount++);
+ }
+
+ private Method findMethod(Method[] methods, String name, Class[] params,
+ Class returnType, boolean mustBePrivate)
+ {
+outer:
+ for (int i = 0; i < methods.length; i++)
+ {
+ final Method m = methods[i];
+ int mods = m.getModifiers();
+ if (Modifier.isStatic(mods)
+ || (mustBePrivate && !Modifier.isPrivate(mods)))
+ {
+ continue;
+ }
+
+ if (m.getName().equals(name)
+ && m.getReturnType() == returnType)
+ {
+ Class[] mp = m.getParameterTypes();
+ if (mp.length == params.length)
+ {
+ for (int j = 0; j < mp.length; j++)
+ {
+ if (mp[j] != params[j])
+ {
+ continue outer;
+ }
+ }
+ AccessController.doPrivileged(new SetAccessibleAction(m));
+ return m;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static boolean inSamePackage(Class c1, Class c2)
+ {
+ String name1 = c1.getName();
+ String name2 = c2.getName();
+
+ int id1 = name1.lastIndexOf('.');
+ int id2 = name2.lastIndexOf('.');
+
+ // Handle the default package
+ if (id1 == -1 || id2 == -1)
+ return id1 == id2;
+
+ String package1 = name1.substring(0, id1);
+ String package2 = name2.substring(0, id2);
+
+ return package1.equals(package2);
+ }
+
+ final static Class[] noArgs = new Class[0];
+
+ private static Method findAccessibleMethod(String name, Class from)
+ {
+ for (Class c = from; c != null; c = c.getSuperclass())
+ {
+ try
+ {
+ Method res = c.getDeclaredMethod(name, noArgs);
+ int mods = res.getModifiers();
+
+ if (c != from
+ && (Modifier.isPrivate(mods)
+ || ! Modifier.isPublic(mods) && ! inSamePackage(c, from)))
+ continue;
+
+ AccessController.doPrivileged(new SetAccessibleAction(res));
+ return res;
+ }
+ catch (NoSuchMethodException e)
+ {
+ }
+ }
+
+ return null;
+ }
+
+ private void cacheMethods()
+ {
+ Method[] methods = forClass().getDeclaredMethods();
+
+ readObjectMethod = findMethod(methods, "readObject",
+ new Class[] { ObjectInputStream.class },
+ Void.TYPE, true);
+ writeObjectMethod = findMethod(methods, "writeObject",
+ new Class[] { ObjectOutputStream.class },
+ Void.TYPE, true);
+
+ // readResolve and writeReplace can be in parent classes, as long as they
+ // are accessible from this class.
+ readResolveMethod = findAccessibleMethod("readResolve", forClass());
+ writeReplaceMethod = findAccessibleMethod("writeReplace", forClass());
+ }
+
+ private ObjectStreamClass(Class cl)
+ {
+ uid = 0;
+ flags = 0;
+ isProxyClass = Proxy.isProxyClass(cl);
+
+ clazz = cl;
+ cacheMethods();
+ name = cl.getName();
+ setFlags(cl);
+ setFields(cl);
+ // to those class nonserializable, its uid field is 0
+ if ( (Serializable.class).isAssignableFrom(cl) && !isProxyClass)
+ uid = getClassUID(cl);
+ superClass = lookup(cl.getSuperclass());
+ }
+
+
+ // Sets bits in flags according to features of CL.
+ private void setFlags(Class cl)
+ {
+ if ((java.io.Externalizable.class).isAssignableFrom(cl))
+ flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
+ else if ((java.io.Serializable.class).isAssignableFrom(cl))
+ // only set this bit if CL is NOT Externalizable
+ flags |= ObjectStreamConstants.SC_SERIALIZABLE;
+
+ if (writeObjectMethod != null)
+ flags |= ObjectStreamConstants.SC_WRITE_METHOD;
+ }
+
+
+ // Sets fields to be a sorted array of the serializable fields of
+ // clazz.
+ private void setFields(Class cl)
+ {
+ SetAccessibleAction setAccessible = new SetAccessibleAction();
+
+ if (!isSerializable() || isExternalizable())
+ {
+ fields = NO_FIELDS;
+ return;
+ }
+
+ try
+ {
+ final Field f =
+ cl.getDeclaredField("serialPersistentFields");
+ setAccessible.setMember(f);
+ AccessController.doPrivileged(setAccessible);
+ int modifiers = f.getModifiers();
+
+ if (Modifier.isStatic(modifiers)
+ && Modifier.isFinal(modifiers)
+ && Modifier.isPrivate(modifiers))
+ {
+ fields = getSerialPersistentFields(cl);
+ if (fields != null)
+ {
+ Arrays.sort (fields);
+ // Retrieve field reference.
+ for (int i=0; i < fields.length; i++)
+ {
+ try
+ {
+ fields[i].lookupField(cl);
+ }
+ catch (NoSuchFieldException _)
+ {
+ fields[i].setToSet(false);
+ }
+ }
+
+ calculateOffsets();
+ return;
+ }
+ }
+ }
+ catch (NoSuchFieldException ignore)
+ {
+ }
+ catch (IllegalAccessException ignore)
+ {
+ }
+
+ int num_good_fields = 0;
+ Field[] all_fields = cl.getDeclaredFields();
+
+ int modifiers;
+ // set non-serializable fields to null in all_fields
+ for (int i = 0; i < all_fields.length; i++)
+ {
+ modifiers = all_fields[i].getModifiers();
+ if (Modifier.isTransient(modifiers)
+ || Modifier.isStatic(modifiers))
+ all_fields[i] = null;
+ else
+ num_good_fields++;
+ }
+
+ // make a copy of serializable (non-null) fields
+ fields = new ObjectStreamField[ num_good_fields ];
+ for (int from = 0, to = 0; from < all_fields.length; from++)
+ if (all_fields[from] != null)
+ {
+ final Field f = all_fields[from];
+ setAccessible.setMember(f);
+ AccessController.doPrivileged(setAccessible);
+ fields[to] = new ObjectStreamField(all_fields[from]);
+ to++;
+ }
+
+ Arrays.sort(fields);
+ // Make sure we don't have any duplicate field names
+ // (Sun JDK 1.4.1. throws an Internal Error as well)
+ for (int i = 1; i < fields.length; i++)
+ {
+ if(fields[i - 1].getName().equals(fields[i].getName()))
+ throw new InternalError("Duplicate field " +
+ fields[i].getName() + " in class " + cl.getName());
+ }
+ calculateOffsets();
+ }
+
+ // Returns the serial version UID defined by class, or if that
+ // isn't present, calculates value of serial version UID.
+ private long getClassUID(Class cl)
+ {
+ try
+ {
+ // Use getDeclaredField rather than getField, since serialVersionUID
+ // may not be public AND we only want the serialVersionUID of this
+ // class, not a superclass or interface.
+ final Field suid = cl.getDeclaredField("serialVersionUID");
+ SetAccessibleAction setAccessible = new SetAccessibleAction(suid);
+ AccessController.doPrivileged(setAccessible);
+ int modifiers = suid.getModifiers();
+
+ if (Modifier.isStatic(modifiers)
+ && Modifier.isFinal(modifiers)
+ && suid.getType() == Long.TYPE)
+ return suid.getLong(null);
+ }
+ catch (NoSuchFieldException ignore)
+ {
+ }
+ catch (IllegalAccessException ignore)
+ {
+ }
+
+ // cl didn't define serialVersionUID, so we have to compute it
+ try
+ {
+ MessageDigest md;
+ try
+ {
+ md = MessageDigest.getInstance("SHA");
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // If a provider already provides SHA, use it; otherwise, use this.
+ Gnu gnuProvider = new Gnu();
+ Security.addProvider(gnuProvider);
+ md = MessageDigest.getInstance("SHA");
+ }
+
+ DigestOutputStream digest_out =
+ new DigestOutputStream(nullOutputStream, md);
+ DataOutputStream data_out = new DataOutputStream(digest_out);
+
+ data_out.writeUTF(cl.getName());
+
+ int modifiers = cl.getModifiers();
+ // just look at interesting bits
+ modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
+ | Modifier.INTERFACE | Modifier.PUBLIC);
+ data_out.writeInt(modifiers);
+
+ // Pretend that an array has no interfaces, because when array
+ // serialization was defined (JDK 1.1), arrays didn't have it.
+ if (! cl.isArray())
+ {
+ Class[] interfaces = cl.getInterfaces();
+ Arrays.sort(interfaces, interfaceComparator);
+ for (int i = 0; i < interfaces.length; i++)
+ data_out.writeUTF(interfaces[i].getName());
+ }
+
+ Field field;
+ Field[] fields = cl.getDeclaredFields();
+ Arrays.sort(fields, memberComparator);
+ for (int i = 0; i < fields.length; i++)
+ {
+ field = fields[i];
+ modifiers = field.getModifiers();
+ if (Modifier.isPrivate(modifiers)
+ && (Modifier.isStatic(modifiers)
+ || Modifier.isTransient(modifiers)))
+ continue;
+
+ data_out.writeUTF(field.getName());
+ data_out.writeInt(modifiers);
+ data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
+ }
+
+ // write class initializer method if present
+ if (VMObjectStreamClass.hasClassInitializer(cl))
+ {
+ data_out.writeUTF("<clinit>");
+ data_out.writeInt(Modifier.STATIC);
+ data_out.writeUTF("()V");
+ }
+
+ Constructor constructor;
+ Constructor[] constructors = cl.getDeclaredConstructors();
+ Arrays.sort (constructors, memberComparator);
+ for (int i = 0; i < constructors.length; i++)
+ {
+ constructor = constructors[i];
+ modifiers = constructor.getModifiers();
+ if (Modifier.isPrivate(modifiers))
+ continue;
+
+ data_out.writeUTF("<init>");
+ data_out.writeInt(modifiers);
+
+ // the replacement of '/' with '.' was needed to make computed
+ // SUID's agree with those computed by JDK
+ data_out.writeUTF
+ (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
+ }
+
+ Method method;
+ Method[] methods = cl.getDeclaredMethods();
+ Arrays.sort(methods, memberComparator);
+ for (int i = 0; i < methods.length; i++)
+ {
+ method = methods[i];
+ modifiers = method.getModifiers();
+ if (Modifier.isPrivate(modifiers))
+ continue;
+
+ data_out.writeUTF(method.getName());
+ data_out.writeInt(modifiers);
+
+ // the replacement of '/' with '.' was needed to make computed
+ // SUID's agree with those computed by JDK
+ data_out.writeUTF
+ (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
+ }
+
+ data_out.close();
+ byte[] sha = md.digest();
+ long result = 0;
+ int len = sha.length < 8 ? sha.length : 8;
+ for (int i = 0; i < len; i++)
+ result += (long) (sha[i] & 0xFF) << (8 * i);
+
+ return result;
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException
+ ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
+ + cl.getName(), e);
+ }
+ catch (IOException ioe)
+ {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ /**
+ * Returns the value of CLAZZ's private static final field named
+ * `serialPersistentFields'. It performs some sanity checks before
+ * returning the real array. Besides, the returned array is a clean
+ * copy of the original. So it can be modified.
+ *
+ * @param clazz Class to retrieve 'serialPersistentFields' from.
+ * @return The content of 'serialPersistentFields'.
+ */
+ private ObjectStreamField[] getSerialPersistentFields(Class clazz)
+ throws NoSuchFieldException, IllegalAccessException
+ {
+ ObjectStreamField[] fieldsArray = null;
+ ObjectStreamField[] o;
+
+ // Use getDeclaredField rather than getField for the same reason
+ // as above in getDefinedSUID.
+ Field f = clazz.getDeclaredField("serialPersistentFields");
+ f.setAccessible(true);
+
+ int modifiers = f.getModifiers();
+ if (!(Modifier.isStatic(modifiers) &&
+ Modifier.isFinal(modifiers) &&
+ Modifier.isPrivate(modifiers)))
+ return null;
+
+ o = (ObjectStreamField[]) f.get(null);
+
+ if (o == null)
+ return null;
+
+ fieldsArray = new ObjectStreamField[ o.length ];
+ System.arraycopy(o, 0, fieldsArray, 0, o.length);
+
+ return fieldsArray;
+ }
+
+ /**
+ * Returns a new instance of the Class this ObjectStreamClass corresponds
+ * to.
+ * Note that this should only be used for Externalizable classes.
+ *
+ * @return A new instance.
+ */
+ Externalizable newInstance() throws InvalidClassException
+ {
+ synchronized(this)
+ {
+ if (constructor == null)
+ {
+ try
+ {
+ final Constructor c = clazz.getConstructor(new Class[0]);
+
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ c.setAccessible(true);
+ return null;
+ }
+ });
+
+ constructor = c;
+ }
+ catch(NoSuchMethodException x)
+ {
+ throw new InvalidClassException(clazz.getName(),
+ "No public zero-argument constructor");
+ }
+ }
+ }
+
+ try
+ {
+ return (Externalizable)constructor.newInstance(null);
+ }
+ catch(Exception x)
+ {
+ throw (InvalidClassException)
+ new InvalidClassException(clazz.getName(),
+ "Unable to instantiate").initCause(x);
+ }
+ }
+
+ public static final ObjectStreamField[] NO_FIELDS = {};
+
+ private static Hashtable classLookupTable = new Hashtable();
+ private static final NullOutputStream nullOutputStream = new NullOutputStream();
+ private static final Comparator interfaceComparator = new InterfaceComparator();
+ private static final Comparator memberComparator = new MemberComparator();
+ private static final
+ Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };
+
+ private ObjectStreamClass superClass;
+ private Class clazz;
+ private String name;
+ private long uid;
+ private byte flags;
+
+ // this field is package protected so that ObjectInputStream and
+ // ObjectOutputStream can access it directly
+ ObjectStreamField[] fields;
+
+ // these are accessed by ObjectIn/OutputStream
+ int primFieldSize = -1; // -1 if not yet calculated
+ int objectFieldCount;
+
+ Method readObjectMethod;
+ Method readResolveMethod;
+ Method writeReplaceMethod;
+ Method writeObjectMethod;
+ boolean realClassIsSerializable;
+ boolean realClassIsExternalizable;
+ ObjectStreamField[] fieldMapping;
+ Constructor firstNonSerializableParentConstructor;
+ private Constructor constructor; // default constructor for Externalizable
+
+ boolean isProxyClass = false;
+
+ // This is probably not necessary because this class is special cased already
+ // but it will avoid showing up as a discrepancy when comparing SUIDs.
+ private static final long serialVersionUID = -6120832682080437368L;
+
+
+ // interfaces are compared only by name
+ private static final class InterfaceComparator implements Comparator
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return ((Class) o1).getName().compareTo(((Class) o2).getName());
+ }
+ }
+
+
+ // Members (Methods and Constructors) are compared first by name,
+ // conflicts are resolved by comparing type signatures
+ private static final class MemberComparator implements Comparator
+ {
+ public int compare(Object o1, Object o2)
+ {
+ Member m1 = (Member) o1;
+ Member m2 = (Member) o2;
+
+ int comp = m1.getName().compareTo(m2.getName());
+
+ if (comp == 0)
+ return TypeSignature.getEncodingOfMember(m1).
+ compareTo(TypeSignature.getEncodingOfMember(m2));
+ else
+ return comp;
+ }
+ }
+}
diff --git a/libjava/classpath/java/io/ObjectStreamConstants.java b/libjava/classpath/java/io/ObjectStreamConstants.java
new file mode 100644
index 00000000000..f1a4af724e7
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectStreamConstants.java
@@ -0,0 +1,89 @@
+/* ObjectStreamConstants.java -- Interface containing constant values
+ used in reading and writing serialized objects
+ Copyright (C) 1998, 1999, 2003 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.io;
+
+/**
+ * This interface contains constants that are used in object
+ * serialization. This interface is used by <code>ObjectOutputStream</code>,
+ * <code>ObjectInputStream</code>, and <code>ObjectStreamClass</code>.
+ * The values for these constants are specified by the Java library
+ * specification.
+ */
+public interface ObjectStreamConstants
+{
+ // FIXME: Javadoc comment these values.
+ int PROTOCOL_VERSION_1 = 1;
+ int PROTOCOL_VERSION_2 = 2;
+
+ short STREAM_MAGIC = (short)0xaced;
+ short STREAM_VERSION = 5;
+
+ byte TC_NULL = (byte)112; //0x70
+ byte TC_REFERENCE = (byte)113; //0x71
+ byte TC_CLASSDESC = (byte)114; //0x72
+ byte TC_OBJECT = (byte)115; //0x73
+ byte TC_STRING = (byte)116; //0x74
+ byte TC_ARRAY = (byte)117; //0x75
+ byte TC_CLASS = (byte)118; //0x76
+ byte TC_BLOCKDATA = (byte)119; //0x77
+ byte TC_ENDBLOCKDATA = (byte)120; //0x78
+ byte TC_RESET = (byte)121; //0x79
+ byte TC_BLOCKDATALONG = (byte)122; //0x7A
+ byte TC_EXCEPTION = (byte)123; //0x7B
+ byte TC_LONGSTRING = (byte)124; //0x7C
+ byte TC_PROXYCLASSDESC = (byte)125; //0x7D
+
+ byte TC_BASE = TC_NULL;
+ byte TC_MAX = TC_PROXYCLASSDESC;
+
+ int baseWireHandle = 0x7e0000;
+
+ byte SC_WRITE_METHOD = 0x01;
+ byte SC_SERIALIZABLE = 0x02;
+ byte SC_EXTERNALIZABLE = 0x04;
+ byte SC_BLOCK_DATA = 0x08;
+
+ SerializablePermission SUBSTITUTION_PERMISSION
+ = new SerializablePermission("enableSubstitution");
+
+ SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION
+ = new SerializablePermission("enableSubclassImplementation");
+}
+
diff --git a/libjava/classpath/java/io/ObjectStreamException.java b/libjava/classpath/java/io/ObjectStreamException.java
new file mode 100644
index 00000000000..61d4dd09e52
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectStreamException.java
@@ -0,0 +1,74 @@
+/* ObjectStreamException.java -- Superclass of all serialization exceptions
+ Copyright (C) 1998, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown when a problem occurs during serialization.
+ * There are more specific subclasses that give more fine grained
+ * indications of the precise failure.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ObjectStreamException extends IOException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 7260898174833392607L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ protected ObjectStreamException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ protected ObjectStreamException(String message)
+ {
+ super(message);
+ }
+} // class ObjectStreamException
diff --git a/libjava/classpath/java/io/ObjectStreamField.java b/libjava/classpath/java/io/ObjectStreamField.java
new file mode 100644
index 00000000000..611457b3cfb
--- /dev/null
+++ b/libjava/classpath/java/io/ObjectStreamField.java
@@ -0,0 +1,412 @@
+/* ObjectStreamField.java -- Class used to store name and class of fields
+ Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.java.lang.reflect.TypeSignature;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * This class intends to describe the field of a class for the serialization
+ * subsystem. Serializable fields in a serializable class can be explicitly
+ * exported using an array of ObjectStreamFields.
+ */
+public class ObjectStreamField implements Comparable
+{
+ private String name;
+ private Class type;
+ private String typename;
+ private int offset = -1; // XXX make sure this is correct
+ private boolean unshared;
+ private boolean persistent = false;
+ private boolean toset = true;
+ private Field field;
+
+ ObjectStreamField (Field field)
+ {
+ this (field.getName(), field.getType());
+ this.field = field;
+ }
+
+ /**
+ * This constructor creates an ObjectStreamField instance
+ * which represents a field named <code>name</code> and is
+ * of the type <code>type</code>.
+ *
+ * @param name Name of the field to export.
+ * @param type Type of the field in the concerned class.
+ */
+ public ObjectStreamField (String name, Class type)
+ {
+ this (name, type, false);
+ }
+
+ /**
+ * This constructor creates an ObjectStreamField instance
+ * which represents a field named <code>name</code> and is
+ * of the type <code>type</code>.
+ *
+ * @param name Name of the field to export.
+ * @param type Type of the field in the concerned class.
+ * @param unshared true if field will be unshared, false otherwise.
+ */
+ public ObjectStreamField (String name, Class type, boolean unshared)
+ {
+ if (name == null)
+ throw new NullPointerException();
+
+ this.name = name;
+ this.type = type;
+ this.typename = TypeSignature.getEncodingOfClass(type);
+ this.unshared = unshared;
+ }
+
+ /**
+ * There are many cases you can not get java.lang.Class from typename
+ * if your context class loader cannot 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.
+ */
+ ObjectStreamField (String name, String typename)
+ {
+ 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)
+ {
+ this.name = name;
+ this.typename = typename;
+ try
+ {
+ type = TypeSignature.getClassForEncoding(typename, true, loader);
+ }
+ catch(ClassNotFoundException e)
+ {
+ }
+ }
+
+ /**
+ * This method returns the name of the field represented by the
+ * ObjectStreamField instance.
+ *
+ * @return A string containing the name of the field.
+ */
+ public String getName ()
+ {
+ return name;
+ }
+
+ /**
+ * This method returns the class representing the type of the
+ * field which is represented by this instance of ObjectStreamField.
+ *
+ * @return A class representing the type of the field.
+ */
+ public Class getType ()
+ {
+ return type;
+ }
+
+ /**
+ * This method returns the char encoded type of the field which
+ * is represented by this instance of ObjectStreamField.
+ *
+ * @return A char representing the type of the field.
+ */
+ public char getTypeCode ()
+ {
+ return typename.charAt (0);
+ }
+
+ /**
+ * This method returns a more explicit type name than
+ * {@link #getTypeCode()} in the case the type is a real
+ * class (and not a primitive).
+ *
+ * @return The name of the type (class name) if it is not a
+ * primitive, in the other case null is returned.
+ */
+ public String getTypeString ()
+ {
+ // use intern()
+ if (isPrimitive())
+ return null;
+ return typename.intern();
+ }
+
+ /**
+ * This method returns the current offset of the field in
+ * the serialization stream relatively to the other fields.
+ * The offset is expressed in bytes.
+ *
+ * @return The offset of the field in bytes.
+ * @see #setOffset(int)
+ */
+ public int getOffset ()
+ {
+ return offset;
+ }
+
+ /**
+ * This method sets the current offset of the field.
+ *
+ * @param off The offset of the field in bytes.
+ * @see getOffset()
+ */
+ protected void setOffset (int off)
+ {
+ offset = off;
+ }
+
+ /**
+ * This method returns whether the field represented by this object is
+ * unshared or not.
+ *
+ * @return Tells if this field is unshared or not.
+ */
+ public boolean isUnshared ()
+ {
+ return unshared;
+ }
+
+ /**
+ * This method returns true if the type of the field
+ * represented by this instance is a primitive.
+ *
+ * @return true if the type is a primitive, false
+ * in the other case.
+ */
+ public boolean isPrimitive ()
+ {
+ return typename.length() == 1;
+ }
+
+ /**
+ * Compares this object to the given object.
+ *
+ * @param obj the object to compare to.
+ *
+ * @return -1, 0 or 1.
+ */
+ public int compareTo (Object obj)
+ {
+ ObjectStreamField f = (ObjectStreamField) obj;
+ boolean this_is_primitive = isPrimitive ();
+ boolean f_is_primitive = f.isPrimitive ();
+
+ if (this_is_primitive && !f_is_primitive)
+ return -1;
+
+ if (!this_is_primitive && f_is_primitive)
+ return 1;
+
+ return getName ().compareTo (f.getName ());
+ }
+
+ /**
+ * This method is specific to classpath's implementation and so has the default
+ * access. It changes the state of this field to "persistent". It means that
+ * the field should not be changed when the stream is read (if it is not
+ * explicitly specified using serialPersistentFields).
+ *
+ * @param persistent True if the field is persistent, false in the
+ * other cases.
+ * @see #isPersistent()
+ */
+ void setPersistent(boolean persistent)
+ {
+ this.persistent = persistent;
+ }
+
+ /**
+ * This method returns true if the field is marked as persistent.
+ *
+ * @return True if persistent, false in the other cases.
+ * @see #setPersistent(boolean)
+ */
+ boolean isPersistent()
+ {
+ return persistent;
+ }
+
+ /**
+ * This method is specific to classpath's implementation and so
+ * has the default access. It changes the state of this field as
+ * to be set by ObjectInputStream.
+ *
+ * @param toset True if this field should be set, false in the other
+ * cases.
+ * @see #isToSet()
+ */
+ void setToSet(boolean toset)
+ {
+ this.toset = toset;
+ }
+
+ /**
+ * This method returns true if the field is marked as to be
+ * set.
+ *
+ * @return True if it is to be set, false in the other cases.
+ * @see #setToSet(boolean)
+ */
+ boolean isToSet()
+ {
+ return toset;
+ }
+
+ /**
+ * This method searches for its field reference in the specified class
+ * object. It requests privileges. If an error occurs the internal field
+ * reference is not modified.
+ *
+ * @throws NoSuchFieldException if the field name does not exist in this class.
+ * @throws SecurityException if there was an error requesting the privileges.
+ */
+ void lookupField(Class clazz) throws NoSuchFieldException, SecurityException
+ {
+ final Field f = clazz.getDeclaredField(name);
+
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ f.setAccessible(true);
+ return null;
+ }
+ });
+
+ this.field = f;
+ }
+
+ /**
+ * This method check whether the field described by this
+ * instance of ObjectStreamField is compatible with the
+ * actual implementation of this field.
+ *
+ * @throws NullPointerException if this field does not exist
+ * in the real class.
+ * @throws InvalidClassException if the types are incompatible.
+ */
+ void checkFieldType() throws InvalidClassException
+ {
+ Class ftype = field.getType();
+
+ if (!ftype.isAssignableFrom(type))
+ throw new InvalidClassException
+ ("invalid field type for " + name +
+ " in class " + field.getDeclaringClass());
+ }
+
+ /**
+ * Returns a string representing this object.
+ *
+ * @return the string.
+ */
+ public String toString ()
+ {
+ return "ObjectStreamField< " + type + " " + name + " >";
+ }
+
+ final void setBooleanField(Object obj, boolean val)
+ {
+ VMObjectStreamClass.setBooleanNative(field, obj, val);
+ }
+
+ final void setByteField(Object obj, byte val)
+ {
+ VMObjectStreamClass.setByteNative(field, obj, val);
+ }
+
+ final void setCharField(Object obj, char val)
+ {
+ VMObjectStreamClass.setCharNative(field, obj, val);
+ }
+
+ final void setShortField(Object obj, short val)
+ {
+ VMObjectStreamClass.setShortNative(field, obj, val);
+ }
+
+ final void setIntField(Object obj, int val)
+ {
+ VMObjectStreamClass.setIntNative(field, obj, val);
+ }
+
+ final void setLongField(Object obj, long val)
+ {
+ VMObjectStreamClass.setLongNative(field, obj, val);
+ }
+
+ final void setFloatField(Object obj, float val)
+ {
+ VMObjectStreamClass.setFloatNative(field, obj, val);
+ }
+
+ final void setDoubleField(Object obj, double val)
+ {
+ VMObjectStreamClass.setDoubleNative(field, obj, val);
+ }
+
+ final void setObjectField(Object obj, Object val)
+ {
+ VMObjectStreamClass.setObjectNative(field, obj, val);
+ }
+}
diff --git a/libjava/classpath/java/io/OptionalDataException.java b/libjava/classpath/java/io/OptionalDataException.java
new file mode 100644
index 00000000000..8d8b1bda0e3
--- /dev/null
+++ b/libjava/classpath/java/io/OptionalDataException.java
@@ -0,0 +1,91 @@
+/* OptionalDataException.java -- indicates unexpected data in serialized stream
+ Copyright (C) 1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown when unexpected data appears in the input
+ * stream from which a serialized object is being read. There are two
+ * cases:<br><ul>
+ * <li>The next stream element is primitive data. <code>eof</code> will
+ * be false, and <code>count</code> is the number of bytes of primitive
+ * data available.</li>
+ * <li>The data consumable by readObject or readExternal has been exhausted.
+ * <code>eof</code> is true, and <code>count</code> is 0.</li>
+ * </ul>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class OptionalDataException extends ObjectStreamException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -8011121865681257820L;
+
+ /**
+ * Whether or not the end of the stream has been reached.
+ *
+ * @serial the end of the buffer was reached
+ */
+ public boolean eof;
+
+ /**
+ * The number of valid bytes that can be read.
+ *
+ * @serial the bytes of the buffer remaining
+ */
+ public int length;
+
+ /**
+ * Create a new OptionalDataException with an eof parameter indicating
+ * whether or not the end of stream is reached and the number of valid
+ * bytes that may be read.
+ *
+ * @param eof 'true' if end of stream reached, 'false' otherwise
+ * @param count The number of valid bytes to be read
+ */
+ OptionalDataException(boolean eof, int count)
+ {
+ this.eof = eof;
+ this.length = count;
+ }
+} // class OptionalDataException
diff --git a/libjava/classpath/java/io/OutputStream.java b/libjava/classpath/java/io/OutputStream.java
new file mode 100644
index 00000000000..8608daaa161
--- /dev/null
+++ b/libjava/classpath/java/io/OutputStream.java
@@ -0,0 +1,140 @@
+/* OutputStream.java -- Base class for byte output streams
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This abstract class forms the base of the hierarchy of classes that
+ * write output as a stream of bytes. It provides a common set of methods
+ * for writing bytes to stream. Subclasses implement and/or extend these
+ * methods to write bytes in a particular manner or to a particular
+ * destination such as a file on disk or network connection.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public abstract class OutputStream
+{
+ /**
+ * This is the default no-argument constructor for this class. This method
+ * does nothing in this class.
+ */
+ public OutputStream ()
+ {
+ }
+
+ /**
+ * This method writes a single byte to the output stream. The byte written
+ * is the low eight bits of the <code>int</code> passed and a argument.
+ * <p>
+ * Subclasses must provide an implementation of this abstract method
+ *
+ * @param b The byte to be written to the output stream, passed as
+ * the low eight bits of an <code>int</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract void write (int b) throws IOException;
+
+ /**
+ * This method all the writes bytes from the passed array to the
+ * output stream. This method is equivalent to <code>write(b, 0,
+ * buf.length)</code> which is exactly how it is implemented in this
+ * class.
+ *
+ * @param b The array of bytes to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (byte[] b) throws IOException, NullPointerException
+ {
+ write (b, 0, b.length);
+ }
+
+ /**
+ * This method writes <code>len</code> bytes from the specified array
+ * <code>b</code> starting at index <code>off</code> into the array.
+ * <p>
+ * This method in this class calls the single byte <code>write()</code>
+ * method in a loop until all bytes have been written. Subclasses should
+ * override this method if possible in order to provide a more efficent
+ * implementation.
+ *
+ * @param b The array of bytes to write from
+ * @param off The index into the array to start writing from
+ * @param len The number of bytes to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (byte[] b, int off, int len)
+ throws IOException, NullPointerException, IndexOutOfBoundsException
+ {
+ if (off < 0 || len < 0 || off + len > b.length)
+ throw new ArrayIndexOutOfBoundsException ();
+ for (int i = 0; i < len; ++i)
+ write (b[off + i]);
+ }
+
+ /**
+ * This method forces any data that may have been buffered to be written
+ * to the underlying output device. Please note that the host environment
+ * might perform its own buffering unbeknowst to Java. In that case, a
+ * write made (for example, to a disk drive) might be cached in OS
+ * buffers instead of actually being written to disk.
+ * <p>
+ * This method in this class does nothing.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void flush () throws IOException
+ {
+ }
+
+ /**
+ * This method closes the stream. Any internal or native resources
+ * associated with this stream are freed. Any subsequent attempt to
+ * access the stream might throw an exception.
+ * <p>
+ * This method in this class does nothing.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close () throws IOException
+ {
+ }
+}
diff --git a/libjava/classpath/java/io/OutputStreamWriter.java b/libjava/classpath/java/io/OutputStreamWriter.java
new file mode 100644
index 00000000000..ee229796cce
--- /dev/null
+++ b/libjava/classpath/java/io/OutputStreamWriter.java
@@ -0,0 +1,356 @@
+/* OutputStreamWriter.java -- Writer that converts chars to bytes
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.java.nio.charset.EncodingHelper;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+
+/**
+ * This class writes characters to an output stream that is byte oriented
+ * It converts the chars that are written to bytes using an encoding layer,
+ * which is specific to a particular encoding standard. The desired
+ * encoding can either be specified by name, or if no encoding is specified,
+ * the system default encoding will be used. The system default encoding
+ * name is determined from the system property <code>file.encoding</code>.
+ * The only encodings that are guaranteed to be available are "8859_1"
+ * (the Latin-1 character set) and "UTF8". Unfortunately, Java does not
+ * provide a mechanism for listing the encodings that are supported in
+ * a given implementation.
+ * <p>
+ * Here is a list of standard encoding names that may be available:
+ * <p>
+ * <ul>
+ * <li>8859_1 (ISO-8859-1/Latin-1)
+ * <li>8859_2 (ISO-8859-2/Latin-2)
+ * <li>8859_3 (ISO-8859-3/Latin-3)
+ * <li>8859_4 (ISO-8859-4/Latin-4)
+ * <li>8859_5 (ISO-8859-5/Latin-5)
+ * <li>8859_6 (ISO-8859-6/Latin-6)
+ * <li>8859_7 (ISO-8859-7/Latin-7)
+ * <li>8859_8 (ISO-8859-8/Latin-8)
+ * <li>8859_9 (ISO-8859-9/Latin-9)
+ * <li>ASCII (7-bit ASCII)
+ * <li>UTF8 (UCS Transformation Format-8)
+ * <li>More Later
+ * </ul>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ * @date April 17, 1998.
+ */
+public class OutputStreamWriter extends Writer
+{
+ /**
+ * The output stream.
+ */
+ private OutputStream out;
+
+ /**
+ * The charset encoder.
+ */
+ private CharsetEncoder encoder;
+
+ /**
+ * java.io canonical name of the encoding.
+ */
+ private String encodingName;
+
+ /**
+ * Buffer output before character conversion as it has costly overhead.
+ */
+ private CharBuffer outputBuffer;
+ private final static int BUFFER_SIZE = 1024;
+
+ /**
+ * This method initializes a new instance of <code>OutputStreamWriter</code>
+ * to write to the specified stream using a caller supplied character
+ * encoding scheme. Note that due to a deficiency in the Java language
+ * design, there is no way to determine which encodings are supported.
+ *
+ * @param out The <code>OutputStream</code> to write to
+ * @param encoding_scheme The name of the encoding scheme to use for
+ * character to byte translation
+ *
+ * @exception UnsupportedEncodingException If the named encoding is
+ * not available.
+ */
+ public OutputStreamWriter (OutputStream out, String encoding_scheme)
+ throws UnsupportedEncodingException
+ {
+ this.out = out;
+ try
+ {
+ // Don't use NIO if avoidable
+ if(EncodingHelper.isISOLatin1(encoding_scheme))
+ {
+ encodingName = "ISO8859_1";
+ encoder = null;
+ return;
+ }
+
+ /*
+ * Workraround for encodings with a byte-order-mark.
+ * We only want to write it once per stream.
+ */
+ try {
+ if(encoding_scheme.equalsIgnoreCase("UnicodeBig") ||
+ encoding_scheme.equalsIgnoreCase("UTF-16") ||
+ encoding_scheme.equalsIgnoreCase("UTF16"))
+ {
+ encoding_scheme = "UTF-16BE";
+ out.write((byte)0xFE);
+ out.write((byte)0xFF);
+ } else if(encoding_scheme.equalsIgnoreCase("UnicodeLittle")){
+ encoding_scheme = "UTF-16LE";
+ out.write((byte)0xFF);
+ out.write((byte)0xFE);
+ }
+ } catch(IOException ioe){
+ }
+
+ outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
+
+ Charset cs = EncodingHelper.getCharset(encoding_scheme);
+ if(cs == null)
+ throw new UnsupportedEncodingException("Encoding "+encoding_scheme+
+ " unknown");
+ encoder = cs.newEncoder();
+ encodingName = EncodingHelper.getOldCanonical(cs.name());
+
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ } catch(RuntimeException e) {
+ // Default to ISO Latin-1, will happen if this is called, for instance,
+ // before the NIO provider is loadable.
+ encoder = null;
+ encodingName = "ISO8859_1";
+ }
+ }
+
+ /**
+ * This method initializes a new instance of <code>OutputStreamWriter</code>
+ * to write to the specified stream using the default encoding.
+ *
+ * @param out The <code>OutputStream</code> to write to
+ */
+ public OutputStreamWriter (OutputStream out)
+ {
+ this.out = out;
+ outputBuffer = null;
+ try
+ {
+ String encoding = System.getProperty("file.encoding");
+ Charset cs = Charset.forName(encoding);
+ encoder = cs.newEncoder();
+ encodingName = EncodingHelper.getOldCanonical(cs.name());
+ } catch(RuntimeException e) {
+ encoder = null;
+ encodingName = "ISO8859_1";
+ }
+ if(encoder != null)
+ {
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
+ }
+ }
+
+ /**
+ * This method closes this stream, and the underlying
+ * <code>OutputStream</code>
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close () throws IOException
+ {
+ if(out == null)
+ return;
+ flush();
+ out.close ();
+ out = null;
+ }
+
+ /**
+ * This method returns the name of the character encoding scheme currently
+ * in use by this stream. If the stream has been closed, then this method
+ * may return <code>null</code>.
+ *
+ * @return The encoding scheme name
+ */
+ public String getEncoding ()
+ {
+ return out != null ? encodingName : null;
+ }
+
+ /**
+ * This method flushes any buffered bytes to the underlying output sink.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void flush () throws IOException
+ {
+ if(out != null){
+ if(outputBuffer != null){
+ char[] buf = new char[outputBuffer.position()];
+ if(buf.length > 0){
+ outputBuffer.flip();
+ outputBuffer.get(buf);
+ writeConvert(buf, 0, buf.length);
+ outputBuffer.clear();
+ }
+ }
+ out.flush ();
+ }
+ }
+
+ /**
+ * This method writes <code>count</code> characters from the specified
+ * array to the output stream starting at position <code>offset</code>
+ * into the array.
+ *
+ * @param buf The array of character to write from
+ * @param offset The offset into the array to start writing chars from
+ * @param count The number of chars to write.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (char[] buf, int offset, int count) throws IOException
+ {
+ if(out == null)
+ throw new IOException("Stream is closed.");
+ if(buf == null)
+ throw new IOException("Buffer is null.");
+
+ if(outputBuffer != null)
+ {
+ if(count >= outputBuffer.remaining())
+ {
+ int r = outputBuffer.remaining();
+ outputBuffer.put(buf, offset, r);
+ writeConvert(outputBuffer.array(), 0, BUFFER_SIZE);
+ outputBuffer.clear();
+ offset += r;
+ count -= r;
+ // if the remaining bytes is larger than the whole buffer,
+ // just don't buffer.
+ if(count >= outputBuffer.remaining()){
+ writeConvert(buf, offset, count);
+ return;
+ }
+ }
+ outputBuffer.put(buf, offset, count);
+ } else writeConvert(buf, offset, count);
+ }
+
+ /**
+ * Converts and writes characters.
+ */
+ private void writeConvert (char[] buf, int offset, int count)
+ throws IOException
+ {
+ if(encoder == null)
+ {
+ byte[] b = new byte[count];
+ for(int i=0;i<count;i++)
+ b[i] = (byte)((buf[offset+i] <= 0xFF)?buf[offset+i]:'?');
+ out.write(b);
+ } else {
+ try {
+ ByteBuffer output = encoder.encode(CharBuffer.wrap(buf,offset,count));
+ encoder.reset();
+ if(output.hasArray())
+ out.write(output.array());
+ else
+ {
+ byte[] outbytes = new byte[output.remaining()];
+ output.get(outbytes);
+ out.write(outbytes);
+ }
+ } catch(IllegalStateException e) {
+ throw new IOException("Internal error.");
+ } catch(MalformedInputException e) {
+ throw new IOException("Invalid character sequence.");
+ } catch(CharacterCodingException e) {
+ throw new IOException("Unmappable character.");
+ }
+ }
+ }
+
+ /**
+ * This method writes <code>count</code> bytes from the specified
+ * <code>String</code> starting at position <code>offset</code> into the
+ * <code>String</code>.
+ *
+ * @param str The <code>String</code> to write chars from
+ * @param offset The position in the <code>String</code> to start
+ * writing chars from
+ * @param count The number of chars to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (String str, int offset, int count) throws IOException
+ {
+ if(str == null)
+ throw new IOException("String is null.");
+
+ write(str.toCharArray(), offset, count);
+ }
+
+ /**
+ * This method writes a single character to the output stream.
+ *
+ * @param ch The char to write, passed as an int.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (int ch) throws IOException
+ {
+ write(new char[]{ (char)ch }, 0, 1);
+ }
+} // class OutputStreamWriter
+
diff --git a/libjava/classpath/java/io/PipedInputStream.java b/libjava/classpath/java/io/PipedInputStream.java
new file mode 100644
index 00000000000..beb310b4f0c
--- /dev/null
+++ b/libjava/classpath/java/io/PipedInputStream.java
@@ -0,0 +1,374 @@
+/* PipedInputStream.java -- Read portion of piped streams.
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.io;
+
+// NOTE: This implementation is very similar to that of PipedReader. If you
+// fix a bug in here, chances are you should make a similar change to the
+// PipedReader code.
+
+/**
+ * An input stream that reads its bytes from an output stream
+ * to which it is connected.
+ * <p>
+ * Data is read and written to an internal buffer. It is highly recommended
+ * that the <code>PipedInputStream</code> and connected
+ * <code>PipedOutputStream</code>
+ * be part of different threads. If they are not, the read and write
+ * operations could deadlock their thread.
+ *
+ * @specnote The JDK implementation appears to have some undocumented
+ * functionality where it keeps track of what thread is writing
+ * to pipe and throws an IOException if that thread susequently
+ * dies. This behaviour seems dubious and unreliable - we don't
+ * implement it.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class PipedInputStream extends InputStream
+{
+ /** PipedOutputStream to which this is connected. Null only if this
+ * InputStream hasn't been connected yet. */
+ PipedOutputStream source;
+
+ /** Set to true if close() has been called on this InputStream. */
+ boolean closed;
+
+
+ /**
+ * The size of the internal buffer used for input/output.
+ */
+ /* The "Constant Field Values" Javadoc of the Sun J2SE 1.4
+ * specifies 1024.
+ */
+ protected static final int PIPE_SIZE = 1024;
+
+
+ /**
+ * This is the internal circular buffer used for storing bytes written
+ * to the pipe and from which bytes are read by this stream
+ */
+ protected byte[] buffer = new byte[PIPE_SIZE];
+
+ /**
+ * The index into buffer where the next byte from the connected
+ * <code>PipedOutputStream</code> will be written. If this variable is
+ * equal to <code>out</code>, then the buffer is full. If set to < 0,
+ * the buffer is empty.
+ */
+ protected int in = -1;
+
+ /**
+ * This index into the buffer where bytes will be read from.
+ */
+ protected int out = 0;
+
+ /** Buffer used to implement single-argument read/receive */
+ private byte[] read_buf = new byte[1];
+
+ /**
+ * Creates a new <code>PipedInputStream</code> that is not connected to a
+ * <code>PipedOutputStream</code>. It must be connected before bytes can
+ * be read from this stream.
+ */
+ public PipedInputStream()
+ {
+ }
+
+ /**
+ * This constructor creates a new <code>PipedInputStream</code> and connects
+ * it to the passed in <code>PipedOutputStream</code>. The stream is then
+ * ready for reading.
+ *
+ * @param source The <code>PipedOutputStream</code> to connect this
+ * stream to
+ *
+ * @exception IOException If <code>source</code> is already connected.
+ */
+ public PipedInputStream(PipedOutputStream source) throws IOException
+ {
+ connect(source);
+ }
+
+ /**
+ * This method connects this stream to the passed in
+ * <code>PipedOutputStream</code>.
+ * This stream is then ready for reading. If this stream is already
+ * connected or has been previously closed, then an exception is thrown
+ *
+ * @param src The <code>PipedOutputStream</code> to connect this stream to
+ *
+ * @exception IOException If this PipedInputStream or <code>source</code>
+ * has been connected already.
+ */
+ public void connect(PipedOutputStream source) throws IOException
+ {
+ // The JDK (1.3) does not appear to check for a previously closed
+ // connection here.
+
+ if (this.source != null || source.sink != null)
+ throw new IOException ("Already connected");
+
+ source.sink = this;
+ this.source = source;
+ }
+
+ /**
+ * This method receives a byte of input from the source PipedOutputStream.
+ * If the internal circular buffer is full, this method blocks.
+ *
+ * @param val The byte to write to this stream
+ *
+ * @exception IOException if error occurs
+ * @specnote Weird. This method must be some sort of accident.
+ */
+ protected synchronized void receive(int val) throws IOException
+ {
+ read_buf[0] = (byte) (val & 0xff);
+ receive (read_buf, 0, 1);
+ }
+
+ /**
+ * This method is used by the connected <code>PipedOutputStream</code> to
+ * write bytes into the buffer.
+ *
+ * @param buf The array containing bytes to write to this stream
+ * @param offset The offset into the array to start writing from
+ * @param len The number of bytes to write.
+ *
+ * @exception IOException If an error occurs
+ * @specnote This code should be in PipedOutputStream.write, but we
+ * put it here in order to support that bizarre recieve(int)
+ * method.
+ */
+ synchronized void receive(byte[] buf, int offset, int len)
+ throws IOException
+ {
+ if (closed)
+ throw new IOException ("Pipe closed");
+
+ int bufpos = offset;
+ int copylen;
+
+ while (len > 0)
+ {
+ try
+ {
+ while (in == out)
+ {
+ // The pipe is full. Wake up any readers and wait for them.
+ notifyAll();
+ wait();
+ // The pipe could have been closed while we were waiting.
+ if (closed)
+ throw new IOException ("Pipe closed");
+ }
+ }
+ catch (InterruptedException ix)
+ {
+ throw new InterruptedIOException ();
+ }
+
+ if (in < 0) // The pipe is empty.
+ in = 0;
+
+ // Figure out how many bytes from buf can be copied without
+ // overrunning out or going past the length of the buffer.
+ if (in < out)
+ copylen = Math.min (len, out - in);
+ else
+ copylen = Math.min (len, buffer.length - in);
+
+ // Copy bytes until the pipe is filled, wrapping if necessary.
+ System.arraycopy(buf, bufpos, buffer, in, copylen);
+ len -= copylen;
+ bufpos += copylen;
+ in += copylen;
+ if (in == buffer.length)
+ in = 0;
+ }
+ // Notify readers that new data is in the pipe.
+ notifyAll();
+ }
+
+ /**
+ * This method reads one byte from the stream.
+ * -1 is returned to indicated that no bytes can be read
+ * because the end of the stream was reached. If the stream is already
+ * closed, a -1 will again be returned to indicate the end of the stream.
+ *
+ * <p>This method will block if no byte is available to be read.</p>
+ *
+ * @return the value of the read byte value, or -1 of the end of the stream
+ * was reached
+ *
+ * @throws IOException if an error occured
+ */
+ public int read() throws IOException
+ {
+ // Method operates by calling the multibyte overloaded read method
+ // Note that read_buf is an internal instance variable. I allocate it
+ // there to avoid constant reallocation overhead for applications that
+ // call this method in a loop at the cost of some unneeded overhead
+ // if this method is never called.
+
+ int r = read(read_buf, 0, 1);
+ return r != -1 ? (read_buf[0] & 0xff) : -1;
+ }
+
+ /**
+ * This method reads bytes from the stream into a caller supplied buffer.
+ * It starts storing bytes at position <code>offset</code> into the
+ * buffer and
+ * reads a maximum of <code>len</code> bytes. Note that this method
+ * can actually
+ * read fewer than <code>len</code> bytes. The actual number of bytes
+ * read is
+ * returned. A -1 is returned to indicated that no bytes can be read
+ * because the end of the stream was reached - ie close() was called on the
+ * connected PipedOutputStream.
+ * <p>
+ * This method will block if no bytes are available to be read.
+ *
+ * @param buf The buffer into which bytes will be stored
+ * @param offset The index into the buffer at which to start writing.
+ * @param len The maximum number of bytes to read.
+ *
+ * @exception IOException If <code>close()</code> was called on this Piped
+ * InputStream.
+ */
+ public synchronized int read(byte[] buf, int offset, int len)
+ throws IOException
+ {
+ if (source == null)
+ throw new IOException ("Not connected");
+ if (closed)
+ throw new IOException ("Pipe closed");
+
+ // If the buffer is empty, wait until there is something in the pipe
+ // to read.
+ try
+ {
+ while (in < 0)
+ {
+ if (source.closed)
+ return -1;
+ wait();
+ }
+ }
+ catch (InterruptedException ix)
+ {
+ throw new InterruptedIOException();
+ }
+
+ int total = 0;
+ int copylen;
+
+ while (true)
+ {
+ // Figure out how many bytes from the pipe can be copied without
+ // overrunning in or going past the length of buf.
+ if (out < in)
+ copylen = Math.min (len, in - out);
+ else
+ copylen = Math.min (len, buffer.length - out);
+
+ System.arraycopy (buffer, out, buf, offset, copylen);
+ offset += copylen;
+ len -= copylen;
+ out += copylen;
+ total += copylen;
+
+ if (out == buffer.length)
+ out = 0;
+
+ if (out == in)
+ {
+ // Pipe is now empty.
+ in = -1;
+ out = 0;
+ }
+
+ // If output buffer is filled or the pipe is empty, we're done.
+ if (len == 0 || in == -1)
+ {
+ // Notify any waiting outputstream that there is now space
+ // to write.
+ notifyAll();
+ return total;
+ }
+ }
+ }
+
+ /**
+ * This method returns the number of bytes that can be read from this stream
+ * before blocking could occur. This is the number of bytes that are
+ * currently unread in the internal circular buffer. Note that once this
+ * many additional bytes are read, the stream may block on a subsequent
+ * read, but it not guaranteed to block.
+ *
+ * @return The number of bytes that can be read before blocking might occur
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized int available() throws IOException
+ {
+ // The JDK 1.3 implementation does not appear to check for the closed or
+ // unconnected stream conditions here.
+
+ if (in < 0)
+ return 0;
+ else if (out < in)
+ return in - out;
+ else
+ return (buffer.length - out) + in;
+ }
+
+ /**
+ * This methods closes the stream so that no more data can be read
+ * from it.
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized void close() throws IOException
+ {
+ closed = true;
+ // Wake any thread which may be in receive() waiting to write data.
+ notifyAll();
+ }
+}
+
diff --git a/libjava/classpath/java/io/PipedOutputStream.java b/libjava/classpath/java/io/PipedOutputStream.java
new file mode 100644
index 00000000000..81881050d1b
--- /dev/null
+++ b/libjava/classpath/java/io/PipedOutputStream.java
@@ -0,0 +1,181 @@
+/* PipedOutputStream.java -- Write portion of piped streams.
+ Copyright (C) 1998, 2000, 2001, 2003 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.io;
+
+// NOTE: This implementation is very similar to that of PipedWriter. If you
+// fix a bug in here, chances are you should make a similar change to the
+// PipedWriter code.
+
+/**
+ * This class writes its bytes to a <code>PipedInputStream</code> to
+ * which it is connected.
+ * <p>
+ * It is highly recommended that a <code>PipedOutputStream</code> and its
+ * connected <code>PipedInputStream</code> be in different threads. If
+ * they are in the same thread, read and write operations could deadlock
+ * the thread.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class PipedOutputStream extends OutputStream
+{
+ /** Target PipedInputStream to which this is connected. Null only if this
+ * OutputStream hasn't been connected yet. */
+ PipedInputStream sink;
+
+ /** Set to true if close() has been called on this OutputStream. */
+ boolean closed;
+
+ /**
+ * Create an unconnected PipedOutputStream. It must be connected
+ * to a <code>PipedInputStream</code> using the <code>connect</code>
+ * method prior to writing any data or an exception will be thrown.
+ */
+ public PipedOutputStream()
+ {
+ }
+
+ /**
+ * Create a new <code>PipedOutputStream</code> instance
+ * to write to the specified <code>PipedInputStream</code>. This stream
+ * is then ready for writing.
+ *
+ * @param sink The <code>PipedInputStream</code> to connect this stream to.
+ *
+ * @exception IOException If <code>sink</code> has already been connected
+ * to a different PipedOutputStream.
+ */
+ public PipedOutputStream(PipedInputStream sink) throws IOException
+ {
+ sink.connect(this);
+ }
+
+ /**
+ * Connects this object to the specified <code>PipedInputStream</code>
+ * object. This stream will then be ready for writing.
+ *
+ * @param sink The <code>PipedInputStream</code> to connect this stream to
+ *
+ * @exception IOException If the stream has not been connected or has
+ * been closed.
+ */
+ public void connect(PipedInputStream sink) throws IOException
+ {
+ if (this.sink != null || sink.source != null)
+ throw new IOException ("Already connected");
+ sink.connect(this);
+ }
+
+ /**
+ * Write a single byte of date to the stream. Note that this method will
+ * block if the <code>PipedInputStream</code> to which this object is
+ * connected has a full buffer.
+ *
+ * @param b The byte of data to be written, passed as an <code>int</code>.
+ *
+ * @exception IOException If the stream has not been connected or has
+ * been closed.
+ */
+ public void write(int b) throws IOException
+ {
+ if (sink == null)
+ throw new IOException ("Not connected");
+ if (closed)
+ throw new IOException ("Pipe closed");
+
+ sink.receive (b);
+ }
+
+ /**
+ * This method writes <code>len</code> bytes of data from the byte array
+ * <code>buf</code> starting at index <code>offset</code> in the array
+ * to the stream. Note that this method will block if the
+ * <code>PipedInputStream</code> to which this object is connected has
+ * a buffer that cannot hold all of the bytes to be written.
+ *
+ * @param buffer The array containing bytes to write to the stream.
+ * @param offset The index into the array to start writing bytes from.
+ * @param len The number of bytes to write.
+ *
+ * @exception IOException If the stream has not been connected or has
+ * been closed.
+ */
+ public void write(byte[] buffer, int offset, int len) throws IOException
+ {
+ if (sink == null)
+ throw new IOException ("Not connected");
+ if (closed)
+ throw new IOException ("Pipe closed");
+
+ sink.receive(buffer, offset, len);
+ }
+
+ /**
+ * This method does nothing.
+ *
+ * @exception IOException If the stream is closed.
+ * @specnote You'd think that this method would block until the sink
+ * had read all available data. Thats not the case - this method
+ * appears to be a no-op?
+ */
+ public void flush() throws IOException
+ {
+ }
+
+ /**
+ * This method closes this stream so that no more data can be written
+ * to it. Any further attempts to write to this stream may throw an
+ * exception
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ // A close call on an unconnected PipedOutputStream has no effect.
+ if (sink != null)
+ {
+ closed = true;
+ // Notify any waiting readers that the stream is now closed.
+ synchronized (sink)
+ {
+ sink.notifyAll();
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/io/PipedReader.java b/libjava/classpath/java/io/PipedReader.java
new file mode 100644
index 00000000000..90fc10f672d
--- /dev/null
+++ b/libjava/classpath/java/io/PipedReader.java
@@ -0,0 +1,361 @@
+/* PipedReader.java -- Read portion of piped character streams.
+ Copyright (C) 1998, 1999, 2000, 2001 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.io;
+
+// NOTE: This implementation is very similar to that of PipedInputStream.
+// If you fix a bug in here, chances are you should make a similar change to
+// the PipedInputStream code.
+
+/**
+ * An input stream that reads characters from a piped writer to which it is
+ * connected.
+ * <p>
+ * Data is read and written to an internal buffer. It is highly recommended
+ * that the <code>PipedReader</code> and connected <code>PipedWriter</code>
+ * be part of different threads. If they are not, there is a possibility
+ * that the read and write operations could deadlock their thread.
+ *
+ * @specnote The JDK implementation appears to have some undocumented
+ * functionality where it keeps track of what thread is writing
+ * to pipe and throws an IOException if that thread susequently
+ * dies. This behaviour seems dubious and unreliable - we don't
+ * implement it.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class PipedReader extends Reader
+{
+ /** PipedWriter to which this is connected. Null only if this
+ * Reader hasn't been connected yet. */
+ PipedWriter source;
+
+ /** Set to true if close() has been called on this Reader. */
+ boolean closed;
+
+ /**
+ * The size of the internal buffer used for input/output.
+ */
+ static final int PIPE_SIZE = 2048;
+
+ /**
+ * This is the internal circular buffer used for storing chars written
+ * to the pipe and from which chars are read by this stream
+ */
+ char[] buffer = new char[PIPE_SIZE];
+
+ /**
+ * The index into buffer where the next char from the connected
+ * <code>PipedWriter</code> will be written. If this variable is
+ * equal to <code>out</code>, then the buffer is full. If set to < 0,
+ * the buffer is empty.
+ */
+ int in = -1;
+
+ /**
+ * This index into the buffer where chars will be read from.
+ */
+ int out = 0;
+
+ /** Buffer used to implement single-argument read/receive */
+ char[] read_buf = new char[1];
+
+ /**
+ * Creates a new <code>PipedReader</code> that is not connected to a
+ * <code>PipedWriter</code>. It must be connected before chars can
+ * be read from this stream.
+ */
+ public PipedReader()
+ {
+ }
+
+ /**
+ * This constructor creates a new <code>PipedReader</code> and connects
+ * it to the passed in <code>PipedWriter</code>. The stream is then
+ * ready for reading.
+ *
+ * @param source The <code>PipedWriter</code> to connect this stream to
+ *
+ * @exception IOException If <code>source</code> is already connected.
+ */
+ public PipedReader(PipedWriter source) throws IOException
+ {
+ connect(source);
+ }
+
+ /**
+ * This method connects this stream to the passed in
+ * <code>PipedWriter</code>.
+ * This stream is then ready for reading. If this stream is already
+ * connected or has been previously closed, then an exception is thrown
+ *
+ * @param source The <code>PipedWriter</code> to connect this stream to
+ *
+ * @exception IOException If this PipedReader or <code>source</code>
+ * has been connected already.
+ */
+ public void connect(PipedWriter source) throws IOException
+ {
+ // The JDK (1.3) does not appear to check for a previously closed
+ // connection here.
+
+ if (this.source != null || source.sink != null)
+ throw new IOException ("Already connected");
+
+ source.sink = this;
+ this.source = source;
+ }
+
+ /**
+ * This method is used by the connected <code>PipedWriter</code> to
+ * write chars into the buffer.
+ *
+ * @param buf The array containing chars to write to this stream
+ * @param offset The offset into the array to start writing from
+ * @param len The number of chars to write.
+ *
+ * @exception IOException If an error occurs
+ * @specnote This code should be in PipedWriter.write, but we
+ * put it here in order to support that bizarre recieve(int)
+ * method.
+ */
+ void receive(char[] buf, int offset, int len)
+ throws IOException
+ {
+ synchronized (lock)
+ {
+ if (closed)
+ throw new IOException ("Pipe closed");
+
+ int bufpos = offset;
+ int copylen;
+
+ while (len > 0)
+ {
+ try
+ {
+ while (in == out)
+ {
+ // The pipe is full. Wake up any readers and wait for them.
+ lock.notifyAll();
+ lock.wait();
+ // The pipe could have been closed while we were waiting.
+ if (closed)
+ throw new IOException ("Pipe closed");
+ }
+ }
+ catch (InterruptedException ix)
+ {
+ throw new InterruptedIOException ();
+ }
+
+ if (in < 0) // The pipe is empty.
+ in = 0;
+
+ // Figure out how many chars from buf can be copied without
+ // overrunning out or going past the length of the buffer.
+ if (in < out)
+ copylen = Math.min (len, out - in);
+ else
+ copylen = Math.min (len, buffer.length - in);
+
+ // Copy chars until the pipe is filled, wrapping if necessary.
+ System.arraycopy(buf, bufpos, buffer, in, copylen);
+ len -= copylen;
+ bufpos += copylen;
+ in += copylen;
+ if (in == buffer.length)
+ in = 0;
+ }
+ // Notify readers that new data is in the pipe.
+ lock.notifyAll();
+ }
+ }
+
+ /**
+ * This method reads chars from the stream into a caller supplied buffer.
+ * It starts storing chars at position <code>offset</code> into the
+ * buffer and
+ * reads a maximum of <code>len</code> chars. Note that this method
+ * can actually
+ * read fewer than <code>len</code> chars. The actual number of chars
+ * read is
+ * returned. A -1 is returned to indicated that no chars can be read
+ * because the end of the stream was reached. If the stream is already
+ * closed, a -1 will again be returned to indicate the end of the stream.
+ * <p>
+ * This method will block if no char is available to be read.
+ */
+ public int read() throws IOException
+ {
+ // Method operates by calling the multichar overloaded read method
+ // Note that read_buf is an internal instance variable. I allocate it
+ // there to avoid constant reallocation overhead for applications that
+ // call this method in a loop at the cost of some unneeded overhead
+ // if this method is never called.
+
+ int r = read(read_buf, 0, 1);
+ return r != -1 ? read_buf[0] : -1;
+ }
+
+ /**
+ * This method reads characters from the stream into a caller supplied
+ * buffer. It starts storing chars at position <code>offset</code> into
+ * the buffer and reads a maximum of <code>len</code> chars. Note that
+ * this method can actually read fewer than <code>len</code> chars.
+ * The actual number of chars read is
+ * returned. A -1 is returned to indicated that no chars can be read
+ * because the end of the stream was reached - ie close() was called on the
+ * connected PipedWriter.
+ * <p>
+ * This method will block if no chars are available to be read.
+ *
+ * @param buf The buffer into which chars will be stored
+ * @param offset The index into the buffer at which to start writing.
+ * @param len The maximum number of chars to read.
+ *
+ * @exception IOException If <code>close()</code> was called on this Piped
+ * Reader.
+ */
+ public int read(char[] buf, int offset, int len)
+ throws IOException
+ {
+ synchronized (lock)
+ {
+ if (source == null)
+ throw new IOException ("Not connected");
+ if (closed)
+ throw new IOException ("Pipe closed");
+
+ // If the buffer is empty, wait until there is something in the pipe
+ // to read.
+ try
+ {
+ while (in < 0)
+ {
+ if (source.closed)
+ return -1;
+ lock.wait();
+ }
+ }
+ catch (InterruptedException ix)
+ {
+ throw new InterruptedIOException();
+ }
+
+ int total = 0;
+ int copylen;
+
+ while (true)
+ {
+ // Figure out how many chars from the pipe can be copied without
+ // overrunning in or going past the length of buf.
+ if (out < in)
+ copylen = Math.min (len, in - out);
+ else
+ copylen = Math.min (len, buffer.length - out);
+
+ System.arraycopy (buffer, out, buf, offset, copylen);
+ offset += copylen;
+ len -= copylen;
+ out += copylen;
+ total += copylen;
+
+ if (out == buffer.length)
+ out = 0;
+
+ if (out == in)
+ {
+ // Pipe is now empty.
+ in = -1;
+ out = 0;
+ }
+
+ // If output buffer is filled or the pipe is empty, we're done.
+ if (len == 0 || in == -1)
+ {
+ // Notify any waiting Writer that there is now space
+ // to write.
+ lock.notifyAll();
+ return total;
+ }
+ }
+ }
+ }
+
+ public boolean ready() throws IOException
+ {
+ // The JDK 1.3 implementation does not appear to check for the closed or
+ // unconnected stream conditions here. However, checking for a
+ // closed stream is explicitly required by the JDK 1.2 and 1.3
+ // documentation (for Reader.close()), so we do it.
+
+ synchronized (lock)
+ {
+ if (closed)
+ throw new IOException("Pipe closed");
+
+ if (in < 0)
+ return false;
+
+ int count;
+ if (out < in)
+ count = in - out;
+ else
+ count = (buffer.length - out) - in;
+
+ return (count > 0);
+ }
+ }
+
+ /**
+ * This methods closes the stream so that no more data can be read
+ * from it.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ synchronized (lock)
+ {
+ closed = true;
+ // Wake any thread which may be in receive() waiting to write data.
+ lock.notifyAll();
+ }
+ }
+}
+
diff --git a/libjava/classpath/java/io/PipedWriter.java b/libjava/classpath/java/io/PipedWriter.java
new file mode 100644
index 00000000000..92786e5de7d
--- /dev/null
+++ b/libjava/classpath/java/io/PipedWriter.java
@@ -0,0 +1,182 @@
+/* PipedWriter.java -- Write portion of piped character streams.
+ Copyright (C) 1998, 2000, 2001, 2003 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.io;
+
+// NOTE: This implementation is very similar to that of PipedOutputStream.
+// If you fix a bug in here, chances are you should make a similar change to
+// the PipedOutputStream code.
+
+/**
+ * This class writes its chars to a <code>PipedReader</code> to
+ * which it is connected.
+ * <p>
+ * It is highly recommended that a <code>PipedWriter</code> and its
+ * connected <code>PipedReader</code> be in different threads. If
+ * they are in the same thread, read and write operations could deadlock
+ * the thread.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class PipedWriter extends Writer
+{
+ /** Target PipedReader to which this is connected. Null only if this
+ * Writer hasn't been connected yet. */
+ PipedReader sink;
+
+ /** Set to true if close() has been called on this Writer. */
+ boolean closed;
+
+ /** Buffer used to implement single-argument write */
+ char[] read_buf = new char[1];
+
+ /**
+ * Create an unconnected PipedWriter. It must be connected
+ * to a <code>PipedReader</code> using the <code>connect</code>
+ * method prior to writing any data or an exception will be thrown.
+ */
+ public PipedWriter()
+ {
+ }
+
+ /**
+ * Create a new <code>PipedWriter</code> instance
+ * to write to the specified <code>PipedReader</code>. This stream
+ * is then ready for writing.
+ *
+ * @param sink The <code>PipedReader</code> to connect this stream to.
+ *
+ * @exception IOException If <code>sink</code> has already been connected
+ * to a different PipedWriter.
+ */
+ public PipedWriter(PipedReader sink) throws IOException
+ {
+ sink.connect(this);
+ }
+
+ /**
+ * Connects this object to the specified <code>PipedReader</code>
+ * object. This stream will then be ready for writing.
+ *
+ * @param sink The <code>PipedReader</code> to connect this stream to
+ *
+ * @exception IOException If the stream has not been connected or has
+ * been closed.
+ */
+ public void connect(PipedReader sink) throws IOException
+ {
+ if (this.sink != null || sink.source != null)
+ throw new IOException ("Already connected");
+ sink.connect(this);
+ }
+
+ /**
+ * Write a single char of date to the stream. Note that this method will
+ * block if the <code>PipedReader</code> to which this object is
+ * connected has a full buffer.
+ *
+ * @param b The char of data to be written, passed as an <code>int</code>.
+ *
+ * @exception IOException If the stream has not been connected or has
+ * been closed.
+ */
+ public void write(int b) throws IOException
+ {
+ read_buf[0] = (char) (b & 0xffff);
+ sink.receive (read_buf, 0, 1);
+ }
+
+ /**
+ * This method writes <code>len</code> chars of data from the char array
+ * <code>buf</code> starting at index <code>offset</code> in the array
+ * to the stream. Note that this method will block if the
+ * <code>PipedReader</code> to which this object is connected has
+ * a buffer that cannot hold all of the chars to be written.
+ *
+ * @param buffer The array containing chars to write to the stream.
+ * @param offset The index into the array to start writing chars from.
+ * @param len The number of chars to write.
+ *
+ * @exception IOException If the stream has not been connected or has
+ * been closed.
+ */
+ public void write(char[] buffer, int offset, int len) throws IOException
+ {
+ if (sink == null)
+ throw new IOException ("Not connected");
+ if (closed)
+ throw new IOException ("Pipe closed");
+
+ sink.receive(buffer, offset, len);
+ }
+
+ /**
+ * This method does nothing.
+ *
+ * @exception IOException If the stream is closed.
+ * @specnote You'd think that this method would block until the sink
+ * had read all available data. Thats not the case - this method
+ * appears to be a no-op?
+ */
+ public void flush() throws IOException
+ {
+ if (closed)
+ throw new IOException ("Pipe closed");
+ }
+
+ /**
+ * This method closes this stream so that no more data can be written
+ * to it. Any further attempts to write to this stream may throw an
+ * exception
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ // A close call on an unconnected PipedWriter has no effect.
+ if (sink != null)
+ {
+ closed = true;
+ // Notify any waiting readers that the stream is now closed.
+ synchronized (sink)
+ {
+ sink.notifyAll();
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/io/PrintStream.java b/libjava/classpath/java/io/PrintStream.java
new file mode 100644
index 00000000000..8e50559b310
--- /dev/null
+++ b/libjava/classpath/java/io/PrintStream.java
@@ -0,0 +1,553 @@
+/* PrintStream.java -- OutputStream for printing output
+ Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Believed complete and correct to 1.3
+ */
+
+/**
+ * This class prints Java primitive values and object to a stream as
+ * text. None of the methods in this class throw an exception. However,
+ * errors can be detected by calling the <code>checkError()</code> method.
+ * Additionally, this stream can be designated as "autoflush" when
+ * created so that any writes are automatically flushed to the underlying
+ * output sink when the current line is terminated.
+ * <p>
+ * This class converts char's into byte's using the system default encoding.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class PrintStream extends FilterOutputStream
+{
+ /* Notice the implementation is quite similar to OutputStreamWriter.
+ * This leads to some minor duplication, because neither inherits
+ * from the other, and we want to maximize performance. */
+
+ // Line separator string.
+ private static final char[] line_separator
+ = System.getProperty("line.separator").toCharArray();
+
+ /**
+ * Encoding name
+ */
+ private String encoding;
+
+ /**
+ * This boolean indicates whether or not an error has ever occurred
+ * on this stream.
+ */
+ private boolean error_occurred = false;
+
+ /**
+ * This is <code>true</code> if auto-flush is enabled,
+ * <code>false</code> otherwise
+ */
+ private boolean auto_flush;
+
+ /**
+ * This method intializes a new <code>PrintStream</code> object to write
+ * to the specified output sink.
+ *
+ * @param out The <code>OutputStream</code> to write to.
+ */
+ public PrintStream (OutputStream out)
+ {
+ this (out, false);
+ }
+
+ /**
+ * This method intializes 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
+ * <code>write</code> methods with array arguments are called, or when a
+ * single new-line character is written.
+ * <p>
+ *
+ * @param out The <code>OutputStream</code> to write to.
+ * @param auto_flush <code>true</code> to flush the stream after every
+ * line, <code>false</code> otherwise
+ */
+ public PrintStream (OutputStream out, boolean auto_flush)
+ {
+ super (out);
+
+ try {
+ this.encoding = System.getProperty("file.encoding");
+ } catch (SecurityException e){
+ this.encoding = "ISO8859_1";
+ } catch (IllegalArgumentException e){
+ this.encoding = "ISO8859_1";
+ } catch (NullPointerException e){
+ this.encoding = "ISO8859_1";
+ }
+ this.auto_flush = auto_flush;
+ }
+
+ /**
+ * This method intializes 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
+ * <code>write</code> methods with array arguments are called, or when a
+ * single new-line character is written.
+ * <p>
+ *
+ * @param out The <code>OutputStream</code> to write to.
+ * @param auto_flush <code>true</code> to flush the stream after every
+ * line, <code>false</code> otherwise
+ * @param encoding The name of the character encoding to use for this
+ * object.
+ */
+ public PrintStream (OutputStream out, boolean auto_flush, String encoding)
+ throws UnsupportedEncodingException
+ {
+ super (out);
+
+ new String(new byte[]{0}, encoding); // check if encoding is supported
+ this.encoding = encoding;
+ this.auto_flush = auto_flush;
+ }
+
+ /**
+ * This method checks to see if an error has occurred on this stream. Note
+ * that once an error has occurred, this method will continue to report
+ * <code>true</code> forever for this stream. Before checking for an
+ * error condition, this method flushes the stream.
+ *
+ * @return <code>true</code> if an error has occurred,
+ * <code>false</code> otherwise
+ */
+ public boolean checkError ()
+ {
+ flush ();
+ return error_occurred;
+ }
+
+ /**
+ * This method can be called by subclasses to indicate that an error
+ * has occurred and should be reported by <code>checkError</code>.
+ */
+ protected void setError ()
+ {
+ error_occurred = true;
+ }
+
+ /**
+ * This method closes this stream and all underlying streams.
+ */
+ public void close ()
+ {
+ try
+ {
+ flush();
+ out.close();
+ }
+ catch (InterruptedIOException iioe)
+ {
+ Thread.currentThread().interrupt();
+ }
+ catch (IOException e)
+ {
+ setError ();
+ }
+ }
+
+ /**
+ * This method flushes any buffered bytes to the underlying stream and
+ * then flushes that stream as well.
+ */
+ public void flush ()
+ {
+ try
+ {
+ out.flush();
+ }
+ catch (InterruptedIOException iioe)
+ {
+ Thread.currentThread().interrupt();
+ }
+ catch (IOException e)
+ {
+ setError ();
+ }
+ }
+
+ private synchronized void print (String str, boolean println)
+ {
+ try
+ {
+ writeChars(str, 0, str.length());
+ if (println)
+ writeChars(line_separator, 0, line_separator.length);
+ if (auto_flush)
+ flush();
+ }
+ catch (InterruptedIOException iioe)
+ {
+ Thread.currentThread().interrupt();
+ }
+ catch (IOException e)
+ {
+ setError ();
+ }
+ }
+
+ private synchronized void print (char[] chars, int pos, int len,
+ boolean println)
+ {
+ try
+ {
+ writeChars(chars, pos, len);
+ if (println)
+ writeChars(line_separator, 0, line_separator.length);
+ if (auto_flush)
+ flush();
+ }
+ catch (InterruptedIOException iioe)
+ {
+ Thread.currentThread().interrupt();
+ }
+ catch (IOException e)
+ {
+ setError ();
+ }
+ }
+
+ private void writeChars(char[] buf, int offset, int count)
+ throws IOException
+ {
+ byte[] bytes = (new String(buf, offset, count)).getBytes(encoding);
+ out.write(bytes, 0, bytes.length);
+ }
+
+ private void writeChars(String str, int offset, int count)
+ throws IOException
+ {
+ byte[] bytes = str.substring(offset, offset+count).getBytes(encoding);
+ out.write(bytes, 0, bytes.length);
+ }
+
+ /**
+ * This methods prints a boolean value to the stream. <code>true</code>
+ * values are printed as "true" and <code>false</code> values are printed
+ * as "false".
+ *
+ * @param bool The <code>boolean</code> value to print
+ */
+ public void print (boolean bool)
+ {
+ print(String.valueOf(bool), false);
+ }
+
+ /**
+ * This method prints an integer to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * @param inum The <code>int</code> value to be printed
+ */
+ public void print (int inum)
+ {
+ print(String.valueOf(inum), false);
+ }
+
+ /**
+ * This method prints a long to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * @param lnum The <code>long</code> value to be printed
+ */
+ public void print (long lnum)
+ {
+ print(String.valueOf(lnum), false);
+ }
+
+ /**
+ * This method prints a float to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * @param fnum The <code>float</code> value to be printed
+ */
+ public void print (float fnum)
+ {
+ print(String.valueOf(fnum), false);
+ }
+
+ /**
+ * This method prints a double to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * @param dnum The <code>double</code> value to be printed
+ */
+ public void print (double dnum)
+ {
+ print(String.valueOf(dnum), false);
+ }
+
+ /**
+ * This method prints an <code>Object</code> to the stream. The actual
+ * value printed is determined by calling the <code>String.valueOf()</code>
+ * method.
+ *
+ * @param obj The <code>Object</code> to print.
+ */
+ public void print (Object obj)
+ {
+ print(obj == null ? "null" : obj.toString(), false);
+ }
+
+ /**
+ * This method prints a <code>String</code> to the stream. The actual
+ * value printed depends on the system default encoding.
+ *
+ * @param str The <code>String</code> to print.
+ */
+ public void print (String str)
+ {
+ print(str == null ? "null" : str, false);
+ }
+
+ /**
+ * This method prints a char to the stream. The actual value printed is
+ * determined by the character encoding in use.
+ *
+ * @param ch The <code>char</code> value to be printed
+ */
+ public synchronized void print (char ch)
+ {
+ print(new char[]{ch}, 0, 1, false);
+ }
+
+ /**
+ * This method prints an array of characters to the stream. The actual
+ * value printed depends on the system default encoding.
+ *
+ * @param charArray The array of characters to print.
+ */
+ public void print (char[] charArray)
+ {
+ print(charArray, 0, charArray.length, false);
+ }
+
+ /**
+ * This method prints a line separator sequence to the stream. The value
+ * printed is determined by the system property <xmp>line.separator</xmp>
+ * and is not necessarily the Unix '\n' newline character.
+ */
+ public void println ()
+ {
+ print(line_separator, 0, line_separator.length, false);
+ }
+
+ /**
+ * This methods prints a boolean value to the stream. <code>true</code>
+ * values are printed as "true" and <code>false</code> values are printed
+ * as "false".
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param bool The <code>boolean</code> value to print
+ */
+ public void println (boolean bool)
+ {
+ print(String.valueOf(bool), true);
+ }
+
+ /**
+ * This method prints an integer to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param inum The <code>int</code> value to be printed
+ */
+ public void println (int inum)
+ {
+ print(String.valueOf(inum), true);
+ }
+
+ /**
+ * This method prints a long to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param lnum The <code>long</code> value to be printed
+ */
+ public void println (long lnum)
+ {
+ print(String.valueOf(lnum), true);
+ }
+
+ /**
+ * This method prints a float to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param fnum The <code>float</code> value to be printed
+ */
+ public void println (float fnum)
+ {
+ print(String.valueOf(fnum), true);
+ }
+
+ /**
+ * This method prints a double to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param dnum The <code>double</code> value to be printed
+ */
+ public void println (double dnum)
+ {
+ print(String.valueOf(dnum), true);
+ }
+
+ /**
+ * This method prints an <code>Object</code> to the stream. The actual
+ * value printed is determined by calling the <code>String.valueOf()</code>
+ * method.
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param obj The <code>Object</code> to print.
+ */
+ public void println (Object obj)
+ {
+ print(obj == null ? "null" : obj.toString(), true);
+ }
+
+ /**
+ * This method prints a <code>String</code> to the stream. The actual
+ * value printed depends on the system default encoding.
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param str The <code>String</code> to print.
+ */
+ public void println (String str)
+ {
+ print (str == null ? "null" : str, true);
+ }
+
+ /**
+ * This method prints a char to the stream. The actual value printed is
+ * determined by the character encoding in use.
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param ch The <code>char</code> value to be printed
+ */
+ public synchronized void println (char ch)
+ {
+ print(new char[]{ch}, 0, 1, true);
+ }
+
+ /**
+ * This method prints an array of characters to the stream. The actual
+ * value printed depends on the system default encoding.
+ * <p>
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param charArray The array of characters to print.
+ */
+ public void println (char[] charArray)
+ {
+ print(charArray, 0, charArray.length, true);
+ }
+
+ /**
+ * This method writes a byte of data to the stream. If auto-flush is
+ * enabled, printing a newline character will cause the stream to be
+ * flushed after the character is written.
+ *
+ * @param oneByte The byte to be written
+ */
+ public void write (int oneByte)
+ {
+ try
+ {
+ out.write (oneByte & 0xff);
+
+ if (auto_flush && (oneByte == '\n'))
+ flush ();
+ }
+ catch (InterruptedIOException iioe)
+ {
+ Thread.currentThread ().interrupt ();
+ }
+ catch (IOException e)
+ {
+ setError ();
+ }
+ }
+
+ /**
+ * This method writes <code>len</code> bytes from the specified array
+ * starting at index <code>offset</code> into the array.
+ *
+ * @param buffer The array of bytes to write
+ * @param offset The index into the array to start writing from
+ * @param len The number of bytes to write
+ */
+ public void write (byte[] buffer, int offset, int len)
+ {
+ try
+ {
+ out.write (buffer, offset, len);
+
+ if (auto_flush)
+ flush ();
+ }
+ catch (InterruptedIOException iioe)
+ {
+ Thread.currentThread ().interrupt ();
+ }
+ catch (IOException e)
+ {
+ setError ();
+ }
+ }
+} // class PrintStream
+
diff --git a/libjava/classpath/java/io/PrintWriter.java b/libjava/classpath/java/io/PrintWriter.java
new file mode 100644
index 00000000000..5fd0b162f31
--- /dev/null
+++ b/libjava/classpath/java/io/PrintWriter.java
@@ -0,0 +1,571 @@
+/* PrintWriter.java -- prints primitive values and objects to a stream as text
+ Copyright (C) 1998, 1999, 2000, 2001 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.io;
+
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ * However, should use native methods for conversion.
+ */
+
+/**
+ * This class prints Java primitive values and objects to a stream as
+ * text. None of the methods in this class throw an exception. However,
+ * errors can be detected by calling the <code>checkError()</code> method.
+ * Additionally, this stream can be designated as "autoflush" when
+ * created so that any writes are automatically flushed to the underlying
+ * output sink whenever one of the <code>println</code> methods is
+ * called. (Note that this differs from the <code>PrintStream</code>
+ * class which also auto-flushes when it encounters a newline character
+ * in the chars written).
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @date April 17, 1998.
+ */
+public class PrintWriter extends Writer
+{
+ /**
+ * <code>true</code> if auto-flush is enabled, <code>false</code> otherwise
+ */
+ private boolean autoflush;
+
+ /**
+ * This boolean indicates whether or not an error has ever occurred
+ * on this stream.
+ */
+ private boolean error;
+
+ /**
+ * This is the underlying <code>Writer</code> we are sending output
+ * to
+ */
+ protected Writer out;
+
+ /**
+ * This method intializes a new <code>PrintWriter</code> object to write
+ * to the specified output sink. The form of the constructor does not
+ * enable auto-flush functionality.
+ *
+ * @param wr The <code>Writer</code> to write to.
+ */
+ public PrintWriter(Writer wr)
+ {
+ super(wr.lock);
+ this.out = wr;
+ }
+
+ /**
+ * This method intializes a new <code>PrintWriter</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 line is terminated or newline character is written.
+ *
+ * @param wr The <code>Writer</code> to write to.
+ * @param autoflush <code>true</code> to flush the stream after every
+ * line, <code>false</code> otherwise
+ */
+ public PrintWriter(Writer wr, boolean autoflush)
+ {
+ super(wr.lock);
+ this.out = wr;
+ this.autoflush = autoflush;
+ }
+
+ /**
+ * This method initializes a new <code>PrintWriter</code> object to write
+ * to the specified <code>OutputStream</code>. Characters will be converted
+ * to chars using the system default encoding. Auto-flush functionality
+ * will not be enabled.
+ *
+ * @param out The <code>OutputStream</code> to write to
+ */
+ public PrintWriter(OutputStream out)
+ {
+ super();
+ this.out = new OutputStreamWriter(out);
+ this.lock = this.out;
+ }
+
+ /**
+ * This method initializes a new <code>PrintWriter</code> object to write
+ * to the specified <code>OutputStream</code>. Characters will be converted
+ * to chars using the system default encoding. This form of the
+ * constructor allows auto-flush functionality to be enabled if desired
+ *
+ * @param out The <code>OutputStream</code> to write to
+ * @param autoflush <code>true</code> to flush the stream after every
+ * <code>println</code> call, <code>false</code> otherwise.
+ */
+ public PrintWriter(OutputStream out, boolean autoflush)
+ {
+ this(out);
+ this.autoflush = autoflush;
+ }
+
+ /**
+ * This method can be called by subclasses to indicate that an error
+ * has occurred and should be reported by <code>checkError</code>.
+ */
+ protected void setError()
+ {
+ error = true;
+ }
+
+ /**
+ * This method checks to see if an error has occurred on this stream. Note
+ * that once an error has occurred, this method will continue to report
+ * <code>true</code> forever for this stream. Before checking for an
+ * error condition, this method flushes the stream.
+ *
+ * @return <code>true</code> if an error has occurred,
+ * <code>false</code> otherwise
+ */
+ public boolean checkError()
+ {
+ flush();
+ return error;
+ }
+
+ /**
+ * This method flushes any buffered chars to the underlying stream and
+ * then flushes that stream as well.
+ */
+ public void flush()
+ {
+ try
+ {
+ out.flush();
+ }
+ catch (IOException ex)
+ {
+ error = true;
+ }
+ }
+
+ /**
+ * This method closes this stream and all underlying streams.
+ */
+ public void close()
+ {
+ try
+ {
+ out.close();
+ }
+ catch (IOException ex)
+ {
+ error = true;
+ }
+ }
+
+ /**
+ * This method prints a <code>String</code> to the stream. The actual
+ * value printed depends on the system default encoding.
+ *
+ * @param str The <code>String</code> to print.
+ */
+ public void print(String str)
+ {
+ write(str == null ? "null" : str);
+ }
+
+ /**
+ * This method prints a char to the stream. The actual value printed is
+ * determined by the character encoding in use.
+ *
+ * @param ch The <code>char</code> value to be printed
+ */
+ public void print(char ch)
+ {
+ write((int) ch);
+ }
+
+ /**
+ * This method prints an array of characters to the stream. The actual
+ * value printed depends on the system default encoding.
+ *
+ * @param charArray The array of characters to print.
+ */
+ public void print(char[] charArray)
+ {
+ write(charArray, 0, charArray.length);
+ }
+
+ /**
+ * This methods prints a boolean value to the stream. <code>true</code>
+ * values are printed as "true" and <code>false</code> values are printed
+ * as "false".
+ *
+ * @param bool The <code>boolean</code> value to print
+ */
+ public void print(boolean bool)
+ {
+ // We purposely call write() and not print() here. This preserves
+ // compatibility with JDK 1.2.
+ write (bool ? "true" : "false");
+ }
+
+ /**
+ * This method prints an integer to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * @param inum The <code>int</code> value to be printed
+ */
+ public void print(int inum)
+ {
+ // We purposely call write() and not print() here. This preserves
+ // compatibility with JDK 1.2.
+ write(Integer.toString(inum));
+ }
+
+ /**
+ * This method prints a long to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * @param lnum The <code>long</code> value to be printed
+ */
+ public void print(long lnum)
+ {
+ // We purposely call write() and not print() here. This preserves
+ // compatibility with JDK 1.2.
+ write(Long.toString(lnum));
+ }
+
+ /**
+ * This method prints a float to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * @param fnum The <code>float</code> value to be printed
+ */
+ public void print(float fnum)
+ {
+ // We purposely call write() and not print() here. This preserves
+ // compatibility with JDK 1.2.
+ write(Float.toString(fnum));
+ }
+
+ /**
+ * This method prints a double to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * @param dnum The <code>double</code> value to be printed
+ */
+ public void print(double dnum)
+ {
+ // We purposely call write() and not print() here. This preserves
+ // compatibility with JDK 1.2.
+ write(Double.toString(dnum));
+ }
+
+ /**
+ * This method prints an <code>Object</code> to the stream. The actual
+ * value printed is determined by calling the <code>String.valueOf()</code>
+ * method.
+ *
+ * @param obj The <code>Object</code> to print.
+ */
+ public void print(Object obj)
+ {
+ // We purposely call write() and not print() here. This preserves
+ // compatibility with JDK 1.2.
+ write(obj == null ? "null" : obj.toString());
+ }
+
+ /**
+ * This is the system dependent line separator
+ */
+ private static final char[] line_separator
+ = System.getProperty("line.separator").toCharArray();
+
+ /**
+ * This method prints a line separator sequence to the stream. The value
+ * printed is determined by the system property <xmp>line.separator</xmp>
+ * and is not necessarily the Unix '\n' newline character.
+ */
+ public void println()
+ {
+ synchronized (lock)
+ {
+ try
+ {
+ write(line_separator, 0, line_separator.length);
+ if (autoflush)
+ out.flush();
+ }
+ catch (IOException ex)
+ {
+ error = true;
+ }
+ }
+ }
+
+ /**
+ * This methods prints a boolean value to the stream. <code>true</code>
+ * values are printed as "true" and <code>false</code> values are printed
+ * as "false".
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param bool The <code>boolean</code> value to print
+ */
+ public void println(boolean bool)
+ {
+ synchronized (lock)
+ {
+ print(bool);
+ println();
+ }
+ }
+
+ /**
+ * This method prints an integer to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param inum The <code>int</code> value to be printed
+ */
+ public void println(int inum)
+ {
+ synchronized (lock)
+ {
+ print(inum);
+ println();
+ }
+ }
+
+ /**
+ * This method prints a long to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param lnum The <code>long</code> value to be printed
+ */
+ public void println(long lnum)
+ {
+ synchronized (lock)
+ {
+ print(lnum);
+ println();
+ }
+ }
+
+ /**
+ * This method prints a float to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param fnum The <code>float</code> value to be printed
+ */
+ public void println(float fnum)
+ {
+ synchronized (lock)
+ {
+ print(fnum);
+ println();
+ }
+ }
+
+ /**
+ * This method prints a double to the stream. The value printed is
+ * determined using the <code>String.valueOf()</code> method.
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param dnum The <code>double</code> value to be printed
+ */
+ public void println(double dnum)
+ {
+ synchronized (lock)
+ {
+ print(dnum);
+ println();
+ }
+ }
+
+ /**
+ * This method prints an <code>Object</code> to the stream. The actual
+ * value printed is determined by calling the <code>String.valueOf()</code>
+ * method.
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param obj The <code>Object</code> to print.
+ */
+ public void println(Object obj)
+ {
+ synchronized (lock)
+ {
+ print(obj);
+ println();
+ }
+ }
+
+ /**
+ * This method prints a <code>String</code> to the stream. The actual
+ * value printed depends on the system default encoding.
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param str The <code>String</code> to print.
+ */
+ public void println(String str)
+ {
+ synchronized (lock)
+ {
+ print(str);
+ println();
+ }
+ }
+
+ /**
+ * This method prints a char to the stream. The actual value printed is
+ * determined by the character encoding in use.
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param ch The <code>char</code> value to be printed
+ */
+ public void println(char ch)
+ {
+ synchronized (lock)
+ {
+ print(ch);
+ println();
+ }
+ }
+
+ /**
+ * This method prints an array of characters to the stream. The actual
+ * value printed depends on the system default encoding.
+ *
+ * This method prints a line termination sequence after printing the value.
+ *
+ * @param charArray The array of characters to print.
+ */
+ public void println(char[] charArray)
+ {
+ synchronized (lock)
+ {
+ print(charArray);
+ println();
+ }
+ }
+
+ /**
+ * This method writes a single char to the stream.
+ *
+ * @param ch The char to be written, passed as a int
+ */
+ public void write(int ch)
+ {
+ try
+ {
+ out.write(ch);
+ }
+ catch (IOException ex)
+ {
+ error = true;
+ }
+ }
+
+ /**
+ * This method writes <code>count</code> chars from the specified array
+ * starting at index <code>offset</code> into the array.
+ *
+ * @param charArray The array of chars to write
+ * @param offset The index into the array to start writing from
+ * @param count The number of chars to write
+ */
+ public void write(char[] charArray, int offset, int count)
+ {
+ try
+ {
+ out.write(charArray, offset, count);
+ }
+ catch (IOException ex)
+ {
+ error = true;
+ }
+ }
+
+ /**
+ * This method writes <code>count</code> chars from the specified
+ * <code>String</code> to the output starting at character position
+ * <code>offset</code> into the <code>String</code>
+ *
+ * @param str The <code>String</code> to write chars from
+ * @param offset The offset into the <code>String</code> to start writing from
+ * @param count The number of chars to write.
+ */
+ public void write(String str, int offset, int count)
+ {
+ try
+ {
+ out.write(str, offset, count);
+ }
+ catch (IOException ex)
+ {
+ error = true;
+ }
+ }
+
+ /**
+ * This method write all the chars in the specified array to the output.
+ *
+ * @param charArray The array of characters to write
+ */
+ public void write(char[] charArray)
+ {
+ write(charArray, 0, charArray.length);
+ }
+
+ /**
+ * This method writes the contents of the specified <code>String</code>
+ * to the underlying stream.
+ *
+ * @param str The <code>String</code> to write
+ */
+ public void write(String str)
+ {
+ write(str, 0, str.length());
+ }
+}
+
diff --git a/libjava/classpath/java/io/PushbackInputStream.java b/libjava/classpath/java/io/PushbackInputStream.java
new file mode 100644
index 00000000000..71cf244274e
--- /dev/null
+++ b/libjava/classpath/java/io/PushbackInputStream.java
@@ -0,0 +1,328 @@
+/* PushbackInputStream.java -- An input stream that can unread bytes
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.io;
+
+/**
+ * This subclass of <code>FilterInputStream</code> provides the ability to
+ * unread data from a stream. It maintains an internal buffer of unread
+ * data that is supplied to the next read operation. This is conceptually
+ * similar to mark/reset functionality, except that in this case the
+ * position to reset the stream to does not need to be known in advance.
+ * <p>
+ * The default pushback buffer size one byte, but this can be overridden
+ * by the creator of the stream.
+ * <p>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class PushbackInputStream extends FilterInputStream
+{
+ /**
+ * This is the default buffer size
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 1;
+
+ /**
+ * This is the buffer that is used to store the pushed back data
+ */
+ protected byte[] buf;
+
+ /**
+ * This is the position in the buffer from which the next byte will be
+ * read. Bytes are stored in reverse order in the buffer, starting from
+ * <code>buf[buf.length - 1]</code> to <code>buf[0]</code>. Thus when
+ * <code>pos</code> is 0 the buffer is full and <code>buf.length</code> when
+ * it is empty
+ */
+ protected int pos;
+
+ /**
+ * This method initializes a <code>PushbackInputStream</code> to
+ * read from the specified subordinate <code>InputStream</code>
+ * with a default pushback buffer size of 1.
+ *
+ * @param in The subordinate stream to read from
+ */
+ public PushbackInputStream(InputStream in)
+ {
+ this(in, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * This method initializes a <code>PushbackInputStream</code> to
+ * read from the specified subordinate <code>InputStream</code> with
+ * the specified buffer size
+ *
+ * @param in The subordinate <code>InputStream</code> to read from
+ * @param size The pushback buffer size to use
+ */
+ public PushbackInputStream(InputStream in, int size)
+ {
+ super(in);
+ if (size < 0)
+ throw new IllegalArgumentException();
+ buf = new byte[size];
+ pos = buf.length;
+ }
+
+ /**
+ * This method returns the number of bytes that can be read from this
+ * stream before a read can block. A return of 0 indicates that blocking
+ * might (or might not) occur on the very next read attempt.
+ * <p>
+ * This method will return the number of bytes available from the
+ * pushback buffer plus the number of bytes available from the
+ * underlying stream.
+ *
+ * @return The number of bytes that can be read before blocking could occur
+ *
+ * @exception IOException If an error occurs
+ */
+ public int available() throws IOException
+ {
+ return (buf.length - pos) + super.available();
+ }
+
+ /**
+ * This method closes the stream and releases any associated resources.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public synchronized void close() throws IOException
+ {
+ buf = null;
+ super.close();
+ }
+
+ /**
+ * This method returns <code>false</code> to indicate that it does
+ * not support mark/reset functionality.
+ *
+ * @return This method returns <code>false</code> to indicate that
+ * this class does not support mark/reset functionality
+ */
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ /**
+ * This method always throws an IOException in this class because
+ * mark/reset functionality is not supported.
+ *
+ * @exception IOException Always thrown for this class
+ */
+ public void reset() throws IOException
+ {
+ throw new IOException("Mark not supported in this class");
+ }
+
+ /**
+ * This method reads an unsigned byte from the input stream and returns it
+ * as an int in the range of 0-255. This method also will return -1 if
+ * the end of the stream has been reached. The byte returned will be read
+ * from the pushback buffer, unless the buffer is empty, in which case
+ * the byte will be read from the underlying stream.
+ * <p>
+ * This method will block until the byte can be read.
+ *
+ * @return The byte read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized int read() throws IOException
+ {
+ if (pos < buf.length)
+ return ((int) buf[pos++]) & 0xFF;
+
+ return super.read();
+ }
+
+ /**
+ * This method read bytes from a stream and stores them into a
+ * caller supplied buffer. It starts storing the data at index
+ * <code>offset</code> into the buffer and attempts to read
+ * <code>len</code> bytes. This method can return before reading the
+ * number of bytes requested. The actual number of bytes read is
+ * returned as an int. A -1 is returned to indicate the end of the
+ * stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * This method first reads bytes from the pushback buffer in order to
+ * satisfy the read request. If the pushback buffer cannot provide all
+ * of the bytes requested, the remaining bytes are read from the
+ * underlying stream.
+ *
+ * @param b The array into which the bytes read should be stored
+ * @param off The offset into the array to start storing bytes
+ * @param len The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public synchronized int read(byte[] b, int off, int len) throws IOException
+ {
+ int numBytes = Math.min(buf.length - pos, len);
+
+ if (numBytes > 0)
+ {
+ System.arraycopy (buf, pos, b, off, numBytes);
+ pos += numBytes;
+ len -= numBytes;
+ off += numBytes;
+ }
+
+ if (len > 0)
+ {
+ len = super.read(b, off, len);
+ if (len == -1) //EOF
+ return numBytes > 0 ? numBytes : -1;
+ numBytes += len;
+ }
+ return numBytes;
+ }
+
+ /**
+ * This method pushes a single byte of data into the pushback buffer.
+ * The byte pushed back is the one that will be returned as the first byte
+ * of the next read.
+ * <p>
+ * If the pushback buffer is full, this method throws an exception.
+ * <p>
+ * The argument to this method is an <code>int</code>. Only the low
+ * eight bits of this value are pushed back.
+ *
+ * @param b The byte to be pushed back, passed as an int
+ *
+ * @exception IOException If the pushback buffer is full.
+ */
+ public synchronized void unread(int b) throws IOException
+ {
+ if (pos <= 0)
+ throw new IOException("Insufficient space in pushback buffer");
+
+ buf[--pos] = (byte) b;
+ }
+
+ /**
+ * This method pushes all of the bytes in the passed byte array into
+ * the pushback bfer. These bytes are pushed in reverse order so that
+ * the next byte read from the stream after this operation will be
+ * <code>b[0]</code> followed by <code>b[1]</code>, etc.
+ * <p>
+ * If the pushback buffer cannot hold all of the requested bytes, an
+ * exception is thrown.
+ *
+ * @param b The byte array to be pushed back
+ *
+ * @exception IOException If the pushback buffer is full
+ */
+ public synchronized void unread(byte[] b) throws IOException
+ {
+ unread(b, 0, b.length);
+ }
+
+ /**
+ * This method pushed back bytes from the passed in array into the
+ * pushback buffer. The bytes from <code>b[offset]</code> to
+ * <code>b[offset + len]</code> are pushed in reverse order so that
+ * the next byte read from the stream after this operation will be
+ * <code>b[offset]</code> followed by <code>b[offset + 1]</code>,
+ * etc.
+ * <p>
+ * If the pushback buffer cannot hold all of the requested bytes, an
+ * exception is thrown.
+ *
+ * @param b The byte array to be pushed back
+ * @param off The index into the array where the bytes to be push start
+ * @param len The number of bytes to be pushed.
+ *
+ * @exception IOException If the pushback buffer is full
+ */
+ public synchronized void unread(byte[] b, int off, int len)
+ throws IOException
+ {
+ if (pos < len)
+ throw new IOException("Insufficient space in pushback buffer");
+
+ // Note the order that these bytes are being added is the opposite
+ // of what would be done if they were added to the buffer one at a time.
+ // See the Java Class Libraries book p. 1390.
+ System.arraycopy(b, off, buf, pos - len, len);
+
+ // Don't put this into the arraycopy above, an exception might be thrown
+ // and in that case we don't want to modify pos.
+ pos -= len;
+ }
+
+ /**
+ * This method skips the specified number of bytes in the stream. It
+ * returns the actual number of bytes skipped, which may be less than the
+ * requested amount.
+ * <p>
+ * This method first discards bytes from the buffer, then calls the
+ * <code>skip</code> method on the underlying <code>InputStream</code> to
+ * skip additional bytes if necessary.
+ *
+ * @param n The requested number of bytes to skip
+ *
+ * @return The actual number of bytes skipped.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.2
+ */
+ public synchronized long skip(long n) throws IOException
+ {
+ final long origN = n;
+
+ if (n > 0L)
+ {
+ int numread = (int) Math.min((long) (buf.length - pos), n);
+ pos += numread;
+ n -= numread;
+ if (n > 0)
+ n -= super.skip(n);
+ }
+
+ return origN - n;
+ }
+}
diff --git a/libjava/classpath/java/io/PushbackReader.java b/libjava/classpath/java/io/PushbackReader.java
new file mode 100644
index 00000000000..04bccc70fc5
--- /dev/null
+++ b/libjava/classpath/java/io/PushbackReader.java
@@ -0,0 +1,384 @@
+/* PushbackReader.java -- An character stream that can unread chars
+ Copyright (C) 1998, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This subclass of <code>FilterReader</code> provides the ability to
+ * unread data from a stream. It maintains an internal buffer of unread
+ * data that is supplied to the next read operation. This is conceptually
+ * similar to mark/reset functionality, except that in this case the
+ * position to reset the stream to does not need to be known in advance.
+ * <p>
+ * The default pushback buffer size one char, but this can be overridden
+ * by the creator of the stream.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class PushbackReader extends FilterReader
+{
+ /**
+ * This is the default buffer size
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 1;
+
+ /**
+ * This is the buffer that is used to store the pushed back data
+ */
+ private char[] buf;
+
+ /**
+ * This is the position in the buffer from which the next char will be
+ * read. Bytes are stored in reverse order in the buffer, starting from
+ * <code>buf[buf.length - 1]</code> to <code>buf[0]</code>. Thus when
+ * <code>pos</code> is 0 the buffer is full and <code>buf.length</code> when
+ * it is empty
+ */
+ private int pos;
+
+ /**
+ * This method initializes a <code>PushbackReader</code> to read from the
+ * specified subordinate <code>Reader</code> with a default pushback buffer
+ * size of 1.
+ *
+ * @param in The subordinate stream to read from
+ */
+ public PushbackReader(Reader in)
+ {
+ this(in, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * This method initializes a <code>PushbackReader</code> to read from the
+ * specified subordinate <code>Reader</code> with the specified buffer
+ * size
+ *
+ * @param in The subordinate <code>Reader</code> to read from
+ * @param bufsize The pushback buffer size to use
+ */
+ public PushbackReader(Reader in, int bufsize)
+ {
+ super(in);
+
+ if (bufsize < 0)
+ throw new IllegalArgumentException("buffer size must be positive");
+
+ buf = new char[bufsize];
+ pos = bufsize;
+ }
+
+ /**
+ * This method closes the stream and frees any associated resources.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public void close() throws IOException
+ {
+ synchronized (lock)
+ {
+ buf = null;
+ super.close();
+ }
+ }
+
+ /**
+ * This method throws an exception when called since this class does
+ * not support mark/reset.
+ *
+ * @param read_limit Not used.
+ *
+ * @exception IOException Always thrown to indicate mark/reset not supported.
+ */
+ public void mark(int read_limit) throws IOException
+ {
+ throw new IOException("mark not supported in this class");
+ }
+
+ /**
+ * This method returns <code>false</code> to indicate that it does not support
+ * mark/reset functionality.
+ *
+ * @return This method returns <code>false</code> to indicate that this
+ * class does not support mark/reset functionality
+ *
+ */
+ public boolean markSupported()
+ {
+ return(false);
+ }
+
+ /**
+ * This method always throws an IOException in this class because
+ * mark/reset functionality is not supported.
+ *
+ * @exception IOException Always thrown for this class
+ */
+ public void reset() throws IOException
+ {
+ throw new IOException("reset not supported in this class");
+ }
+
+ /**
+ * This method determines whether or not this stream is ready to be read.
+ * If it returns <code>false</code> to indicate that the stream is not
+ * ready, any attempt to read from the stream could (but is not
+ * guaranteed to) block.
+ * <p>
+ * This stream is ready to read if there are either chars waiting to be
+ * read in the pushback buffer or if the underlying stream is ready to
+ * be read.
+ *
+ * @return <code>true</code> if this stream is ready to be read,
+ * <code>false</code> otherwise
+ *
+ * @exception IOException If an error occurs
+ */
+ public boolean ready() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException ("stream closed");
+
+ if (((buf.length - pos) > 0) || super.ready())
+ return(true);
+ else
+ return(false);
+ }
+ }
+
+ // Don't delete this method just because the spec says it shouldn't be there!
+ // See the CVS log for details.
+ /**
+ * This method skips the specified number of chars in the stream. It
+ * returns the actual number of chars skipped, which may be less than the
+ * requested amount.
+ * <p>
+ * This method first discards chars from the buffer, then calls the
+ * <code>skip</code> method on the underlying <code>Reader</code> to
+ * skip additional chars if necessary.
+ *
+ * @param num_chars The requested number of chars to skip
+ *
+ * @return The actual number of chars skipped.
+ *
+ * @exception IOException If an error occurs
+ */
+ public long skip(long num_chars) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (num_chars <= 0)
+ return(0);
+
+ if ((buf.length - pos) >= num_chars)
+ {
+ pos += num_chars;
+ return(num_chars);
+ }
+
+ int chars_discarded = buf.length - pos;
+ pos = buf.length;
+
+ long chars_skipped = in.skip(num_chars - chars_discarded);
+
+ return(chars_discarded + chars_skipped);
+ }
+ }
+
+ /**
+ * This method reads an unsigned char from the input stream and returns it
+ * as an int in the range of 0-65535. This method also will return -1 if
+ * the end of the stream has been reached. The char returned will be read
+ * from the pushback buffer, unless the buffer is empty, in which case
+ * the char will be read from the underlying stream.
+ * <p>
+ * This method will block until the char can be read.
+ *
+ * @return The char read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("stream closed");
+
+ if (pos == buf.length)
+ return(super.read());
+
+ ++pos;
+ return((buf[pos - 1] & 0xFFFF));
+ }
+ }
+
+ /**
+ * This method read chars from a stream and stores them into a caller
+ * supplied buffer. It starts storing the data at index <code>offset</code>
+ * into
+ * the buffer and attempts to read <code>len</code> chars. This method can
+ * return before reading the number of chars requested. The actual number
+ * of chars read is returned as an int. A -1 is returned to indicate the
+ * end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * This method first reads chars from the pushback buffer in order to
+ * satisfy the read request. If the pushback buffer cannot provide all
+ * of the chars requested, the remaining chars are read from the
+ * underlying stream.
+ *
+ * @param buffer The array into which the chars read should be stored
+ * @param offset The offset into the array to start storing chars
+ * @param length The requested number of chars to read
+ *
+ * @return The actual number of chars read, or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public synchronized int read(char[] buffer, int offset, int length)
+ throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("stream closed");
+
+ if (offset < 0 || length < 0 || offset + length > buffer.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ int numBytes = Math.min(buf.length - pos, length);
+ if (numBytes > 0)
+ {
+ System.arraycopy (buf, pos, buffer, offset, numBytes);
+ pos += numBytes;
+ return numBytes;
+ }
+
+ return super.read(buffer, offset, length);
+ }
+ }
+
+ /**
+ * This method pushes a single char of data into the pushback buffer.
+ * The char pushed back is the one that will be returned as the first char
+ * of the next read.
+ * <p>
+ * If the pushback buffer is full, this method throws an exception.
+ * <p>
+ * The argument to this method is an <code>int</code>. Only the low eight
+ * bits of this value are pushed back.
+ *
+ * @param b The char to be pushed back, passed as an int
+ *
+ * @exception IOException If the pushback buffer is full.
+ */
+ public void unread(int b) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("stream closed");
+ if (pos == 0)
+ throw new IOException("Pushback buffer is full");
+
+ --pos;
+ buf[pos] = (char)(b & 0xFFFF);
+ }
+ }
+
+ /**
+ * This method pushes all of the chars in the passed char array into
+ * the pushback buffer. These chars are pushed in reverse order so that
+ * the next char read from the stream after this operation will be
+ * <code>buf[0]</code> followed by <code>buf[1]</code>, etc.
+ * <p>
+ * If the pushback buffer cannot hold all of the requested chars, an
+ * exception is thrown.
+ *
+ * @param buf The char array to be pushed back
+ *
+ * @exception IOException If the pushback buffer is full
+ */
+ public synchronized void unread(char[] buf) throws IOException
+ {
+ unread(buf, 0, buf.length);
+ }
+
+ /**
+ * This method pushed back chars from the passed in array into the pushback
+ * buffer. The chars from <code>buf[offset]</code> to
+ * <code>buf[offset + len]</code>
+ * are pushed in reverse order so that the next char read from the stream
+ * after this operation will be <code>buf[offset]</code> followed by
+ * <code>buf[offset + 1]</code>, etc.
+ * <p>
+ * If the pushback buffer cannot hold all of the requested chars, an
+ * exception is thrown.
+ *
+ * @param buffer The char array to be pushed back
+ * @param offset The index into the array where the chars to be push start
+ * @param length The number of chars to be pushed.
+ *
+ * @exception IOException If the pushback buffer is full
+ */
+ public synchronized void unread(char[] buffer, int offset, int length)
+ throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("stream closed");
+ if (pos < length)
+ throw new IOException("Pushback buffer is full");
+
+ // Note the order that these chars are being added is the opposite
+ // of what would be done if they were added to the buffer one at a time.
+ // See the Java Class Libraries book p. 1397.
+ System.arraycopy(buffer, offset, buf, pos - length, length);
+
+ // Don't put this into the arraycopy above, an exception might be thrown
+ // and in that case we don't want to modify pos.
+ pos -= length;
+ }
+ }
+}
+
diff --git a/libjava/classpath/java/io/RandomAccessFile.java b/libjava/classpath/java/io/RandomAccessFile.java
new file mode 100644
index 00000000000..23be5a31947
--- /dev/null
+++ b/libjava/classpath/java/io/RandomAccessFile.java
@@ -0,0 +1,991 @@
+/* RandomAccessFile.java -- Class supporting random file I/O
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import gnu.java.nio.channels.FileChannelImpl;
+
+import java.nio.channels.FileChannel;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Believe complete and correct to 1.1.
+ */
+
+/**
+ * This class allows reading and writing of files at random locations.
+ * Most Java I/O classes are either pure sequential input or output. This
+ * class fulfills the need to be able to read the bytes of a file in an
+ * arbitrary order. In addition, this class implements the
+ * <code>DataInput</code> and <code>DataOutput</code> interfaces to allow
+ * the reading and writing of Java primitives.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class RandomAccessFile implements DataOutput, DataInput
+{
+
+ // The underlying file.
+ private FileChannelImpl ch;
+ private FileDescriptor fd;
+ // The corresponding input and output streams.
+ private DataOutputStream out;
+ private DataInputStream in;
+
+
+ /**
+ * This method initializes a new instance of <code>RandomAccessFile</code>
+ * to read from the specified <code>File</code> object with the specified
+ * access mode. The access mode is either "r" for read only access or "rw"
+ * for read-write access.
+ * <p>
+ * Note that a <code>SecurityManager</code> check is made prior to
+ * opening the file to determine whether or not this file is allowed to
+ * be read or written.
+ *
+ * @param file The <code>File</code> object to read and/or write.
+ * @param mode "r" for read only or "rw" for read-write access to the file
+ *
+ * @exception IllegalArgumentException If <code>mode</code> has an
+ * illegal value
+ * @exception SecurityException If the requested access to the file
+ * is not allowed
+ * @exception FileNotFoundException If the file is a directory, or
+ * any other error occurs
+ */
+ public RandomAccessFile (File file, String mode)
+ throws FileNotFoundException
+ {
+ int fdmode;
+ if (mode.equals("r"))
+ fdmode = FileChannelImpl.READ;
+ else if (mode.equals("rw"))
+ fdmode = FileChannelImpl.READ | FileChannelImpl.WRITE;
+ else if (mode.equals("rws"))
+ {
+ fdmode = (FileChannelImpl.READ | FileChannelImpl.WRITE
+ | FileChannelImpl.SYNC);
+ }
+ else if (mode.equals("rwd"))
+ {
+ fdmode = (FileChannelImpl.READ | FileChannelImpl.WRITE
+ | FileChannelImpl.DSYNC);
+ }
+ else
+ throw new IllegalArgumentException ("invalid mode: " + mode);
+
+ final String fileName = file.getPath();
+
+ // The obligatory SecurityManager stuff
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ {
+ s.checkRead(fileName);
+
+ if ((fdmode & FileChannelImpl.WRITE) != 0)
+ s.checkWrite(fileName);
+ }
+
+ ch = FileChannelImpl.create(file, fdmode);
+ fd = new FileDescriptor(ch);
+ out = new DataOutputStream (new FileOutputStream (fd));
+ in = new DataInputStream (new FileInputStream (fd));
+ }
+
+ /**
+ * This method initializes a new instance of <code>RandomAccessFile</code>
+ * to read from the specified file name with the specified access mode.
+ * The access mode is either "r" for read only access, "rw" for read
+ * write access, "rws" for synchronized read/write access of both
+ * content and metadata, or "rwd" for read/write access
+ * where only content is required to be synchronous.
+ * <p>
+ * Note that a <code>SecurityManager</code> check is made prior to
+ * opening the file to determine whether or not this file is allowed to
+ * be read or written.
+ *
+ * @param fileName The name of the file to read and/or write
+ * @param mode "r", "rw", "rws", or "rwd"
+ *
+ * @exception IllegalArgumentException If <code>mode</code> has an
+ * illegal value
+ * @exception SecurityException If the requested access to the file
+ * is not allowed
+ * @exception FileNotFoundException If the file is a directory or
+ * any other error occurs
+ */
+ public RandomAccessFile (String fileName, String mode)
+ throws FileNotFoundException
+ {
+ this (new File(fileName), mode);
+ }
+
+ /**
+ * This method closes the file and frees up all file related system
+ * resources. Since most operating systems put a limit on how many files
+ * may be opened at any given time, it is a good idea to close all files
+ * when no longer needed to avoid hitting this limit
+ */
+ public void close () throws IOException
+ {
+ ch.close();
+ }
+
+ /**
+ * This method returns a <code>FileDescriptor</code> object that
+ * represents the native file handle for this file.
+ *
+ * @return The <code>FileDescriptor</code> object for this file
+ *
+ * @exception IOException If an error occurs
+ */
+ public final FileDescriptor getFD () throws IOException
+ {
+ synchronized (this)
+ {
+ if (fd == null)
+ fd = new FileDescriptor (ch);
+ return fd;
+ }
+ }
+
+ /**
+ * This method returns the current offset in the file at which the next
+ * read or write will occur
+ *
+ * @return The current file position
+ *
+ * @exception IOException If an error occurs
+ */
+ public long getFilePointer () throws IOException
+ {
+ return ch.position();
+ }
+
+ /**
+ * This method sets the length of the file to the specified length.
+ * If the currently length of the file is longer than the specified
+ * length, then the file is truncated to the specified length (the
+ * file position is set to the end of file in this case). If the
+ * current length of the file is shorter than the specified length,
+ * the file is extended with bytes of an undefined value (the file
+ * position is unchanged in this case).
+ * <p>
+ * The file must be open for write access for this operation to succeed.
+ *
+ * @param newLen The new length of the file
+ *
+ * @exception IOException If an error occurs
+ */
+ public void setLength (long newLen) throws IOException
+ {
+ // FIXME: Extending a file should probably be done by one method call.
+
+ // FileChannel.truncate() can only shrink a file.
+ // To expand it we need to seek forward and write at least one byte.
+ if (newLen < length())
+ ch.truncate (newLen);
+ else if (newLen > length())
+ {
+ long pos = getFilePointer();
+ seek(newLen - 1);
+ write(0);
+ seek(pos);
+ }
+ }
+
+ /**
+ * This method returns the length of the file in bytes
+ *
+ * @return The length of the file
+ *
+ * @exception IOException If an error occurs
+ */
+ public long length () throws IOException
+ {
+ return ch.size();
+ }
+
+ /**
+ * This method reads a single byte of data from the file and returns it
+ * as an integer.
+ *
+ * @return The byte read as an int, or -1 if the end of the file was reached.
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read () throws IOException
+ {
+ return in.read();
+ }
+
+ /**
+ * This method reads bytes from the file into the specified array. The
+ * bytes are stored starting at the beginning of the array and up to
+ * <code>buf.length</code> bytes can be read.
+ *
+ * @param buffer The buffer to read bytes from the file into
+ *
+ * @return The actual number of bytes read or -1 if end of file
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read (byte[] buffer) throws IOException
+ {
+ return in.read (buffer);
+ }
+
+ /**
+ * This methods reads up to <code>len</code> bytes from the file into the
+ * specified array starting at position <code>offset</code> into the array.
+ *
+ * @param buffer The array to read the bytes into
+ * @param offset The index into the array to start storing bytes
+ * @param len The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of file
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read (byte[] buffer, int offset, int len) throws IOException
+ {
+ return in.read (buffer, offset, len);
+ }
+
+ /**
+ * This method reads a Java boolean value from an input stream. It does
+ * so by reading a single byte of data. If that byte is zero, then the
+ * value returned is <code>false</code> If the byte is non-zero, then
+ * the value returned is <code>true</code>
+ * <p>
+ * This method can read a <code>boolean</code> written by an object
+ * implementing the
+ * <code>writeBoolean()</code> method in the <code>DataOutput</code>
+ * interface.
+ *
+ * @return The <code>boolean</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the
+ * boolean
+ * @exception IOException If any other error occurs
+ */
+ public final boolean readBoolean () throws IOException
+ {
+ return in.readBoolean ();
+ }
+
+ /**
+ * This method reads a Java byte value from an input stream. The value
+ * is in the range of -128 to 127.
+ * <p>
+ * This method can read a <code>byte</code> written by an object
+ * implementing the
+ * <code>writeByte()</code> method in the <code>DataOutput</code> interface.
+ *
+ * @return The <code>byte</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the byte
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput
+ */
+ public final byte readByte () throws IOException
+ {
+ return in.readByte ();
+ }
+
+ /**
+ * This method reads a Java <code>char</code> value from an input stream.
+ * It operates by reading two bytes from the stream and converting them to
+ * a single 16-bit Java <code>char</code> The two bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code> represent
+ * the first
+ * and second byte read from the stream respectively, they will be
+ * transformed to a <code>char</code> in the following manner:
+ * <p>
+ * <code>(char)(((byte1 &amp; 0xFF) &lt;&lt; 8) | (byte2 &amp; 0xFF)</code>
+ * <p>
+ * This method can read a <code>char</code> written by an object
+ * implementing the
+ * <code>writeChar()</code> method in the <code>DataOutput</code> interface.
+ *
+ * @return The <code>char</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the char
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput
+ */
+ public final char readChar () throws IOException
+ {
+ return in.readChar();
+ }
+
+ /**
+ * This method reads a Java double value from an input stream. It operates
+ * by first reading a <code>logn</code> value from the stream by calling the
+ * <code>readLong()</code> method in this interface, then
+ * converts that <code>long</code>
+ * to a <code>double</code> using the <code>longBitsToDouble</code>
+ * method in the class <code>java.lang.Double</code>
+ * <p>
+ * This method can read a <code>double</code> written by an object
+ * implementing the
+ * <code>writeDouble()</code> method in the <code>DataOutput</code>
+ * interface.
+ *
+ * @return The <code>double</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading
+ * the double
+ * @exception IOException If any other error occurs
+ *
+ * @see java.lang.Double
+ * @see DataOutput
+ */
+ public final double readDouble () throws IOException
+ {
+ return in.readDouble ();
+ }
+
+ /**
+ * This method reads a Java float value from an input stream. It operates
+ * by first reading an <code>int</code> value from the stream by calling the
+ * <code>readInt()</code> method in this interface, then converts
+ * that <code>int</code>
+ * to a <code>float</code> using the <code>intBitsToFloat</code> method in
+ * the class <code>java.lang.Float</code>
+ * <p>
+ * This method can read a <code>float</code> written by an object
+ * implementing the
+ * <code>writeFloat()</code> method in the <code>DataOutput</code> interface.
+ *
+ * @return The <code>float</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the float
+ * @exception IOException If any other error occurs
+ *
+ * @see java.lang.Float
+ * @see DataOutput
+ */
+ public final float readFloat () throws IOException
+ {
+ return in.readFloat();
+ }
+
+ /**
+ * This method reads raw bytes into the passed array until the array is
+ * full. Note that this method blocks until the data is available and
+ * throws an exception if there is not enough data left in the stream to
+ * fill the buffer
+ *
+ * @param buffer The buffer into which to read the data
+ *
+ * @exception EOFException If end of file is reached before filling the
+ * buffer
+ * @exception IOException If any other error occurs
+ */
+ public final void readFully (byte[] buffer) throws IOException
+ {
+ in.readFully(buffer);
+ }
+
+ /**
+ * This method reads raw bytes into the passed array <code>buf</code>
+ * starting
+ * <code>offset</code> bytes into the buffer. The number of bytes read
+ * will be
+ * exactly <code>len</code> Note that this method blocks until the data is
+ * available and throws an exception if there is not enough data left in
+ * the stream to read <code>len</code> bytes.
+ *
+ * @param buffer The buffer into which to read the data
+ * @param offset The offset into the buffer to start storing data
+ * @param count The number of bytes to read into the buffer
+ *
+ * @exception EOFException If end of file is reached before filling
+ * the buffer
+ * @exception IOException If any other error occurs
+ */
+ public final void readFully (byte[] buffer, int offset, int count)
+ throws IOException
+ {
+ in.readFully (buffer, offset, count);
+ }
+
+ /**
+ * This method reads a Java <code>int</code> value from an input stream
+ * It operates by reading four bytes from the stream and converting them to
+ * a single Java <code>int</code> The bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> through <code>byte4</code>
+ * represent the first
+ * four bytes read from the stream, they will be
+ * transformed to an <code>int</code> in the following manner:
+ * <p>
+ * <code>(int)(((byte1 &amp; 0xFF) &lt;&lt; 24) + ((byte2 &amp; 0xFF) &lt;&lt; 16) +
+ * ((byte3 &amp; 0xFF) &lt;&lt; 8) + (byte4 &amp; 0xFF)))</code>
+ * <p>
+ * The value returned is in the range of 0 to 65535.
+ * <p>
+ * This method can read an <code>int</code> written by an object
+ * implementing the
+ * <code>writeInt()</code> method in the <code>DataOutput</code> interface.
+ *
+ * @return The <code>int</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the int
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput
+ */
+ public final int readInt () throws IOException
+ {
+ return in.readInt();
+ }
+
+ /**
+ * This method reads the next line of text data from an input stream.
+ * It operates by reading bytes and converting those bytes to
+ * <code>char</code>
+ * values by treating the byte read as the low eight bits of the
+ * <code>char</code>
+ * and using <code>0</code> as the high eight bits. Because of this, it does
+ * not support the full 16-bit Unicode character set.
+ * <p>
+ * The reading of bytes ends when either the end of file or a line terminator
+ * is encountered. The bytes read are then returned as a <code>String</code>
+ * A line terminator is a byte sequence consisting of either
+ * <code>\r</code> <code>\n</code> or <code>\r\n</code> These
+ * termination charaters are
+ * discarded and are not returned as part of the string.
+ * <p>
+ * This method can read data that was written by an object implementing the
+ * <code>writeLine()</code> method in <code>DataOutput</code>
+ *
+ * @return The line read as a <code>String</code>
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see DataOutput
+ */
+ public final String readLine () throws IOException
+ {
+ return in.readLine ();
+ }
+
+ /**
+ * This method reads a Java long value from an input stream
+ * It operates by reading eight bytes from the stream and converting them to
+ * a single Java <code>long</code> The bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> through <code>byte8</code>
+ * represent the first
+ * eight bytes read from the stream, they will be
+ * transformed to an <code>long</code> in the following manner:
+ * <p>
+ * <code>
+ * (long)((((long)byte1 &amp; 0xFF) &lt;&lt; 56) + (((long)byte2 &amp; 0xFF) &lt;&lt; 48) +
+ * (((long)byte3 &amp; 0xFF) &lt;&lt; 40) + (((long)byte4 &amp; 0xFF) &lt;&lt; 32) +
+ * (((long)byte5 &amp; 0xFF) &lt;&lt; 24) + (((long)byte6 &amp; 0xFF) &lt;&lt; 16) +
+ * (((long)byte7 &amp; 0xFF) &lt;&lt; 8) + ((long)byte9 &amp; 0xFF)))</code>
+ * <p>
+ * The value returned is in the range of 0 to 65535.
+ * <p>
+ * This method can read an <code>long</code> written by an object
+ * implementing the
+ * <code>writeLong()</code> method in the <code>DataOutput</code> interface.
+ *
+ * @return The <code>long</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the long
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput
+ */
+ public final long readLong () throws IOException
+ {
+ return in.readLong();
+ }
+
+ /**
+ * This method reads a signed 16-bit value into a Java in from the stream.
+ * It operates by reading two bytes from the stream and converting them to
+ * a single 16-bit Java <code>short</code> The two bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code>
+ * represent the first
+ * and second byte read from the stream respectively, they will be
+ * transformed to a <code>short</code> in the following manner:
+ * <p>
+ * <code>(short)(((byte1 &amp; 0xFF) &lt;&lt; 8) | (byte2 &amp; 0xFF)</code>
+ * <p>
+ * The value returned is in the range of -32768 to 32767.
+ * <p>
+ * This method can read a <code>short</code> written by an object
+ * implementing the
+ * <code>writeShort()</code> method in the <code>DataOutput</code> interface.
+ *
+ * @return The <code>short</code> value read
+ *
+ * @exception EOFException If end of file is reached before reading the value
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput
+ */
+ public final short readShort () throws IOException
+ {
+ return in.readShort();
+ }
+
+ /**
+ * This method reads 8 unsigned bits into a Java <code>int</code> value
+ * from the
+ * stream. The value returned is in the range of 0 to 255.
+ * <p>
+ * This method can read an unsigned byte written by an object implementing
+ * the <code>writeUnsignedByte()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The unsigned bytes value read as a Java <code>int</code>
+ *
+ * @exception EOFException If end of file is reached before reading the value
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput
+ */
+ public final int readUnsignedByte () throws IOException
+ {
+ return in.readUnsignedByte();
+ }
+
+ /**
+ * This method reads 16 unsigned bits into a Java int value from the stream.
+ * It operates by reading two bytes from the stream and converting them to
+ * a single Java <code>int</code> The two bytes are stored most
+ * significant byte first (i.e., "big endian") regardless of the native
+ * host byte ordering.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code>
+ * represent the first
+ * and second byte read from the stream respectively, they will be
+ * transformed to an <code>int</code> in the following manner:
+ * <p>
+ * <code>(int)(((byte1 &amp; 0xFF) &lt;&lt; 8) + (byte2 &amp; 0xFF))</code>
+ * <p>
+ * The value returned is in the range of 0 to 65535.
+ * <p>
+ * This method can read an unsigned short written by an object implementing
+ * the <code>writeUnsignedShort()</code> method in the
+ * <code>DataOutput</code> interface.
+ *
+ * @return The unsigned short value read as a Java <code>int</code>
+ *
+ * @exception EOFException If end of file is reached before reading the value
+ * @exception IOException If any other error occurs
+ */
+ public final int readUnsignedShort () throws IOException
+ {
+ return in.readUnsignedShort();
+ }
+
+ /**
+ * This method reads a <code>String</code> from an input stream that
+ * is encoded in
+ * a modified UTF-8 format. This format has a leading two byte sequence
+ * that contains the remaining number of bytes to read. This two byte
+ * sequence is read using the <code>readUnsignedShort()</code> method of this
+ * interface.
+ * <p>
+ * After the number of remaining bytes have been determined, these bytes
+ * are read an transformed into <code>char</code> values.
+ * These <code>char</code> values
+ * are encoded in the stream using either a one, two, or three byte format.
+ * The particular format in use can be determined by examining the first
+ * byte read.
+ * <p>
+ * If the first byte has a high order bit of 0 then
+ * that character consists on only one byte. This character value consists
+ * of seven bits that are at positions 0 through 6 of the byte. As an
+ * example, if <code>byte1</code> is the byte read from the stream, it would
+ * be converted to a <code>char</code> like so:
+ * <p>
+ * <code>(char)byte1</code>
+ * <p>
+ * If the first byte has <code>110</code> as its high order bits, then the
+ * character consists of two bytes. The bits that make up the character
+ * value are in positions 0 through 4 of the first byte and bit positions
+ * 0 through 5 of the second byte. (The second byte should have
+ * 10 as its high order bits). These values are in most significant
+ * byte first (i.e., "big endian") order.
+ * <p>
+ * As an example, if <code>byte1</code> and <code>byte2</code>
+ * are the first two bytes
+ * read respectively, and the high order bits of them match the patterns
+ * which indicate a two byte character encoding, then they would be
+ * converted to a Java <code>char</code> like so:
+ * <p>
+ * <code>(char)(((byte1 & 0x1F) << 6) | (byte2 & 0x3F))</code>
+ * <p>
+ * If the first byte has a <code>1110</code> as its high order bits, then the
+ * character consists of three bytes. The bits that make up the character
+ * value are in positions 0 through 3 of the first byte and bit positions
+ * 0 through 5 of the other two bytes. (The second and third bytes should
+ * have <code>10</code> as their high order bits). These values are in most
+ * significant byte first (i.e., "big endian") order.
+ * <p>
+ * As an example, if <code>byte1</code> <code>byte2</code>
+ * and <code>byte3</code> are the
+ * three bytes read, and the high order bits of them match the patterns
+ * which indicate a three byte character encoding, then they would be
+ * converted to a Java <code>char</code> like so:
+ * <p>
+ * <code>(char)(((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) |
+ * (byte3 & 0x3F))</code>
+ * <p>
+ * Note that all characters are encoded in the method that requires the
+ * fewest number of bytes with the exception of the character with the
+ * value of <code>&#92;u0000</code> which is encoded as two bytes. This is
+ * a modification of the UTF standard used to prevent C language style
+ * <code>NUL</code> values from appearing in the byte stream.
+ * <p>
+ * This method can read data that was written by an object implementing the
+ * <code>writeUTF()</code> method in <code>DataOutput</code>
+ *
+ * @return The <code>String</code> read
+ *
+ * @exception EOFException If end of file is reached before reading the
+ * String
+ * @exception UTFDataFormatException If the data is not in UTF-8 format
+ * @exception IOException If any other error occurs
+ *
+ * @see DataOutput
+ */
+ public final String readUTF () throws IOException
+ {
+ return in.readUTF();
+ }
+
+ /**
+ * This method sets the current file position to the specified offset
+ * from the beginning of the file. Note that some operating systems will
+ * allow the file pointer to be set past the current end of the file.
+ *
+ * @param pos The offset from the beginning of the file at which to set
+ * the file pointer
+ *
+ * @exception IOException If an error occurs
+ */
+ public void seek (long pos) throws IOException
+ {
+ ch.position(pos);
+ }
+
+ /**
+ * This method attempts to skip and discard the specified number of bytes
+ * in the input stream. It may actually skip fewer bytes than requested.
+ * The actual number of bytes skipped is returned. This method will not
+ * skip any bytes if passed a negative number of bytes to skip.
+ *
+ * @param numBytes The requested number of bytes to skip.
+ *
+ * @return The number of bytes actually skipped.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public int skipBytes (int numBytes) throws IOException
+ {
+ if (numBytes < 0)
+ throw new IllegalArgumentException ("Can't skip negative bytes: " +
+ numBytes);
+
+ if (numBytes == 0)
+ return 0;
+
+ long oldPos = ch.position();
+ long newPos = oldPos + numBytes;
+ long size = ch.size();
+ if (newPos > size)
+ newPos = size;
+ ch.position(newPos);
+ return (int) (ch.position() - oldPos);
+ }
+
+ /**
+ * This method writes a single byte of data to the file. The file must
+ * be open for read-write in order for this operation to succeed.
+ *
+ * @param oneByte The byte of data to write, passed as an int.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (int oneByte) throws IOException
+ {
+ out.write(oneByte);
+ }
+
+ /**
+ * This method writes all the bytes in the specified array to the file.
+ * The file must be open read-write in order for this operation to succeed.
+ *
+ * @param buffer The array of bytes to write to the file
+ */
+ public void write (byte[] buffer) throws IOException
+ {
+ out.write(buffer);
+ }
+
+ /**
+ * This method writes <code>len</code> bytes to the file from the specified
+ * array starting at index <code>offset</code> into the array.
+ *
+ * @param buffer The array of bytes to write to the file
+ * @param offset The index into the array to start writing file
+ * @param len The number of bytes to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write (byte[] buffer, int offset, int len) throws IOException
+ {
+ out.write (buffer, offset, len);
+ }
+
+ /**
+ * This method writes a Java <code>boolean</code> to the underlying output
+ * stream. For a value of <code>true</code>, 1 is written to the stream.
+ * For a value of <code>false</code>, 0 is written.
+ *
+ * @param val The <code>boolean</code> value to write to the stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeBoolean (boolean val) throws IOException
+ {
+ out.writeBoolean(val);
+ }
+
+ /**
+ * This method writes a Java <code>byte</code> value to the underlying
+ * output stream.
+ *
+ * @param val The <code>byte</code> to write to the stream, passed
+ * as an <code>int</code>.
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeByte (int val) throws IOException
+ {
+ out.writeByte(val);
+ }
+
+ /**
+ * This method writes a Java <code>short</code> to the stream, high byte
+ * first. This method requires two bytes to encode the value.
+ *
+ * @param val The <code>short</code> value to write to the stream,
+ * passed as an <code>int</code>.
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeShort (int val) throws IOException
+ {
+ out.writeShort(val);
+ }
+
+ /**
+ * This method writes a single <code>char</code> value to the stream,
+ * high byte first.
+ *
+ * @param val The <code>char</code> value to write, passed as
+ * an <code>int</code>.
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeChar (int val) throws IOException
+ {
+ out.writeChar(val);
+ }
+
+ /**
+ * This method writes a Java <code>int</code> to the stream, high bytes
+ * first. This method requires four bytes to encode the value.
+ *
+ * @param val The <code>int</code> value to write to the stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeInt (int val) throws IOException
+ {
+ out.writeInt(val);
+ }
+
+ /**
+ * This method writes a Java <code>long</code> to the stream, high bytes
+ * first. This method requires eight bytes to encode the value.
+ *
+ * @param val The <code>long</code> value to write to the stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeLong (long val) throws IOException
+ {
+ out.writeLong(val);
+ }
+
+ /**
+ * This method writes a Java <code>float</code> value to the stream. This
+ * value is written by first calling the method
+ * <code>Float.floatToIntBits</code>
+ * to retrieve an <code>int</code> representing the floating point number,
+ * then writing this <code>int</code> value to the stream exactly the same
+ * as the <code>writeInt()</code> method does.
+ *
+ * @param val The floating point number to write to the stream.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see #writeInt(int)
+ */
+ public final void writeFloat (float val) throws IOException
+ {
+ out.writeFloat(val);
+ }
+
+ /**
+ * This method writes a Java <code>double</code> value to the stream. This
+ * value is written by first calling the method
+ * <code>Double.doubleToLongBits</code>
+ * to retrieve an <code>long</code> representing the floating point number,
+ * then writing this <code>long</code> value to the stream exactly the same
+ * as the <code>writeLong()</code> method does.
+ *
+ * @param val The double precision floating point number to write to the
+ * stream.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @see #writeLong(long)
+ */
+ public final void writeDouble (double val) throws IOException
+ {
+ out.writeDouble(val);
+ }
+
+ /**
+ * This method writes all the bytes in a <code>String</code> out to the
+ * stream. One byte is written for each character in the <code>String</code>.
+ * The high eight bits of each character are discarded.
+ *
+ * @param val The <code>String</code> to write to the stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeBytes (String val) throws IOException
+ {
+ out.writeBytes(val);
+ }
+
+ /**
+ * This method writes all the characters in a <code>String</code> to the
+ * stream. There will be two bytes for each character value. The high
+ * byte of the character will be written first.
+ *
+ * @param val The <code>String</code> to write to the stream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeChars (String val) throws IOException
+ {
+ out.writeChars(val);
+ }
+
+ /**
+ * This method writes a Java <code>String</code> to the stream in a modified
+ * UTF-8 format. First, two bytes are written to the stream indicating the
+ * number of bytes to follow. Note that this is the number of bytes in the
+ * encoded <code>String</code> not the <code>String</code> length. Next
+ * come the encoded characters. Each character in the <code>String</code>
+ * is encoded as either one, two or three bytes. For characters in the
+ * range of <code>&#92;u0001</code> to <code>&#92;u007F</code>,
+ * one byte is used. The character
+ * value goes into bits 0-7 and bit eight is 0. For characters in the range
+ * of <code>&#92;u0080</code> to <code>&#92;u007FF</code>, two
+ * bytes are used. Bits
+ * 6-10 of the character value are encoded bits 0-4 of the first byte, with
+ * the high bytes having a value of "110". Bits 0-5 of the character value
+ * are stored in bits 0-5 of the second byte, with the high bits set to
+ * "10". This type of encoding is also done for the null character
+ * <code>&#92;u0000</code>. This eliminates any C style NUL character values
+ * in the output. All remaining characters are stored as three bytes.
+ * Bits 12-15 of the character value are stored in bits 0-3 of the first
+ * byte. The high bits of the first bytes are set to "1110". Bits 6-11
+ * of the character value are stored in bits 0-5 of the second byte. The
+ * high bits of the second byte are set to "10". And bits 0-5 of the
+ * character value are stored in bits 0-5 of byte three, with the high bits
+ * of that byte set to "10".
+ *
+ * @param val The <code>String</code> to write to the output in UTF format
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void writeUTF (String val) throws IOException
+ {
+ out.writeUTF(val);
+ }
+
+ /**
+ * This method creates a java.nio.channels.FileChannel.
+ * Nio does not allow one to create a file channel directly.
+ * A file channel must be created by first creating an instance of
+ * Input/Output/RandomAccessFile and invoking the getChannel() method on it.
+ */
+ public final synchronized FileChannel getChannel ()
+ {
+ return ch;
+ }
+}
diff --git a/libjava/classpath/java/io/Reader.java b/libjava/classpath/java/io/Reader.java
new file mode 100644
index 00000000000..7970d9a2434
--- /dev/null
+++ b/libjava/classpath/java/io/Reader.java
@@ -0,0 +1,271 @@
+/* Reader.java -- base class of classes that read input as a stream of chars
+ Copyright (C) 1998, 1999, 2000, 2003 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.io;
+
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This abstract class forms the base of the hierarchy of classes that read
+ * input as a stream of characters. It provides a common set of methods for
+ * reading characters from streams. Subclasses implement and extend these
+ * methods to read characters from a particular input source such as a file
+ * or network connection.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @date April 21, 1998.
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class Reader
+{
+ /**
+ * This is the <code>Object</code> used for synchronizing critical code
+ * sections. Subclasses should use this variable instead of a
+ * synchronized method or an explicit synchronization on <code>this</code>
+ */
+ protected Object lock;
+
+ /**
+ * Unitializes a <code>Reader</code> that will use the object
+ * itself for synchronization of critical code sections.
+ */
+ protected Reader()
+ {
+ this.lock = this;
+ }
+
+ /**
+ * Initializes a <code>Reader</code> that will use the specified
+ * <code>Object</code> for synchronization of critical code sections.
+ *
+ * @param lock The <code>Object</code> to use for synchronization
+ */
+ protected Reader(Object lock)
+ {
+ this.lock = lock;
+ }
+
+ /**
+ * Read chars from a stream and stores them into a caller
+ * supplied buffer. It starts storing the data at index <code>offset</code>
+ * into the buffer and attempts to read <code>len</code> chars. This method
+ * can return before reading the number of chars requested. The actual
+ * number of chars read is returned as an int. A -1 is returned to indicate
+ * the end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * This method operates by calling the single char <code>read()</code> method
+ * in a loop until the desired number of chars are read. The read loop
+ * stops short if the end of the stream is encountered or if an IOException
+ * is encountered on any read operation except the first. If the first
+ * attempt to read a chars fails, the IOException is allowed to propagate
+ * upward. And subsequent IOException is caught and treated identically
+ * to an end of stream condition. Subclasses can (and should if possible)
+ * override this method to provide a more efficient implementation.
+ *
+ * @param buf The array into which the chars read should be stored
+ * @param offset The offset into the array to start storing chars
+ * @param count The requested number of chars to read
+ *
+ * @return The actual number of chars read, or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public abstract int read(char buf[], int offset, int count)
+ throws IOException;
+
+ /**
+ * Reads chars from a stream and stores them into a caller
+ * supplied buffer. This method attempts to completely fill the buffer,
+ * but can return before doing so. The actual number of chars read is
+ * returned as an int. A -1 is returned to indicate the end of the stream.
+ * <p>
+ * This method will block until some data can be read.
+ * <p>
+ * This method operates by calling an overloaded read method like so:
+ * <code>read(buf, 0, buf.length)</code>
+ *
+ * @param buf The buffer into which the chars read will be stored.
+ *
+ * @return The number of chars read or -1 if end of stream.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public int read(char buf[]) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ /**
+ * Reads an char from the input stream and returns it
+ * as an int in the range of 0-65535. This method also will return -1 if
+ * the end of the stream has been reached.
+ * <p>
+ * This method will block until the char can be read.
+ *
+ * @return The char read or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ char[] buf = new char[1];
+ int count = read(buf, 0, 1);
+ return count > 0 ? buf[0] : -1;
+ }
+
+ /**
+ * Closes the stream. Any futher attempts to read from the
+ * stream may generate an <code>IOException</code>.
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract void close() throws IOException;
+
+ /**
+ * Returns a boolean that indicates whether the mark/reset
+ * methods are supported in this class. Those methods can be used to
+ * remember a specific point in the stream and reset the stream to that
+ * point.
+ * <p>
+ * This method always returns <code>false</code> in this class, but
+ * subclasses can override this method to return <code>true</code> if they
+ * support mark/reset functionality.
+ *
+ * @return <code>true</code> if mark/reset functionality is supported,
+ * <code>false</code> otherwise
+ *
+ */
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ /**
+ * Marks a position in the input to which the stream can be
+ * "reset" by calling the <code>reset()</code> method. The parameter
+ * <code>readlimit</code> is the number of chars that can be read from the
+ * stream after setting the mark before the mark becomes invalid. For
+ * example, if <code>mark()</code> is called with a read limit of 10, then
+ * when 11 chars of data are read from the stream before the
+ * <code>reset()</code> method is called, then the mark is invalid and the
+ * stream object instance is not required to remember the mark.
+ *
+ * @param readLimit The number of chars that can be read before the mark
+ * becomes invalid
+ *
+ * @exception IOException If an error occurs such as mark not being
+ * supported for this class
+ */
+ public void mark(int readLimit) throws IOException
+ {
+ throw new IOException("mark not supported");
+ }
+
+ /**
+ * Resets a stream to the point where the <code>mark()</code>
+ * method was called. Any chars that were read after the mark point was
+ * set will be re-read during subsequent reads.
+ * <p>
+ * This method always throws an IOException in this class, but subclasses
+ * can override this method if they provide mark/reset functionality.
+ *
+ * @exception IOException Always thrown for this class
+ */
+ public void reset() throws IOException
+ {
+ throw new IOException("reset not supported");
+ }
+
+ /**
+ * Determines whether or not this stream is ready to be
+ * read. If it returns <code>false</code> the stream may block if a
+ * read is attempted, but it is not guaranteed to do so.
+ * <p>
+ * This method always returns <code>false</code> in this class
+ *
+ * @return <code>true</code> if the stream is ready to be read,
+ * <code>false</code> otherwise.
+ *
+ * @exception IOException If an error occurs
+ */
+ public boolean ready() throws IOException
+ {
+ return false;
+ }
+
+ /**
+ * Skips the specified number of chars in the stream. It
+ * returns the actual number of chars skipped, which may be less than the
+ * requested amount.
+ * <p>
+ * This method reads and discards chars into a 256 char array until the
+ * specified number of chars were skipped or until either the end of stream
+ * is reached or a read attempt returns a short count. Subclasses can
+ * override this method to provide a more efficient implementation where
+ * one exists.
+ *
+ * @param count The requested number of chars to skip
+ *
+ * @return The actual number of chars skipped.
+ *
+ * @exception IOException If an error occurs
+ */
+ public long skip(long count) throws IOException
+ {
+ if (count <= 0)
+ return 0;
+ int bsize = count > 1024 ? 1024 : (int) count;
+ char[] buffer = new char[bsize];
+ long todo = count;
+ synchronized (lock)
+ {
+ while (todo > 0)
+ {
+ int skipped = read(buffer, 0, bsize > todo ? (int) todo : bsize);
+ if (skipped <= 0)
+ break;
+ todo -= skipped;
+ }
+ }
+ return count - todo;
+ }
+}
diff --git a/libjava/classpath/java/io/SequenceInputStream.java b/libjava/classpath/java/io/SequenceInputStream.java
new file mode 100644
index 00000000000..7fefe243263
--- /dev/null
+++ b/libjava/classpath/java/io/SequenceInputStream.java
@@ -0,0 +1,221 @@
+/* SequenceInputStream.java -- Reads multiple input streams in sequence
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+import java.util.Enumeration;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This class merges a sequence of multiple <code>InputStream</code>'s in
+ * order to form a single logical stream that can be read by applications
+ * that expect only one stream.
+ * <p>
+ * The streams passed to the constructor method are read in order until
+ * they return -1 to indicate they are at end of stream. When a stream
+ * reports end of stream, it is closed, then the next stream is read.
+ * When the last stream is closed, the next attempt to read from this
+ * stream will return a -1 to indicate it is at end of stream.
+ * <p>
+ * If this stream is closed prior to all subordinate streams being read
+ * to completion, all subordinate streams are closed.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class SequenceInputStream extends InputStream
+{
+ /** The handle for the current input stream. */
+ private InputStream in;
+
+ /** Secondary input stream; not used if constructed w/ enumeration. */
+ private InputStream in2;
+
+ /** The enumeration handle; not used if constructed w/ 2 explicit input streams. */
+ private Enumeration e;
+
+ /**
+ * This method creates a new <code>SequenceInputStream</code> that obtains
+ * its list of subordinate <code>InputStream</code>s from the specified
+ * <code>Enumeration</code>
+ *
+ * @param e An <code>Enumeration</code> that will return a list of
+ * <code>InputStream</code>s to read in sequence
+ */
+ public SequenceInputStream(Enumeration e)
+ {
+ this.e = e;
+ in = (InputStream) e.nextElement();
+ in2 = null;
+ }
+
+ /**
+ * This method creates a new <code>SequenceInputStream</code> that will read
+ * the two specified subordinate <code>InputStream</code>s in sequence.
+ *
+ * @param s1 The first <code>InputStream</code> to read
+ * @param s2 The second <code>InputStream</code> to read
+ */
+ public SequenceInputStream(InputStream s1, InputStream s2)
+ {
+ in = s1;
+ in2 = s2;
+ }
+
+ /**
+ * This method returns the number of bytes than can be read from the
+ * currently being read subordinate stream before that stream could
+ * block. Note that it is possible more bytes than this can actually
+ * be read without the stream blocking. If a 0 is returned, then the
+ * stream could block on the very next read.
+ *
+ * @return The number of bytes that can be read before blocking could occur
+ *
+ * @exception IOException If an error occurs
+ */
+ public int available() throws IOException
+ {
+ if (in == null)
+ return 0;
+
+ return in.available();
+ }
+
+ /**
+ * Closes this stream. This will cause any remaining unclosed subordinate
+ * <code>InputStream</code>'s to be closed as well. Subsequent attempts to
+ * read from this stream may cause an exception.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ while (in != null)
+ {
+ in.close();
+ in = getNextStream ();
+ }
+ }
+
+ /**
+ * This method reads an unsigned byte from the input stream and returns it
+ * as an int in the range of 0-255. This method also will return -1 if
+ * the end of the stream has been reached. This will only happen when
+ * all of the subordinate streams have been read.
+ * <p>
+ * This method will block until the byte can be read.
+ *
+ * @return The byte read, or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read() throws IOException
+ {
+ int ch = -1;
+
+ while (in != null && (ch = in.read()) < 0)
+ {
+ in.close();
+ in = getNextStream();
+ }
+
+ return ch;
+ }
+
+ /**
+ * This method reads bytes from a stream and stores them into a caller
+ * supplied buffer. It starts storing the data at index <code>offset</code>
+ * into the buffer and attempts to read <code>len</code> bytes. This method
+ * can return before reading the number of bytes requested. The actual number
+ * of bytes read is returned as an int. A -1 is returend to indicate the
+ * end of the stream. This will only happen when all of the subordinate
+ * streams have been read.
+ * <p>
+ * This method will block until at least one byte can be read.
+ *
+ * @param b The array into which bytes read should be stored
+ * @param off The offset into the array to start storing bytes
+ * @param len The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of stream
+ *
+ * @exception IOException If an error occurs
+ */
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ int ch = -1;
+
+ // The validity of the parameters will be checked by in.read so
+ // don't bother doing it here.
+ while (in != null && (ch = in.read(b, off, len)) < 0)
+ {
+ in.close();
+ in = getNextStream();
+ }
+
+ return ch;
+ }
+
+ /**
+ * This private method is used to get the next <code>InputStream</code> to
+ * read from. Returns null when no more streams are available.
+ */
+ private InputStream getNextStream()
+ {
+ InputStream nextIn = null;
+
+ if (e != null)
+ {
+ if (e.hasMoreElements())
+ nextIn = (InputStream) e.nextElement();
+ }
+ else
+ if (in2 != null)
+ {
+ nextIn = in2;
+ in2 = null;
+ }
+
+ return nextIn;
+ }
+}
diff --git a/libjava/classpath/java/io/Serializable.java b/libjava/classpath/java/io/Serializable.java
new file mode 100644
index 00000000000..a6d99f6d522
--- /dev/null
+++ b/libjava/classpath/java/io/Serializable.java
@@ -0,0 +1,54 @@
+/* Serializable.java -- Interface to indicate a class may be serialized
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * Status: Believed complete
+ */
+
+/**
+ * This interface has no methods. It simply serves to indicate that
+ * the implementing class may be serialized.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public interface Serializable
+{
+} // interface Serializable
diff --git a/libjava/classpath/java/io/SerializablePermission.java b/libjava/classpath/java/io/SerializablePermission.java
new file mode 100644
index 00000000000..b5c07e4ec2c
--- /dev/null
+++ b/libjava/classpath/java/io/SerializablePermission.java
@@ -0,0 +1,113 @@
+/* SerializablePermission.java -- Basic permissions related to serialization.
+ Copyright (C) 1998, 2000, 2003 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.io;
+
+import java.security.BasicPermission;
+
+/**
+ * This class models permissions related to serialization. As a subclass
+ * of <code>BasicPermission</code>, this class has permissions that have
+ * a name only. There is no associated action list.
+ * <p>
+ * There are currently two allowable permission names for this class:
+ * <ul>
+ * <li><code>enableSubclassImplementation</code> - Allows a subclass to
+ * override the default serialization behavior of objects.</li>
+ * <li><code>enableSubstitution</code> - Allows substitution of one object
+ * for another during serialization or deserialization.</li>
+ * </ul>
+ *
+ * @see java.security.BasicPermission
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public final class SerializablePermission extends BasicPermission
+{
+ static final long serialVersionUID = 8537212141160296410L;
+
+ /*
+ * Class Variables
+ */
+
+ private static final String[] legal_names = { "enableSubclassImplementation",
+ "enableSubstitution" };
+ /*
+ * Constructors
+ */
+
+ /**
+ * This method initializes a new instance of
+ * <code>SerializablePermission</code>
+ * that has the specified name.
+ *
+ * @param name The name of the permission.
+ *
+ * @exception IllegalArgumentException If the name is not valid for
+ * this class.
+ */
+ public SerializablePermission(String name)
+ {
+ this(name, null);
+ }
+
+ /**
+ * This method initializes a new instance of
+ * <code>SerializablePermission</code>
+ * that has the specified name and action list. Note that the action list
+ * is unused in this class.
+ *
+ * @param name The name of the permission.
+ * @param actions The action list (unused).
+ *
+ * @exception IllegalArgumentException If the name is not valid for
+ * this class.
+ */
+ public SerializablePermission(String name, String actions)
+ {
+ super(name, actions);
+
+ for (int i = 0; i < legal_names.length; i++)
+ if (legal_names[i].equals(name))
+ return;
+
+ throw new IllegalArgumentException("Bad permission name: " + name);
+ }
+
+} // class SerializablePermission
+
diff --git a/libjava/classpath/java/io/StreamCorruptedException.java b/libjava/classpath/java/io/StreamCorruptedException.java
new file mode 100644
index 00000000000..d24d12150c5
--- /dev/null
+++ b/libjava/classpath/java/io/StreamCorruptedException.java
@@ -0,0 +1,73 @@
+/* StreamCorruptedException.java -- Error in stream during serialization
+ Copyright (C) 1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown when there is an error in the data that is
+ * read from a stream during de-serialization.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class StreamCorruptedException extends ObjectStreamException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 8983558202217591746L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ public StreamCorruptedException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public StreamCorruptedException(String message)
+ {
+ super(message);
+ }
+} // class StreamCorruptedException
diff --git a/libjava/classpath/java/io/StreamTokenizer.java b/libjava/classpath/java/io/StreamTokenizer.java
new file mode 100644
index 00000000000..bd7773b1990
--- /dev/null
+++ b/libjava/classpath/java/io/StreamTokenizer.java
@@ -0,0 +1,708 @@
+/* StreamTokenizer.java -- parses streams of characters into tokens
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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.io;
+
+/**
+ * This class parses streams of characters into tokens. There are a
+ * million-zillion flags that can be set to control the parsing, as
+ * described under the various method headings.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @date October 25, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+public class StreamTokenizer
+{
+ /** A constant indicating that the end of the stream has been read. */
+ public static final int TT_EOF = -1;
+
+ /** A constant indicating that the end of the line has been read. */
+ public static final int TT_EOL = '\n';
+
+ /** A constant indicating that a number token has been read. */
+ public static final int TT_NUMBER = -2;
+
+ /** A constant indicating that a word token has been read. */
+ public static final int TT_WORD = -3;
+
+ /** A constant indicating that no tokens have been read yet. */
+ private static final int TT_NONE = -4;
+
+ /**
+ * Contains the type of the token read resulting from a call to nextToken
+ * The rules are as follows:
+ * <ul>
+ * <li>For a token consisting of a single ordinary character, this is the
+ * value of that character.</li>
+ * <li>For a quoted string, this is the value of the quote character</li>
+ * <li>For a word, this is TT_WORD</li>
+ * <li>For a number, this is TT_NUMBER</li>
+ * <li>For the end of the line, this is TT_EOL</li>
+ * <li>For the end of the stream, this is TT_EOF</li>
+ * </ul>
+ */
+ public int ttype = TT_NONE;
+
+ /** The String associated with word and string tokens. */
+ public String sval;
+
+ /** The numeric value associated with number tokens. */
+ public double nval;
+
+ /* Indicates whether end-of-line is recognized as a token. */
+ private boolean eolSignificant = false;
+
+ /* Indicates whether word tokens are automatically made lower case. */
+ private boolean lowerCase = false;
+
+ /* Indicates whether C++ style comments are recognized and skipped. */
+ private boolean slashSlash = false;
+
+ /* Indicates whether C style comments are recognized and skipped. */
+ private boolean slashStar = false;
+
+ /* Attribute tables of each byte from 0x00 to 0xFF. */
+ private boolean[] whitespace = new boolean[256];
+ private boolean[] alphabetic = new boolean[256];
+ private boolean[] numeric = new boolean[256];
+ private boolean[] quote = new boolean[256];
+ private boolean[] comment = new boolean[256];
+
+ /* The Reader associated with this class. */
+ private PushbackReader in;
+
+ /* Indicates if a token has been pushed back. */
+ private boolean pushedBack = false;
+
+ /* Contains the current line number of the reader. */
+ private int lineNumber = 1;
+
+ /**
+ * This method reads bytes from an <code>InputStream</code> and tokenizes
+ * them. For details on how this method operates by default, see
+ * <code>StreamTokenizer(Reader)</code>.
+ *
+ * @param is The <code>InputStream</code> to read from
+ *
+ * @deprecated Since JDK 1.1.
+ */
+ public StreamTokenizer(InputStream is)
+ {
+ this(new InputStreamReader(is));
+ }
+
+ /**
+ * This method initializes a new <code>StreamTokenizer</code> to read
+ * characters from a <code>Reader</code> and parse them. The char values
+ * have their hight bits masked so that the value is treated a character
+ * in the range of 0x0000 to 0x00FF.
+ * <p>
+ * This constructor sets up the parsing table to parse the stream in the
+ * following manner:
+ * <ul>
+ * <li>The values 'A' through 'Z', 'a' through 'z' and 0xA0 through 0xFF
+ * are initialized as alphabetic</li>
+ * <li>The values 0x00 through 0x20 are initialized as whitespace</li>
+ * <li>The values '\'' and '"' are initialized as quote characters</li>
+ * <li>'/' is a comment character</li>
+ * <li>Numbers will be parsed</li>
+ * <li>EOL is not treated as significant</li>
+ * <li>C and C++ (//) comments are not recognized</li>
+ * </ul>
+ *
+ * @param r The <code>Reader</code> to read chars from
+ */
+ public StreamTokenizer(Reader r)
+ {
+ in = new PushbackReader(r);
+
+ whitespaceChars(0x00, 0x20);
+ wordChars('A', 'Z');
+ wordChars('a', 'z');
+ wordChars(0xA0, 0xFF);
+ commentChar('/');
+ quoteChar('\'');
+ quoteChar('"');
+ parseNumbers();
+ }
+
+ /**
+ * This method sets the comment attribute on the specified
+ * character. Other attributes for the character are cleared.
+ *
+ * @param ch The character to set the comment attribute for, passed as an int
+ */
+ public void commentChar(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ {
+ comment[ch] = true;
+ whitespace[ch] = false;
+ alphabetic[ch] = false;
+ numeric[ch] = false;
+ quote[ch] = false;
+ }
+ }
+
+ /**
+ * This method sets a flag that indicates whether or not the end of line
+ * sequence terminates and is a token. The defaults to <code>false</code>
+ *
+ * @param flag <code>true</code> if EOF is significant, <code>false</code>
+ * otherwise
+ */
+ public void eolIsSignificant(boolean flag)
+ {
+ eolSignificant = flag;
+ }
+
+ /**
+ * This method returns the current line number. Note that if the
+ * <code>pushBack()</code> method is called, it has no effect on the
+ * line number returned by this method.
+ *
+ * @return The current line number
+ */
+ public int lineno()
+ {
+ return lineNumber;
+ }
+
+ /**
+ * This method sets a flag that indicates whether or not alphabetic
+ * tokens that are returned should be converted to lower case.
+ *
+ * @param flag <code>true</code> to convert to lower case,
+ * <code>false</code> otherwise
+ */
+ public void lowerCaseMode(boolean flag)
+ {
+ lowerCase = flag;
+ }
+
+ private boolean isWhitespace(int ch)
+ {
+ return (ch >= 0 && ch <= 255 && whitespace[ch]);
+ }
+
+ private boolean isAlphabetic(int ch)
+ {
+ return ((ch > 255) || (ch >= 0 && alphabetic[ch]));
+ }
+
+ private boolean isNumeric(int ch)
+ {
+ return (ch >= 0 && ch <= 255 && numeric[ch]);
+ }
+
+ private boolean isQuote(int ch)
+ {
+ return (ch >= 0 && ch <= 255 && quote[ch]);
+ }
+
+ private boolean isComment(int ch)
+ {
+ return (ch >= 0 && ch <= 255 && comment[ch]);
+ }
+
+ /**
+ * This method reads the next token from the stream. It sets the
+ * <code>ttype</code> variable to the appropriate token type and
+ * returns it. It also can set <code>sval</code> or <code>nval</code>
+ * as described below. The parsing strategy is as follows:
+ * <ul>
+ * <li>Skip any whitespace characters.</li>
+ * <li>If a numeric character is encountered, attempt to parse a numeric
+ * value. Leading '-' characters indicate a numeric only if followed by
+ * another non-'-' numeric. The value of the numeric token is terminated
+ * by either the first non-numeric encountered, or the second occurrence of
+ * '-' or '.'. The token type returned is TT_NUMBER and <code>nval</code>
+ * is set to the value parsed.</li>
+ * <li>If an alphabetic character is parsed, all subsequent characters
+ * are read until the first non-alphabetic or non-numeric character is
+ * encountered. The token type returned is TT_WORD and the value parsed
+ * is stored in <code>sval</code>. If lower case mode is set, the token
+ * stored in <code>sval</code> is converted to lower case. The end of line
+ * sequence terminates a word only if EOL signficance has been turned on.
+ * The start of a comment also terminates a word. Any character with a
+ * non-alphabetic and non-numeric attribute (such as white space, a quote,
+ * or a commet) are treated as non-alphabetic and terminate the word.</li>
+ * <li>If a comment character is parsed, then all remaining characters on
+ * the current line are skipped and another token is parsed. Any EOL or
+ * EOF's encountered are not discarded, but rather terminate the comment.</li>
+ * <li>If a quote character is parsed, then all characters up to the
+ * second occurrence of the same quote character are parsed into a
+ * <code>String</code>. This <code>String</code> is stored as
+ * <code>sval</code>, but is not converted to lower case, even if lower case
+ * mode is enabled. The token type returned is the value of the quote
+ * character encountered. Any escape sequences
+ * (\b (backspace), \t (HTAB), \n (linefeed), \f (form feed), \r
+ * (carriage return), \" (double quote), \' (single quote), \\
+ * (backslash), \XXX (octal esacpe)) are converted to the appropriate
+ * char values. Invalid esacape sequences are left in untranslated.
+ * Unicode characters like ('\ u0000') are not recognized. </li>
+ * <li>If the C++ comment sequence "//" is encountered, and the parser
+ * is configured to handle that sequence, then the remainder of the line
+ * is skipped and another token is read exactly as if a character with
+ * the comment attribute was encountered.</li>
+ * <li>If the C comment sequence "/*" is encountered, and the parser
+ * is configured to handle that sequence, then all characters up to and
+ * including the comment terminator sequence are discarded and another
+ * token is parsed.</li>
+ * <li>If all cases above are not met, then the character is an ordinary
+ * character that is parsed as a token by itself. The char encountered
+ * is returned as the token type.</li>
+ * </ul>
+ *
+ * @return The token type
+ * @exception IOException If an I/O error occurs
+ */
+ public int nextToken() throws IOException
+ {
+ if (pushedBack)
+ {
+ pushedBack = false;
+ if (ttype != TT_NONE)
+ return ttype;
+ }
+
+ sval = null;
+ int ch;
+
+ // Skip whitespace. Deal with EOL along the way.
+ while (isWhitespace(ch = in.read()))
+ if (ch == '\n' || ch == '\r')
+ {
+ lineNumber++;
+
+ // Throw away \n if in combination with \r.
+ if (ch == '\r' && (ch = in.read()) != '\n')
+ {
+ if (ch != TT_EOF)
+ in.unread(ch);
+ }
+ if (eolSignificant)
+ return (ttype = TT_EOL);
+ }
+
+ if (ch == '/')
+ if ((ch = in.read()) == '/' && slashSlash)
+ {
+ while ((ch = in.read()) != '\n' && ch != '\r' && ch != TT_EOF)
+ ;
+ if (ch != TT_EOF)
+ in.unread(ch);
+ return nextToken(); // Recursive, but not too deep in normal cases
+ }
+ else if (ch == '*' && slashStar)
+ {
+ while (true)
+ {
+ ch = in.read();
+ if (ch == '*')
+ {
+ if ((ch = in.read()) == '/')
+ break;
+ else if (ch != TT_EOF)
+ in.unread(ch);
+ }
+ else if (ch == '\n' || ch == '\r')
+ {
+ lineNumber++;
+ if (ch == '\r' && (ch = in.read()) != '\n')
+ {
+ if (ch != TT_EOF)
+ in.unread(ch);
+ }
+ }
+ else if (ch == TT_EOF)
+ {
+ break;
+ }
+ }
+ return nextToken(); // Recursive, but not too deep in normal cases
+ }
+ else
+ {
+ if (ch != TT_EOF)
+ in.unread(ch);
+ ch = '/';
+ }
+
+ if (ch == TT_EOF)
+ ttype = TT_EOF;
+ else if (isNumeric(ch))
+ {
+ boolean isNegative = false;
+ if (ch == '-')
+ {
+ // Read ahead to see if this is an ordinary '-' rather than numeric.
+ ch = in.read();
+ if (isNumeric(ch) && ch != '-')
+ {
+ isNegative = true;
+ }
+ else
+ {
+ if (ch != TT_EOF)
+ in.unread(ch);
+ return (ttype = '-');
+ }
+ }
+
+ StringBuffer tokbuf = new StringBuffer();
+ tokbuf.append((char) ch);
+
+ int decCount = 0;
+ while (isNumeric(ch = in.read()) && ch != '-')
+ if (ch == '.' && decCount++ > 0)
+ break;
+ else
+ tokbuf.append((char) ch);
+
+ if (ch != TT_EOF)
+ in.unread(ch);
+ ttype = TT_NUMBER;
+ try
+ {
+ nval = Double.valueOf(tokbuf.toString()).doubleValue();
+ }
+ catch (NumberFormatException _)
+ {
+ nval = 0.0;
+ }
+ if (isNegative)
+ nval = -nval;
+ }
+ else if (isAlphabetic(ch))
+ {
+ StringBuffer tokbuf = new StringBuffer();
+ tokbuf.append((char) ch);
+ while (isAlphabetic(ch = in.read()) || isNumeric(ch))
+ tokbuf.append((char) ch);
+ if (ch != TT_EOF)
+ in.unread(ch);
+ ttype = TT_WORD;
+ sval = tokbuf.toString();
+ if (lowerCase)
+ sval = sval.toLowerCase();
+ }
+ else if (isComment(ch))
+ {
+ while ((ch = in.read()) != '\n' && ch != '\r' && ch != TT_EOF)
+ ;
+ if (ch != TT_EOF)
+ in.unread(ch);
+ return nextToken(); // Recursive, but not too deep in normal cases.
+ }
+ else if (isQuote(ch))
+ {
+ ttype = ch;
+ StringBuffer tokbuf = new StringBuffer();
+ while ((ch = in.read()) != ttype && ch != '\n' && ch != '\r' &&
+ ch != TT_EOF)
+ {
+ if (ch == '\\')
+ switch (ch = in.read())
+ {
+ case 'a': ch = 0x7;
+ break;
+ case 'b': ch = '\b';
+ break;
+ case 'f': ch = 0xC;
+ break;
+ case 'n': ch = '\n';
+ break;
+ case 'r': ch = '\r';
+ break;
+ case 't': ch = '\t';
+ break;
+ case 'v': ch = 0xB;
+ break;
+ case '\n': ch = '\n';
+ break;
+ case '\r': ch = '\r';
+ break;
+ case '\"':
+ case '\'':
+ case '\\':
+ break;
+ default:
+ int ch1, nextch;
+ if ((nextch = ch1 = ch) >= '0' && ch <= '7')
+ {
+ ch -= '0';
+ if ((nextch = in.read()) >= '0' && nextch <= '7')
+ {
+ ch = ch * 8 + nextch - '0';
+ if ((nextch = in.read()) >= '0' && nextch <= '7' &&
+ ch1 >= '0' && ch1 <= '3')
+ {
+ ch = ch * 8 + nextch - '0';
+ nextch = in.read();
+ }
+ }
+ }
+
+ if (nextch != TT_EOF)
+ in.unread(nextch);
+ }
+
+ tokbuf.append((char) ch);
+ }
+
+ // Throw away matching quote char.
+ if (ch != ttype && ch != TT_EOF)
+ in.unread(ch);
+
+ sval = tokbuf.toString();
+ }
+ else
+ {
+ ttype = ch;
+ }
+
+ return ttype;
+ }
+
+ private void resetChar(int ch)
+ {
+ whitespace[ch] = alphabetic[ch] = numeric[ch] = quote[ch] = comment[ch] =
+ false;
+ }
+
+ /**
+ * This method makes the specified character an ordinary character. This
+ * means that none of the attributes (whitespace, alphabetic, numeric,
+ * quote, or comment) will be set on this character. This character will
+ * parse as its own token.
+ *
+ * @param ch The character to make ordinary, passed as an int
+ */
+ public void ordinaryChar(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ resetChar(ch);
+ }
+
+ /**
+ * This method makes all the characters in the specified range, range
+ * terminators included, ordinary. This means the none of the attributes
+ * (whitespace, alphabetic, numeric, quote, or comment) will be set on
+ * any of the characters in the range. This makes each character in this
+ * range parse as its own token.
+ *
+ * @param low The low end of the range of values to set the whitespace
+ * attribute for
+ * @param hi The high end of the range of values to set the whitespace
+ * attribute for
+ */
+ public void ordinaryChars(int low, int hi)
+ {
+ if (low < 0)
+ low = 0;
+ if (hi > 255)
+ hi = 255;
+ for (int i = low; i <= hi; i++)
+ resetChar(i);
+ }
+
+ /**
+ * This method sets the numeric attribute on the characters '0' - '9' and
+ * the characters '.' and '-'.
+ */
+ public void parseNumbers()
+ {
+ for (int i = 0; i <= 9; i++)
+ numeric['0' + i] = true;
+
+ numeric['.'] = true;
+ numeric['-'] = true;
+ }
+
+ /**
+ * Puts the current token back into the StreamTokenizer so
+ * <code>nextToken</code> will return the same value on the next call.
+ * May cause the lineno method to return an incorrect value
+ * if lineno is called before the next call to nextToken.
+ */
+ public void pushBack()
+ {
+ pushedBack = true;
+ }
+
+ /**
+ * This method sets the quote attribute on the specified character.
+ * Other attributes for the character are cleared.
+ *
+ * @param ch The character to set the quote attribute for, passed as an int.
+ */
+ public void quoteChar(int ch)
+ {
+ if (ch >= 0 && ch <= 255)
+ {
+ quote[ch] = true;
+ comment[ch] = false;
+ whitespace[ch] = false;
+ alphabetic[ch] = false;
+ numeric[ch] = false;
+ }
+ }
+
+ /**
+ * This method removes all attributes (whitespace, alphabetic, numeric,
+ * quote, and comment) from all characters. It is equivalent to calling
+ * <code>ordinaryChars(0x00, 0xFF)</code>.
+ *
+ * @see #ordinaryChars(int, int)
+ */
+ public void resetSyntax()
+ {
+ ordinaryChars(0x00, 0xFF);
+ }
+
+ /**
+ * This method sets a flag that indicates whether or not "C++" language style
+ * comments ("//" comments through EOL ) are handled by the parser.
+ * If this is <code>true</code> commented out sequences are skipped and
+ * ignored by the parser. This defaults to <code>false</code>.
+ *
+ * @param flag <code>true</code> to recognized and handle "C++" style
+ * comments, <code>false</code> otherwise
+ */
+ public void slashSlashComments(boolean flag)
+ {
+ slashSlash = flag;
+ }
+
+ /**
+ * This method sets a flag that indicates whether or not "C" language style
+ * comments (with nesting not allowed) are handled by the parser.
+ * If this is <code>true</code> commented out sequences are skipped and
+ * ignored by the parser. This defaults to <code>false</code>.
+ *
+ * @param flag <code>true</code> to recognized and handle "C" style comments,
+ * <code>false</code> otherwise
+ */
+ public void slashStarComments(boolean flag)
+ {
+ slashStar = flag;
+ }
+
+ /**
+ * This method returns the current token value as a <code>String</code> in
+ * the form "Token[x], line n", where 'n' is the current line numbers and
+ * 'x' is determined as follows.
+ * <p>
+ * <ul>
+ * <li>If no token has been read, then 'x' is "NOTHING" and 'n' is 0</li>
+ * <li>If <code>ttype</code> is TT_EOF, then 'x' is "EOF"</li>
+ * <li>If <code>ttype</code> is TT_EOL, then 'x' is "EOL"</li>
+ * <li>If <code>ttype</code> is TT_WORD, then 'x' is <code>sval</code></li>
+ * <li>If <code>ttype</code> is TT_NUMBER, then 'x' is "n=strnval" where
+ * 'strnval' is <code>String.valueOf(nval)</code>.</li>
+ * <li>If <code>ttype</code> is a quote character, then 'x' is
+ * <code>sval</code></li>
+ * <li>For all other cases, 'x' is <code>ttype</code></li>
+ * </ul>
+ */
+ public String toString()
+ {
+ String tempstr;
+ if (ttype == TT_EOF)
+ tempstr = "EOF";
+ else if (ttype == TT_EOL)
+ tempstr = "EOL";
+ else if (ttype == TT_WORD)
+ tempstr = sval;
+ else if (ttype == TT_NUMBER)
+ tempstr = "n=" + nval;
+ else if (ttype == TT_NONE)
+ tempstr = "NOTHING";
+ else // must be an ordinary char.
+ tempstr = "\'" + (char) ttype + "\'";
+
+ return "Token[" + tempstr + "], line " + lineno();
+ }
+
+ /**
+ * This method sets the whitespace attribute for all characters in the
+ * specified range, range terminators included.
+ *
+ * @param low The low end of the range of values to set the whitespace
+ * attribute for
+ * @param hi The high end of the range of values to set the whitespace
+ * attribute for
+ */
+ public void whitespaceChars(int low, int hi)
+ {
+ if (low < 0)
+ low = 0;
+ if (hi > 255)
+ hi = 255;
+ for (int i = low; i <= hi; i++)
+ {
+ resetChar(i);
+ whitespace[i] = true;
+ }
+ }
+
+ /**
+ * This method sets the alphabetic attribute for all characters in the
+ * specified range, range terminators included.
+ *
+ * @param low The low end of the range of values to set the alphabetic
+ * attribute for
+ * @param hi The high end of the range of values to set the alphabetic
+ * attribute for
+ */
+ public void wordChars(int low, int hi)
+ {
+ if (low < 0)
+ low = 0;
+ if (hi > 255)
+ hi = 255;
+ for (int i = low; i <= hi; i++)
+ alphabetic[i] = true;
+ }
+}
diff --git a/libjava/classpath/java/io/StringBufferInputStream.java b/libjava/classpath/java/io/StringBufferInputStream.java
new file mode 100644
index 00000000000..090881985b8
--- /dev/null
+++ b/libjava/classpath/java/io/StringBufferInputStream.java
@@ -0,0 +1,187 @@
+/* StringBufferInputStream.java -- Read an String as a stream
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct. Deprecated in JDK 1.1.
+ */
+
+/**
+ * This class permits a <code>String</code> to be read as an input stream.
+ * The low eight bits of each character in the <code>String</code> are the
+ * bytes that are returned. The high eight bits of each character are
+ * discarded.
+ * <p>
+ * The mark/reset functionality in this class behaves differently than
+ * normal. The <code>mark()</code> method is always ignored and the
+ * <code>reset()</code> method always resets in stream to start reading from
+ * position 0 in the String. Note that since this method does not override
+ * <code>markSupported()</code> in <code>InputStream</code>, calling that
+ * method will return <code>false</code>.
+ * <p>
+ * Note that this class is deprecated because it does not properly handle
+ * 16-bit Java characters. It is provided for backwards compatibility only
+ * and should not be used for new development. The <code>StringReader</code>
+ * class should be used instead.
+ *
+ * @deprecated
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class StringBufferInputStream extends InputStream
+{
+ /** The String which is the input to this stream. */
+ protected String buffer;
+
+ /** Position of the next byte in buffer to be read. */
+ protected int pos = 0;
+
+ /** The length of the String buffer. */
+ protected int count;
+
+ /**
+ * Create a new <code>StringBufferInputStream</code> that will read bytes
+ * from the passed in <code>String</code>. This stream will read from the
+ * beginning to the end of the <code>String</code>.
+ *
+ * @param s The <code>String</code> this stream will read from.
+ */
+ public StringBufferInputStream(String s)
+ {
+ buffer = s;
+ count = s.length();
+ }
+
+ /**
+ * This method returns the number of bytes available to be read from this
+ * stream. The value returned will be equal to <code>count - pos</code>.
+ *
+ * @return The number of bytes that can be read from this stream before
+ * blocking, which is all of them
+ */
+ public int available()
+ {
+ return count - pos;
+ }
+
+ /**
+ * This method reads one byte from the stream. The <code>pos</code> counter
+ * is advanced to the next byte to be read. The byte read is returned as
+ * an int in the range of 0-255. If the stream position is already at the
+ * end of the buffer, no byte is read and a -1 is returned in order to
+ * indicate the end of the stream.
+ *
+ * @return The byte read, or -1 if end of stream
+ */
+ public int read()
+ {
+ if (pos >= count)
+ return -1; // EOF
+
+ return ((int) buffer.charAt(pos++)) & 0xFF;
+ }
+
+/**
+ * This method reads bytes from the stream and stores them into a caller
+ * supplied buffer. It starts storing the data at index <code>offset</code>
+ * into the buffer and attempts to read <code>len</code> bytes. This method
+ * can return before reading the number of bytes requested if the end of the
+ * stream is encountered first. The actual number of bytes read is
+ * returned. If no bytes can be read because the stream is already at
+ * the end of stream position, a -1 is returned.
+ * <p>
+ * This method does not block.
+ *
+ * @param b The array into which the bytes read should be stored.
+ * @param off The offset into the array to start storing bytes
+ * @param len The requested number of bytes to read
+ *
+ * @return The actual number of bytes read, or -1 if end of stream.
+ */
+ public int read(byte[] b, int off, int len)
+ {
+ if (off < 0 || len < 0 || off + len > b.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ if (pos >= count)
+ return -1; // EOF
+
+ int numRead = Math.min(len, count - pos);
+ if (numRead < 0)
+ return 0;
+
+ buffer.getBytes(pos, pos + numRead, b, off);
+ pos += numRead;
+ return numRead;
+ }
+
+ /**
+ * This method sets the read position in the stream to the beginning
+ * setting the <code>pos</code> variable equal to 0. Note that this differs
+ * from the common implementation of the <code>reset()</code> method.
+ */
+ public void reset()
+ {
+ pos = 0;
+ }
+
+ /**
+ * This method attempts to skip the requested number of bytes in the
+ * input stream. It does this by advancing the <code>pos</code> value by the
+ * specified number of bytes. It this would exceed the length of the
+ * buffer, then only enough bytes are skipped to position the stream at
+ * the end of the buffer. The actual number of bytes skipped is returned.
+ *
+ * @param n The requested number of bytes to skip
+ *
+ * @return The actual number of bytes skipped.
+ */
+ public long skip(long n)
+ {
+ if (n < 0)
+ return 0L;
+
+ long actualSkip = Math.min(n, count - pos);
+ pos += actualSkip;
+ return actualSkip;
+ }
+}
diff --git a/libjava/classpath/java/io/StringReader.java b/libjava/classpath/java/io/StringReader.java
new file mode 100644
index 00000000000..7e4e7d84f62
--- /dev/null
+++ b/libjava/classpath/java/io/StringReader.java
@@ -0,0 +1,209 @@
+/* StringReader.java -- permits a String to be read as a character input stream
+ Copyright (C) 1998, 1999, 2000, 2003 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.io;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct
+ */
+
+/**
+ * This class permits a <code>String</code> to be read as a character
+ * input stream.
+ * <p>
+ * The mark/reset functionality in this class behaves differently than
+ * normal. If no mark has been set, then calling the <code>reset()</code>
+ * method rewinds the read pointer to the beginning of the <code>String</code>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @date October 19, 1998.
+ */
+public class StringReader extends Reader
+{
+ /* A String provided by the creator of the stream. */
+ private String buf;
+
+ /* Position of the next char in buf to be read. */
+ private int pos;
+
+ /* The currently marked position in the stream. */
+ private int markedPos;
+
+ /* The index in buf one greater than the last valid character. */
+ private int count;
+
+ /**
+ * Create a new <code>StringReader</code> that will read chars from the
+ * passed in <code>String</code>. This stream will read from the beginning
+ * to the end of the <code>String</code>.
+ *
+ * @param buffer The <code>String</code> this stream will read from.
+ */
+ public StringReader(String buffer)
+ {
+ super();
+ buf = buffer;
+
+ count = buffer.length();
+ markedPos = pos = 0;
+ }
+
+ public void close()
+ {
+ synchronized (lock)
+ {
+ buf = null;
+ }
+ }
+
+ public void mark(int readAheadLimit) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ // readAheadLimit is ignored per Java Class Lib. book, p. 1692.
+ markedPos = pos;
+ }
+ }
+
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ public int read() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ if (pos < count)
+ return ((int) buf.charAt(pos++)) & 0xFFFF;
+ return -1;
+ }
+ }
+
+ public int read(char[] b, int off, int len) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ /* Don't need to check pos value, arraycopy will check it. */
+ if (off < 0 || len < 0 || off + len > b.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ if (pos >= count)
+ return -1;
+
+ int lastChar = Math.min(count, pos + len);
+ buf.getChars(pos, lastChar, b, off);
+ int numChars = lastChar - pos;
+ pos = lastChar;
+ return numChars;
+ }
+ }
+
+ /**
+ * This method determines if the stream is ready to be read. This class
+ * is always ready to read and so always returns <code>true</code>, unless
+ * close() has previously been called in which case an IOException is
+ * thrown.
+ *
+ * @return <code>true</code> to indicate that this object is ready to be read.
+ * @exception IOException If the stream is closed.
+ */
+ public boolean ready() throws IOException
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ return true;
+ }
+
+ /**
+ * Sets the read position in the stream to the previously
+ * marked position or to 0 (i.e., the beginning of the stream) if the mark
+ * has not already been set.
+ */
+ public void reset() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ pos = markedPos;
+ }
+ }
+
+ /**
+ * This method attempts to skip the requested number of chars in the
+ * input stream. It does this by advancing the <code>pos</code> value by
+ * the specified number of chars. It this would exceed the length of the
+ * buffer, then only enough chars are skipped to position the stream at
+ * the end of the buffer. The actual number of chars skipped is returned.
+ *
+ * @param n The requested number of chars to skip
+ *
+ * @return The actual number of chars skipped.
+ */
+ public long skip(long n) throws IOException
+ {
+ synchronized (lock)
+ {
+ if (buf == null)
+ throw new IOException("Stream closed");
+
+ // Even though the var numChars is a long, in reality it can never
+ // be larger than an int since the result of subtracting 2 positive
+ // ints will always fit in an int. Since we have to return a long
+ // anyway, numChars might as well just be a long.
+ long numChars = Math.min((long) (count - pos), n < 0 ? 0L : n);
+ pos += numChars;
+ return numChars;
+ }
+ }
+}
+
diff --git a/libjava/classpath/java/io/StringWriter.java b/libjava/classpath/java/io/StringWriter.java
new file mode 100644
index 00000000000..a1e9aeb6bd2
--- /dev/null
+++ b/libjava/classpath/java/io/StringWriter.java
@@ -0,0 +1,191 @@
+/* StringWriter.java -- Writes bytes to a StringBuffer
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+// Wow is this a dumb class. CharArrayWriter can do all this and
+// more. I would redirect all calls to one in fact, but the javadocs say
+// use a StringBuffer so I will comply.
+
+/**
+ * This class writes chars to an internal <code>StringBuffer</code> that
+ * can then be used to retrieve a <code>String</code>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class StringWriter extends Writer
+{
+ /**
+ * This is the default size of the buffer if the user doesn't specify it.
+ * @specnote The JCL Volume 1 says that 16 is the default size.
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 16;
+
+ /**
+ * This method closes the stream. The contents of the internal buffer
+ * can still be retrieved, but future writes are not guaranteed to work.
+ *
+ * @exception IOException If an error orrurs.
+ */
+ public void close () throws IOException
+ {
+ // JCL says this does nothing. This seems to violate the Writer
+ // contract, in that other methods should still throw an
+ // IOException after a close. Still, we just follow JCL.
+ }
+
+ /**
+ * This method flushes any buffered characters to the underlying output.
+ * It does nothing in this class.
+ */
+ public void flush ()
+ {
+ }
+
+ /**
+ * This method returns the <code>StringBuffer</code> object that this
+ * object is writing to. Note that this is the actual internal buffer, so
+ * any operations performed on it will affect this stream object.
+ *
+ * @return The <code>StringBuffer</code> object being written to
+ */
+ public StringBuffer getBuffer ()
+ {
+ return buffer;
+ }
+
+ /**
+ * This method initializes a new <code>StringWriter</code> to write to a
+ * <code>StringBuffer</code> initially sized to a default size of 16
+ * chars.
+ */
+ public StringWriter ()
+ {
+ this (DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * This method initializes a new <code>StringWriter</code> to write to a
+ * <code>StringBuffer</code> with the specified initial size.
+ *
+ * @param size The initial size to make the <code>StringBuffer</code>
+ */
+ public StringWriter (int size)
+ {
+ super ();
+ buffer = new StringBuffer (size);
+ lock = buffer;
+ }
+
+ /**
+ * This method returns the contents of the internal <code>StringBuffer</code>
+ * as a <code>String</code>.
+ *
+ * @return A <code>String</code> representing the chars written to
+ * this stream.
+ */
+ public String toString ()
+ {
+ return buffer.toString();
+ }
+
+ /**
+ * This method writes a single character to the output, storing it in
+ * the internal buffer.
+ *
+ * @param oneChar The <code>char</code> to write, passed as an int.
+ */
+ public void write (int oneChar)
+ {
+ buffer.append((char) (oneChar & 0xFFFF));
+ }
+
+ /**
+ * This method writes <code>len</code> chars from the specified
+ * array starting at index <code>offset</code> in that array to this
+ * stream by appending the chars to the end of the internal buffer.
+ *
+ * @param chars The array of chars to write
+ * @param offset The index into the array to start writing from
+ * @param len The number of chars to write
+ */
+ public void write (char[] chars, int offset, int len)
+ {
+ buffer.append(chars, offset, len);
+ }
+
+ /**
+ * This method writes the characters in the specified <code>String</code>
+ * to the stream by appending them to the end of the internal buffer.
+ *
+ * @param str The <code>String</code> to write to the stream.
+ */
+ public void write (String str)
+ {
+ buffer.append(str);
+ }
+
+ /**
+ * This method writes out <code>len</code> characters of the specified
+ * <code>String</code> to the stream starting at character position
+ * <code>offset</code> into the stream. This is done by appending the
+ * characters to the internal buffer.
+ *
+ * @param str The <code>String</code> to write characters from
+ * @param offset The character position to start writing from
+ * @param len The number of characters to write.
+ */
+ public void write (String str, int offset, int len)
+ {
+// char[] tmpbuf = new char[len];
+// str.getChars(offset, offset+len, tmpbuf, 0);
+// buf.append(tmpbuf, 0, tmpbuf.length);
+ // This implementation assumes that String.substring is more
+ // efficient than using String.getChars and copying the data
+ // twice. For libgcj, this is true. For Classpath, it is not.
+ // FIXME.
+ buffer.append(str.substring(offset, offset + len));
+ }
+
+ /**
+ * This is the <code>StringBuffer</code> that we use to store bytes that
+ * are written.
+ */
+ private StringBuffer buffer;
+}
diff --git a/libjava/classpath/java/io/SyncFailedException.java b/libjava/classpath/java/io/SyncFailedException.java
new file mode 100644
index 00000000000..c514c44f23f
--- /dev/null
+++ b/libjava/classpath/java/io/SyncFailedException.java
@@ -0,0 +1,66 @@
+/* SyncFailedException.java -- a file sync failed
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * Thrown when a file synchronization fails.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see FileDescriptor#sync()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class SyncFailedException extends IOException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -2353342684412443330L;
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public SyncFailedException(String message)
+ {
+ super(message);
+ }
+} // class SyncFailedException
diff --git a/libjava/classpath/java/io/UTFDataFormatException.java b/libjava/classpath/java/io/UTFDataFormatException.java
new file mode 100644
index 00000000000..6bb76aebdfe
--- /dev/null
+++ b/libjava/classpath/java/io/UTFDataFormatException.java
@@ -0,0 +1,74 @@
+/* UTFDataFormatException.java -- thrown on bad format in UTF data
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * When reading a UTF string from an input stream, this exception is thrown
+ * to indicate that the data read is invalid.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see DataInput
+ * @see DataInputStream#readUTF(DataInput)
+ * @status updated to 1.4
+ */
+public class UTFDataFormatException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 420743449228280612L;
+
+ /**
+ * Create a new UTFDataFormatException without a descriptive error message.
+ */
+ public UTFDataFormatException()
+ {
+ }
+
+ /**
+ * Create a new UTFDataFormatException with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public UTFDataFormatException(String message)
+ {
+ super(message);
+ }
+} // class UTFDataFormatException
diff --git a/libjava/classpath/java/io/UnsupportedEncodingException.java b/libjava/classpath/java/io/UnsupportedEncodingException.java
new file mode 100644
index 00000000000..cf0ab64cb89
--- /dev/null
+++ b/libjava/classpath/java/io/UnsupportedEncodingException.java
@@ -0,0 +1,73 @@
+/* UnsupportedEncodingException.java -- the requested encoding isn't supported
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown when the requested character encoding is
+ * not supported.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class UnsupportedEncodingException extends IOException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -4274276298326136670L;
+
+ /**
+ * Create an exception without a descriptive error message.
+ */
+ public UnsupportedEncodingException()
+ {
+ }
+
+ /**
+ * Create an exception with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public UnsupportedEncodingException(String message)
+ {
+ super(message);
+ }
+} // class UnsupportedEncodingException
diff --git a/libjava/classpath/java/io/WriteAbortedException.java b/libjava/classpath/java/io/WriteAbortedException.java
new file mode 100644
index 00000000000..f051dc975c8
--- /dev/null
+++ b/libjava/classpath/java/io/WriteAbortedException.java
@@ -0,0 +1,109 @@
+/* WriteAbortedException.java -- wraps an exception thrown while writing
+ Copyright (C) 1998, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/**
+ * This exception is thrown when another ObjectStreamException occurs during
+ * a serialization read or write. The stream is reset, and deserialized
+ * objects are discarded.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class WriteAbortedException extends ObjectStreamException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -3326426625597282442L;
+
+ /**
+ * The cause of this exception. This pre-dates the exception chaining
+ * of Throwable; and although you can change this field, you are wiser
+ * to leave it alone.
+ *
+ * @serial the exception cause
+ */
+ public Exception detail;
+
+ /**
+ * Create a new WriteAbortedException with a specified message and
+ * cause.
+ *
+ * @param msg the message
+ * @param detail the cause
+ */
+ public WriteAbortedException(String msg, Exception detail)
+ {
+ super(msg);
+ initCause(detail);
+ this.detail = detail;
+ }
+
+ /**
+ * This method returns a message indicating what went wrong, in this
+ * format:
+ * <code>super.getMessage() + (detail == null ? "" : "; " + detail)</code>.
+ *
+ * @return the chained message
+ */
+ public String getMessage()
+ {
+ if (detail == this || detail == null)
+ return super.getMessage();
+ return super.getMessage() + "; " + detail;
+ }
+
+ /**
+ * Returns the cause of this exception. Note that this may not be the
+ * original cause, thanks to the <code>detail</code> field being public
+ * and non-final (yuck). However, to avoid violating the contract of
+ * Throwable.getCause(), this returns null if <code>detail == this</code>,
+ * as no exception can be its own cause.
+ *
+ * @return the cause
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return detail == this ? null : detail;
+ }
+} // class WriteAbortedException
diff --git a/libjava/classpath/java/io/Writer.java b/libjava/classpath/java/io/Writer.java
new file mode 100644
index 00000000000..f153e31cfed
--- /dev/null
+++ b/libjava/classpath/java/io/Writer.java
@@ -0,0 +1,192 @@
+/* Writer.java -- Base class for character output streams
+ Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.io;
+
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This abstract class forms the base of the hierarchy of classes that
+ * write output as a stream of chars. It provides a common set of methods
+ * for writing chars to stream. Subclasses implement and/or extend these
+ * methods to write chars in a particular manner or to a particular
+ * destination such as a file on disk or network connection.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public abstract class Writer
+{
+ /**
+ * This is the object used to synchronize criticial code sections for
+ * thread safety. Subclasses should use this field instead of using
+ * synchronized methods or explicity synchronizations on <code>this</code>
+ */
+ protected Object lock;
+
+ /**
+ * This is the default no-argument constructor for this class. This method
+ * will set up the class to synchronize criticial sections on itself.
+ */
+ protected Writer()
+ {
+ lock = this;
+ }
+
+ /**
+ * This method initializes a <code>Writer</code> that will synchronize
+ * on the specified <code>Object</code>.
+ *
+ * @param lock The <code>Object</code> to use for synchronizing critical
+ * sections. Must not be null.
+ */
+ protected Writer(Object lock)
+ {
+ if (lock == null)
+ throw new NullPointerException();
+
+ this.lock = lock;
+ }
+
+ /**
+ * This method forces any data that may have been buffered to be written
+ * to the underlying output device. Please note that the host environment
+ * might perform its own buffering unbeknowst to Java. In that case, a
+ * write made (for example, to a disk drive) might be cached in OS
+ * buffers instead of actually being written to disk.
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract void flush() throws IOException;
+
+ /**
+ * This method closes the stream. Any internal or native resources
+ * associated
+ * with this stream are freed. Any subsequent attempt to access the stream
+ * might throw an exception.
+ * <p>
+ * This method in this class does nothing.
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract void close() throws IOException;
+
+ /**
+ * This method writes a single char to the output stream.
+ *
+ * @param b The char to be written to the output stream, passed as an int
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(int b) throws IOException
+ {
+ char[] buf = new char[1];
+
+ buf[0] = (char)b;
+ write(buf, 0, buf.length);
+ }
+
+ /**
+ * This method all the writes char from the passed array to the output
+ * stream. This method is equivalent to
+ * <code>write(buf, 0, buf.length)</code> which
+ * is exactly how it is implemented in this class.
+ *
+ * @param buf The array of char to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(char[] buf) throws IOException
+ {
+ write(buf, 0, buf.length);
+ }
+
+ /**
+ * This method writes <code>len</code> char from the specified array
+ * <code>buf</code> starting at index <code>offset</code> into the array.
+ * <p>
+ * Subclasses must provide an implementation of this abstract method.
+ *
+ * @param buf The array of char to write from
+ * @param offset The index into the array to start writing from
+ * @param len The number of char to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract void write(char[] buf, int offset, int len)
+ throws IOException;
+
+ /**
+ * This method writes all the characters in a <code>String</code> to the
+ * output.
+ *
+ * @param str The <code>String</code> whose chars are to be written.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(String str) throws IOException
+ {
+ write(str, 0, str.length());
+ }
+
+ /**
+ * This method writes <code>len</code> chars from the <code>String</code>
+ * starting at position <code>offset</code>.
+ *
+ * @param str The <code>String</code> that is to be written
+ * @param offset The character offset into the <code>String</code> to start
+ * writing from
+ * @param len The number of chars to write
+ *
+ * @exception IOException If an error occurs
+ */
+ public void write(String str, int offset, int len) throws IOException
+ {
+ // FIXME - for libgcj re-write using native code to not require
+ // copied buffer.
+ char[] buf = new char[len];
+
+ str.getChars(offset, offset + len, buf, 0);
+ write(buf, 0, len);
+ }
+
+} // class Writer
+
diff --git a/libjava/classpath/java/io/class-dependencies.conf b/libjava/classpath/java/io/class-dependencies.conf
new file mode 100644
index 00000000000..633bb174941
--- /dev/null
+++ b/libjava/classpath/java/io/class-dependencies.conf
@@ -0,0 +1,100 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+java/io/File: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/FileDescriptor: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+java/io/FileInputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V
+
+java/io/FileOutputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+java/io/ObjectInputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/ObjectOutputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/RandomAccessFile: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+# end of file
diff --git a/libjava/classpath/java/io/package.html b/libjava/classpath/java/io/package.html
new file mode 100644
index 00000000000..02e1c5bc365
--- /dev/null
+++ b/libjava/classpath/java/io/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.io package.
+ Copyright (C) 2002 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 - java.io</title></head>
+
+<body>
+<p>Classes for manipulating character and byte streams and files.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/lang/AbstractMethodError.java b/libjava/classpath/java/lang/AbstractMethodError.java
new file mode 100644
index 00000000000..b9eb622ee8e
--- /dev/null
+++ b/libjava/classpath/java/lang/AbstractMethodError.java
@@ -0,0 +1,75 @@
+/* AbstractMethodError.java -- thrown if an abstract method is invoked
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An <code>AbstractMethodError</code> is thrown when an application attempts
+ * to access an abstract method. Compilers typically detect this error, but
+ * it can be thrown at run time if the definition of a class has changed
+ * since the application was last compiled. This can also occur when
+ * reflecting on methods.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class AbstractMethodError extends IncompatibleClassChangeError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -1654391082989018462L;
+
+ /**
+ * Create an error without a message.
+ */
+ public AbstractMethodError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public AbstractMethodError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/Appendable.java b/libjava/classpath/java/lang/Appendable.java
new file mode 100644
index 00000000000..c0966773355
--- /dev/null
+++ b/libjava/classpath/java/lang/Appendable.java
@@ -0,0 +1,122 @@
+/* Appendable.java -- Something to which characters can be appended
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.io.IOException;
+
+/**
+ * <p>
+ * An <code>Appendable</code> object is one to which a sequence of Unicode
+ * characters can be added. The appended characters must be valid Unicode
+ * characters, and may include supplementary characters, composed of multiple
+ * 16-bit <code>char</code> values.
+ * </p>
+ * <p>
+ * The behaviour of the <code>Appendable</code> object is heavily dependent
+ * on the particular implementation being used. Some implementations may be
+ * thread-safe, while others may not. Likewise, some implementing classes
+ * may produce errors which aren't propogated to the invoking class, due
+ * to differences in the error handling used.
+ * </p>
+ * <p>
+ * <strong>Note</strong>: implementation of this interface is required for
+ * any class that wishes to receive data from a <code>Formatter</code>
+ * instance.
+ * </p>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface Appendable
+{
+
+ /**
+ * Appends the Unicode character, c, to this <code>Appendable</code>
+ * object.
+ *
+ * @param c the character to append.
+ * @return a reference to this object.
+ * @throws IOException if an I/O error occurs.
+ */
+ Appendable append(char c)
+ throws IOException;
+
+ /**
+ * Appends the specified sequence of Unicode characters to this
+ * <code>Appendable</code> object. The entire sequence may not
+ * be appended, if constrained by the underlying implementation.
+ * For example, a buffer may reach its size limit before the entire
+ * sequence is appended.
+ *
+ * @param seq the character sequence to append. If seq is null,
+ * then the string "null" (the string representation of null)
+ * is appended.
+ * @return a reference to this object.
+ * @throws IOException if an I/O error occurs.
+ */
+ Appendable append(CharSequence seq)
+ throws IOException;
+
+ /**
+ * Appends the specified subsequence of Unicode characters to this
+ * <code>Appendable</code> object, starting and ending at the specified
+ * positions within the sequence. The entire sequence may not
+ * be appended, if constrained by the underlying implementation.
+ * For example, a buffer may reach its size limit before the entire
+ * sequence is appended. The behaviour of this method matches the
+ * behaviour of <code>append(seq.subSequence(start,end))</code> when
+ * the sequence is not null.
+ *
+ * @param seq the character sequence to append. If seq is null,
+ * then the string "null" (the string representation of null)
+ * is appended.
+ * @param start the index of the first Unicode character to use from
+ * the sequence.
+ * @param end the index of the last Unicode character to use from the
+ * sequence.
+ * @return a reference to this object.
+ * @throws IOException if an I/O error occurs.
+ * @throws IndexOutOfBoundsException if either of the indices are negative,
+ * the start index occurs after the end index, or the end index is
+ * beyond the end of the sequence.
+ */
+ Appendable append(CharSequence seq, int start, int end)
+ throws IOException;
+
+}
diff --git a/libjava/classpath/java/lang/ArithmeticException.java b/libjava/classpath/java/lang/ArithmeticException.java
new file mode 100644
index 00000000000..5acea43533b
--- /dev/null
+++ b/libjava/classpath/java/lang/ArithmeticException.java
@@ -0,0 +1,77 @@
+/* ArithmeticException.java -- exception thrown to indicate conditions
+ like divide by zero.
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when a math error has occured, such as trying to divide an
+ * integer by zero. For example:<br>
+ * <pre>
+ * int i = 0;
+ * int j = 2 / i;
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class ArithmeticException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 2256477558314496007L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public ArithmeticException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ArithmeticException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/ArrayIndexOutOfBoundsException.java b/libjava/classpath/java/lang/ArrayIndexOutOfBoundsException.java
new file mode 100644
index 00000000000..371623bdaaa
--- /dev/null
+++ b/libjava/classpath/java/lang/ArrayIndexOutOfBoundsException.java
@@ -0,0 +1,87 @@
+/* ArrayIndexOutOfBoundsException.java -- exception thrown when accessing
+ an illegal index.
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when attempting to access a position outside the valid range of
+ * an array. For example:<br>
+ * <pre>
+ * int[] i = { 1 };
+ * i[1] = 2;
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -5116101128118950844L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public ArrayIndexOutOfBoundsException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ArrayIndexOutOfBoundsException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception indicating the illegal index.
+ *
+ * @param index the invalid index
+ */
+ public ArrayIndexOutOfBoundsException(int index)
+ {
+ super("Array index out of range: " + index);
+ }
+}
diff --git a/libjava/classpath/java/lang/ArrayStoreException.java b/libjava/classpath/java/lang/ArrayStoreException.java
new file mode 100644
index 00000000000..042e78c5515
--- /dev/null
+++ b/libjava/classpath/java/lang/ArrayStoreException.java
@@ -0,0 +1,77 @@
+/* ArrayStoreException.java -- exception thrown to when trying to store an
+ object into an array of a different type.
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when trying to store an object of the wrong runtime type in an
+ * array. For example:<br>
+ * <pre>
+ * Object[] o = new Integer[1];
+ * o[0] = "oops";
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class ArrayStoreException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4522193890499838241L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public ArrayStoreException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ArrayStoreException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/AssertionError.java b/libjava/classpath/java/lang/AssertionError.java
new file mode 100644
index 00000000000..778eb583051
--- /dev/null
+++ b/libjava/classpath/java/lang/AssertionError.java
@@ -0,0 +1,148 @@
+/* AssertionError.java -- indication of a failed assertion
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An assertion error normally occurs as a result of the <code>assert</code>
+ * statement added in JDK 1.4, to indicate that an assertion failed. There
+ * are enough constructors to ensure that
+ * <code>new AssertionError(<em>expression</em>)</code> will work for all
+ * expressions, regardless of type, as if the error message were given by
+ * the string <code>"" + <em>expression</em></code>. This extends Error,
+ * because you usually do not want to inadvertently trap an assertion failure.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class AssertionError extends Error
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -5013299493970297370L;
+
+ /**
+ * Construct an AssertionError with no detail message.
+ */
+ public AssertionError()
+ {
+ }
+
+ /**
+ * Construct an AssertionError with the string conversion of the given
+ * object as its error message. If the object is a Throwable, it is also
+ * set as the cause of this error.
+ *
+ * @param msg the source of the error message
+ * @see Throwable#getCause()
+ */
+ public AssertionError(Object msg)
+ {
+ super("" + msg);
+ if (msg instanceof Throwable)
+ initCause((Throwable) msg);
+ }
+
+ /**
+ * Construct an AssertionError with the string conversion of the given
+ * boolean as its error message.
+ *
+ * @param msg the source of the error message
+ */
+ public AssertionError(boolean msg)
+ {
+ super(msg ? "true" : "false");
+ }
+
+ /**
+ * Construct an AssertionError with the string conversion of the given
+ * char as its error message.
+ *
+ * @param msg the source of the error message
+ */
+ public AssertionError(char msg)
+ {
+ super(String.valueOf(msg));
+ }
+
+ /**
+ * Construct an AssertionError with the string conversion of the given
+ * int as its error message.
+ *
+ * @param msg the source of the error message
+ */
+ public AssertionError(int msg)
+ {
+ super(Integer.toString(msg, 10));
+ }
+
+ /**
+ * Construct an AssertionError with the string conversion of the given
+ * long as its error message.
+ *
+ * @param msg the source of the error message
+ */
+ public AssertionError(long msg)
+ {
+ super(Long.toString(msg));
+ }
+
+ /**
+ * Construct an AssertionError with the string conversion of the given
+ * float as its error message.
+ *
+ * @param msg the source of the error message
+ */
+ public AssertionError(float msg)
+ {
+ super(Float.toString(msg));
+ }
+
+ /**
+ * Construct an AssertionError with the string conversion of the given
+ * double as its error message.
+ *
+ * @param msg the source of the error message
+ */
+ public AssertionError(double msg)
+ {
+ super(Double.toString(msg));
+ }
+}
diff --git a/libjava/classpath/java/lang/Boolean.java b/libjava/classpath/java/lang/Boolean.java
new file mode 100644
index 00000000000..b6910280e6b
--- /dev/null
+++ b/libjava/classpath/java/lang/Boolean.java
@@ -0,0 +1,224 @@
+/* Boolean.java -- object wrapper for boolean
+ Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import java.io.Serializable;
+
+/**
+ * Instances of class <code>Boolean</code> represent primitive
+ * <code>boolean</code> values.
+ *
+ * @author Paul Fisher
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public final class Boolean implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0.2+.
+ */
+ private static final long serialVersionUID = -3665804199014368530L;
+
+ /**
+ * This field is a <code>Boolean</code> object representing the
+ * primitive value <code>true</code>. This instance is returned
+ * by the static <code>valueOf()</code> methods if they return
+ * a <code>Boolean</code> representing <code>true</code>.
+ */
+ public static final Boolean TRUE = new Boolean(true);
+
+ /**
+ * This field is a <code>Boolean</code> object representing the
+ * primitive value <code>false</code>. This instance is returned
+ * by the static <code>valueOf()</code> methods if they return
+ * a <code>Boolean</code> representing <code>false</code>.
+ */
+ public static final Boolean FALSE = new Boolean(false);
+
+ /**
+ * The primitive type <code>boolean</code> is represented by this
+ * <code>Class</code> object.
+ *
+ * @since 1.1
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass('Z');
+
+ /**
+ * The immutable value of this Boolean.
+ * @serial the wrapped value
+ */
+ private final boolean value;
+
+ /**
+ * Create a <code>Boolean</code> object representing the value of the
+ * argument <code>value</code>. In general the use of the static
+ * method <code>valueof(boolean)</code> is more efficient since it will
+ * not create a new object.
+ *
+ * @param value the primitive value of this <code>Boolean</code>
+ * @see #valueOf(boolean)
+ */
+ public Boolean(boolean value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Creates a <code>Boolean</code> object representing the primitive
+ * <code>true</code> if and only if <code>s</code> matches
+ * the string "true" ignoring case, otherwise the object will represent
+ * the primitive <code>false</code>. In general the use of the static
+ * method <code>valueof(String)</code> is more efficient since it will
+ * not create a new object.
+ *
+ * @param s the <code>String</code> representation of <code>true</code>
+ * or false
+ */
+ public Boolean(String s)
+ {
+ value = "true".equalsIgnoreCase(s);
+ }
+
+ /**
+ * Return the primitive <code>boolean</code> value of this
+ * <code>Boolean</code> object.
+ *
+ * @return true or false, depending on the value of this Boolean
+ */
+ public boolean booleanValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the Boolean <code>TRUE</code> if the given boolean is
+ * <code>true</code>, otherwise it will return the Boolean
+ * <code>FALSE</code>.
+ *
+ * @param b the boolean to wrap
+ * @return the wrapper object
+ * @see #TRUE
+ * @see #FALSE
+ * @since 1.4
+ */
+ public static Boolean valueOf(boolean b)
+ {
+ return b ? TRUE : FALSE;
+ }
+
+ /**
+ * Returns the Boolean <code>TRUE</code> if and only if the given
+ * String is equal, ignoring case, to the the String "true", otherwise
+ * it will return the Boolean <code>FALSE</code>.
+ *
+ * @param s the string to convert
+ * @return a wrapped boolean from the string
+ */
+ public static Boolean valueOf(String s)
+ {
+ return "true".equalsIgnoreCase(s) ? TRUE : FALSE;
+ }
+
+ /**
+ * Returns "true" if the value of the give boolean is <code>true</code> and
+ * returns "false" if the value of the given boolean is <code>false</code>.
+ *
+ * @param b the boolean to convert
+ * @return the string representation of the boolean
+ * @since 1.4
+ */
+ public static String toString(boolean b)
+ {
+ return b ? "true" : "false";
+ }
+
+ /**
+ * Returns "true" if the value of this object is <code>true</code> and
+ * returns "false" if the value of this object is <code>false</code>.
+ *
+ * @return the string representation of this
+ */
+ public String toString()
+ {
+ return value ? "true" : "false";
+ }
+
+ /**
+ * Returns the integer <code>1231</code> if this object represents
+ * the primitive <code>true</code> and the integer <code>1237</code>
+ * otherwise.
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return value ? 1231 : 1237;
+ }
+
+ /**
+ * If the <code>obj</code> is an instance of <code>Boolean</code> and
+ * has the same primitive value as this object then <code>true</code>
+ * is returned. In all other cases, including if the <code>obj</code>
+ * is <code>null</code>, <code>false</code> is returned.
+ *
+ * @param obj possibly an instance of any <code>Class</code>
+ * @return true if <code>obj</code> equals this
+ */
+ public boolean equals(Object obj)
+ {
+ return obj instanceof Boolean && value == ((Boolean) obj).value;
+ }
+
+ /**
+ * If the value of the system property <code>name</code> matches
+ * "true" ignoring case then the function returns <code>true</code>.
+ *
+ * @param name the property name to look up
+ * @return true if the property resulted in "true"
+ * @throws SecurityException if accessing the system property is forbidden
+ * @see System#getProperty(String)
+ */
+ public static boolean getBoolean(String name)
+ {
+ if (name == null || "".equals(name))
+ return false;
+ return "true".equalsIgnoreCase(System.getProperty(name));
+ }
+}
diff --git a/libjava/classpath/java/lang/Byte.java b/libjava/classpath/java/lang/Byte.java
new file mode 100644
index 00000000000..338e2167aa1
--- /dev/null
+++ b/libjava/classpath/java/lang/Byte.java
@@ -0,0 +1,357 @@
+/* Byte.java -- object wrapper for byte
+ Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Instances of class <code>Byte</code> represent primitive <code>byte</code>
+ * values.
+ *
+ * Additionally, this class provides various helper functions and variables
+ * useful to bytes.
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Per Bothner
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Byte extends Number implements Comparable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -7183698231559129828L;
+
+ /**
+ * The minimum value a <code>byte</code> can represent is -128 (or
+ * -2<sup>7</sup>).
+ */
+ public static final byte MIN_VALUE = -128;
+
+ /**
+ * The maximum value a <code>byte</code> can represent is 127 (or
+ * 2<sup>7</sup> - 1).
+ */
+ public static final byte MAX_VALUE = 127;
+
+ /**
+ * The primitive type <code>byte</code> is represented by this
+ * <code>Class</code> object.
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass('B');
+
+ /**
+ * The immutable value of this Byte.
+ *
+ * @serial the wrapped byte
+ */
+ private final byte value;
+
+ /**
+ * Create a <code>Byte</code> object representing the value of the
+ * <code>byte</code> argument.
+ *
+ * @param value the value to use
+ */
+ public Byte(byte value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create a <code>Byte</code> object representing the value specified
+ * by the <code>String</code> argument
+ *
+ * @param s the string to convert
+ * @throws NumberFormatException if the String does not contain a byte
+ * @see #valueOf(String)
+ */
+ public Byte(String s)
+ {
+ value = parseByte(s, 10);
+ }
+
+ /**
+ * Converts the <code>byte</code> to a <code>String</code> and assumes
+ * a radix of 10.
+ *
+ * @param b the <code>byte</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toString(byte b)
+ {
+ return String.valueOf(b);
+ }
+
+ /**
+ * Converts the specified <code>String</code> into a <code>byte</code>.
+ * This function assumes a radix of 10.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the <code>byte</code> value of <code>s</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>byte</code>
+ * @see #parseByte(String)
+ */
+ public static byte parseByte(String s)
+ {
+ return parseByte(s, 10);
+ }
+
+ /**
+ * Converts the specified <code>String</code> into an <code>int</code>
+ * using the specified radix (base). The string must not be <code>null</code>
+ * or empty. It may begin with an optional '-', which will negate the answer,
+ * provided that there are also valid digits. Each digit is parsed as if by
+ * <code>Character.digit(d, radix)</code>, and must be in the range
+ * <code>0</code> to <code>radix - 1</code>. Finally, the result must be
+ * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive.
+ * Unlike Double.parseDouble, you may not have a leading '+'.
+ *
+ * @param s the <code>String</code> to convert
+ * @param radix the radix (base) to use in the conversion
+ * @return the <code>String</code> argument converted to <code>byte</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>byte</code>
+ */
+ public static byte parseByte(String s, int radix)
+ {
+ int i = Integer.parseInt(s, radix, false);
+ if ((byte) i != i)
+ throw new NumberFormatException();
+ return (byte) i;
+ }
+
+ /**
+ * Creates a new <code>Byte</code> object using the <code>String</code>
+ * and specified radix (base).
+ *
+ * @param s the <code>String</code> to convert
+ * @param radix the radix (base) to convert with
+ * @return the new <code>Byte</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>byte</code>
+ * @see #parseByte(String, int)
+ */
+ public static Byte valueOf(String s, int radix)
+ {
+ return new Byte(parseByte(s, radix));
+ }
+
+ /**
+ * Creates a new <code>Byte</code> object using the <code>String</code>,
+ * assuming a radix of 10.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the new <code>Byte</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>byte</code>
+ * @see #Byte(String)
+ * @see #parseByte(String)
+ */
+ public static Byte valueOf(String s)
+ {
+ return new Byte(parseByte(s, 10));
+ }
+
+ /**
+ * Convert the specified <code>String</code> into a <code>Byte</code>.
+ * The <code>String</code> may represent decimal, hexadecimal, or
+ * octal numbers.
+ *
+ * <p>The extended BNF grammar is as follows:<br>
+ * <pre>
+ * <em>DecodableString</em>:
+ * ( [ <code>-</code> ] <em>DecimalNumber</em> )
+ * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code>
+ * | <code>#</code> ) { <em>HexDigit</em> }+ )
+ * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } )
+ * <em>DecimalNumber</em>:
+ * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> }
+ * <em>DecimalDigit</em>:
+ * <em>Character.digit(d, 10) has value 0 to 9</em>
+ * <em>OctalDigit</em>:
+ * <em>Character.digit(d, 8) has value 0 to 7</em>
+ * <em>DecimalDigit</em>:
+ * <em>Character.digit(d, 16) has value 0 to 15</em>
+ * </pre>
+ * Finally, the value must be in the range <code>MIN_VALUE</code> to
+ * <code>MAX_VALUE</code>, or an exception is thrown.
+ *
+ * @param s the <code>String</code> to interpret
+ * @return the value of the String as a <code>Byte</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>byte</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @see Integer#decode(String)
+ */
+ public static Byte decode(String s)
+ {
+ int i = Integer.parseInt(s, 10, true);
+ if ((byte) i != i)
+ throw new NumberFormatException();
+ return new Byte((byte) i);
+ }
+
+ /**
+ * Return the value of this <code>Byte</code>.
+ *
+ * @return the byte value
+ */
+ public byte byteValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Byte</code> as a <code>short</code>.
+ *
+ * @return the short value
+ */
+ public short shortValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Byte</code> as an <code>int</code>.
+ *
+ * @return the int value
+ */
+ public int intValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Byte</code> as a <code>long</code>.
+ *
+ * @return the long value
+ */
+ public long longValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Byte</code> as a <code>float</code>.
+ *
+ * @return the float value
+ */
+ public float floatValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Byte</code> as a <code>double</code>.
+ *
+ * @return the double value
+ */
+ public double doubleValue()
+ {
+ return value;
+ }
+
+ /**
+ * Converts the <code>Byte</code> value to a <code>String</code> and
+ * assumes a radix of 10.
+ *
+ * @return the <code>String</code> representation of this <code>Byte</code>
+ * @see Integer#toString()
+ */
+ public String toString()
+ {
+ return String.valueOf(value);
+ }
+
+ /**
+ * Return a hashcode representing this Object. <code>Byte</code>'s hash
+ * code is simply its value.
+ *
+ * @return this Object's hash code
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Returns <code>true</code> if <code>obj</code> is an instance of
+ * <code>Byte</code> and represents the same byte value.
+ *
+ * @param obj the object to compare
+ * @return whether these Objects are semantically equal
+ */
+ public boolean equals(Object obj)
+ {
+ return obj instanceof Byte && value == ((Byte) obj).value;
+ }
+
+ /**
+ * Compare two Bytes numerically by comparing their <code>byte</code> values.
+ * The result is positive if the first is greater, negative if the second
+ * is greater, and 0 if the two are equal.
+ *
+ * @param b the Byte to compare
+ * @return the comparison
+ * @since 1.2
+ */
+ public int compareTo(Byte b)
+ {
+ return value - b.value;
+ }
+
+ /**
+ * Behaves like <code>compareTo(Byte)</code> unless the Object
+ * is not a <code>Byte</code>.
+ *
+ * @param o the object to compare
+ * @return the comparison
+ * @throws ClassCastException if the argument is not a <code>Byte</code>
+ * @see #compareTo(Byte)
+ * @see Comparable
+ * @since 1.2
+ */
+ public int compareTo(Object o)
+ {
+ return compareTo((Byte) o);
+ }
+}
diff --git a/libjava/classpath/java/lang/CharSequence.java b/libjava/classpath/java/lang/CharSequence.java
new file mode 100644
index 00000000000..5c014e173a8
--- /dev/null
+++ b/libjava/classpath/java/lang/CharSequence.java
@@ -0,0 +1,99 @@
+/* CharSequence.java -- Anything that has an indexed sequence of chars
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * General functions on a sequence of chars. This interface is implemented
+ * by <code>String</code>, <code>StringBuffer</code> and
+ * <code>CharBuffer</code> to give a uniform way to get chars at a certain
+ * index, the number of characters in the sequence and a subrange of the
+ * chars. Indexes start at 0 and the last index is <code>length()-1</code>.
+ *
+ * <p>Even when classes implement this interface they are not always
+ * exchangeble because they might implement their compare, equals or hash
+ * function differently. This means that in general one should not use a
+ * <code>CharSequence</code> as keys in collections since two sequences
+ * with the same chars at the same indexes with the same length might not
+ * have the same hash code, be equal or be comparable since the are
+ * represented by different classes.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface CharSequence
+{
+ /**
+ * Returns the character at the given index.
+ *
+ * @param i the index to retrieve from
+ * @return the character at that location
+ * @throws IndexOutOfBoundsException if i &lt; 0 || i &gt;= length() - 1
+ */
+ char charAt(int i);
+
+ /**
+ * Returns the length of the sequence. This is the number of 16-bit
+ * characters in the sequence, which may differ from the length of the
+ * underlying encoding.
+ *
+ * @return the sequence length
+ */
+ int length();
+
+ /**
+ * Returns a new <code>CharSequence</code> of the indicated range.
+ *
+ * @param begin the start index (inclusive)
+ * @param end the end index (exclusive)
+ * @return a subsequence of this
+ * @throws IndexOutOfBoundsException if begin &gt; end || begin &lt; 0 ||
+ * end &gt; length()
+ */
+ CharSequence subSequence(int begin, int end);
+
+ /**
+ * Returns the complete <code>CharSequence</code> as a <code>String</code>.
+ * Classes that implement this interface should return a <code>String</code>
+ * which contains only the characters in the sequence in the correct order.
+ *
+ * @return the character sequence as a String
+ */
+ String toString();
+}
diff --git a/libjava/classpath/java/lang/Character.java b/libjava/classpath/java/lang/Character.java
new file mode 100644
index 00000000000..4eac1476184
--- /dev/null
+++ b/libjava/classpath/java/lang/Character.java
@@ -0,0 +1,2253 @@
+/* java.lang.Character -- Wrapper class for char, and Unicode subsets
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.java.lang.CharData;
+
+import java.io.Serializable;
+
+/**
+ * Wrapper class for the primitive char data type. In addition, this class
+ * allows one to retrieve property information and perform transformations
+ * on the 57,707 defined characters in the Unicode Standard, Version 3.0.0.
+ * java.lang.Character is designed to be very dynamic, and as such, it
+ * retrieves information on the Unicode character set from a separate
+ * database, gnu.java.lang.CharData, which can be easily upgraded.
+ *
+ * <p>For predicates, boundaries are used to describe
+ * the set of characters for which the method will return true.
+ * This syntax uses fairly normal regular expression notation.
+ * See 5.13 of the Unicode Standard, Version 3.0, for the
+ * boundary specification.
+ *
+ * <p>See <a href="http://www.unicode.org">http://www.unicode.org</a>
+ * for more information on the Unicode Standard.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Paul N. Fisher
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see CharData
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public final class Character implements Serializable, Comparable
+{
+ /**
+ * A subset of Unicode blocks.
+ *
+ * @author Paul N. Fisher
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ */
+ public static class Subset
+ {
+ /** The name of the subset. */
+ private final String name;
+
+ /**
+ * Construct a new subset of characters.
+ *
+ * @param name the name of the subset
+ * @throws NullPointerException if name is null
+ */
+ protected Subset(String name)
+ {
+ // Note that name.toString() is name, unless name was null.
+ this.name = name.toString();
+ }
+
+ /**
+ * Compares two Subsets for equality. This is <code>final</code>, and
+ * restricts the comparison on the <code>==</code> operator, so it returns
+ * true only for the same object.
+ *
+ * @param o the object to compare
+ * @return true if o is this
+ */
+ public final boolean equals(Object o)
+ {
+ return o == this;
+ }
+
+ /**
+ * Makes the original hashCode of Object final, to be consistent with
+ * equals.
+ *
+ * @return the hash code for this object
+ */
+ public final int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ * Returns the name of the subset.
+ *
+ * @return the name
+ */
+ public final String toString()
+ {
+ return name;
+ }
+ } // class Subset
+
+ /**
+ * A family of character subsets in the Unicode specification. A character
+ * is in at most one of these blocks.
+ *
+ * This inner class was generated automatically from
+ * <code>doc/unicode/Block-3.txt</code>, by some perl scripts.
+ * This Unicode definition file can be found on the
+ * <a href="http://www.unicode.org">http://www.unicode.org</a> website.
+ * JDK 1.4 uses Unicode version 3.0.0.
+ *
+ * @author scripts/unicode-blocks.pl (written by Eric Blake)
+ * @since 1.2
+ */
+ public static final class UnicodeBlock extends Subset
+ {
+ /** The start of the subset. */
+ private final char start;
+
+ /** The end of the subset. */
+ private final char end;
+
+ /**
+ * Constructor for strictly defined blocks.
+ *
+ * @param start the start character of the range
+ * @param end the end character of the range
+ * @param name the block name
+ */
+ private UnicodeBlock(char start, char end, String name)
+ {
+ super(name);
+ this.start = start;
+ this.end = end;
+ }
+
+ /**
+ * Returns the Unicode character block which a character belongs to.
+ *
+ * @param ch the character to look up
+ * @return the set it belongs to, or null if it is not in one
+ */
+ public static UnicodeBlock of(char ch)
+ {
+ // Special case, since SPECIALS contains two ranges.
+ if (ch == '\uFEFF')
+ return SPECIALS;
+ // Simple binary search for the correct block.
+ int low = 0;
+ int hi = sets.length - 1;
+ while (low <= hi)
+ {
+ int mid = (low + hi) >> 1;
+ UnicodeBlock b = sets[mid];
+ if (ch < b.start)
+ hi = mid - 1;
+ else if (ch > b.end)
+ low = mid + 1;
+ else
+ return b;
+ }
+ return null;
+ }
+
+ /**
+ * Basic Latin.
+ * '\u0000' - '\u007F'.
+ */
+ public static final UnicodeBlock BASIC_LATIN
+ = new UnicodeBlock('\u0000', '\u007F',
+ "BASIC_LATIN");
+
+ /**
+ * Latin-1 Supplement.
+ * '\u0080' - '\u00FF'.
+ */
+ public static final UnicodeBlock LATIN_1_SUPPLEMENT
+ = new UnicodeBlock('\u0080', '\u00FF',
+ "LATIN_1_SUPPLEMENT");
+
+ /**
+ * Latin Extended-A.
+ * '\u0100' - '\u017F'.
+ */
+ public static final UnicodeBlock LATIN_EXTENDED_A
+ = new UnicodeBlock('\u0100', '\u017F',
+ "LATIN_EXTENDED_A");
+
+ /**
+ * Latin Extended-B.
+ * '\u0180' - '\u024F'.
+ */
+ public static final UnicodeBlock LATIN_EXTENDED_B
+ = new UnicodeBlock('\u0180', '\u024F',
+ "LATIN_EXTENDED_B");
+
+ /**
+ * IPA Extensions.
+ * '\u0250' - '\u02AF'.
+ */
+ public static final UnicodeBlock IPA_EXTENSIONS
+ = new UnicodeBlock('\u0250', '\u02AF',
+ "IPA_EXTENSIONS");
+
+ /**
+ * Spacing Modifier Letters.
+ * '\u02B0' - '\u02FF'.
+ */
+ public static final UnicodeBlock SPACING_MODIFIER_LETTERS
+ = new UnicodeBlock('\u02B0', '\u02FF',
+ "SPACING_MODIFIER_LETTERS");
+
+ /**
+ * Combining Diacritical Marks.
+ * '\u0300' - '\u036F'.
+ */
+ public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS
+ = new UnicodeBlock('\u0300', '\u036F',
+ "COMBINING_DIACRITICAL_MARKS");
+
+ /**
+ * Greek.
+ * '\u0370' - '\u03FF'.
+ */
+ public static final UnicodeBlock GREEK
+ = new UnicodeBlock('\u0370', '\u03FF',
+ "GREEK");
+
+ /**
+ * Cyrillic.
+ * '\u0400' - '\u04FF'.
+ */
+ public static final UnicodeBlock CYRILLIC
+ = new UnicodeBlock('\u0400', '\u04FF',
+ "CYRILLIC");
+
+ /**
+ * Armenian.
+ * '\u0530' - '\u058F'.
+ */
+ public static final UnicodeBlock ARMENIAN
+ = new UnicodeBlock('\u0530', '\u058F',
+ "ARMENIAN");
+
+ /**
+ * Hebrew.
+ * '\u0590' - '\u05FF'.
+ */
+ public static final UnicodeBlock HEBREW
+ = new UnicodeBlock('\u0590', '\u05FF',
+ "HEBREW");
+
+ /**
+ * Arabic.
+ * '\u0600' - '\u06FF'.
+ */
+ public static final UnicodeBlock ARABIC
+ = new UnicodeBlock('\u0600', '\u06FF',
+ "ARABIC");
+
+ /**
+ * Syriac.
+ * '\u0700' - '\u074F'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock SYRIAC
+ = new UnicodeBlock('\u0700', '\u074F',
+ "SYRIAC");
+
+ /**
+ * Thaana.
+ * '\u0780' - '\u07BF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock THAANA
+ = new UnicodeBlock('\u0780', '\u07BF',
+ "THAANA");
+
+ /**
+ * Devanagari.
+ * '\u0900' - '\u097F'.
+ */
+ public static final UnicodeBlock DEVANAGARI
+ = new UnicodeBlock('\u0900', '\u097F',
+ "DEVANAGARI");
+
+ /**
+ * Bengali.
+ * '\u0980' - '\u09FF'.
+ */
+ public static final UnicodeBlock BENGALI
+ = new UnicodeBlock('\u0980', '\u09FF',
+ "BENGALI");
+
+ /**
+ * Gurmukhi.
+ * '\u0A00' - '\u0A7F'.
+ */
+ public static final UnicodeBlock GURMUKHI
+ = new UnicodeBlock('\u0A00', '\u0A7F',
+ "GURMUKHI");
+
+ /**
+ * Gujarati.
+ * '\u0A80' - '\u0AFF'.
+ */
+ public static final UnicodeBlock GUJARATI
+ = new UnicodeBlock('\u0A80', '\u0AFF',
+ "GUJARATI");
+
+ /**
+ * Oriya.
+ * '\u0B00' - '\u0B7F'.
+ */
+ public static final UnicodeBlock ORIYA
+ = new UnicodeBlock('\u0B00', '\u0B7F',
+ "ORIYA");
+
+ /**
+ * Tamil.
+ * '\u0B80' - '\u0BFF'.
+ */
+ public static final UnicodeBlock TAMIL
+ = new UnicodeBlock('\u0B80', '\u0BFF',
+ "TAMIL");
+
+ /**
+ * Telugu.
+ * '\u0C00' - '\u0C7F'.
+ */
+ public static final UnicodeBlock TELUGU
+ = new UnicodeBlock('\u0C00', '\u0C7F',
+ "TELUGU");
+
+ /**
+ * Kannada.
+ * '\u0C80' - '\u0CFF'.
+ */
+ public static final UnicodeBlock KANNADA
+ = new UnicodeBlock('\u0C80', '\u0CFF',
+ "KANNADA");
+
+ /**
+ * Malayalam.
+ * '\u0D00' - '\u0D7F'.
+ */
+ public static final UnicodeBlock MALAYALAM
+ = new UnicodeBlock('\u0D00', '\u0D7F',
+ "MALAYALAM");
+
+ /**
+ * Sinhala.
+ * '\u0D80' - '\u0DFF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock SINHALA
+ = new UnicodeBlock('\u0D80', '\u0DFF',
+ "SINHALA");
+
+ /**
+ * Thai.
+ * '\u0E00' - '\u0E7F'.
+ */
+ public static final UnicodeBlock THAI
+ = new UnicodeBlock('\u0E00', '\u0E7F',
+ "THAI");
+
+ /**
+ * Lao.
+ * '\u0E80' - '\u0EFF'.
+ */
+ public static final UnicodeBlock LAO
+ = new UnicodeBlock('\u0E80', '\u0EFF',
+ "LAO");
+
+ /**
+ * Tibetan.
+ * '\u0F00' - '\u0FFF'.
+ */
+ public static final UnicodeBlock TIBETAN
+ = new UnicodeBlock('\u0F00', '\u0FFF',
+ "TIBETAN");
+
+ /**
+ * Myanmar.
+ * '\u1000' - '\u109F'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock MYANMAR
+ = new UnicodeBlock('\u1000', '\u109F',
+ "MYANMAR");
+
+ /**
+ * Georgian.
+ * '\u10A0' - '\u10FF'.
+ */
+ public static final UnicodeBlock GEORGIAN
+ = new UnicodeBlock('\u10A0', '\u10FF',
+ "GEORGIAN");
+
+ /**
+ * Hangul Jamo.
+ * '\u1100' - '\u11FF'.
+ */
+ public static final UnicodeBlock HANGUL_JAMO
+ = new UnicodeBlock('\u1100', '\u11FF',
+ "HANGUL_JAMO");
+
+ /**
+ * Ethiopic.
+ * '\u1200' - '\u137F'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock ETHIOPIC
+ = new UnicodeBlock('\u1200', '\u137F',
+ "ETHIOPIC");
+
+ /**
+ * Cherokee.
+ * '\u13A0' - '\u13FF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock CHEROKEE
+ = new UnicodeBlock('\u13A0', '\u13FF',
+ "CHEROKEE");
+
+ /**
+ * Unified Canadian Aboriginal Syllabics.
+ * '\u1400' - '\u167F'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS
+ = new UnicodeBlock('\u1400', '\u167F',
+ "UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS");
+
+ /**
+ * Ogham.
+ * '\u1680' - '\u169F'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock OGHAM
+ = new UnicodeBlock('\u1680', '\u169F',
+ "OGHAM");
+
+ /**
+ * Runic.
+ * '\u16A0' - '\u16FF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock RUNIC
+ = new UnicodeBlock('\u16A0', '\u16FF',
+ "RUNIC");
+
+ /**
+ * Khmer.
+ * '\u1780' - '\u17FF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock KHMER
+ = new UnicodeBlock('\u1780', '\u17FF',
+ "KHMER");
+
+ /**
+ * Mongolian.
+ * '\u1800' - '\u18AF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock MONGOLIAN
+ = new UnicodeBlock('\u1800', '\u18AF',
+ "MONGOLIAN");
+
+ /**
+ * Latin Extended Additional.
+ * '\u1E00' - '\u1EFF'.
+ */
+ public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL
+ = new UnicodeBlock('\u1E00', '\u1EFF',
+ "LATIN_EXTENDED_ADDITIONAL");
+
+ /**
+ * Greek Extended.
+ * '\u1F00' - '\u1FFF'.
+ */
+ public static final UnicodeBlock GREEK_EXTENDED
+ = new UnicodeBlock('\u1F00', '\u1FFF',
+ "GREEK_EXTENDED");
+
+ /**
+ * General Punctuation.
+ * '\u2000' - '\u206F'.
+ */
+ public static final UnicodeBlock GENERAL_PUNCTUATION
+ = new UnicodeBlock('\u2000', '\u206F',
+ "GENERAL_PUNCTUATION");
+
+ /**
+ * Superscripts and Subscripts.
+ * '\u2070' - '\u209F'.
+ */
+ public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS
+ = new UnicodeBlock('\u2070', '\u209F',
+ "SUPERSCRIPTS_AND_SUBSCRIPTS");
+
+ /**
+ * Currency Symbols.
+ * '\u20A0' - '\u20CF'.
+ */
+ public static final UnicodeBlock CURRENCY_SYMBOLS
+ = new UnicodeBlock('\u20A0', '\u20CF',
+ "CURRENCY_SYMBOLS");
+
+ /**
+ * Combining Marks for Symbols.
+ * '\u20D0' - '\u20FF'.
+ */
+ public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS
+ = new UnicodeBlock('\u20D0', '\u20FF',
+ "COMBINING_MARKS_FOR_SYMBOLS");
+
+ /**
+ * Letterlike Symbols.
+ * '\u2100' - '\u214F'.
+ */
+ public static final UnicodeBlock LETTERLIKE_SYMBOLS
+ = new UnicodeBlock('\u2100', '\u214F',
+ "LETTERLIKE_SYMBOLS");
+
+ /**
+ * Number Forms.
+ * '\u2150' - '\u218F'.
+ */
+ public static final UnicodeBlock NUMBER_FORMS
+ = new UnicodeBlock('\u2150', '\u218F',
+ "NUMBER_FORMS");
+
+ /**
+ * Arrows.
+ * '\u2190' - '\u21FF'.
+ */
+ public static final UnicodeBlock ARROWS
+ = new UnicodeBlock('\u2190', '\u21FF',
+ "ARROWS");
+
+ /**
+ * Mathematical Operators.
+ * '\u2200' - '\u22FF'.
+ */
+ public static final UnicodeBlock MATHEMATICAL_OPERATORS
+ = new UnicodeBlock('\u2200', '\u22FF',
+ "MATHEMATICAL_OPERATORS");
+
+ /**
+ * Miscellaneous Technical.
+ * '\u2300' - '\u23FF'.
+ */
+ public static final UnicodeBlock MISCELLANEOUS_TECHNICAL
+ = new UnicodeBlock('\u2300', '\u23FF',
+ "MISCELLANEOUS_TECHNICAL");
+
+ /**
+ * Control Pictures.
+ * '\u2400' - '\u243F'.
+ */
+ public static final UnicodeBlock CONTROL_PICTURES
+ = new UnicodeBlock('\u2400', '\u243F',
+ "CONTROL_PICTURES");
+
+ /**
+ * Optical Character Recognition.
+ * '\u2440' - '\u245F'.
+ */
+ public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION
+ = new UnicodeBlock('\u2440', '\u245F',
+ "OPTICAL_CHARACTER_RECOGNITION");
+
+ /**
+ * Enclosed Alphanumerics.
+ * '\u2460' - '\u24FF'.
+ */
+ public static final UnicodeBlock ENCLOSED_ALPHANUMERICS
+ = new UnicodeBlock('\u2460', '\u24FF',
+ "ENCLOSED_ALPHANUMERICS");
+
+ /**
+ * Box Drawing.
+ * '\u2500' - '\u257F'.
+ */
+ public static final UnicodeBlock BOX_DRAWING
+ = new UnicodeBlock('\u2500', '\u257F',
+ "BOX_DRAWING");
+
+ /**
+ * Block Elements.
+ * '\u2580' - '\u259F'.
+ */
+ public static final UnicodeBlock BLOCK_ELEMENTS
+ = new UnicodeBlock('\u2580', '\u259F',
+ "BLOCK_ELEMENTS");
+
+ /**
+ * Geometric Shapes.
+ * '\u25A0' - '\u25FF'.
+ */
+ public static final UnicodeBlock GEOMETRIC_SHAPES
+ = new UnicodeBlock('\u25A0', '\u25FF',
+ "GEOMETRIC_SHAPES");
+
+ /**
+ * Miscellaneous Symbols.
+ * '\u2600' - '\u26FF'.
+ */
+ public static final UnicodeBlock MISCELLANEOUS_SYMBOLS
+ = new UnicodeBlock('\u2600', '\u26FF',
+ "MISCELLANEOUS_SYMBOLS");
+
+ /**
+ * Dingbats.
+ * '\u2700' - '\u27BF'.
+ */
+ public static final UnicodeBlock DINGBATS
+ = new UnicodeBlock('\u2700', '\u27BF',
+ "DINGBATS");
+
+ /**
+ * Braille Patterns.
+ * '\u2800' - '\u28FF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock BRAILLE_PATTERNS
+ = new UnicodeBlock('\u2800', '\u28FF',
+ "BRAILLE_PATTERNS");
+
+ /**
+ * CJK Radicals Supplement.
+ * '\u2E80' - '\u2EFF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT
+ = new UnicodeBlock('\u2E80', '\u2EFF',
+ "CJK_RADICALS_SUPPLEMENT");
+
+ /**
+ * Kangxi Radicals.
+ * '\u2F00' - '\u2FDF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock KANGXI_RADICALS
+ = new UnicodeBlock('\u2F00', '\u2FDF',
+ "KANGXI_RADICALS");
+
+ /**
+ * Ideographic Description Characters.
+ * '\u2FF0' - '\u2FFF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS
+ = new UnicodeBlock('\u2FF0', '\u2FFF',
+ "IDEOGRAPHIC_DESCRIPTION_CHARACTERS");
+
+ /**
+ * CJK Symbols and Punctuation.
+ * '\u3000' - '\u303F'.
+ */
+ public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION
+ = new UnicodeBlock('\u3000', '\u303F',
+ "CJK_SYMBOLS_AND_PUNCTUATION");
+
+ /**
+ * Hiragana.
+ * '\u3040' - '\u309F'.
+ */
+ public static final UnicodeBlock HIRAGANA
+ = new UnicodeBlock('\u3040', '\u309F',
+ "HIRAGANA");
+
+ /**
+ * Katakana.
+ * '\u30A0' - '\u30FF'.
+ */
+ public static final UnicodeBlock KATAKANA
+ = new UnicodeBlock('\u30A0', '\u30FF',
+ "KATAKANA");
+
+ /**
+ * Bopomofo.
+ * '\u3100' - '\u312F'.
+ */
+ public static final UnicodeBlock BOPOMOFO
+ = new UnicodeBlock('\u3100', '\u312F',
+ "BOPOMOFO");
+
+ /**
+ * Hangul Compatibility Jamo.
+ * '\u3130' - '\u318F'.
+ */
+ public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO
+ = new UnicodeBlock('\u3130', '\u318F',
+ "HANGUL_COMPATIBILITY_JAMO");
+
+ /**
+ * Kanbun.
+ * '\u3190' - '\u319F'.
+ */
+ public static final UnicodeBlock KANBUN
+ = new UnicodeBlock('\u3190', '\u319F',
+ "KANBUN");
+
+ /**
+ * Bopomofo Extended.
+ * '\u31A0' - '\u31BF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock BOPOMOFO_EXTENDED
+ = new UnicodeBlock('\u31A0', '\u31BF',
+ "BOPOMOFO_EXTENDED");
+
+ /**
+ * Enclosed CJK Letters and Months.
+ * '\u3200' - '\u32FF'.
+ */
+ public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS
+ = new UnicodeBlock('\u3200', '\u32FF',
+ "ENCLOSED_CJK_LETTERS_AND_MONTHS");
+
+ /**
+ * CJK Compatibility.
+ * '\u3300' - '\u33FF'.
+ */
+ public static final UnicodeBlock CJK_COMPATIBILITY
+ = new UnicodeBlock('\u3300', '\u33FF',
+ "CJK_COMPATIBILITY");
+
+ /**
+ * CJK Unified Ideographs Extension A.
+ * '\u3400' - '\u4DB5'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
+ = new UnicodeBlock('\u3400', '\u4DB5',
+ "CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A");
+
+ /**
+ * CJK Unified Ideographs.
+ * '\u4E00' - '\u9FFF'.
+ */
+ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS
+ = new UnicodeBlock('\u4E00', '\u9FFF',
+ "CJK_UNIFIED_IDEOGRAPHS");
+
+ /**
+ * Yi Syllables.
+ * '\uA000' - '\uA48F'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock YI_SYLLABLES
+ = new UnicodeBlock('\uA000', '\uA48F',
+ "YI_SYLLABLES");
+
+ /**
+ * Yi Radicals.
+ * '\uA490' - '\uA4CF'.
+ * @since 1.4
+ */
+ public static final UnicodeBlock YI_RADICALS
+ = new UnicodeBlock('\uA490', '\uA4CF',
+ "YI_RADICALS");
+
+ /**
+ * Hangul Syllables.
+ * '\uAC00' - '\uD7A3'.
+ */
+ public static final UnicodeBlock HANGUL_SYLLABLES
+ = new UnicodeBlock('\uAC00', '\uD7A3',
+ "HANGUL_SYLLABLES");
+
+ /**
+ * Surrogates Area.
+ * '\uD800' - '\uDFFF'.
+ */
+ public static final UnicodeBlock SURROGATES_AREA
+ = new UnicodeBlock('\uD800', '\uDFFF',
+ "SURROGATES_AREA");
+
+ /**
+ * Private Use Area.
+ * '\uE000' - '\uF8FF'.
+ */
+ public static final UnicodeBlock PRIVATE_USE_AREA
+ = new UnicodeBlock('\uE000', '\uF8FF',
+ "PRIVATE_USE_AREA");
+
+ /**
+ * CJK Compatibility Ideographs.
+ * '\uF900' - '\uFAFF'.
+ */
+ public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS
+ = new UnicodeBlock('\uF900', '\uFAFF',
+ "CJK_COMPATIBILITY_IDEOGRAPHS");
+
+ /**
+ * Alphabetic Presentation Forms.
+ * '\uFB00' - '\uFB4F'.
+ */
+ public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS
+ = new UnicodeBlock('\uFB00', '\uFB4F',
+ "ALPHABETIC_PRESENTATION_FORMS");
+
+ /**
+ * Arabic Presentation Forms-A.
+ * '\uFB50' - '\uFDFF'.
+ */
+ public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A
+ = new UnicodeBlock('\uFB50', '\uFDFF',
+ "ARABIC_PRESENTATION_FORMS_A");
+
+ /**
+ * Combining Half Marks.
+ * '\uFE20' - '\uFE2F'.
+ */
+ public static final UnicodeBlock COMBINING_HALF_MARKS
+ = new UnicodeBlock('\uFE20', '\uFE2F',
+ "COMBINING_HALF_MARKS");
+
+ /**
+ * CJK Compatibility Forms.
+ * '\uFE30' - '\uFE4F'.
+ */
+ public static final UnicodeBlock CJK_COMPATIBILITY_FORMS
+ = new UnicodeBlock('\uFE30', '\uFE4F',
+ "CJK_COMPATIBILITY_FORMS");
+
+ /**
+ * Small Form Variants.
+ * '\uFE50' - '\uFE6F'.
+ */
+ public static final UnicodeBlock SMALL_FORM_VARIANTS
+ = new UnicodeBlock('\uFE50', '\uFE6F',
+ "SMALL_FORM_VARIANTS");
+
+ /**
+ * Arabic Presentation Forms-B.
+ * '\uFE70' - '\uFEFE'.
+ */
+ public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B
+ = new UnicodeBlock('\uFE70', '\uFEFE',
+ "ARABIC_PRESENTATION_FORMS_B");
+
+ /**
+ * Halfwidth and Fullwidth Forms.
+ * '\uFF00' - '\uFFEF'.
+ */
+ public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS
+ = new UnicodeBlock('\uFF00', '\uFFEF',
+ "HALFWIDTH_AND_FULLWIDTH_FORMS");
+
+ /**
+ * Specials.
+ * '\uFEFF', '\uFFF0' - '\uFFFD'.
+ */
+ public static final UnicodeBlock SPECIALS
+ = new UnicodeBlock('\uFFF0', '\uFFFD',
+ "SPECIALS");
+
+ /**
+ * The defined subsets.
+ */
+ private static final UnicodeBlock sets[] = {
+ BASIC_LATIN,
+ LATIN_1_SUPPLEMENT,
+ LATIN_EXTENDED_A,
+ LATIN_EXTENDED_B,
+ IPA_EXTENSIONS,
+ SPACING_MODIFIER_LETTERS,
+ COMBINING_DIACRITICAL_MARKS,
+ GREEK,
+ CYRILLIC,
+ ARMENIAN,
+ HEBREW,
+ ARABIC,
+ SYRIAC,
+ THAANA,
+ DEVANAGARI,
+ BENGALI,
+ GURMUKHI,
+ GUJARATI,
+ ORIYA,
+ TAMIL,
+ TELUGU,
+ KANNADA,
+ MALAYALAM,
+ SINHALA,
+ THAI,
+ LAO,
+ TIBETAN,
+ MYANMAR,
+ GEORGIAN,
+ HANGUL_JAMO,
+ ETHIOPIC,
+ CHEROKEE,
+ UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS,
+ OGHAM,
+ RUNIC,
+ KHMER,
+ MONGOLIAN,
+ LATIN_EXTENDED_ADDITIONAL,
+ GREEK_EXTENDED,
+ GENERAL_PUNCTUATION,
+ SUPERSCRIPTS_AND_SUBSCRIPTS,
+ CURRENCY_SYMBOLS,
+ COMBINING_MARKS_FOR_SYMBOLS,
+ LETTERLIKE_SYMBOLS,
+ NUMBER_FORMS,
+ ARROWS,
+ MATHEMATICAL_OPERATORS,
+ MISCELLANEOUS_TECHNICAL,
+ CONTROL_PICTURES,
+ OPTICAL_CHARACTER_RECOGNITION,
+ ENCLOSED_ALPHANUMERICS,
+ BOX_DRAWING,
+ BLOCK_ELEMENTS,
+ GEOMETRIC_SHAPES,
+ MISCELLANEOUS_SYMBOLS,
+ DINGBATS,
+ BRAILLE_PATTERNS,
+ CJK_RADICALS_SUPPLEMENT,
+ KANGXI_RADICALS,
+ IDEOGRAPHIC_DESCRIPTION_CHARACTERS,
+ CJK_SYMBOLS_AND_PUNCTUATION,
+ HIRAGANA,
+ KATAKANA,
+ BOPOMOFO,
+ HANGUL_COMPATIBILITY_JAMO,
+ KANBUN,
+ BOPOMOFO_EXTENDED,
+ ENCLOSED_CJK_LETTERS_AND_MONTHS,
+ CJK_COMPATIBILITY,
+ CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A,
+ CJK_UNIFIED_IDEOGRAPHS,
+ YI_SYLLABLES,
+ YI_RADICALS,
+ HANGUL_SYLLABLES,
+ SURROGATES_AREA,
+ PRIVATE_USE_AREA,
+ CJK_COMPATIBILITY_IDEOGRAPHS,
+ ALPHABETIC_PRESENTATION_FORMS,
+ ARABIC_PRESENTATION_FORMS_A,
+ COMBINING_HALF_MARKS,
+ CJK_COMPATIBILITY_FORMS,
+ SMALL_FORM_VARIANTS,
+ ARABIC_PRESENTATION_FORMS_B,
+ HALFWIDTH_AND_FULLWIDTH_FORMS,
+ SPECIALS,
+ };
+ } // class UnicodeBlock
+
+ /**
+ * The immutable value of this Character.
+ *
+ * @serial the value of this Character
+ */
+ private final char value;
+
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 3786198910865385080L;
+
+ /**
+ * Smallest value allowed for radix arguments in Java. This value is 2.
+ *
+ * @see #digit(char, int)
+ * @see #forDigit(int, int)
+ * @see Integer#toString(int, int)
+ * @see Integer#valueOf(String)
+ */
+ public static final int MIN_RADIX = 2;
+
+ /**
+ * Largest value allowed for radix arguments in Java. This value is 36.
+ *
+ * @see #digit(char, int)
+ * @see #forDigit(int, int)
+ * @see Integer#toString(int, int)
+ * @see Integer#valueOf(String)
+ */
+ public static final int MAX_RADIX = 36;
+
+ /**
+ * The minimum value the char data type can hold.
+ * This value is <code>'\\u0000'</code>.
+ */
+ public static final char MIN_VALUE = '\u0000';
+
+ /**
+ * The maximum value the char data type can hold.
+ * This value is <code>'\\uFFFF'</code>.
+ */
+ public static final char MAX_VALUE = '\uFFFF';
+
+ /**
+ * Class object representing the primitive char data type.
+ *
+ * @since 1.1
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass('C');
+
+ /**
+ * Lu = Letter, Uppercase (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte UPPERCASE_LETTER = 1;
+
+ /**
+ * Ll = Letter, Lowercase (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte LOWERCASE_LETTER = 2;
+
+ /**
+ * Lt = Letter, Titlecase (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte TITLECASE_LETTER = 3;
+
+ /**
+ * Mn = Mark, Non-Spacing (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte NON_SPACING_MARK = 6;
+
+ /**
+ * Mc = Mark, Spacing Combining (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte COMBINING_SPACING_MARK = 8;
+
+ /**
+ * Me = Mark, Enclosing (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte ENCLOSING_MARK = 7;
+
+ /**
+ * Nd = Number, Decimal Digit (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte DECIMAL_DIGIT_NUMBER = 9;
+
+ /**
+ * Nl = Number, Letter (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte LETTER_NUMBER = 10;
+
+ /**
+ * No = Number, Other (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte OTHER_NUMBER = 11;
+
+ /**
+ * Zs = Separator, Space (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte SPACE_SEPARATOR = 12;
+
+ /**
+ * Zl = Separator, Line (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte LINE_SEPARATOR = 13;
+
+ /**
+ * Zp = Separator, Paragraph (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte PARAGRAPH_SEPARATOR = 14;
+
+ /**
+ * Cc = Other, Control (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte CONTROL = 15;
+
+ /**
+ * Cf = Other, Format (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte FORMAT = 16;
+
+ /**
+ * Cs = Other, Surrogate (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte SURROGATE = 19;
+
+ /**
+ * Co = Other, Private Use (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte PRIVATE_USE = 18;
+
+ /**
+ * Cn = Other, Not Assigned (Normative).
+ *
+ * @since 1.1
+ */
+ public static final byte UNASSIGNED = 0;
+
+ /**
+ * Lm = Letter, Modifier (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte MODIFIER_LETTER = 4;
+
+ /**
+ * Lo = Letter, Other (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte OTHER_LETTER = 5;
+
+ /**
+ * Pc = Punctuation, Connector (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte CONNECTOR_PUNCTUATION = 23;
+
+ /**
+ * Pd = Punctuation, Dash (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte DASH_PUNCTUATION = 20;
+
+ /**
+ * Ps = Punctuation, Open (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte START_PUNCTUATION = 21;
+
+ /**
+ * Pe = Punctuation, Close (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte END_PUNCTUATION = 22;
+
+ /**
+ * Pi = Punctuation, Initial Quote (Informative).
+ *
+ * @since 1.4
+ */
+ public static final byte INITIAL_QUOTE_PUNCTUATION = 29;
+
+ /**
+ * Pf = Punctuation, Final Quote (Informative).
+ *
+ * @since 1.4
+ */
+ public static final byte FINAL_QUOTE_PUNCTUATION = 30;
+
+ /**
+ * Po = Punctuation, Other (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte OTHER_PUNCTUATION = 24;
+
+ /**
+ * Sm = Symbol, Math (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte MATH_SYMBOL = 25;
+
+ /**
+ * Sc = Symbol, Currency (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte CURRENCY_SYMBOL = 26;
+
+ /**
+ * Sk = Symbol, Modifier (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte MODIFIER_SYMBOL = 27;
+
+ /**
+ * So = Symbol, Other (Informative).
+ *
+ * @since 1.1
+ */
+ public static final byte OTHER_SYMBOL = 28;
+
+ /**
+ * Undefined bidirectional character type. Undefined char values have
+ * undefined directionality in the Unicode specification.
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_UNDEFINED = -1;
+
+ /**
+ * Strong bidirectional character type "L".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0;
+
+ /**
+ * Strong bidirectional character type "R".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1;
+
+ /**
+ * Strong bidirectional character type "AL".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 2;
+
+ /**
+ * Weak bidirectional character type "EN".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 3;
+
+ /**
+ * Weak bidirectional character type "ES".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 4;
+
+ /**
+ * Weak bidirectional character type "ET".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 5;
+
+ /**
+ * Weak bidirectional character type "AN".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_ARABIC_NUMBER = 6;
+
+ /**
+ * Weak bidirectional character type "CS".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 7;
+
+ /**
+ * Weak bidirectional character type "NSM".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_NONSPACING_MARK = 8;
+
+ /**
+ * Weak bidirectional character type "BN".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 9;
+
+ /**
+ * Neutral bidirectional character type "B".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 10;
+
+ /**
+ * Neutral bidirectional character type "S".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 11;
+
+ /**
+ * Strong bidirectional character type "WS".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_WHITESPACE = 12;
+
+ /**
+ * Neutral bidirectional character type "ON".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 13;
+
+ /**
+ * Strong bidirectional character type "LRE".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 14;
+
+ /**
+ * Strong bidirectional character type "LRO".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 15;
+
+ /**
+ * Strong bidirectional character type "RLE".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 16;
+
+ /**
+ * Strong bidirectional character type "RLO".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 17;
+
+ /**
+ * Weak bidirectional character type "PDF".
+ *
+ * @since 1.4
+ */
+ public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 18;
+
+ /**
+ * Stores unicode block offset lookup table. Exploit package visibility of
+ * String.value to avoid copying the array.
+ * @see #readChar(char)
+ * @see CharData#BLOCKS
+ */
+ private static final char[] blocks = String.zeroBasedStringValue(CharData.BLOCKS);
+
+ /**
+ * Stores unicode attribute offset lookup table. Exploit package visibility
+ * of String.value to avoid copying the array.
+ * @see CharData#DATA
+ */
+ private static final char[] data = String.zeroBasedStringValue(CharData.DATA);
+
+ /**
+ * Stores unicode numeric value attribute table. Exploit package visibility
+ * of String.value to avoid copying the array.
+ * @see CharData#NUM_VALUE
+ */
+ private static final char[] numValue
+ = String.zeroBasedStringValue(CharData.NUM_VALUE);
+
+ /**
+ * Stores unicode uppercase attribute table. Exploit package visibility
+ * of String.value to avoid copying the array.
+ * @see CharData#UPPER
+ */
+ private static final char[] upper = String.zeroBasedStringValue(CharData.UPPER);
+
+ /**
+ * Stores unicode lowercase attribute table. Exploit package visibility
+ * of String.value to avoid copying the array.
+ * @see CharData#LOWER
+ */
+ private static final char[] lower = String.zeroBasedStringValue(CharData.LOWER);
+
+ /**
+ * Stores unicode direction attribute table. Exploit package visibility
+ * of String.value to avoid copying the array.
+ * @see CharData#DIRECTION
+ */
+ // Package visible for use by String.
+ static final char[] direction = String.zeroBasedStringValue(CharData.DIRECTION);
+
+ /**
+ * Stores unicode titlecase table. Exploit package visibility of
+ * String.value to avoid copying the array.
+ * @see CharData#TITLE
+ */
+ private static final char[] title = String.zeroBasedStringValue(CharData.TITLE);
+
+ /**
+ * Mask for grabbing the type out of the contents of data.
+ * @see CharData#DATA
+ */
+ private static final int TYPE_MASK = 0x1F;
+
+ /**
+ * Mask for grabbing the non-breaking space flag out of the contents of
+ * data.
+ * @see CharData#DATA
+ */
+ private static final int NO_BREAK_MASK = 0x20;
+
+ /**
+ * Mask for grabbing the mirrored directionality flag out of the contents
+ * of data.
+ * @see CharData#DATA
+ */
+ private static final int MIRROR_MASK = 0x40;
+
+ /**
+ * Grabs an attribute offset from the Unicode attribute database. The lower
+ * 5 bits are the character type, the next 2 bits are flags, and the top
+ * 9 bits are the offset into the attribute tables.
+ *
+ * @param ch the character to look up
+ * @return the character's attribute offset and type
+ * @see #TYPE_MASK
+ * @see #NO_BREAK_MASK
+ * @see #MIRROR_MASK
+ * @see CharData#DATA
+ * @see CharData#SHIFT
+ */
+ // Package visible for use in String.
+ static char readChar(char ch)
+ {
+ // Perform 16-bit addition to find the correct entry in data.
+ return data[(char) (blocks[ch >> CharData.SHIFT] + ch)];
+ }
+
+ /**
+ * Wraps up a character.
+ *
+ * @param value the character to wrap
+ */
+ public Character(char value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Returns the character which has been wrapped by this class.
+ *
+ * @return the character wrapped
+ */
+ public char charValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the numerical value (unsigned) of the wrapped character.
+ * Range of returned values: 0x0000-0xFFFF.
+ *
+ * @return the value of the wrapped character
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Determines if an object is equal to this object. This is only true for
+ * another Character object wrapping the same value.
+ *
+ * @param o object to compare
+ * @return true if o is a Character with the same value
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof Character && value == ((Character) o).value;
+ }
+
+ /**
+ * Converts the wrapped character into a String.
+ *
+ * @return a String containing one character -- the wrapped character
+ * of this instance
+ */
+ public String toString()
+ {
+ // Package constructor avoids an array copy.
+ return new String(new char[] { value }, 0, 1, true);
+ }
+
+ /**
+ * Returns a String of length 1 representing the specified character.
+ *
+ * @param ch the character to convert
+ * @return a String containing the character
+ * @since 1.4
+ */
+ public static String toString(char ch)
+ {
+ // Package constructor avoids an array copy.
+ return new String(new char[] { ch }, 0, 1, true);
+ }
+
+ /**
+ * Determines if a character is a Unicode lowercase letter. For example,
+ * <code>'a'</code> is lowercase.
+ * <br>
+ * lowercase = [Ll]
+ *
+ * @param ch character to test
+ * @return true if ch is a Unicode lowercase letter, else false
+ * @see #isUpperCase(char)
+ * @see #isTitleCase(char)
+ * @see #toLowerCase(char)
+ * @see #getType(char)
+ */
+ public static boolean isLowerCase(char ch)
+ {
+ return getType(ch) == LOWERCASE_LETTER;
+ }
+
+ /**
+ * Determines if a character is a Unicode uppercase letter. For example,
+ * <code>'A'</code> is uppercase.
+ * <br>
+ * uppercase = [Lu]
+ *
+ * @param ch character to test
+ * @return true if ch is a Unicode uppercase letter, else false
+ * @see #isLowerCase(char)
+ * @see #isTitleCase(char)
+ * @see #toUpperCase(char)
+ * @see #getType(char)
+ */
+ public static boolean isUpperCase(char ch)
+ {
+ return getType(ch) == UPPERCASE_LETTER;
+ }
+
+ /**
+ * Determines if a character is a Unicode titlecase letter. For example,
+ * the character "Lj" (Latin capital L with small letter j) is titlecase.
+ * <br>
+ * titlecase = [Lt]
+ *
+ * @param ch character to test
+ * @return true if ch is a Unicode titlecase letter, else false
+ * @see #isLowerCase(char)
+ * @see #isUpperCase(char)
+ * @see #toTitleCase(char)
+ * @see #getType(char)
+ */
+ public static boolean isTitleCase(char ch)
+ {
+ return getType(ch) == TITLECASE_LETTER;
+ }
+
+ /**
+ * Determines if a character is a Unicode decimal digit. For example,
+ * <code>'0'</code> is a digit.
+ * <br>
+ * Unicode decimal digit = [Nd]
+ *
+ * @param ch character to test
+ * @return true if ch is a Unicode decimal digit, else false
+ * @see #digit(char, int)
+ * @see #forDigit(int, int)
+ * @see #getType(char)
+ */
+ public static boolean isDigit(char ch)
+ {
+ return getType(ch) == DECIMAL_DIGIT_NUMBER;
+ }
+
+ /**
+ * Determines if a character is part of the Unicode Standard. This is an
+ * evolving standard, but covers every character in the data file.
+ * <br>
+ * defined = not [Cn]
+ *
+ * @param ch character to test
+ * @return true if ch is a Unicode character, else false
+ * @see #isDigit(char)
+ * @see #isLetter(char)
+ * @see #isLetterOrDigit(char)
+ * @see #isLowerCase(char)
+ * @see #isTitleCase(char)
+ * @see #isUpperCase(char)
+ */
+ public static boolean isDefined(char ch)
+ {
+ return getType(ch) != UNASSIGNED;
+ }
+
+ /**
+ * Determines if a character is a Unicode letter. Not all letters have case,
+ * so this may return true when isLowerCase and isUpperCase return false.
+ * <br>
+ * letter = [Lu]|[Ll]|[Lt]|[Lm]|[Lo]
+ *
+ * @param ch character to test
+ * @return true if ch is a Unicode letter, else false
+ * @see #isDigit(char)
+ * @see #isJavaIdentifierStart(char)
+ * @see #isJavaLetter(char)
+ * @see #isJavaLetterOrDigit(char)
+ * @see #isLetterOrDigit(char)
+ * @see #isLowerCase(char)
+ * @see #isTitleCase(char)
+ * @see #isUnicodeIdentifierStart(char)
+ * @see #isUpperCase(char)
+ */
+ public static boolean isLetter(char ch)
+ {
+ return ((1 << getType(ch))
+ & ((1 << UPPERCASE_LETTER)
+ | (1 << LOWERCASE_LETTER)
+ | (1 << TITLECASE_LETTER)
+ | (1 << MODIFIER_LETTER)
+ | (1 << OTHER_LETTER))) != 0;
+ }
+
+ /**
+ * Determines if a character is a Unicode letter or a Unicode digit. This
+ * is the combination of isLetter and isDigit.
+ * <br>
+ * letter or digit = [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nd]
+ *
+ * @param ch character to test
+ * @return true if ch is a Unicode letter or a Unicode digit, else false
+ * @see #isDigit(char)
+ * @see #isJavaIdentifierPart(char)
+ * @see #isJavaLetter(char)
+ * @see #isJavaLetterOrDigit(char)
+ * @see #isLetter(char)
+ * @see #isUnicodeIdentifierPart(char)
+ */
+ public static boolean isLetterOrDigit(char ch)
+ {
+ return ((1 << getType(ch))
+ & ((1 << UPPERCASE_LETTER)
+ | (1 << LOWERCASE_LETTER)
+ | (1 << TITLECASE_LETTER)
+ | (1 << MODIFIER_LETTER)
+ | (1 << OTHER_LETTER)
+ | (1 << DECIMAL_DIGIT_NUMBER))) != 0;
+ }
+
+ /**
+ * Determines if a character can start a Java identifier. This is the
+ * combination of isLetter, any character where getType returns
+ * LETTER_NUMBER, currency symbols (like '$'), and connecting punctuation
+ * (like '_').
+ *
+ * @param ch character to test
+ * @return true if ch can start a Java identifier, else false
+ * @deprecated Replaced by {@link #isJavaIdentifierStart(char)}
+ * @see #isJavaLetterOrDigit(char)
+ * @see #isJavaIdentifierStart(char)
+ * @see #isJavaIdentifierPart(char)
+ * @see #isLetter(char)
+ * @see #isLetterOrDigit(char)
+ * @see #isUnicodeIdentifierStart(char)
+ */
+ public static boolean isJavaLetter(char ch)
+ {
+ return isJavaIdentifierStart(ch);
+ }
+
+ /**
+ * Determines if a character can follow the first letter in
+ * a Java identifier. This is the combination of isJavaLetter (isLetter,
+ * type of LETTER_NUMBER, currency, connecting punctuation) and digit,
+ * numeric letter (like Roman numerals), combining marks, non-spacing marks,
+ * or isIdentifierIgnorable.
+ *
+ * @param ch character to test
+ * @return true if ch can follow the first letter in a Java identifier
+ * @deprecated Replaced by {@link #isJavaIdentifierPart(char)}
+ * @see #isJavaLetter(char)
+ * @see #isJavaIdentifierStart(char)
+ * @see #isJavaIdentifierPart(char)
+ * @see #isLetter(char)
+ * @see #isLetterOrDigit(char)
+ * @see #isUnicodeIdentifierPart(char)
+ * @see #isIdentifierIgnorable(char)
+ */
+ public static boolean isJavaLetterOrDigit(char ch)
+ {
+ return isJavaIdentifierPart(ch);
+ }
+
+ /**
+ * Determines if a character can start a Java identifier. This is the
+ * combination of isLetter, any character where getType returns
+ * LETTER_NUMBER, currency symbols (like '$'), and connecting punctuation
+ * (like '_').
+ * <br>
+ * Java identifier start = [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl]|[Sc]|[Pc]
+ *
+ * @param ch character to test
+ * @return true if ch can start a Java identifier, else false
+ * @see #isJavaIdentifierPart(char)
+ * @see #isLetter(char)
+ * @see #isUnicodeIdentifierStart(char)
+ * @since 1.1
+ */
+ public static boolean isJavaIdentifierStart(char ch)
+ {
+ return ((1 << getType(ch))
+ & ((1 << UPPERCASE_LETTER)
+ | (1 << LOWERCASE_LETTER)
+ | (1 << TITLECASE_LETTER)
+ | (1 << MODIFIER_LETTER)
+ | (1 << OTHER_LETTER)
+ | (1 << LETTER_NUMBER)
+ | (1 << CURRENCY_SYMBOL)
+ | (1 << CONNECTOR_PUNCTUATION))) != 0;
+ }
+
+ /**
+ * Determines if a character can follow the first letter in
+ * a Java identifier. This is the combination of isJavaLetter (isLetter,
+ * type of LETTER_NUMBER, currency, connecting punctuation) and digit,
+ * numeric letter (like Roman numerals), combining marks, non-spacing marks,
+ * or isIdentifierIgnorable.
+ * <br>
+ * Java identifier extender =
+ * [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl]|[Sc]|[Pc]|[Mn]|[Mc]|[Nd]|[Cf]
+ * |U+0000-U+0008|U+000E-U+001B|U+007F-U+009F
+ *
+ * @param ch character to test
+ * @return true if ch can follow the first letter in a Java identifier
+ * @see #isIdentifierIgnorable(char)
+ * @see #isJavaIdentifierStart(char)
+ * @see #isLetterOrDigit(char)
+ * @see #isUnicodeIdentifierPart(char)
+ * @since 1.1
+ */
+ public static boolean isJavaIdentifierPart(char ch)
+ {
+ int category = getType(ch);
+ return ((1 << category)
+ & ((1 << UPPERCASE_LETTER)
+ | (1 << LOWERCASE_LETTER)
+ | (1 << TITLECASE_LETTER)
+ | (1 << MODIFIER_LETTER)
+ | (1 << OTHER_LETTER)
+ | (1 << NON_SPACING_MARK)
+ | (1 << COMBINING_SPACING_MARK)
+ | (1 << DECIMAL_DIGIT_NUMBER)
+ | (1 << LETTER_NUMBER)
+ | (1 << CURRENCY_SYMBOL)
+ | (1 << CONNECTOR_PUNCTUATION)
+ | (1 << FORMAT))) != 0
+ || (category == CONTROL && isIdentifierIgnorable(ch));
+ }
+
+ /**
+ * Determines if a character can start a Unicode identifier. Only
+ * letters can start a Unicode identifier, but this includes characters
+ * in LETTER_NUMBER.
+ * <br>
+ * Unicode identifier start = [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl]
+ *
+ * @param ch character to test
+ * @return true if ch can start a Unicode identifier, else false
+ * @see #isJavaIdentifierStart(char)
+ * @see #isLetter(char)
+ * @see #isUnicodeIdentifierPart(char)
+ * @since 1.1
+ */
+ public static boolean isUnicodeIdentifierStart(char ch)
+ {
+ return ((1 << getType(ch))
+ & ((1 << UPPERCASE_LETTER)
+ | (1 << LOWERCASE_LETTER)
+ | (1 << TITLECASE_LETTER)
+ | (1 << MODIFIER_LETTER)
+ | (1 << OTHER_LETTER)
+ | (1 << LETTER_NUMBER))) != 0;
+ }
+
+ /**
+ * Determines if a character can follow the first letter in
+ * a Unicode identifier. This includes letters, connecting punctuation,
+ * digits, numeric letters, combining marks, non-spacing marks, and
+ * isIdentifierIgnorable.
+ * <br>
+ * Unicode identifier extender =
+ * [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl]|[Mn]|[Mc]|[Nd]|[Pc]|[Cf]|
+ * |U+0000-U+0008|U+000E-U+001B|U+007F-U+009F
+ *
+ * @param ch character to test
+ * @return true if ch can follow the first letter in a Unicode identifier
+ * @see #isIdentifierIgnorable(char)
+ * @see #isJavaIdentifierPart(char)
+ * @see #isLetterOrDigit(char)
+ * @see #isUnicodeIdentifierStart(char)
+ * @since 1.1
+ */
+ public static boolean isUnicodeIdentifierPart(char ch)
+ {
+ int category = getType(ch);
+ return ((1 << category)
+ & ((1 << UPPERCASE_LETTER)
+ | (1 << LOWERCASE_LETTER)
+ | (1 << TITLECASE_LETTER)
+ | (1 << MODIFIER_LETTER)
+ | (1 << OTHER_LETTER)
+ | (1 << NON_SPACING_MARK)
+ | (1 << COMBINING_SPACING_MARK)
+ | (1 << DECIMAL_DIGIT_NUMBER)
+ | (1 << LETTER_NUMBER)
+ | (1 << CONNECTOR_PUNCTUATION)
+ | (1 << FORMAT))) != 0
+ || (category == CONTROL && isIdentifierIgnorable(ch));
+ }
+
+ /**
+ * Determines if a character is ignorable in a Unicode identifier. This
+ * includes the non-whitespace ISO control characters (<code>'\u0000'</code>
+ * through <code>'\u0008'</code>, <code>'\u000E'</code> through
+ * <code>'\u001B'</code>, and <code>'\u007F'</code> through
+ * <code>'\u009F'</code>), and FORMAT characters.
+ * <br>
+ * Unicode identifier ignorable = [Cf]|U+0000-U+0008|U+000E-U+001B
+ * |U+007F-U+009F
+ *
+ * @param ch character to test
+ * @return true if ch is ignorable in a Unicode or Java identifier
+ * @see #isJavaIdentifierPart(char)
+ * @see #isUnicodeIdentifierPart(char)
+ * @since 1.1
+ */
+ public static boolean isIdentifierIgnorable(char ch)
+ {
+ return (ch <= '\u009F' && (ch < '\t' || ch >= '\u007F'
+ || (ch <= '\u001B' && ch >= '\u000E')))
+ || getType(ch) == FORMAT;
+ }
+
+ /**
+ * Converts a Unicode character into its lowercase equivalent mapping.
+ * If a mapping does not exist, then the character passed is returned.
+ * Note that isLowerCase(toLowerCase(ch)) does not always return true.
+ *
+ * @param ch character to convert to lowercase
+ * @return lowercase mapping of ch, or ch if lowercase mapping does
+ * not exist
+ * @see #isLowerCase(char)
+ * @see #isUpperCase(char)
+ * @see #toTitleCase(char)
+ * @see #toUpperCase(char)
+ */
+ public static char toLowerCase(char ch)
+ {
+ // Signedness doesn't matter, as result is cast back to char.
+ return (char) (ch + lower[readChar(ch) >> 7]);
+ }
+
+ /**
+ * Converts a Unicode character into its uppercase equivalent mapping.
+ * If a mapping does not exist, then the character passed is returned.
+ * Note that isUpperCase(toUpperCase(ch)) does not always return true.
+ *
+ * @param ch character to convert to uppercase
+ * @return uppercase mapping of ch, or ch if uppercase mapping does
+ * not exist
+ * @see #isLowerCase(char)
+ * @see #isUpperCase(char)
+ * @see #toLowerCase(char)
+ * @see #toTitleCase(char)
+ */
+ public static char toUpperCase(char ch)
+ {
+ // Signedness doesn't matter, as result is cast back to char.
+ return (char) (ch + upper[readChar(ch) >> 7]);
+ }
+
+ /**
+ * Converts a Unicode character into its titlecase equivalent mapping.
+ * If a mapping does not exist, then the character passed is returned.
+ * Note that isTitleCase(toTitleCase(ch)) does not always return true.
+ *
+ * @param ch character to convert to titlecase
+ * @return titlecase mapping of ch, or ch if titlecase mapping does
+ * not exist
+ * @see #isTitleCase(char)
+ * @see #toLowerCase(char)
+ * @see #toUpperCase(char)
+ */
+ public static char toTitleCase(char ch)
+ {
+ // As title is short, it doesn't hurt to exhaustively iterate over it.
+ for (int i = title.length - 2; i >= 0; i -= 2)
+ if (title[i] == ch)
+ return title[i + 1];
+ return toUpperCase(ch);
+ }
+
+ /**
+ * Converts a character into a digit of the specified radix. If the radix
+ * exceeds MIN_RADIX or MAX_RADIX, or if the result of getNumericValue(ch)
+ * exceeds the radix, or if ch is not a decimal digit or in the case
+ * insensitive set of 'a'-'z', the result is -1.
+ * <br>
+ * character argument boundary = [Nd]|U+0041-U+005A|U+0061-U+007A
+ * |U+FF21-U+FF3A|U+FF41-U+FF5A
+ *
+ * @param ch character to convert into a digit
+ * @param radix radix in which ch is a digit
+ * @return digit which ch represents in radix, or -1 not a valid digit
+ * @see #MIN_RADIX
+ * @see #MAX_RADIX
+ * @see #forDigit(int, int)
+ * @see #isDigit(char)
+ * @see #getNumericValue(char)
+ */
+ public static int digit(char ch, int radix)
+ {
+ if (radix < MIN_RADIX || radix > MAX_RADIX)
+ return -1;
+ char attr = readChar(ch);
+ if (((1 << (attr & TYPE_MASK))
+ & ((1 << UPPERCASE_LETTER)
+ | (1 << LOWERCASE_LETTER)
+ | (1 << DECIMAL_DIGIT_NUMBER))) != 0)
+ {
+ // Signedness doesn't matter; 0xffff vs. -1 are both rejected.
+ int digit = numValue[attr >> 7];
+ return (digit < radix) ? digit : -1;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the Unicode numeric value property of a character. For example,
+ * <code>'\\u216C'</code> (the Roman numeral fifty) returns 50.
+ *
+ * <p>This method also returns values for the letters A through Z, (not
+ * specified by Unicode), in these ranges: <code>'\u0041'</code>
+ * through <code>'\u005A'</code> (uppercase); <code>'\u0061'</code>
+ * through <code>'\u007A'</code> (lowercase); and <code>'\uFF21'</code>
+ * through <code>'\uFF3A'</code>, <code>'\uFF41'</code> through
+ * <code>'\uFF5A'</code> (full width variants).
+ *
+ * <p>If the character lacks a numeric value property, -1 is returned.
+ * If the character has a numeric value property which is not representable
+ * as a nonnegative integer, such as a fraction, -2 is returned.
+ *
+ * character argument boundary = [Nd]|[Nl]|[No]|U+0041-U+005A|U+0061-U+007A
+ * |U+FF21-U+FF3A|U+FF41-U+FF5A
+ *
+ * @param ch character from which the numeric value property will
+ * be retrieved
+ * @return the numeric value property of ch, or -1 if it does not exist, or
+ * -2 if it is not representable as a nonnegative integer
+ * @see #forDigit(int, int)
+ * @see #digit(char, int)
+ * @see #isDigit(char)
+ * @since 1.1
+ */
+ public static int getNumericValue(char ch)
+ {
+ // Treat numValue as signed.
+ return (short) numValue[readChar(ch) >> 7];
+ }
+
+ /**
+ * Determines if a character is a ISO-LATIN-1 space. This is only the five
+ * characters <code>'\t'</code>, <code>'\n'</code>, <code>'\f'</code>,
+ * <code>'\r'</code>, and <code>' '</code>.
+ * <br>
+ * Java space = U+0020|U+0009|U+000A|U+000C|U+000D
+ *
+ * @param ch character to test
+ * @return true if ch is a space, else false
+ * @deprecated Replaced by {@link #isWhitespace(char)}
+ * @see #isSpaceChar(char)
+ * @see #isWhitespace(char)
+ */
+ public static boolean isSpace(char ch)
+ {
+ // Performing the subtraction up front alleviates need to compare longs.
+ return ch-- <= ' ' && ((1 << ch)
+ & ((1 << (' ' - 1))
+ | (1 << ('\t' - 1))
+ | (1 << ('\n' - 1))
+ | (1 << ('\r' - 1))
+ | (1 << ('\f' - 1)))) != 0;
+ }
+
+ /**
+ * Determines if a character is a Unicode space character. This includes
+ * SPACE_SEPARATOR, LINE_SEPARATOR, and PARAGRAPH_SEPARATOR.
+ * <br>
+ * Unicode space = [Zs]|[Zp]|[Zl]
+ *
+ * @param ch character to test
+ * @return true if ch is a Unicode space, else false
+ * @see #isWhitespace(char)
+ * @since 1.1
+ */
+ public static boolean isSpaceChar(char ch)
+ {
+ return ((1 << getType(ch))
+ & ((1 << SPACE_SEPARATOR)
+ | (1 << LINE_SEPARATOR)
+ | (1 << PARAGRAPH_SEPARATOR))) != 0;
+ }
+
+ /**
+ * Determines if a character is Java whitespace. This includes Unicode
+ * space characters (SPACE_SEPARATOR, LINE_SEPARATOR, and
+ * PARAGRAPH_SEPARATOR) except the non-breaking spaces
+ * (<code>'\u00A0'</code>, <code>'\u2007'</code>, and <code>'\u202F'</code>);
+ * and these characters: <code>'\u0009'</code>, <code>'\u000A'</code>,
+ * <code>'\u000B'</code>, <code>'\u000C'</code>, <code>'\u000D'</code>,
+ * <code>'\u001C'</code>, <code>'\u001D'</code>, <code>'\u001E'</code>,
+ * and <code>'\u001F'</code>.
+ * <br>
+ * Java whitespace = ([Zs] not Nb)|[Zl]|[Zp]|U+0009-U+000D|U+001C-U+001F
+ *
+ * @param ch character to test
+ * @return true if ch is Java whitespace, else false
+ * @see #isSpaceChar(char)
+ * @since 1.1
+ */
+ public static boolean isWhitespace(char ch)
+ {
+ int attr = readChar(ch);
+ return ((((1 << (attr & TYPE_MASK))
+ & ((1 << SPACE_SEPARATOR)
+ | (1 << LINE_SEPARATOR)
+ | (1 << PARAGRAPH_SEPARATOR))) != 0)
+ && (attr & NO_BREAK_MASK) == 0)
+ || (ch <= '\u001F' && ((1 << ch)
+ & ((1 << '\t')
+ | (1 << '\n')
+ | (1 << '\u000B')
+ | (1 << '\u000C')
+ | (1 << '\r')
+ | (1 << '\u001C')
+ | (1 << '\u001D')
+ | (1 << '\u001E')
+ | (1 << '\u001F'))) != 0);
+ }
+
+ /**
+ * Determines if a character has the ISO Control property.
+ * <br>
+ * ISO Control = [Cc]
+ *
+ * @param ch character to test
+ * @return true if ch is an ISO Control character, else false
+ * @see #isSpaceChar(char)
+ * @see #isWhitespace(char)
+ * @since 1.1
+ */
+ public static boolean isISOControl(char ch)
+ {
+ return getType(ch) == CONTROL;
+ }
+
+ /**
+ * Returns the Unicode general category property of a character.
+ *
+ * @param ch character from which the general category property will
+ * be retrieved
+ * @return the character category property of ch as an integer
+ * @see #UNASSIGNED
+ * @see #UPPERCASE_LETTER
+ * @see #LOWERCASE_LETTER
+ * @see #TITLECASE_LETTER
+ * @see #MODIFIER_LETTER
+ * @see #OTHER_LETTER
+ * @see #NON_SPACING_MARK
+ * @see #ENCLOSING_MARK
+ * @see #COMBINING_SPACING_MARK
+ * @see #DECIMAL_DIGIT_NUMBER
+ * @see #LETTER_NUMBER
+ * @see #OTHER_NUMBER
+ * @see #SPACE_SEPARATOR
+ * @see #LINE_SEPARATOR
+ * @see #PARAGRAPH_SEPARATOR
+ * @see #CONTROL
+ * @see #FORMAT
+ * @see #PRIVATE_USE
+ * @see #SURROGATE
+ * @see #DASH_PUNCTUATION
+ * @see #START_PUNCTUATION
+ * @see #END_PUNCTUATION
+ * @see #CONNECTOR_PUNCTUATION
+ * @see #OTHER_PUNCTUATION
+ * @see #MATH_SYMBOL
+ * @see #CURRENCY_SYMBOL
+ * @see #MODIFIER_SYMBOL
+ * @see #INITIAL_QUOTE_PUNCTUATION
+ * @see #FINAL_QUOTE_PUNCTUATION
+ * @since 1.1
+ */
+ public static int getType(char ch)
+ {
+ return readChar(ch) & TYPE_MASK;
+ }
+
+ /**
+ * Converts a digit into a character which represents that digit
+ * in a specified radix. If the radix exceeds MIN_RADIX or MAX_RADIX,
+ * or the digit exceeds the radix, then the null character <code>'\0'</code>
+ * is returned. Otherwise the return value is in '0'-'9' and 'a'-'z'.
+ * <br>
+ * return value boundary = U+0030-U+0039|U+0061-U+007A
+ *
+ * @param digit digit to be converted into a character
+ * @param radix radix of digit
+ * @return character representing digit in radix, or '\0'
+ * @see #MIN_RADIX
+ * @see #MAX_RADIX
+ * @see #digit(char, int)
+ */
+ public static char forDigit(int digit, int radix)
+ {
+ if (radix < MIN_RADIX || radix > MAX_RADIX
+ || digit < 0 || digit >= radix)
+ return '\0';
+ return Number.digits[digit];
+ }
+
+ /**
+ * Returns the Unicode directionality property of the character. This
+ * is used in the visual ordering of text.
+ *
+ * @param ch the character to look up
+ * @return the directionality constant, or DIRECTIONALITY_UNDEFINED
+ * @see #DIRECTIONALITY_UNDEFINED
+ * @see #DIRECTIONALITY_LEFT_TO_RIGHT
+ * @see #DIRECTIONALITY_RIGHT_TO_LEFT
+ * @see #DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC
+ * @see #DIRECTIONALITY_EUROPEAN_NUMBER
+ * @see #DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR
+ * @see #DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR
+ * @see #DIRECTIONALITY_ARABIC_NUMBER
+ * @see #DIRECTIONALITY_COMMON_NUMBER_SEPARATOR
+ * @see #DIRECTIONALITY_NONSPACING_MARK
+ * @see #DIRECTIONALITY_BOUNDARY_NEUTRAL
+ * @see #DIRECTIONALITY_PARAGRAPH_SEPARATOR
+ * @see #DIRECTIONALITY_SEGMENT_SEPARATOR
+ * @see #DIRECTIONALITY_WHITESPACE
+ * @see #DIRECTIONALITY_OTHER_NEUTRALS
+ * @see #DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING
+ * @see #DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE
+ * @see #DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING
+ * @see #DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE
+ * @see #DIRECTIONALITY_POP_DIRECTIONAL_FORMAT
+ * @since 1.4
+ */
+ public static byte getDirectionality(char ch)
+ {
+ // The result will correctly be signed.
+ return (byte) (direction[readChar(ch) >> 7] >> 2);
+ }
+
+ /**
+ * Determines whether the character is mirrored according to Unicode. For
+ * example, <code>\u0028</code> (LEFT PARENTHESIS) appears as '(' in
+ * left-to-right text, but ')' in right-to-left text.
+ *
+ * @param ch the character to look up
+ * @return true if the character is mirrored
+ * @since 1.4
+ */
+ public static boolean isMirrored(char ch)
+ {
+ return (readChar(ch) & MIRROR_MASK) != 0;
+ }
+
+ /**
+ * Compares another Character to this Character, numerically.
+ *
+ * @param anotherCharacter Character to compare with this Character
+ * @return a negative integer if this Character is less than
+ * anotherCharacter, zero if this Character is equal, and
+ * a positive integer if this Character is greater
+ * @throws NullPointerException if anotherCharacter is null
+ * @since 1.2
+ */
+ public int compareTo(Character anotherCharacter)
+ {
+ return value - anotherCharacter.value;
+ }
+
+ /**
+ * Compares an object to this Character. Assuming the object is a
+ * Character object, this method performs the same comparison as
+ * compareTo(Character).
+ *
+ * @param o object to compare
+ * @return the comparison value
+ * @throws ClassCastException if o is not a Character object
+ * @throws NullPointerException if o is null
+ * @see #compareTo(Character)
+ * @since 1.2
+ */
+ public int compareTo(Object o)
+ {
+ return compareTo((Character) o);
+ }
+} // class Character
diff --git a/libjava/classpath/java/lang/Class.java b/libjava/classpath/java/lang/Class.java
new file mode 100644
index 00000000000..6b8bc93ae63
--- /dev/null
+++ b/libjava/classpath/java/lang/Class.java
@@ -0,0 +1,1324 @@
+/* Class.java -- Representation of a Java class.
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005
+ Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import gnu.classpath.VMStackWalker;
+
+import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+
+
+/**
+ * A Class represents a Java type. There will never be multiple Class
+ * objects with identical names and ClassLoaders. Primitive types, array
+ * types, and void also have a Class object.
+ *
+ * <p>Arrays with identical type and number of dimensions share the same class.
+ * The array class ClassLoader is the same as the ClassLoader of the element
+ * type of the array (which can be null to indicate the bootstrap classloader).
+ * The name of an array class is <code>[&lt;signature format&gt;;</code>.
+ * <p> For example,
+ * String[]'s class is <code>[Ljava.lang.String;</code>. boolean, byte,
+ * short, char, int, long, float and double have the "type name" of
+ * Z,B,S,C,I,J,F,D for the purposes of array classes. If it's a
+ * multidimensioned array, the same principle applies:
+ * <code>int[][][]</code> == <code>[[[I</code>.
+ *
+ * <p>There is no public constructor - Class objects are obtained only through
+ * the virtual machine, as defined in ClassLoaders.
+ *
+ * @serialData Class objects serialize specially:
+ * <code>TC_CLASS ClassDescriptor</code>. For more serialization information,
+ * see {@link ObjectStreamClass}.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @since 1.0
+ * @see ClassLoader
+ */
+public final class Class implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 3206093459760846163L;
+
+ /** The class signers. */
+ private Object[] signers = null;
+ /** The class protection domain. */
+ private final ProtectionDomain pd;
+
+ /* We use an inner class, so that Class doesn't have a static initializer */
+ private static final class StaticData
+ {
+ static final ProtectionDomain unknownProtectionDomain;
+
+ static
+ {
+ Permissions permissions = new Permissions();
+ permissions.add(new AllPermission());
+ unknownProtectionDomain = new ProtectionDomain(null, permissions);
+ }
+ }
+
+ final transient Object vmdata;
+
+ /** newInstance() caches the default constructor */
+ private transient Constructor constructor;
+
+ /**
+ * Class is non-instantiable from Java code; only the VM can create
+ * instances of this class.
+ */
+ Class(Object vmdata)
+ {
+ this(vmdata, null);
+ }
+
+ Class(Object vmdata, ProtectionDomain pd)
+ {
+ this.vmdata = vmdata;
+ // If the VM didn't supply a protection domain and the class is an array,
+ // we "inherit" the protection domain from the component type class. This
+ // saves the VM from having to worry about protection domains for array
+ // classes.
+ if (pd == null && isArray())
+ this.pd = getComponentType().pd;
+ else
+ this.pd = pd;
+ }
+
+ /**
+ * Use the classloader of the current class to load, link, and initialize
+ * a class. This is equivalent to your code calling
+ * <code>Class.forName(name, true, getClass().getClassLoader())</code>.
+ *
+ * @param name the name of the class to find
+ * @return the Class object representing the class
+ * @throws ClassNotFoundException if the class was not found by the
+ * classloader
+ * @throws LinkageError if linking the class fails
+ * @throws ExceptionInInitializerError if the class loads, but an exception
+ * occurs during initialization
+ */
+ public static Class forName(String name) throws ClassNotFoundException
+ {
+ Class result = VMClass.forName (name);
+ if (result == null)
+ result = Class.forName(name, true,
+ VMStackWalker.getCallingClassLoader());
+ return result;
+ }
+
+ /**
+ * Use the specified classloader to load and link a class. If the loader
+ * is null, this uses the bootstrap class loader (provide the security
+ * check succeeds). Unfortunately, this method cannot be used to obtain
+ * the Class objects for primitive types or for void, you have to use
+ * the fields in the appropriate java.lang wrapper classes.
+ *
+ * <p>Calls <code>classloader.loadclass(name, initialize)</code>.
+ *
+ * @param name the name of the class to find
+ * @param initialize whether or not to initialize the class at this time
+ * @param classloader the classloader to use to find the class; null means
+ * to use the bootstrap class loader
+ *
+ * @return the class object for the given class
+ *
+ * @throws ClassNotFoundException if the class was not found by the
+ * classloader
+ * @throws LinkageError if linking the class fails
+ * @throws ExceptionInInitializerError if the class loads, but an exception
+ * occurs during initialization
+ * @throws SecurityException if the <code>classloader</code> argument
+ * is <code>null</code> and the caller does not have the
+ * <code>RuntimePermission("getClassLoader")</code> permission
+ * @see ClassLoader
+ * @since 1.2
+ */
+ public static Class forName(String name, boolean initialize,
+ ClassLoader classloader)
+ throws ClassNotFoundException
+ {
+ if (classloader == null)
+ {
+ // Check if we may access the bootstrap classloader
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ {
+ // Get the calling classloader
+ ClassLoader cl = VMStackWalker.getCallingClassLoader();
+ if (cl != null)
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ }
+ if (name.startsWith("["))
+ return VMClass.loadArrayClass(name, null);
+ Class c = VMClassLoader.loadClass(name, true);
+ if (c != null)
+ {
+ if (initialize)
+ VMClass.initialize(c);
+ return c;
+ }
+ throw new ClassNotFoundException(name);
+ }
+ if (name.startsWith("["))
+ return VMClass.loadArrayClass(name, classloader);
+ Class c = classloader.loadClass(name);
+ classloader.resolveClass(c);
+ if (initialize)
+ VMClass.initialize(c);
+ return c;
+ }
+
+ /**
+ * Get all the public member classes and interfaces declared in this
+ * class or inherited from superclasses. This returns an array of length
+ * 0 if there are no member classes, including for primitive types. A
+ * security check may be performed, with
+ * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return all public member classes in this class
+ * @throws SecurityException if the security check fails
+ * @since 1.1
+ */
+ public Class[] getClasses()
+ {
+ memberAccessCheck(Member.PUBLIC);
+ return internalGetClasses();
+ }
+
+ /**
+ * Like <code>getClasses()</code> but without the security checks.
+ */
+ private Class[] internalGetClasses()
+ {
+ ArrayList list = new ArrayList();
+ list.addAll(Arrays.asList(getDeclaredClasses(true)));
+ Class superClass = getSuperclass();
+ if (superClass != null)
+ list.addAll(Arrays.asList(superClass.internalGetClasses()));
+ return (Class[])list.toArray(new Class[list.size()]);
+ }
+
+ /**
+ * Get the ClassLoader that loaded this class. If the class was loaded
+ * by the bootstrap classloader, this method will return null.
+ * If there is a security manager, and the caller's class loader is not
+ * an ancestor of the requested one, a security check of
+ * <code>RuntimePermission("getClassLoader")</code>
+ * must first succeed. Primitive types and void return null.
+ *
+ * @return the ClassLoader that loaded this class
+ * @throws SecurityException if the security check fails
+ * @see ClassLoader
+ * @see RuntimePermission
+ */
+ public ClassLoader getClassLoader()
+ {
+ if (isPrimitive())
+ return null;
+
+ ClassLoader loader = VMClass.getClassLoader(this);
+ // Check if we may get the classloader
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ {
+ // Get the calling classloader
+ ClassLoader cl = VMStackWalker.getCallingClassLoader();
+ if (cl != null && !cl.isAncestorOf(loader))
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ }
+ return loader;
+ }
+
+ /**
+ * If this is an array, get the Class representing the type of array.
+ * Examples: "[[Ljava.lang.String;" would return "[Ljava.lang.String;", and
+ * calling getComponentType on that would give "java.lang.String". If
+ * this is not an array, returns null.
+ *
+ * @return the array type of this class, or null
+ * @see Array
+ * @since 1.1
+ */
+ public Class getComponentType()
+ {
+ return VMClass.getComponentType (this);
+ }
+
+ /**
+ * Get a public constructor declared in this class. If the constructor takes
+ * no argument, an array of zero elements and null are equivalent for the
+ * types argument. A security check may be performed, with
+ * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @param types the type of each parameter
+ * @return the constructor
+ * @throws NoSuchMethodException if the constructor does not exist
+ * @throws SecurityException if the security check fails
+ * @see #getConstructors()
+ * @since 1.1
+ */
+ public Constructor getConstructor(Class[] types) throws NoSuchMethodException
+ {
+ memberAccessCheck(Member.PUBLIC);
+ Constructor[] constructors = getDeclaredConstructors(true);
+ for (int i = 0; i < constructors.length; i++)
+ {
+ Constructor constructor = constructors[i];
+ if (matchParameters(types, constructor.getParameterTypes()))
+ return constructor;
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /**
+ * Get all the public constructors of this class. This returns an array of
+ * length 0 if there are no constructors, including for primitive types,
+ * arrays, and interfaces. It does, however, include the default
+ * constructor if one was supplied by the compiler. A security check may
+ * be performed, with <code>checkMemberAccess(this, Member.PUBLIC)</code>
+ * as well as <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return all public constructors in this class
+ * @throws SecurityException if the security check fails
+ * @since 1.1
+ */
+ public Constructor[] getConstructors()
+ {
+ memberAccessCheck(Member.PUBLIC);
+ return getDeclaredConstructors(true);
+ }
+
+ /**
+ * Get a constructor declared in this class. If the constructor takes no
+ * argument, an array of zero elements and null are equivalent for the
+ * types argument. A security check may be performed, with
+ * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @param types the type of each parameter
+ * @return the constructor
+ * @throws NoSuchMethodException if the constructor does not exist
+ * @throws SecurityException if the security check fails
+ * @see #getDeclaredConstructors()
+ * @since 1.1
+ */
+ public Constructor getDeclaredConstructor(Class[] types)
+ throws NoSuchMethodException
+ {
+ memberAccessCheck(Member.DECLARED);
+ Constructor[] constructors = getDeclaredConstructors(false);
+ for (int i = 0; i < constructors.length; i++)
+ {
+ Constructor constructor = constructors[i];
+ if (matchParameters(types, constructor.getParameterTypes()))
+ return constructor;
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /**
+ * Get all the declared member classes and interfaces in this class, but
+ * not those inherited from superclasses. This returns an array of length
+ * 0 if there are no member classes, including for primitive types. A
+ * security check may be performed, with
+ * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return all declared member classes in this class
+ * @throws SecurityException if the security check fails
+ * @since 1.1
+ */
+ public Class[] getDeclaredClasses()
+ {
+ memberAccessCheck(Member.DECLARED);
+ return getDeclaredClasses(false);
+ }
+
+ Class[] getDeclaredClasses (boolean publicOnly)
+ {
+ return VMClass.getDeclaredClasses (this, publicOnly);
+ }
+
+ /**
+ * Get all the declared constructors of this class. This returns an array of
+ * length 0 if there are no constructors, including for primitive types,
+ * arrays, and interfaces. It does, however, include the default
+ * constructor if one was supplied by the compiler. A security check may
+ * be performed, with <code>checkMemberAccess(this, Member.DECLARED)</code>
+ * as well as <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return all constructors in this class
+ * @throws SecurityException if the security check fails
+ * @since 1.1
+ */
+ public Constructor[] getDeclaredConstructors()
+ {
+ memberAccessCheck(Member.DECLARED);
+ return getDeclaredConstructors(false);
+ }
+
+ Constructor[] getDeclaredConstructors (boolean publicOnly)
+ {
+ return VMClass.getDeclaredConstructors (this, publicOnly);
+ }
+
+ /**
+ * Get a field declared in this class, where name is its simple name. The
+ * implicit length field of arrays is not available. A security check may
+ * be performed, with <code>checkMemberAccess(this, Member.DECLARED)</code>
+ * as well as <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @param name the name of the field
+ * @return the field
+ * @throws NoSuchFieldException if the field does not exist
+ * @throws SecurityException if the security check fails
+ * @see #getDeclaredFields()
+ * @since 1.1
+ */
+ public Field getDeclaredField(String name) throws NoSuchFieldException
+ {
+ memberAccessCheck(Member.DECLARED);
+ Field[] fields = getDeclaredFields(false);
+ for (int i = 0; i < fields.length; i++)
+ {
+ if (fields[i].getName().equals(name))
+ return fields[i];
+ }
+ throw new NoSuchFieldException();
+ }
+
+ /**
+ * Get all the declared fields in this class, but not those inherited from
+ * superclasses. This returns an array of length 0 if there are no fields,
+ * including for primitive types. This does not return the implicit length
+ * field of arrays. A security check may be performed, with
+ * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return all declared fields in this class
+ * @throws SecurityException if the security check fails
+ * @since 1.1
+ */
+ public Field[] getDeclaredFields()
+ {
+ memberAccessCheck(Member.DECLARED);
+ return getDeclaredFields(false);
+ }
+
+ Field[] getDeclaredFields (boolean publicOnly)
+ {
+ return VMClass.getDeclaredFields (this, publicOnly);
+ }
+
+ /**
+ * Get a method declared in this class, where name is its simple name. The
+ * implicit methods of Object are not available from arrays or interfaces.
+ * Constructors (named "&lt;init&gt;" in the class file) and class initializers
+ * (name "&lt;clinit&gt;") are not available. The Virtual Machine allows
+ * multiple methods with the same signature but differing return types; in
+ * such a case the most specific return types are favored, then the final
+ * choice is arbitrary. If the method takes no argument, an array of zero
+ * elements and null are equivalent for the types argument. A security
+ * check may be performed, with
+ * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @param methodName the name of the method
+ * @param types the type of each parameter
+ * @return the method
+ * @throws NoSuchMethodException if the method does not exist
+ * @throws SecurityException if the security check fails
+ * @see #getDeclaredMethods()
+ * @since 1.1
+ */
+ public Method getDeclaredMethod(String methodName, Class[] types)
+ throws NoSuchMethodException
+ {
+ memberAccessCheck(Member.DECLARED);
+ Method match = matchMethod(getDeclaredMethods(false), methodName, types);
+ if (match == null)
+ throw new NoSuchMethodException(methodName);
+ return match;
+ }
+
+ /**
+ * Get all the declared methods in this class, but not those inherited from
+ * superclasses. This returns an array of length 0 if there are no methods,
+ * including for primitive types. This does include the implicit methods of
+ * arrays and interfaces which mirror methods of Object, nor does it
+ * include constructors or the class initialization methods. The Virtual
+ * Machine allows multiple methods with the same signature but differing
+ * return types; all such methods are in the returned array. A security
+ * check may be performed, with
+ * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return all declared methods in this class
+ * @throws SecurityException if the security check fails
+ * @since 1.1
+ */
+ public Method[] getDeclaredMethods()
+ {
+ memberAccessCheck(Member.DECLARED);
+ return getDeclaredMethods(false);
+ }
+
+ Method[] getDeclaredMethods (boolean publicOnly)
+ {
+ return VMClass.getDeclaredMethods (this, publicOnly);
+ }
+
+ /**
+ * If this is a nested or inner class, return the class that declared it.
+ * If not, return null.
+ *
+ * @return the declaring class of this class
+ * @since 1.1
+ */
+ public Class getDeclaringClass()
+ {
+ return VMClass.getDeclaringClass (this);
+ }
+
+ /**
+ * Get a public field declared or inherited in this class, where name is
+ * its simple name. If the class contains multiple accessible fields by
+ * that name, an arbitrary one is returned. The implicit length field of
+ * arrays is not available. A security check may be performed, with
+ * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @param fieldName the name of the field
+ * @return the field
+ * @throws NoSuchFieldException if the field does not exist
+ * @throws SecurityException if the security check fails
+ * @see #getFields()
+ * @since 1.1
+ */
+ public Field getField(String fieldName)
+ throws NoSuchFieldException
+ {
+ memberAccessCheck(Member.PUBLIC);
+ Field field = internalGetField(fieldName);
+ if (field == null)
+ throw new NoSuchFieldException(fieldName);
+ return field;
+ }
+
+ /**
+ * Get all the public fields declared in this class or inherited from
+ * superclasses. This returns an array of length 0 if there are no fields,
+ * including for primitive types. This does not return the implicit length
+ * field of arrays. A security check may be performed, with
+ * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return all public fields in this class
+ * @throws SecurityException if the security check fails
+ * @since 1.1
+ */
+ public Field[] getFields()
+ {
+ memberAccessCheck(Member.PUBLIC);
+ return internalGetFields();
+ }
+
+ /**
+ * Like <code>getFields()</code> but without the security checks.
+ */
+ private Field[] internalGetFields()
+ {
+ HashSet set = new HashSet();
+ set.addAll(Arrays.asList(getDeclaredFields(true)));
+ Class[] interfaces = getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ set.addAll(Arrays.asList(interfaces[i].internalGetFields()));
+ Class superClass = getSuperclass();
+ if (superClass != null)
+ set.addAll(Arrays.asList(superClass.internalGetFields()));
+ return (Field[])set.toArray(new Field[set.size()]);
+ }
+
+ /**
+ * Returns the <code>Package</code> in which this class is defined
+ * Returns null when this information is not available from the
+ * classloader of this class or when the classloader of this class
+ * is null.
+ *
+ * @return the package for this class, if it is available
+ * @since 1.2
+ */
+ public Package getPackage()
+ {
+ ClassLoader cl = getClassLoader();
+ if (cl != null)
+ return cl.getPackage(getPackagePortion(getName()));
+ return null;
+ }
+
+ /**
+ * Get the interfaces this class <em>directly</em> implements, in the
+ * order that they were declared. This returns an empty array, not null,
+ * for Object, primitives, void, and classes or interfaces with no direct
+ * superinterface. Array types return Cloneable and Serializable.
+ *
+ * @return the interfaces this class directly implements
+ */
+ public Class[] getInterfaces()
+ {
+ return VMClass.getInterfaces (this);
+ }
+
+ private static final class MethodKey
+ {
+ private String name;
+ private Class[] params;
+ private Class returnType;
+ private int hash;
+
+ MethodKey(Method m)
+ {
+ name = m.getName();
+ params = m.getParameterTypes();
+ returnType = m.getReturnType();
+ hash = name.hashCode() ^ returnType.hashCode();
+ for(int i = 0; i < params.length; i++)
+ {
+ hash ^= params[i].hashCode();
+ }
+ }
+
+ public boolean equals(Object o)
+ {
+ if(o instanceof MethodKey)
+ {
+ MethodKey m = (MethodKey)o;
+ if(m.name.equals(name) && m.params.length == params.length && m.returnType == returnType)
+ {
+ for(int i = 0; i < params.length; i++)
+ {
+ if(m.params[i] != params[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return hash;
+ }
+ }
+
+ /**
+ * Get a public method declared or inherited in this class, where name is
+ * its simple name. The implicit methods of Object are not available from
+ * interfaces. Constructors (named "&lt;init&gt;" in the class file) and class
+ * initializers (name "&lt;clinit&gt;") are not available. The Virtual
+ * Machine allows multiple methods with the same signature but differing
+ * return types, and the class can inherit multiple methods of the same
+ * return type; in such a case the most specific return types are favored,
+ * then the final choice is arbitrary. If the method takes no argument, an
+ * array of zero elements and null are equivalent for the types argument.
+ * A security check may be performed, with
+ * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @param methodName the name of the method
+ * @param types the type of each parameter
+ * @return the method
+ * @throws NoSuchMethodException if the method does not exist
+ * @throws SecurityException if the security check fails
+ * @see #getMethods()
+ * @since 1.1
+ */
+ public Method getMethod(String methodName, Class[] types)
+ throws NoSuchMethodException
+ {
+ memberAccessCheck(Member.PUBLIC);
+ Method method = internalGetMethod(methodName, types);
+ if (method == null)
+ throw new NoSuchMethodException(methodName);
+ return method;
+ }
+
+ /**
+ * Like <code>getMethod(String,Class[])</code> but without the security
+ * checks and returns null instead of throwing NoSuchMethodException.
+ */
+ private Method internalGetMethod(String methodName, Class[] args)
+ {
+ Method match = matchMethod(getDeclaredMethods(true), methodName, args);
+ if (match != null)
+ return match;
+ Class superClass = getSuperclass();
+ if (superClass != null)
+ {
+ match = superClass.internalGetMethod(methodName, args);
+ if(match != null)
+ return match;
+ }
+ Class[] interfaces = getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ {
+ match = interfaces[i].internalGetMethod(methodName, args);
+ if (match != null)
+ return match;
+ }
+ return null;
+ }
+
+ /**
+ * Find the best matching method in <code>list</code> according to
+ * the definition of ``best matching'' used by <code>getMethod()</code>
+ *
+ * <p>
+ * Returns the method if any, otherwise <code>null</code>.
+ *
+ * @param list List of methods to search
+ * @param name Name of method
+ * @param args Method parameter types
+ * @see #getMethod()
+ */
+ private static Method matchMethod(Method[] list, String name, Class[] args)
+ {
+ Method match = null;
+ for (int i = 0; i < list.length; i++)
+ {
+ Method method = list[i];
+ if (!method.getName().equals(name))
+ continue;
+ if (!matchParameters(args, method.getParameterTypes()))
+ continue;
+ if (match == null
+ || match.getReturnType().isAssignableFrom(method.getReturnType()))
+ match = method;
+ }
+ return match;
+ }
+
+ /**
+ * Check for an exact match between parameter type lists.
+ * Either list may be <code>null</code> to mean a list of
+ * length zero.
+ */
+ private static boolean matchParameters(Class[] types1, Class[] types2)
+ {
+ if (types1 == null)
+ return types2 == null || types2.length == 0;
+ if (types2 == null)
+ return types1 == null || types1.length == 0;
+ if (types1.length != types2.length)
+ return false;
+ for (int i = 0; i < types1.length; i++)
+ {
+ if (types1[i] != types2[i])
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get all the public methods declared in this class or inherited from
+ * superclasses. This returns an array of length 0 if there are no methods,
+ * including for primitive types. This does not include the implicit
+ * methods of interfaces which mirror methods of Object, nor does it
+ * include constructors or the class initialization methods. The Virtual
+ * Machine allows multiple methods with the same signature but differing
+ * return types; all such methods are in the returned array. A security
+ * check may be performed, with
+ * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as
+ * <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return all public methods in this class
+ * @throws SecurityException if the security check fails
+ * @since 1.1
+ */
+ public Method[] getMethods()
+ {
+ memberAccessCheck(Member.PUBLIC);
+ // NOTE the API docs claim that no methods are returned for arrays,
+ // but Sun's implementation *does* return the public methods of Object
+ // (as would be expected), so we follow their implementation instead
+ // of their documentation.
+ return internalGetMethods();
+ }
+
+ /**
+ * Like <code>getMethods()</code> but without the security checks.
+ */
+ private Method[] internalGetMethods()
+ {
+ HashMap map = new HashMap();
+ Method[] methods;
+ Class[] interfaces = getInterfaces();
+ for(int i = 0; i < interfaces.length; i++)
+ {
+ methods = interfaces[i].internalGetMethods();
+ for(int j = 0; j < methods.length; j++)
+ {
+ map.put(new MethodKey(methods[j]), methods[j]);
+ }
+ }
+ Class superClass = getSuperclass();
+ if(superClass != null)
+ {
+ methods = superClass.internalGetMethods();
+ for(int i = 0; i < methods.length; i++)
+ {
+ map.put(new MethodKey(methods[i]), methods[i]);
+ }
+ }
+ methods = getDeclaredMethods(true);
+ for(int i = 0; i < methods.length; i++)
+ {
+ map.put(new MethodKey(methods[i]), methods[i]);
+ }
+ return (Method[])map.values().toArray(new Method[map.size()]);
+ }
+
+ /**
+ * Get the modifiers of this class. These can be decoded using Modifier,
+ * and is limited to one of public, protected, or private, and any of
+ * final, static, abstract, or interface. An array class has the same
+ * public, protected, or private modifier as its component type, and is
+ * marked final but not an interface. Primitive types and void are marked
+ * public and final, but not an interface.
+ *
+ * @return the modifiers of this class
+ * @see Modifer
+ * @since 1.1
+ */
+ public int getModifiers()
+ {
+ return VMClass.getModifiers (this, false);
+ }
+
+ /**
+ * Get the name of this class, separated by dots for package separators.
+ * If the class represents a primitive type, or void, then the
+ * name of the type as it appears in the Java programming language
+ * is returned. For instance, <code>Byte.TYPE.getName()</code>
+ * returns "byte".
+ *
+ * Arrays are specially encoded as shown on this table.
+ * <pre>
+ * array type [<em>element type</em>
+ * (note that the element type is encoded per
+ * this table)
+ * boolean Z
+ * byte B
+ * char C
+ * short S
+ * int I
+ * long J
+ * float F
+ * double D
+ * void V
+ * class or interface, alone: &lt;dotted name&gt;
+ * class or interface, as element type: L&lt;dotted name&gt;;
+ * </pre>
+ *
+ * @return the name of this class
+ */
+ public String getName()
+ {
+ return VMClass.getName (this);
+ }
+
+ /**
+ * Get a resource URL using this class's package using the
+ * getClassLoader().getResource() method. If this class was loaded using
+ * the system classloader, ClassLoader.getSystemResource() is used instead.
+ *
+ * <p>If the name you supply is absolute (it starts with a <code>/</code>),
+ * then the leading <code>/</code> is removed and it is passed on to
+ * getResource(). If it is relative, the package name is prepended, and
+ * <code>.</code>'s are replaced with <code>/</code>.
+ *
+ * <p>The URL returned is system- and classloader-dependent, and could
+ * change across implementations.
+ *
+ * @param resourceName the name of the resource, generally a path
+ * @return the URL to the resource
+ * @throws NullPointerException if name is null
+ * @since 1.1
+ */
+ public URL getResource(String resourceName)
+ {
+ String name = resourcePath(resourceName);
+ ClassLoader loader = getClassLoader();
+ if (loader == null)
+ return ClassLoader.getSystemResource(name);
+ return loader.getResource(name);
+ }
+
+ /**
+ * Get a resource using this class's package using the
+ * getClassLoader().getResourceAsStream() method. If this class was loaded
+ * using the system classloader, ClassLoader.getSystemResource() is used
+ * instead.
+ *
+ * <p>If the name you supply is absolute (it starts with a <code>/</code>),
+ * then the leading <code>/</code> is removed and it is passed on to
+ * getResource(). If it is relative, the package name is prepended, and
+ * <code>.</code>'s are replaced with <code>/</code>.
+ *
+ * <p>The URL returned is system- and classloader-dependent, and could
+ * change across implementations.
+ *
+ * @param resourceName the name of the resource, generally a path
+ * @return an InputStream with the contents of the resource in it, or null
+ * @throws NullPointerException if name is null
+ * @since 1.1
+ */
+ public InputStream getResourceAsStream(String resourceName)
+ {
+ String name = resourcePath(resourceName);
+ ClassLoader loader = getClassLoader();
+ if (loader == null)
+ return ClassLoader.getSystemResourceAsStream(name);
+ return loader.getResourceAsStream(name);
+ }
+
+ private String resourcePath(String resourceName)
+ {
+ if (resourceName.length() > 0)
+ {
+ if (resourceName.charAt(0) != '/')
+ {
+ String pkg = getPackagePortion(getName());
+ if (pkg.length() > 0)
+ resourceName = pkg.replace('.','/') + '/' + resourceName;
+ }
+ else
+ {
+ resourceName = resourceName.substring(1);
+ }
+ }
+ return resourceName;
+ }
+
+ /**
+ * Get the signers of this class. This returns null if there are no signers,
+ * such as for primitive types or void.
+ *
+ * @return the signers of this class
+ * @since 1.1
+ */
+ public Object[] getSigners()
+ {
+ return signers == null ? null : (Object[]) signers.clone ();
+ }
+
+ /**
+ * Set the signers of this class.
+ *
+ * @param signers the signers of this class
+ */
+ void setSigners(Object[] signers)
+ {
+ this.signers = signers;
+ }
+
+ /**
+ * Get the direct superclass of this class. If this is an interface,
+ * Object, a primitive type, or void, it will return null. If this is an
+ * array type, it will return Object.
+ *
+ * @return the direct superclass of this class
+ */
+ public Class getSuperclass()
+ {
+ return VMClass.getSuperclass (this);
+ }
+
+ /**
+ * Return whether this class is an array type.
+ *
+ * @return whether this class is an array type
+ * @since 1.1
+ */
+ public boolean isArray()
+ {
+ return VMClass.isArray (this);
+ }
+
+ /**
+ * Discover whether an instance of the Class parameter would be an
+ * instance of this Class as well. Think of doing
+ * <code>isInstance(c.newInstance())</code> or even
+ * <code>c.newInstance() instanceof (this class)</code>. While this
+ * checks widening conversions for objects, it must be exact for primitive
+ * types.
+ *
+ * @param c the class to check
+ * @return whether an instance of c would be an instance of this class
+ * as well
+ * @throws NullPointerException if c is null
+ * @since 1.1
+ */
+ public boolean isAssignableFrom(Class c)
+ {
+ return VMClass.isAssignableFrom (this, c);
+ }
+
+ /**
+ * Discover whether an Object is an instance of this Class. Think of it
+ * as almost like <code>o instanceof (this class)</code>.
+ *
+ * @param o the Object to check
+ * @return whether o is an instance of this class
+ * @since 1.1
+ */
+ public boolean isInstance(Object o)
+ {
+ return VMClass.isInstance (this, o);
+ }
+
+ /**
+ * Check whether this class is an interface or not. Array types are not
+ * interfaces.
+ *
+ * @return whether this class is an interface or not
+ */
+ public boolean isInterface()
+ {
+ return VMClass.isInterface (this);
+ }
+
+ /**
+ * Return whether this class is a primitive type. A primitive type class
+ * is a class representing a kind of "placeholder" for the various
+ * primitive types, or void. You can access the various primitive type
+ * classes through java.lang.Boolean.TYPE, java.lang.Integer.TYPE, etc.,
+ * or through boolean.class, int.class, etc.
+ *
+ * @return whether this class is a primitive type
+ * @see Boolean#TYPE
+ * @see Byte#TYPE
+ * @see Character#TYPE
+ * @see Short#TYPE
+ * @see Integer#TYPE
+ * @see Long#TYPE
+ * @see Float#TYPE
+ * @see Double#TYPE
+ * @see Void#TYPE
+ * @since 1.1
+ */
+ public boolean isPrimitive()
+ {
+ return VMClass.isPrimitive (this);
+ }
+
+ /**
+ * Get a new instance of this class by calling the no-argument constructor.
+ * The class is initialized if it has not been already. A security check
+ * may be performed, with <code>checkMemberAccess(this, Member.PUBLIC)</code>
+ * as well as <code>checkPackageAccess</code> both having to succeed.
+ *
+ * @return a new instance of this class
+ * @throws InstantiationException if there is not a no-arg constructor
+ * for this class, including interfaces, abstract classes, arrays,
+ * primitive types, and void; or if an exception occurred during
+ * the constructor
+ * @throws IllegalAccessException if you are not allowed to access the
+ * no-arg constructor because of scoping reasons
+ * @throws SecurityException if the security check fails
+ * @throws ExceptionInInitializerError if class initialization caused by
+ * this call fails with an exception
+ */
+ public Object newInstance()
+ throws InstantiationException, IllegalAccessException
+ {
+ memberAccessCheck(Member.PUBLIC);
+ Constructor constructor;
+ synchronized(this)
+ {
+ constructor = this.constructor;
+ }
+ if (constructor == null)
+ {
+ Constructor[] constructors = getDeclaredConstructors(false);
+ for (int i = 0; i < constructors.length; i++)
+ {
+ if (constructors[i].getParameterTypes().length == 0)
+ {
+ constructor = constructors[i];
+ break;
+ }
+ }
+ if (constructor == null)
+ throw new InstantiationException(getName());
+ if (!Modifier.isPublic(constructor.getModifiers())
+ || !Modifier.isPublic(VMClass.getModifiers(this, true)))
+ {
+ final Constructor finalConstructor = constructor;
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ finalConstructor.setAccessible(true);
+ return null;
+ }
+ });
+ }
+ synchronized(this)
+ {
+ if (this.constructor == null)
+ this.constructor = constructor;
+ }
+ }
+ int modifiers = constructor.getModifiers();
+ if (!Modifier.isPublic(modifiers)
+ || !Modifier.isPublic(VMClass.getModifiers(this, true)))
+ {
+ Class caller = VMStackWalker.getCallingClass();
+ if (caller != null &&
+ caller != this &&
+ (Modifier.isPrivate(modifiers)
+ || getClassLoader() != caller.getClassLoader()
+ || !getPackagePortion(getName())
+ .equals(getPackagePortion(caller.getName()))))
+ throw new IllegalAccessException(getName()
+ + " has an inaccessible constructor");
+ }
+ try
+ {
+ return constructor.newInstance(null);
+ }
+ catch (InvocationTargetException e)
+ {
+ VMClass.throwException(e.getTargetException());
+ throw (InternalError) new InternalError
+ ("VMClass.throwException returned").initCause(e);
+ }
+ }
+
+ /**
+ * Returns the protection domain of this class. If the classloader did not
+ * record the protection domain when creating this class the unknown
+ * protection domain is returned which has a <code>null</code> code source
+ * and all permissions. A security check may be performed, with
+ * <code>RuntimePermission("getProtectionDomain")</code>.
+ *
+ * @return the protection domain
+ * @throws SecurityException if the security manager exists and the caller
+ * does not have <code>RuntimePermission("getProtectionDomain")</code>.
+ * @see RuntimePermission
+ * @since 1.2
+ */
+ public ProtectionDomain getProtectionDomain()
+ {
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("getProtectionDomain"));
+
+ return pd == null ? StaticData.unknownProtectionDomain : pd;
+ }
+
+ /**
+ * Return the human-readable form of this Object. For an object, this
+ * is either "interface " or "class " followed by <code>getName()</code>,
+ * for primitive types and void it is just <code>getName()</code>.
+ *
+ * @return the human-readable form of this Object
+ */
+ public String toString()
+ {
+ if (isPrimitive())
+ return getName();
+ return (isInterface() ? "interface " : "class ") + getName();
+ }
+
+ /**
+ * Returns the desired assertion status of this class, if it were to be
+ * initialized at this moment. The class assertion status, if set, is
+ * returned; the backup is the default package status; then if there is
+ * a class loader, that default is returned; and finally the system default
+ * is returned. This method seldom needs calling in user code, but exists
+ * for compilers to implement the assert statement. Note that there is no
+ * guarantee that the result of this method matches the class's actual
+ * assertion status.
+ *
+ * @return the desired assertion status
+ * @see ClassLoader#setClassAssertionStatus(String, boolean)
+ * @see ClassLoader#setPackageAssertionStatus(String, boolean)
+ * @see ClassLoader#setDefaultAssertionStatus(boolean)
+ * @since 1.4
+ */
+ public boolean desiredAssertionStatus()
+ {
+ ClassLoader c = getClassLoader();
+ Object status;
+ if (c == null)
+ return VMClassLoader.defaultAssertionStatus();
+ if (c.classAssertionStatus != null)
+ synchronized (c)
+ {
+ status = c.classAssertionStatus.get(getName());
+ if (status != null)
+ return status.equals(Boolean.TRUE);
+ }
+ else
+ {
+ status = ClassLoader.StaticData.
+ systemClassAssertionStatus.get(getName());
+ if (status != null)
+ return status.equals(Boolean.TRUE);
+ }
+ if (c.packageAssertionStatus != null)
+ synchronized (c)
+ {
+ String name = getPackagePortion(getName());
+ if ("".equals(name))
+ status = c.packageAssertionStatus.get(null);
+ else
+ do
+ {
+ status = c.packageAssertionStatus.get(name);
+ name = getPackagePortion(name);
+ }
+ while (! "".equals(name) && status == null);
+ if (status != null)
+ return status.equals(Boolean.TRUE);
+ }
+ else
+ {
+ String name = getPackagePortion(getName());
+ if ("".equals(name))
+ status = ClassLoader.StaticData.
+ systemPackageAssertionStatus.get(null);
+ else
+ do
+ {
+ status = ClassLoader.StaticData.
+ systemPackageAssertionStatus.get(name);
+ name = getPackagePortion(name);
+ }
+ while (! "".equals(name) && status == null);
+ if (status != null)
+ return status.equals(Boolean.TRUE);
+ }
+ return c.defaultAssertionStatus;
+ }
+
+ /**
+ * Like <code>getField(String)</code> but without the security checks and returns null
+ * instead of throwing NoSuchFieldException.
+ */
+ private Field internalGetField(String name)
+ {
+ Field[] fields = getDeclaredFields(true);
+ for (int i = 0; i < fields.length; i++)
+ {
+ Field field = fields[i];
+ if (field.getName().equals(name))
+ return field;
+ }
+ Class[] interfaces = getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ {
+ Field field = interfaces[i].internalGetField(name);
+ if(field != null)
+ return field;
+ }
+ Class superClass = getSuperclass();
+ if (superClass != null)
+ return superClass.internalGetField(name);
+ return null;
+ }
+
+ /**
+ * Strip the last portion of the name (after the last dot).
+ *
+ * @param name the name to get package of
+ * @return the package name, or "" if no package
+ */
+ private static String getPackagePortion(String name)
+ {
+ int lastInd = name.lastIndexOf('.');
+ if (lastInd == -1)
+ return "";
+ return name.substring(0, lastInd);
+ }
+
+ /**
+ * Perform security checks common to all of the methods that
+ * get members of this Class.
+ */
+ private void memberAccessCheck(int which)
+ {
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ {
+ sm.checkMemberAccess(this, which);
+ Package pkg = getPackage();
+ if (pkg != null)
+ sm.checkPackageAccess(pkg.getName());
+ }
+ }
+}
diff --git a/libjava/classpath/java/lang/ClassCastException.java b/libjava/classpath/java/lang/ClassCastException.java
new file mode 100644
index 00000000000..c490f42aaa8
--- /dev/null
+++ b/libjava/classpath/java/lang/ClassCastException.java
@@ -0,0 +1,76 @@
+/* ClassCastException.java -- exception thrown on bad cast
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when an attempt is made to cast an object which is not of the
+ * appropriate runtime type. For example:<br>
+ * <pre>
+ * Object o = new Vector();
+ * String s = (String) o;
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class ClassCastException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -9223365651070458532L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public ClassCastException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ClassCastException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/ClassCircularityError.java b/libjava/classpath/java/lang/ClassCircularityError.java
new file mode 100644
index 00000000000..ecdfb7aaf3a
--- /dev/null
+++ b/libjava/classpath/java/lang/ClassCircularityError.java
@@ -0,0 +1,73 @@
+/* ClassCircularityError.java -- thrown when linking circular classes
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>ClassCircularityError</code> is thrown when a circular dependency
+ * has been detected while initializing a class. This signals binary
+ * incompatible versions of class files, as the compiler normally catches this.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class ClassCircularityError extends LinkageError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 1054362542914539689L;
+
+ /**
+ * Create an error without a message.
+ */
+ public ClassCircularityError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public ClassCircularityError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/ClassFormatError.java b/libjava/classpath/java/lang/ClassFormatError.java
new file mode 100644
index 00000000000..7f90f5cd83e
--- /dev/null
+++ b/libjava/classpath/java/lang/ClassFormatError.java
@@ -0,0 +1,72 @@
+/* ClassFormatError.java -- thrown if a class file is invalid
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>ClassFormatError</code> is thrown when a Java Virtual Machine
+ * unable to read a class file because the file is corrupted or cannot be
+ * interpreted as a class file.
+ *
+ * @author Brian Jones
+ * @status updated to 1.4
+ */
+public class ClassFormatError extends LinkageError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -8420114879011949195L;
+
+ /**
+ * Create an error without a message.
+ */
+ public ClassFormatError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public ClassFormatError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/ClassLoader.java b/libjava/classpath/java/lang/ClassLoader.java
new file mode 100644
index 00000000000..b644511cf27
--- /dev/null
+++ b/libjava/classpath/java/lang/ClassLoader.java
@@ -0,0 +1,1116 @@
+/* ClassLoader.java -- responsible for loading classes into the VM
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.classpath.SystemProperties;
+import gnu.classpath.VMStackWalker;
+import gnu.java.util.DoubleEnumeration;
+import gnu.java.util.EmptyEnumeration;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * The ClassLoader is a way of customizing the way Java gets its classes
+ * and loads them into memory. The verifier and other standard Java things
+ * still run, but the ClassLoader is allowed great flexibility in determining
+ * where to get the classfiles and when to load and resolve them. For that
+ * matter, a custom ClassLoader can perform on-the-fly code generation or
+ * modification!
+ *
+ * <p>Every classloader has a parent classloader that is consulted before
+ * the 'child' classloader when classes or resources should be loaded.
+ * This is done to make sure that classes can be loaded from an hierarchy of
+ * multiple classloaders and classloaders do not accidentially redefine
+ * already loaded classes by classloaders higher in the hierarchy.
+ *
+ * <p>The grandparent of all classloaders is the bootstrap classloader, which
+ * loads all the standard system classes as implemented by GNU Classpath. The
+ * other special classloader is the system classloader (also called
+ * application classloader) that loads all classes from the CLASSPATH
+ * (<code>java.class.path</code> system property). The system classloader
+ * is responsible for finding the application classes from the classpath,
+ * and delegates all requests for the standard library classes to its parent
+ * the bootstrap classloader. Most programs will load all their classes
+ * through the system classloaders.
+ *
+ * <p>The bootstrap classloader in GNU Classpath is implemented as a couple of
+ * static (native) methods on the package private class
+ * <code>java.lang.VMClassLoader</code>, the system classloader is an
+ * anonymous inner class of ClassLoader and a subclass of
+ * <code>java.net.URLClassLoader</code>.
+ *
+ * <p>Users of a <code>ClassLoader</code> will normally just use the methods
+ * <ul>
+ * <li> <code>loadClass()</code> to load a class.</li>
+ * <li> <code>getResource()</code> or <code>getResourceAsStream()</code>
+ * to access a resource.</li>
+ * <li> <code>getResources()</code> to get an Enumeration of URLs to all
+ * the resources provided by the classloader and its parents with the
+ * same name.</li>
+ * </ul>
+ *
+ * <p>Subclasses should implement the methods
+ * <ul>
+ * <li> <code>findClass()</code> which is called by <code>loadClass()</code>
+ * when the parent classloader cannot provide a named class.</li>
+ * <li> <code>findResource()</code> which is called by
+ * <code>getResource()</code> when the parent classloader cannot provide
+ * a named resource.</li>
+ * <li> <code>findResources()</code> which is called by
+ * <code>getResource()</code> to combine all the resources with the
+ * same name from the classloader and its parents.</li>
+ * <li> <code>findLibrary()</code> which is called by
+ * <code>Runtime.loadLibrary()</code> when a class defined by the
+ * classloader wants to load a native library.</li>
+ * </ul>
+ *
+ * @author John Keiser
+ * @author Mark Wielaard
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Class
+ * @since 1.0
+ * @status still missing 1.4 functionality
+ */
+public abstract class ClassLoader
+{
+ /**
+ * All classes loaded by this classloader. VM's may choose to implement
+ * this cache natively; but it is here available for use if necessary. It
+ * is not private in order to allow native code (and trusted subclasses)
+ * access to this field.
+ */
+ final HashMap loadedClasses = new HashMap();
+
+ /**
+ * All packages defined by this classloader. It is not private in order to
+ * allow native code (and trusted subclasses) access to this field.
+ */
+ final HashMap definedPackages = new HashMap();
+
+ /**
+ * The classloader that is consulted before this classloader.
+ * If null then the parent is the bootstrap classloader.
+ */
+ private final ClassLoader parent;
+
+ /**
+ * This is true if this classloader was successfully initialized.
+ * This flag is needed to avoid a class loader attack: even if the
+ * security manager rejects an attempt to create a class loader, the
+ * malicious class could have a finalize method which proceeds to
+ * define classes.
+ */
+ private final boolean initialized;
+
+ static class StaticData
+ {
+ /**
+ * The System Class Loader (a.k.a. Application Class Loader). The one
+ * returned by ClassLoader.getSystemClassLoader.
+ */
+ static final ClassLoader systemClassLoader =
+ VMClassLoader.getSystemClassLoader();
+ static
+ {
+ // Find out if we have to install a default security manager. Note that
+ // this is done here because we potentially need the system class loader
+ // to load the security manager and note also that we don't need the
+ // security manager until the system class loader is created.
+ // If the runtime chooses to use a class loader that doesn't have the
+ // system class loader as its parent, it is responsible for setting
+ // up a security manager before doing so.
+ String secman = SystemProperties.getProperty("java.security.manager");
+ if (secman != null && SecurityManager.current == null)
+ {
+ if (secman.equals("") || secman.equals("default"))
+ {
+ SecurityManager.current = new SecurityManager();
+ }
+ else
+ {
+ try
+ {
+ Class cl = Class.forName(secman, false, StaticData.systemClassLoader);
+ SecurityManager.current = (SecurityManager)cl.newInstance();
+ }
+ catch (Exception x)
+ {
+ throw (InternalError)
+ new InternalError("Unable to create SecurityManager")
+ .initCause(x);
+ }
+ }
+ }
+ }
+
+ /**
+ * The default protection domain, used when defining a class with a null
+ * parameter for the domain.
+ */
+ static final ProtectionDomain defaultProtectionDomain;
+ static
+ {
+ CodeSource cs = new CodeSource(null, null);
+ PermissionCollection perm = Policy.getPolicy().getPermissions(cs);
+ defaultProtectionDomain = new ProtectionDomain(cs, perm);
+ }
+ /**
+ * The command-line state of the package assertion status overrides. This
+ * map is never modified, so it does not need to be synchronized.
+ */
+ // Package visible for use by Class.
+ static final Map systemPackageAssertionStatus
+ = VMClassLoader.packageAssertionStatus();
+ /**
+ * The command-line state of the class assertion status overrides. This
+ * map is never modified, so it does not need to be synchronized.
+ */
+ // Package visible for use by Class.
+ static final Map systemClassAssertionStatus
+ = VMClassLoader.classAssertionStatus();
+ }
+
+ /**
+ * The desired assertion status of classes loaded by this loader, if not
+ * overridden by package or class instructions.
+ */
+ // Package visible for use by Class.
+ boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus();
+
+ /**
+ * The map of package assertion status overrides, or null if no package
+ * overrides have been specified yet. The values of the map should be
+ * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented
+ * by the null key. This map must be synchronized on this instance.
+ */
+ // Package visible for use by Class.
+ Map packageAssertionStatus;
+
+ /**
+ * The map of class assertion status overrides, or null if no class
+ * overrides have been specified yet. The values of the map should be
+ * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this
+ * instance.
+ */
+ // Package visible for use by Class.
+ Map classAssertionStatus;
+
+ /**
+ * VM private data.
+ */
+ transient Object vmdata;
+
+ /**
+ * Create a new ClassLoader with as parent the system classloader. There
+ * may be a security check for <code>checkCreateClassLoader</code>.
+ *
+ * @throws SecurityException if the security check fails
+ */
+ protected ClassLoader() throws SecurityException
+ {
+ this(StaticData.systemClassLoader);
+ }
+
+ /**
+ * Create a new ClassLoader with the specified parent. The parent will
+ * be consulted when a class or resource is requested through
+ * <code>loadClass()</code> or <code>getResource()</code>. Only when the
+ * parent classloader cannot provide the requested class or resource the
+ * <code>findClass()</code> or <code>findResource()</code> method
+ * of this classloader will be called. There may be a security check for
+ * <code>checkCreateClassLoader</code>.
+ *
+ * @param parent the classloader's parent, or null for the bootstrap
+ * classloader
+ * @throws SecurityException if the security check fails
+ * @since 1.2
+ */
+ protected ClassLoader(ClassLoader parent)
+ {
+ // May we create a new classloader?
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ sm.checkCreateClassLoader();
+ this.parent = parent;
+ this.initialized = true;
+ }
+
+ /**
+ * Load a class using this ClassLoader or its parent, without resolving
+ * it. Calls <code>loadClass(name, false)</code>.
+ *
+ * <p>Subclasses should not override this method but should override
+ * <code>findClass()</code> which is called by this method.</p>
+ *
+ * @param name the name of the class relative to this ClassLoader
+ * @return the loaded class
+ * @throws ClassNotFoundException if the class cannot be found
+ */
+ public Class loadClass(String name) throws ClassNotFoundException
+ {
+ return loadClass(name, false);
+ }
+
+ /**
+ * Load a class using this ClassLoader or its parent, possibly resolving
+ * it as well using <code>resolveClass()</code>. It first tries to find
+ * out if the class has already been loaded through this classloader by
+ * calling <code>findLoadedClass()</code>. Then it calls
+ * <code>loadClass()</code> on the parent classloader (or when there is
+ * no parent it uses the VM bootclassloader). If the class is still
+ * not loaded it tries to create a new class by calling
+ * <code>findClass()</code>. Finally when <code>resolve</code> is
+ * <code>true</code> it also calls <code>resolveClass()</code> on the
+ * newly loaded class.
+ *
+ * <p>Subclasses should not override this method but should override
+ * <code>findClass()</code> which is called by this method.</p>
+ *
+ * @param name the fully qualified name of the class to load
+ * @param resolve whether or not to resolve the class
+ * @return the loaded class
+ * @throws ClassNotFoundException if the class cannot be found
+ */
+ protected synchronized Class loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ // Have we already loaded this class?
+ Class c = findLoadedClass(name);
+ if (c == null)
+ {
+ // Can the class be loaded by a parent?
+ try
+ {
+ if (parent == null)
+ {
+ c = VMClassLoader.loadClass(name, resolve);
+ if (c != null)
+ return c;
+ }
+ else
+ {
+ return parent.loadClass(name, resolve);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ }
+ // Still not found, we have to do it ourself.
+ c = findClass(name);
+ }
+ if (resolve)
+ resolveClass(c);
+ return c;
+ }
+
+ /**
+ * Called for every class name that is needed but has not yet been
+ * defined by this classloader or one of its parents. It is called by
+ * <code>loadClass()</code> after both <code>findLoadedClass()</code> and
+ * <code>parent.loadClass()</code> couldn't provide the requested class.
+ *
+ * <p>The default implementation throws a
+ * <code>ClassNotFoundException</code>. Subclasses should override this
+ * method. An implementation of this method in a subclass should get the
+ * class bytes of the class (if it can find them), if the package of the
+ * requested class doesn't exist it should define the package and finally
+ * it should call define the actual class. It does not have to resolve the
+ * class. It should look something like the following:<br>
+ *
+ * <pre>
+ * // Get the bytes that describe the requested class
+ * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name);
+ * // Get the package name
+ * int lastDot = name.lastIndexOf('.');
+ * if (lastDot != -1)
+ * {
+ * String packageName = name.substring(0, lastDot);
+ * // Look if the package already exists
+ * if (getPackage(packageName) == null)
+ * {
+ * // define the package
+ * definePackage(packageName, ...);
+ * }
+ * }
+ * // Define and return the class
+ * return defineClass(name, classBytes, 0, classBytes.length);
+ * </pre>
+ *
+ * <p><code>loadClass()</code> makes sure that the <code>Class</code>
+ * returned by <code>findClass()</code> will later be returned by
+ * <code>findLoadedClass()</code> when the same class name is requested.
+ *
+ * @param name class name to find (including the package name)
+ * @return the requested Class
+ * @throws ClassNotFoundException when the class can not be found
+ * @since 1.2
+ */
+ protected Class findClass(String name) throws ClassNotFoundException
+ {
+ throw new ClassNotFoundException(name);
+ }
+
+ /**
+ * Helper to define a class using a string of bytes. This version is not
+ * secure.
+ *
+ * @param data the data representing the classfile, in classfile format
+ * @param offset the offset into the data where the classfile starts
+ * @param len the length of the classfile data in the array
+ * @return the class that was defined
+ * @throws ClassFormatError if data is not in proper classfile format
+ * @throws IndexOutOfBoundsException if offset or len is negative, or
+ * offset + len exceeds data
+ * @deprecated use {@link #defineClass(String, byte[], int, int)} instead
+ */
+ protected final Class defineClass(byte[] data, int offset, int len)
+ throws ClassFormatError
+ {
+ return defineClass(null, data, offset, len);
+ }
+
+ /**
+ * Helper to define a class using a string of bytes without a
+ * ProtectionDomain. Subclasses should call this method from their
+ * <code>findClass()</code> implementation. The name should use '.'
+ * separators, and discard the trailing ".class". The default protection
+ * domain has the permissions of
+ * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>.
+ *
+ * @param name the name to give the class, or null if unknown
+ * @param data the data representing the classfile, in classfile format
+ * @param offset the offset into the data where the classfile starts
+ * @param len the length of the classfile data in the array
+ * @return the class that was defined
+ * @throws ClassFormatError if data is not in proper classfile format
+ * @throws IndexOutOfBoundsException if offset or len is negative, or
+ * offset + len exceeds data
+ * @throws SecurityException if name starts with "java."
+ * @since 1.1
+ */
+ protected final Class defineClass(String name, byte[] data, int offset,
+ int len) throws ClassFormatError
+ {
+ return defineClass(name, data, offset, len, null);
+ }
+
+ /**
+ * Helper to define a class using a string of bytes. Subclasses should call
+ * this method from their <code>findClass()</code> implementation. If the
+ * domain is null, the default of
+ * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>
+ * is used. Once a class has been defined in a package, all further classes
+ * in that package must have the same set of certificates or a
+ * SecurityException is thrown.
+ *
+ * @param name the name to give the class. null if unknown
+ * @param data the data representing the classfile, in classfile format
+ * @param offset the offset into the data where the classfile starts
+ * @param len the length of the classfile data in the array
+ * @param domain the ProtectionDomain to give to the class, null for the
+ * default protection domain
+ * @return the class that was defined
+ * @throws ClassFormatError if data is not in proper classfile format
+ * @throws IndexOutOfBoundsException if offset or len is negative, or
+ * offset + len exceeds data
+ * @throws SecurityException if name starts with "java.", or if certificates
+ * do not match up
+ * @since 1.2
+ */
+ protected final synchronized Class defineClass(String name, byte[] data,
+ int offset, int len,
+ ProtectionDomain domain)
+ throws ClassFormatError
+ {
+ if (domain == null)
+ domain = StaticData.defaultProtectionDomain;
+ if (! initialized)
+ throw new SecurityException("attempt to define class from uninitialized class loader");
+
+ Class retval = VMClassLoader.defineClass(this, name, data,
+ offset, len, domain);
+ loadedClasses.put(retval.getName(), retval);
+ return retval;
+ }
+
+ /**
+ * Links the class, if that has not already been done. Linking basically
+ * resolves all references to other classes made by this class.
+ *
+ * @param c the class to resolve
+ * @throws NullPointerException if c is null
+ * @throws LinkageError if linking fails
+ */
+ protected final void resolveClass(Class c)
+ {
+ VMClassLoader.resolveClass(c);
+ }
+
+ /**
+ * Helper to find a Class using the system classloader, possibly loading it.
+ * A subclass usually does not need to call this, if it correctly
+ * overrides <code>findClass(String)</code>.
+ *
+ * @param name the name of the class to find
+ * @return the found class
+ * @throws ClassNotFoundException if the class cannot be found
+ */
+ protected final Class findSystemClass(String name)
+ throws ClassNotFoundException
+ {
+ return Class.forName(name, false, StaticData.systemClassLoader);
+ }
+
+ /**
+ * Returns the parent of this classloader. If the parent of this
+ * classloader is the bootstrap classloader then this method returns
+ * <code>null</code>. A security check may be performed on
+ * <code>RuntimePermission("getClassLoader")</code>.
+ *
+ * @return the parent <code>ClassLoader</code>
+ * @throws SecurityException if the security check fails
+ * @since 1.2
+ */
+ public final ClassLoader getParent()
+ {
+ // Check if we may return the parent classloader.
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ {
+ ClassLoader cl = VMStackWalker.getCallingClassLoader();
+ if (cl != null && ! cl.isAncestorOf(this))
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ }
+ return parent;
+ }
+
+ /**
+ * Helper to set the signers of a class. This should be called after
+ * defining the class.
+ *
+ * @param c the Class to set signers of
+ * @param signers the signers to set
+ * @since 1.1
+ */
+ protected final void setSigners(Class c, Object[] signers)
+ {
+ c.setSigners(signers);
+ }
+
+ /**
+ * Helper to find an already-loaded class in this ClassLoader.
+ *
+ * @param name the name of the class to find
+ * @return the found Class, or null if it is not found
+ * @since 1.1
+ */
+ protected final synchronized Class findLoadedClass(String name)
+ {
+ // NOTE: If the VM is keeping its own cache, it may make sense to have
+ // this method be native.
+ return (Class) loadedClasses.get(name);
+ }
+
+ /**
+ * Get the URL to a resource using this classloader or one of its parents.
+ * First tries to get the resource by calling <code>getResource()</code>
+ * on the parent classloader. If the parent classloader returns null then
+ * it tries finding the resource by calling <code>findResource()</code> on
+ * this classloader. The resource name should be separated by '/' for path
+ * elements.
+ *
+ * <p>Subclasses should not override this method but should override
+ * <code>findResource()</code> which is called by this method.
+ *
+ * @param name the name of the resource relative to this classloader
+ * @return the URL to the resource or null when not found
+ */
+ public URL getResource(String name)
+ {
+ URL result;
+
+ if (parent == null)
+ result = VMClassLoader.getResource(name);
+ else
+ result = parent.getResource(name);
+
+ if (result == null)
+ result = findResource(name);
+ return result;
+ }
+
+ /**
+ * Returns an Enumeration of all resources with a given name that can
+ * be found by this classloader and its parents. Certain classloaders
+ * (such as the URLClassLoader when given multiple jar files) can have
+ * multiple resources with the same name that come from multiple locations.
+ * It can also occur that a parent classloader offers a resource with a
+ * certain name and the child classloader also offers a resource with that
+ * same name. <code>getResource()</code> only offers the first resource (of the
+ * parent) with a given name. This method lists all resources with the
+ * same name. The name should use '/' as path separators.
+ *
+ * <p>The Enumeration is created by first calling <code>getResources()</code>
+ * on the parent classloader and then calling <code>findResources()</code>
+ * on this classloader.</p>
+ *
+ * @param name the resource name
+ * @return an enumaration of all resources found
+ * @throws IOException if I/O errors occur in the process
+ * @since 1.2
+ */
+ public final Enumeration getResources(String name) throws IOException
+ {
+ Enumeration parentResources;
+ if (parent == null)
+ parentResources = VMClassLoader.getResources(name);
+ else
+ parentResources = parent.getResources(name);
+ return new DoubleEnumeration(parentResources, findResources(name));
+ }
+
+ /**
+ * Called whenever all locations of a named resource are needed.
+ * It is called by <code>getResources()</code> after it has called
+ * <code>parent.getResources()</code>. The results are combined by
+ * the <code>getResources()</code> method.
+ *
+ * <p>The default implementation always returns an empty Enumeration.
+ * Subclasses should override it when they can provide an Enumeration of
+ * URLs (possibly just one element) to the named resource.
+ * The first URL of the Enumeration should be the same as the one
+ * returned by <code>findResource</code>.
+ *
+ * @param name the name of the resource to be found
+ * @return a possibly empty Enumeration of URLs to the named resource
+ * @throws IOException if I/O errors occur in the process
+ * @since 1.2
+ */
+ protected Enumeration findResources(String name) throws IOException
+ {
+ return EmptyEnumeration.getInstance();
+ }
+
+ /**
+ * Called whenever a resource is needed that could not be provided by
+ * one of the parents of this classloader. It is called by
+ * <code>getResource()</code> after <code>parent.getResource()</code>
+ * couldn't provide the requested resource.
+ *
+ * <p>The default implementation always returns null. Subclasses should
+ * override this method when they can provide a way to return a URL
+ * to a named resource.
+ *
+ * @param name the name of the resource to be found
+ * @return a URL to the named resource or null when not found
+ * @since 1.2
+ */
+ protected URL findResource(String name)
+ {
+ return null;
+ }
+
+ /**
+ * Get the URL to a resource using the system classloader.
+ *
+ * @param name the name of the resource relative to the system classloader
+ * @return the URL to the resource
+ * @since 1.1
+ */
+ public static final URL getSystemResource(String name)
+ {
+ return StaticData.systemClassLoader.getResource(name);
+ }
+
+ /**
+ * Get an Enumeration of URLs to resources with a given name using the
+ * the system classloader. The enumeration firsts lists the resources with
+ * the given name that can be found by the bootstrap classloader followed
+ * by the resources with the given name that can be found on the classpath.
+ *
+ * @param name the name of the resource relative to the system classloader
+ * @return an Enumeration of URLs to the resources
+ * @throws IOException if I/O errors occur in the process
+ * @since 1.2
+ */
+ public static Enumeration getSystemResources(String name) throws IOException
+ {
+ return StaticData.systemClassLoader.getResources(name);
+ }
+
+ /**
+ * Get a resource as stream using this classloader or one of its parents.
+ * First calls <code>getResource()</code> and if that returns a URL to
+ * the resource then it calls and returns the InputStream given by
+ * <code>URL.openStream()</code>.
+ *
+ * <p>Subclasses should not override this method but should override
+ * <code>findResource()</code> which is called by this method.
+ *
+ * @param name the name of the resource relative to this classloader
+ * @return an InputStream to the resource, or null
+ * @since 1.1
+ */
+ public InputStream getResourceAsStream(String name)
+ {
+ try
+ {
+ URL url = getResource(name);
+ if (url == null)
+ return null;
+ return url.openStream();
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Get a resource using the system classloader.
+ *
+ * @param name the name of the resource relative to the system classloader
+ * @return an input stream for the resource, or null
+ * @since 1.1
+ */
+ public static final InputStream getSystemResourceAsStream(String name)
+ {
+ try
+ {
+ URL url = getSystemResource(name);
+ if (url == null)
+ return null;
+ return url.openStream();
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the system classloader. The system classloader (also called
+ * the application classloader) is the classloader that is used to
+ * load the application classes on the classpath (given by the system
+ * property <code>java.class.path</code>. This is set as the context
+ * class loader for a thread. The system property
+ * <code>java.system.class.loader</code>, if defined, is taken to be the
+ * name of the class to use as the system class loader, which must have
+ * a public constructor which takes a ClassLoader as a parent. The parent
+ * class loader passed in the constructor is the default system class
+ * loader.
+ *
+ * <p>Note that this is different from the bootstrap classloader that
+ * actually loads all the real "system" classes.
+ *
+ * <p>A security check will be performed for
+ * <code>RuntimePermission("getClassLoader")</code> if the calling class
+ * is not a parent of the system class loader.
+ *
+ * @return the system class loader
+ * @throws SecurityException if the security check fails
+ * @throws IllegalStateException if this is called recursively
+ * @throws Error if <code>java.system.class.loader</code> fails to load
+ * @since 1.2
+ */
+ public static ClassLoader getSystemClassLoader()
+ {
+ // Check if we may return the system classloader
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ {
+ ClassLoader cl = VMStackWalker.getCallingClassLoader();
+ if (cl != null && cl != StaticData.systemClassLoader)
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ }
+
+ return StaticData.systemClassLoader;
+ }
+
+ /**
+ * Defines a new package and creates a Package object. The package should
+ * be defined before any class in the package is defined with
+ * <code>defineClass()</code>. The package should not yet be defined
+ * before in this classloader or in one of its parents (which means that
+ * <code>getPackage()</code> should return <code>null</code>). All
+ * parameters except the <code>name</code> of the package may be
+ * <code>null</code>.
+ *
+ * <p>Subclasses should call this method from their <code>findClass()</code>
+ * implementation before calling <code>defineClass()</code> on a Class
+ * in a not yet defined Package (which can be checked by calling
+ * <code>getPackage()</code>).
+ *
+ * @param name the name of the Package
+ * @param specTitle the name of the specification
+ * @param specVendor the name of the specification designer
+ * @param specVersion the version of this specification
+ * @param implTitle the name of the implementation
+ * @param implVendor the vendor that wrote this implementation
+ * @param implVersion the version of this implementation
+ * @param sealed if sealed the origin of the package classes
+ * @return the Package object for the specified package
+ * @throws IllegalArgumentException if the package name is null or it
+ * was already defined by this classloader or one of its parents
+ * @see Package
+ * @since 1.2
+ */
+ protected Package definePackage(String name, String specTitle,
+ String specVendor, String specVersion,
+ String implTitle, String implVendor,
+ String implVersion, URL sealed)
+ {
+ if (getPackage(name) != null)
+ throw new IllegalArgumentException("Package " + name
+ + " already defined");
+ Package p = new Package(name, specTitle, specVendor, specVersion,
+ implTitle, implVendor, implVersion, sealed);
+ synchronized (definedPackages)
+ {
+ definedPackages.put(name, p);
+ }
+ return p;
+ }
+
+ /**
+ * Returns the Package object for the requested package name. It returns
+ * null when the package is not defined by this classloader or one of its
+ * parents.
+ *
+ * @param name the package name to find
+ * @return the package, if defined
+ * @since 1.2
+ */
+ protected Package getPackage(String name)
+ {
+ Package p;
+ if (parent == null)
+ p = VMClassLoader.getPackage(name);
+ else
+ p = parent.getPackage(name);
+
+ if (p == null)
+ {
+ synchronized (definedPackages)
+ {
+ p = (Package) definedPackages.get(name);
+ }
+ }
+ return p;
+ }
+
+ /**
+ * Returns all Package objects defined by this classloader and its parents.
+ *
+ * @return an array of all defined packages
+ * @since 1.2
+ */
+ protected Package[] getPackages()
+ {
+ // Get all our packages.
+ Package[] packages;
+ synchronized(definedPackages)
+ {
+ packages = new Package[definedPackages.size()];
+ definedPackages.values().toArray(packages);
+ }
+
+ // If we have a parent get all packages defined by our parents.
+ Package[] parentPackages;
+ if (parent == null)
+ parentPackages = VMClassLoader.getPackages();
+ else
+ parentPackages = parent.getPackages();
+
+ Package[] allPackages = new Package[parentPackages.length
+ + packages.length];
+ System.arraycopy(parentPackages, 0, allPackages, 0,
+ parentPackages.length);
+ System.arraycopy(packages, 0, allPackages, parentPackages.length,
+ packages.length);
+ return allPackages;
+ }
+
+ /**
+ * Called by <code>Runtime.loadLibrary()</code> to get an absolute path
+ * to a (system specific) library that was requested by a class loaded
+ * by this classloader. The default implementation returns
+ * <code>null</code>. It should be implemented by subclasses when they
+ * have a way to find the absolute path to a library. If this method
+ * returns null the library is searched for in the default locations
+ * (the directories listed in the <code>java.library.path</code> system
+ * property).
+ *
+ * @param name the (system specific) name of the requested library
+ * @return the full pathname to the requested library, or null
+ * @see Runtime#loadLibrary()
+ * @since 1.2
+ */
+ protected String findLibrary(String name)
+ {
+ return null;
+ }
+
+ /**
+ * Set the default assertion status for classes loaded by this classloader,
+ * used unless overridden by a package or class request.
+ *
+ * @param enabled true to set the default to enabled
+ * @see #setClassAssertionStatus(String, boolean)
+ * @see #setPackageAssertionStatus(String, boolean)
+ * @see #clearAssertionStatus()
+ * @since 1.4
+ */
+ public void setDefaultAssertionStatus(boolean enabled)
+ {
+ defaultAssertionStatus = enabled;
+ }
+
+ /**
+ * Set the default assertion status for packages, used unless overridden
+ * by a class request. This default also covers subpackages, unless they
+ * are also specified. The unnamed package should use null for the name.
+ *
+ * @param name the package (and subpackages) to affect
+ * @param enabled true to set the default to enabled
+ * @see #setDefaultAssertionStatus(String, boolean)
+ * @see #setClassAssertionStatus(String, boolean)
+ * @see #clearAssertionStatus()
+ * @since 1.4
+ */
+ public synchronized void setPackageAssertionStatus(String name,
+ boolean enabled)
+ {
+ if (packageAssertionStatus == null)
+ packageAssertionStatus
+ = new HashMap(StaticData.systemPackageAssertionStatus);
+ packageAssertionStatus.put(name, Boolean.valueOf(enabled));
+ }
+
+ /**
+ * Set the default assertion status for a class. This only affects the
+ * status of top-level classes, any other string is harmless.
+ *
+ * @param name the class to affect
+ * @param enabled true to set the default to enabled
+ * @throws NullPointerException if name is null
+ * @see #setDefaultAssertionStatus(String, boolean)
+ * @see #setPackageAssertionStatus(String, boolean)
+ * @see #clearAssertionStatus()
+ * @since 1.4
+ */
+ public synchronized void setClassAssertionStatus(String name,
+ boolean enabled)
+ {
+ if (classAssertionStatus == null)
+ classAssertionStatus =
+ new HashMap(StaticData.systemClassAssertionStatus);
+ // The toString() hack catches null, as required.
+ classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled));
+ }
+
+ /**
+ * Resets the default assertion status of this classloader, its packages
+ * and classes, all to false. This allows overriding defaults inherited
+ * from the command line.
+ *
+ * @see #setDefaultAssertionStatus(boolean)
+ * @see #setClassAssertionStatus(String, boolean)
+ * @see #setPackageAssertionStatus(String, boolean)
+ * @since 1.4
+ */
+ public synchronized void clearAssertionStatus()
+ {
+ defaultAssertionStatus = false;
+ packageAssertionStatus = new HashMap();
+ classAssertionStatus = new HashMap();
+ }
+
+ /**
+ * Return true if this loader is either the specified class loader
+ * or an ancestor thereof.
+ * @param loader the class loader to check
+ */
+ final boolean isAncestorOf(ClassLoader loader)
+ {
+ while (loader != null)
+ {
+ if (this == loader)
+ return true;
+ loader = loader.parent;
+ }
+ return false;
+ }
+
+ private static URL[] getExtClassLoaderUrls()
+ {
+ String classpath = SystemProperties.getProperty("java.ext.dirs", "");
+ StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator);
+ ArrayList list = new ArrayList();
+ while (tok.hasMoreTokens())
+ {
+ try
+ {
+ File f = new File(tok.nextToken());
+ File[] files = f.listFiles();
+ if (files != null)
+ for (int i = 0; i < files.length; i++)
+ list.add(files[i].toURL());
+ }
+ catch(Exception x)
+ {
+ }
+ }
+ URL[] urls = new URL[list.size()];
+ list.toArray(urls);
+ return urls;
+ }
+
+ private static void addFileURL(ArrayList list, String file)
+ {
+ try
+ {
+ list.add(new File(file).toURL());
+ }
+ catch(java.net.MalformedURLException x)
+ {
+ }
+ }
+
+ private static URL[] getSystemClassLoaderUrls()
+ {
+ String classpath = SystemProperties.getProperty("java.class.path", ".");
+ StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator, true);
+ ArrayList list = new ArrayList();
+ while (tok.hasMoreTokens())
+ {
+ String s = tok.nextToken();
+ if (s.equals(File.pathSeparator))
+ addFileURL(list, ".");
+ else
+ {
+ addFileURL(list, s);
+ if (tok.hasMoreTokens())
+ {
+ // Skip the separator.
+ tok.nextToken();
+ // If the classpath ended with a separator,
+ // append the current directory.
+ if (!tok.hasMoreTokens())
+ addFileURL(list, ".");
+ }
+ }
+ }
+ URL[] urls = new URL[list.size()];
+ list.toArray(urls);
+ return urls;
+ }
+
+ static ClassLoader defaultGetSystemClassLoader()
+ {
+ return createAuxiliarySystemClassLoader(
+ createSystemClassLoader(getSystemClassLoaderUrls(),
+ createExtClassLoader(getExtClassLoaderUrls(), null)));
+ }
+
+ static ClassLoader createExtClassLoader(URL[] urls, ClassLoader parent)
+ {
+ if (urls.length > 0)
+ return new URLClassLoader(urls, parent);
+ else
+ return parent;
+ }
+
+ static ClassLoader createSystemClassLoader(URL[] urls, ClassLoader parent)
+ {
+ return
+ new URLClassLoader(urls, parent)
+ {
+ protected synchronized Class loadClass(String name,
+ boolean resolve)
+ throws ClassNotFoundException
+ {
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ {
+ int lastDot = name.lastIndexOf('.');
+ if (lastDot != -1)
+ sm.checkPackageAccess(name.substring(0, lastDot));
+ }
+ return super.loadClass(name, resolve);
+ }
+ };
+ }
+
+ static ClassLoader createAuxiliarySystemClassLoader(ClassLoader parent)
+ {
+ String loader = SystemProperties.getProperty("java.system.class.loader", null);
+ if (loader == null)
+ {
+ return parent;
+ }
+ try
+ {
+ Constructor c = Class.forName(loader, false, parent)
+ .getConstructor(new Class[] { ClassLoader.class });
+ return (ClassLoader)c.newInstance(new Object[] { parent });
+ }
+ catch (Exception e)
+ {
+ System.err.println("Requested system classloader " + loader + " failed.");
+ throw (Error)
+ new Error("Requested system classloader " + loader + " failed.")
+ .initCause(e);
+ }
+ }
+}
diff --git a/libjava/classpath/java/lang/ClassNotFoundException.java b/libjava/classpath/java/lang/ClassNotFoundException.java
new file mode 100644
index 00000000000..6b6ae949dd2
--- /dev/null
+++ b/libjava/classpath/java/lang/ClassNotFoundException.java
@@ -0,0 +1,125 @@
+/* ClassNotFoundException.java -- thrown when class definition cannot be found
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when a class is requested by reflection, but the class definition
+ * cannot be found. This exception is often chained from another Throwable.
+ *
+ * @author Brian Jones
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Class#forName(String)
+ * @see ClassLoader#findSystemClass(String)
+ * @see ClassLoader#loadClass(String, boolean)
+ * @status updated to 1.4
+ */
+public class ClassNotFoundException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 9176873029745254542L;
+
+ /**
+ * The cause of this exception (duplicates the one stored in Throwable).
+ *
+ * @serial the exception cause
+ * @since 1.2
+ */
+ private final Throwable ex;
+
+ /**
+ * Create an exception without a message. Note that this initializes the
+ * cause to null.
+ */
+ public ClassNotFoundException()
+ {
+ this(null, null);
+ }
+
+ /**
+ * Create an exception with a message. Note that this initializes the
+ * cause to null.
+ *
+ * @param s the message
+ */
+ public ClassNotFoundException(String s)
+ {
+ this(s, null);
+ }
+
+ /**
+ * Create an exception with a message and chain it to the exception
+ * which occurred while loading the class.
+ *
+ * @param s the message
+ * @param ex the chained exception
+ * @since 1.2
+ */
+ public ClassNotFoundException(String s, Throwable ex)
+ {
+ super(s, ex);
+ this.ex = ex;
+ }
+
+ /**
+ * Returns the exception which occurred while loading the class,
+ * otherwise returns null. This is a legacy method; the preferred choice
+ * now is {@link Throwable#getCause()}.
+ *
+ * @return the cause of this exception
+ * @since 1.2
+ */
+ public Throwable getException()
+ {
+ return ex;
+ }
+
+ /**
+ * Returns the exception which occurred while loading the class,
+ * otherwise returns null.
+ *
+ * @return the cause of this exception
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return ex;
+ }
+}
diff --git a/libjava/classpath/java/lang/CloneNotSupportedException.java b/libjava/classpath/java/lang/CloneNotSupportedException.java
new file mode 100644
index 00000000000..9d10cf389f9
--- /dev/null
+++ b/libjava/classpath/java/lang/CloneNotSupportedException.java
@@ -0,0 +1,92 @@
+/* CloneNotSupportedException.java -- thrown when an object cannot be cloned
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown to indicate an object should not or could not be cloned. This
+ * includes the case when {@link Object#clone()} is called on an object
+ * which does not implement the {@link Cloneable} interface. For example:<br>
+ * <pre>
+ * void m() throws CloneNotSupportedException
+ * {
+ * clone();
+ * }
+ * </pre>
+ *
+ * <p>Notice that calling <code>clone()</code> on an array will never produce
+ * this exception, as the VM will always succeed in copying the array, or
+ * cause an OutOfMemoryError first. For example:<br>
+ * <pre>
+ * void m(int[] array)
+ * {
+ * int[] copy = (int[]) array.clone();
+ * }
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Cloneable
+ * @see Object#clone()
+ * @status updated to 1.4
+ */
+public class CloneNotSupportedException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 5195511250079656443L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public CloneNotSupportedException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the error message
+ */
+ public CloneNotSupportedException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/Cloneable.java b/libjava/classpath/java/lang/Cloneable.java
new file mode 100644
index 00000000000..10f20ce3b6e
--- /dev/null
+++ b/libjava/classpath/java/lang/Cloneable.java
@@ -0,0 +1,78 @@
+/* Cloneable.java -- Interface for marking objects cloneable by Object.clone()
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * This interface should be implemented by classes wishing to
+ * support of override <code>Object.clone()</code>. The default
+ * behaviour of <code>clone()</code> performs a shallow copy, but
+ * subclasses often change this to perform a deep copy. Therefore,
+ * it is a good idea to document how deep your clone will go.
+ * If <code>clone()</code> is called on an object which does not
+ * implement this interface, a <code>CloneNotSupportedException</code>
+ * will be thrown.
+ *
+ * <p>This interface is simply a tagging interface; it carries no
+ * requirements on methods to implement. However, it is typical for
+ * a Cloneable class to implement at least <code>equals</code>,
+ * <code>hashCode</code>, and <code>clone</code>, sometimes
+ * increasing the accessibility of clone to be public. The typical
+ * implementation of <code>clone</code> invokes <code>super.clone()</code>
+ * rather than a constructor, but this is not a requirement.
+ *
+ * <p>If an object that implement Cloneable should not be cloned,
+ * simply override the <code>clone</code> method to throw a
+ * <code>CloneNotSupportedException</code>.
+ *
+ * <p>All array types implement Cloneable, and have a public
+ * <code>clone</code> method that will never fail with a
+ * <code>CloneNotSupportedException</code>.
+ *
+ * @author Paul Fisher
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see Object#clone()
+ * @see CloneNotSupportedException
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface Cloneable
+{
+ // Tagging interface only.
+}
diff --git a/libjava/classpath/java/lang/Comparable.java b/libjava/classpath/java/lang/Comparable.java
new file mode 100644
index 00000000000..a8afe1ec33e
--- /dev/null
+++ b/libjava/classpath/java/lang/Comparable.java
@@ -0,0 +1,98 @@
+/* Comparable.java -- Interface for comparaing objects to obtain an ordering
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Interface for objects that can be ordering among other objects. The
+ * ordering can be <em>total</em>, such that two objects only compare equal
+ * if they are also equal by the equals method, or <em>partial</em> such
+ * that this is not necessarily true. For example, a case-sensitive
+ * dictionary order comparison of Strings is total, but if it is
+ * case-insensitive it is partial, because "abc" and "ABC" compare as
+ * equal even though "abc".equals("ABC") returns false. However, if you use
+ * a partial ordering, it is a good idea to document your class as
+ * "inconsistent with equals", because the behavior of your class in a
+ * SortedMap will be different than in a HashMap.
+ *
+ * <p>Lists, arrays, and sets of objects that implement this interface can
+ * be sorted automatically, without the need for an explicit
+ * {@link java.util.Comparator}. Note that <code>e1.compareTo(null)</code>
+ * should throw an Exception; as should comparison between incompatible
+ * classes.
+ *
+ * @author Geoff Berry
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see java.util.Comparator
+ * @see java.util.Collections#sort(java.util.List)
+ * @see java.util.Arrays#sort(Object[])
+ * @see java.util.SortedSet
+ * @see java.util.SortedMap
+ * @see java.util.TreeSet
+ * @see java.util.TreeMap
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Comparable
+{
+ /**
+ * Compares this object with another, and returns a numerical result based
+ * on the comparison. If the result is negative, this object sorts less
+ * than the other; if 0, the two are equal, and if positive, this object
+ * sorts greater than the other. To translate this into boolean, simply
+ * perform <code>o1.compareTo(o2) <em>&lt;op&gt;</em> 0</code>, where op
+ * is one of &lt;, &lt;=, =, !=, &gt;, or &gt;=.
+ *
+ * <p>You must make sure that the comparison is mutual, ie.
+ * <code>sgn(x.compareTo(y)) == -sgn(y.compareTo(x))</code> (where sgn() is
+ * defined as -1, 0, or 1 based on the sign). This includes throwing an
+ * exception in either direction if the two are not comparable; hence,
+ * <code>compareTo(null)</code> should always throw an Exception.
+ *
+ * <p>You should also ensure transitivity, in two forms:
+ * <code>x.compareTo(y) &gt; 0 && y.compareTo(z) &gt; 0</code> implies
+ * <code>x.compareTo(z) &gt; 0</code>; and <code>x.compareTo(y) == 0</code>
+ * implies <code>x.compareTo(z) == y.compareTo(z)</code>.
+ *
+ * @param o the object to be compared
+ * @return an integer describing the comparison
+ * @throws NullPointerException if o is null
+ * @throws ClassCastException if o cannot be compared
+ */
+ int compareTo(Object o);
+}
diff --git a/libjava/classpath/java/lang/Compiler.java b/libjava/classpath/java/lang/Compiler.java
new file mode 100644
index 00000000000..56fb951bbd9
--- /dev/null
+++ b/libjava/classpath/java/lang/Compiler.java
@@ -0,0 +1,127 @@
+/* Compiler.java -- placeholder for Java-to-native runtime compilers
+ Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * The <code>Compiler</code> class is a placeholder for a JIT compiler
+ * implementation, and does nothing unless there is such a compiler.
+ *
+ * <p>The system property <code>java.compiler</code> may contain the name
+ * of a library to load with <code>System.loadLibrary</code> when the
+ * virtual machine first starts. If so, and loading the library succeeds,
+ * then a function by the name of <code>java_lang_Compiler_start()</code>
+ * in that library is called.
+ *
+ * <p>Note that a VM might not have implemented any of this.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see System#getProperty(String)
+ * @see System#getProperty(String, String)
+ * @see System#loadLibrary(String)
+ * @since JDK 1.0
+ * @status updated to 1.4
+ */
+public final class Compiler
+{
+ /**
+ * Don't allow new `Compiler's to be made.
+ */
+ private Compiler()
+ {
+ }
+
+ /**
+ * Compile the class named by <code>oneClass</code>.
+ *
+ * @param oneClass the class to compile
+ * @return <code>false</code> if no compiler is available or
+ * compilation failed, <code>true</code> if compilation succeeded
+ * @throws NullPointerException if oneClass is null
+ */
+ public static boolean compileClass(Class oneClass)
+ {
+ return VMCompiler.compileClass(oneClass);
+ }
+
+ /**
+ * Compile the classes whose name matches <code>classNames</code>.
+ *
+ * @param classNames the name of classes to compile
+ * @return <code>false</code> if no compiler is available or
+ * compilation failed, <code>true</code> if compilation succeeded
+ * @throws NullPointerException if classNames is null
+ */
+ public static boolean compileClasses(String classNames)
+ {
+ return VMCompiler.compileClasses(classNames);
+ }
+
+ /**
+ * This method examines the argument and performs an operation
+ * according to the compilers documentation. No specific operation
+ * is required.
+ *
+ * @param arg a compiler-specific argument
+ * @return a compiler-specific value, including null
+ * @throws NullPointerException if the compiler doesn't like a null arg
+ */
+ public static Object command(Object arg)
+ {
+ return VMCompiler.command(arg);
+ }
+
+ /**
+ * Calling <code>Compiler.enable()</code> will cause the compiler
+ * to resume operation if it was previously disabled; provided that a
+ * compiler even exists.
+ */
+ public static void enable()
+ {
+ VMCompiler.enable();
+ }
+
+ /**
+ * Calling <code>Compiler.disable()</code> will cause the compiler
+ * to be suspended; provided that a compiler even exists.
+ */
+ public static void disable()
+ {
+ VMCompiler.disable();
+ }
+}
diff --git a/libjava/classpath/java/lang/Double.java b/libjava/classpath/java/lang/Double.java
new file mode 100644
index 00000000000..4fa47f46ddd
--- /dev/null
+++ b/libjava/classpath/java/lang/Double.java
@@ -0,0 +1,521 @@
+/* Double.java -- object wrapper for double
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import gnu.classpath.Configuration;
+
+/**
+ * Instances of class <code>Double</code> represent primitive
+ * <code>double</code> values.
+ *
+ * Additionally, this class provides various helper functions and variables
+ * related to doubles.
+ *
+ * @author Paul Fisher
+ * @author Andrew Haley (aph@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public final class Double extends Number implements Comparable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -9172774392245257468L;
+
+ /**
+ * The maximum positive value a <code>double</code> may represent
+ * is 1.7976931348623157e+308.
+ */
+ public static final double MAX_VALUE = 1.7976931348623157e+308;
+
+ /**
+ * The minimum positive value a <code>double</code> may represent
+ * is 5e-324.
+ */
+ public static final double MIN_VALUE = 5e-324;
+
+ /**
+ * The value of a double representation -1.0/0.0, negative
+ * infinity.
+ */
+ public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
+
+ /**
+ * The value of a double representing 1.0/0.0, positive infinity.
+ */
+ public static final double POSITIVE_INFINITY = 1.0 / 0.0;
+
+ /**
+ * All IEEE 754 values of NaN have the same value in Java.
+ */
+ public static final double NaN = 0.0 / 0.0;
+
+ /**
+ * The primitive type <code>double</code> is represented by this
+ * <code>Class</code> object.
+ * @since 1.1
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass('D');
+
+ /**
+ * The immutable value of this Double.
+ *
+ * @serial the wrapped double
+ */
+ private final double value;
+
+ /**
+ * Create a <code>Double</code> from the primitive <code>double</code>
+ * specified.
+ *
+ * @param value the <code>double</code> argument
+ */
+ public Double(double value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create a <code>Double</code> from the specified <code>String</code>.
+ * This method calls <code>Double.parseDouble()</code>.
+ *
+ * @param s the <code>String</code> to convert
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>double</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @see #parseDouble(String)
+ */
+ public Double(String s)
+ {
+ value = parseDouble(s);
+ }
+
+ /**
+ * Convert the <code>double</code> to a <code>String</code>.
+ * Floating-point string representation is fairly complex: here is a
+ * rundown of the possible values. "<code>[-]</code>" indicates that a
+ * negative sign will be printed if the value (or exponent) is negative.
+ * "<code>&lt;number&gt;</code>" means a string of digits ('0' to '9').
+ * "<code>&lt;digit&gt;</code>" means a single digit ('0' to '9').<br>
+ *
+ * <table border=1>
+ * <tr><th>Value of Double</th><th>String Representation</th></tr>
+ * <tr><td>[+-] 0</td> <td><code>[-]0.0</code></td></tr>
+ * <tr><td>Between [+-] 10<sup>-3</sup> and 10<sup>7</sup>, exclusive</td>
+ * <td><code>[-]number.number</code></td></tr>
+ * <tr><td>Other numeric value</td>
+ * <td><code>[-]&lt;digit&gt;.&lt;number&gt;
+ * E[-]&lt;number&gt;</code></td></tr>
+ * <tr><td>[+-] infinity</td> <td><code>[-]Infinity</code></td></tr>
+ * <tr><td>NaN</td> <td><code>NaN</code></td></tr>
+ * </table>
+ *
+ * Yes, negative zero <em>is</em> a possible value. Note that there is
+ * <em>always</em> a <code>.</code> and at least one digit printed after
+ * it: even if the number is 3, it will be printed as <code>3.0</code>.
+ * After the ".", all digits will be printed except trailing zeros. The
+ * result is rounded to the shortest decimal number which will parse back
+ * to the same double.
+ *
+ * <p>To create other output formats, use {@link java.text.NumberFormat}.
+ *
+ * @XXX specify where we are not in accord with the spec.
+ *
+ * @param d the <code>double</code> to convert
+ * @return the <code>String</code> representing the <code>double</code>
+ */
+ public static String toString(double d)
+ {
+ return VMDouble.toString(d, false);
+ }
+
+ /**
+ * Create a new <code>Double</code> object using the <code>String</code>.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the new <code>Double</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>double</code>
+ * @throws NullPointerException if <code>s</code> is null.
+ * @see #parseDouble(String)
+ */
+ public static Double valueOf(String s)
+ {
+ return new Double(parseDouble(s));
+ }
+
+ /**
+ * Parse the specified <code>String</code> as a <code>double</code>. The
+ * extended BNF grammar is as follows:<br>
+ * <pre>
+ * <em>DecodableString</em>:
+ * ( [ <code>-</code> | <code>+</code> ] <code>NaN</code> )
+ * | ( [ <code>-</code> | <code>+</code> ] <code>Infinity</code> )
+ * | ( [ <code>-</code> | <code>+</code> ] <em>FloatingPoint</em>
+ * [ <code>f</code> | <code>F</code> | <code>d</code>
+ * | <code>D</code>] )
+ * <em>FloatingPoint</em>:
+ * ( { <em>Digit</em> }+ [ <code>.</code> { <em>Digit</em> } ]
+ * [ <em>Exponent</em> ] )
+ * | ( <code>.</code> { <em>Digit</em> }+ [ <em>Exponent</em> ] )
+ * <em>Exponent</em>:
+ * ( ( <code>e</code> | <code>E</code> )
+ * [ <code>-</code> | <code>+</code> ] { <em>Digit</em> }+ )
+ * <em>Digit</em>: <em><code>'0'</code> through <code>'9'</code></em>
+ * </pre>
+ *
+ * <p>NaN and infinity are special cases, to allow parsing of the output
+ * of toString. Otherwise, the result is determined by calculating
+ * <em>n * 10<sup>exponent</sup></em> to infinite precision, then rounding
+ * to the nearest double. Remember that many numbers cannot be precisely
+ * represented in floating point. In case of overflow, infinity is used,
+ * and in case of underflow, signed zero is used. Unlike Integer.parseInt,
+ * this does not accept Unicode digits outside the ASCII range.
+ *
+ * <p>If an unexpected character is found in the <code>String</code>, a
+ * <code>NumberFormatException</code> will be thrown. Leading and trailing
+ * 'whitespace' is ignored via <code>String.trim()</code>, but spaces
+ * internal to the actual number are not allowed.
+ *
+ * <p>To parse numbers according to another format, consider using
+ * {@link java.text.NumberFormat}.
+ *
+ * @XXX specify where/how we are not in accord with the spec.
+ *
+ * @param str the <code>String</code> to convert
+ * @return the <code>double</code> value of <code>s</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>double</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @see #MIN_VALUE
+ * @see #MAX_VALUE
+ * @see #POSITIVE_INFINITY
+ * @see #NEGATIVE_INFINITY
+ * @since 1.2
+ */
+ public static double parseDouble(String str)
+ {
+ return VMDouble.parseDouble(str);
+ }
+
+ /**
+ * Return <code>true</code> if the <code>double</code> has the same
+ * value as <code>NaN</code>, otherwise return <code>false</code>.
+ *
+ * @param v the <code>double</code> to compare
+ * @return whether the argument is <code>NaN</code>.
+ */
+ public static boolean isNaN(double v)
+ {
+ // This works since NaN != NaN is the only reflexive inequality
+ // comparison which returns true.
+ return v != v;
+ }
+
+ /**
+ * Return <code>true</code> if the <code>double</code> has a value
+ * equal to either <code>NEGATIVE_INFINITY</code> or
+ * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>.
+ *
+ * @param v the <code>double</code> to compare
+ * @return whether the argument is (-/+) infinity.
+ */
+ public static boolean isInfinite(double v)
+ {
+ return v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY;
+ }
+
+ /**
+ * Return <code>true</code> if the value of this <code>Double</code>
+ * is the same as <code>NaN</code>, otherwise return <code>false</code>.
+ *
+ * @return whether this <code>Double</code> is <code>NaN</code>
+ */
+ public boolean isNaN()
+ {
+ return isNaN(value);
+ }
+
+ /**
+ * Return <code>true</code> if the value of this <code>Double</code>
+ * is the same as <code>NEGATIVE_INFINITY</code> or
+ * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>.
+ *
+ * @return whether this <code>Double</code> is (-/+) infinity
+ */
+ public boolean isInfinite()
+ {
+ return isInfinite(value);
+ }
+
+ /**
+ * Convert the <code>double</code> value of this <code>Double</code>
+ * to a <code>String</code>. This method calls
+ * <code>Double.toString(double)</code> to do its dirty work.
+ *
+ * @return the <code>String</code> representation
+ * @see #toString(double)
+ */
+ public String toString()
+ {
+ return toString(value);
+ }
+
+ /**
+ * Return the value of this <code>Double</code> as a <code>byte</code>.
+ *
+ * @return the byte value
+ * @since 1.1
+ */
+ public byte byteValue()
+ {
+ return (byte) value;
+ }
+
+ /**
+ * Return the value of this <code>Double</code> as a <code>short</code>.
+ *
+ * @return the short value
+ * @since 1.1
+ */
+ public short shortValue()
+ {
+ return (short) value;
+ }
+
+ /**
+ * Return the value of this <code>Double</code> as an <code>int</code>.
+ *
+ * @return the int value
+ */
+ public int intValue()
+ {
+ return (int) value;
+ }
+
+ /**
+ * Return the value of this <code>Double</code> as a <code>long</code>.
+ *
+ * @return the long value
+ */
+ public long longValue()
+ {
+ return (long) value;
+ }
+
+ /**
+ * Return the value of this <code>Double</code> as a <code>float</code>.
+ *
+ * @return the float value
+ */
+ public float floatValue()
+ {
+ return (float) value;
+ }
+
+ /**
+ * Return the value of this <code>Double</code>.
+ *
+ * @return the double value
+ */
+ public double doubleValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return a hashcode representing this Object. <code>Double</code>'s hash
+ * code is calculated by:<br>
+ * <code>long v = Double.doubleToLongBits(doubleValue());<br>
+ * int hash = (int)(v^(v&gt;&gt;32))</code>.
+ *
+ * @return this Object's hash code
+ * @see #doubleToLongBits(double)
+ */
+ public int hashCode()
+ {
+ long v = doubleToLongBits(value);
+ return (int) (v ^ (v >>> 32));
+ }
+
+ /**
+ * Returns <code>true</code> if <code>obj</code> is an instance of
+ * <code>Double</code> and represents the same double value. Unlike comparing
+ * two doubles with <code>==</code>, this treats two instances of
+ * <code>Double.NaN</code> as equal, but treats <code>0.0</code> and
+ * <code>-0.0</code> as unequal.
+ *
+ * <p>Note that <code>d1.equals(d2)</code> is identical to
+ * <code>doubleToLongBits(d1.doubleValue()) ==
+ * doubleToLongBits(d2.doubleValue())</code>.
+ *
+ * @param obj the object to compare
+ * @return whether the objects are semantically equal
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Double))
+ return false;
+
+ double d = ((Double) obj).value;
+
+ // Avoid call to native method. However, some implementations, like gcj,
+ // are better off using floatToIntBits(value) == floatToIntBits(f).
+ // Check common case first, then check NaN and 0.
+ if (value == d)
+ return (value != 0) || (1 / value == 1 / d);
+ return isNaN(value) && isNaN(d);
+ }
+
+ /**
+ * Convert the double to the IEEE 754 floating-point "double format" bit
+ * layout. Bit 63 (the most significant) is the sign bit, bits 62-52
+ * (masked by 0x7ff0000000000000L) represent the exponent, and bits 51-0
+ * (masked by 0x000fffffffffffffL) are the mantissa. This function
+ * collapses all versions of NaN to 0x7ff8000000000000L. The result of this
+ * function can be used as the argument to
+ * <code>Double.longBitsToDouble(long)</code> to obtain the original
+ * <code>double</code> value.
+ *
+ * @param value the <code>double</code> to convert
+ * @return the bits of the <code>double</code>
+ * @see #longBitsToDouble(long)
+ */
+ public static long doubleToLongBits(double value)
+ {
+ return VMDouble.doubleToLongBits(value);
+ }
+
+ /**
+ * Convert the double to the IEEE 754 floating-point "double format" bit
+ * layout. Bit 63 (the most significant) is the sign bit, bits 62-52
+ * (masked by 0x7ff0000000000000L) represent the exponent, and bits 51-0
+ * (masked by 0x000fffffffffffffL) are the mantissa. This function
+ * leaves NaN alone, rather than collapsing to a canonical value. The
+ * result of this function can be used as the argument to
+ * <code>Double.longBitsToDouble(long)</code> to obtain the original
+ * <code>double</code> value.
+ *
+ * @param value the <code>double</code> to convert
+ * @return the bits of the <code>double</code>
+ * @see #longBitsToDouble(long)
+ */
+ public static long doubleToRawLongBits(double value)
+ {
+ return VMDouble.doubleToRawLongBits(value);
+ }
+
+ /**
+ * Convert the argument in IEEE 754 floating-point "double format" bit
+ * layout to the corresponding float. Bit 63 (the most significant) is the
+ * sign bit, bits 62-52 (masked by 0x7ff0000000000000L) represent the
+ * exponent, and bits 51-0 (masked by 0x000fffffffffffffL) are the mantissa.
+ * This function leaves NaN alone, so that you can recover the bit pattern
+ * with <code>Double.doubleToRawLongBits(double)</code>.
+ *
+ * @param bits the bits to convert
+ * @return the <code>double</code> represented by the bits
+ * @see #doubleToLongBits(double)
+ * @see #doubleToRawLongBits(double)
+ */
+ public static double longBitsToDouble(long bits)
+ {
+ return VMDouble.longBitsToDouble(bits);
+ }
+
+ /**
+ * Compare two Doubles numerically by comparing their <code>double</code>
+ * values. The result is positive if the first is greater, negative if the
+ * second is greater, and 0 if the two are equal. However, this special
+ * cases NaN and signed zero as follows: NaN is considered greater than
+ * all other doubles, including <code>POSITIVE_INFINITY</code>, and positive
+ * zero is considered greater than negative zero.
+ *
+ * @param d the Double to compare
+ * @return the comparison
+ * @since 1.2
+ */
+ public int compareTo(Double d)
+ {
+ return compare(value, d.value);
+ }
+
+ /**
+ * Behaves like <code>compareTo(Double)</code> unless the Object
+ * is not an <code>Double</code>.
+ *
+ * @param o the object to compare
+ * @return the comparison
+ * @throws ClassCastException if the argument is not a <code>Double</code>
+ * @see #compareTo(Double)
+ * @see Comparable
+ * @since 1.2
+ */
+ public int compareTo(Object o)
+ {
+ return compare(value, ((Double) o).value);
+ }
+
+ /**
+ * Behaves like <code>new Double(x).compareTo(new Double(y))</code>; in
+ * other words this compares two doubles, special casing NaN and zero,
+ * without the overhead of objects.
+ *
+ * @param x the first double to compare
+ * @param y the second double to compare
+ * @return the comparison
+ * @since 1.4
+ */
+ public static int compare(double x, double y)
+ {
+ if (isNaN(x))
+ return isNaN(y) ? 0 : 1;
+ if (isNaN(y))
+ return -1;
+ // recall that 0.0 == -0.0, so we convert to infinites and try again
+ if (x == 0 && y == 0)
+ return (int) (1 / x - 1 / y);
+ if (x == y)
+ return 0;
+
+ return x > y ? 1 : -1;
+ }
+}
diff --git a/libjava/classpath/java/lang/Error.java b/libjava/classpath/java/lang/Error.java
new file mode 100644
index 00000000000..f66c7548b33
--- /dev/null
+++ b/libjava/classpath/java/lang/Error.java
@@ -0,0 +1,107 @@
+/* Error.java -- Indication of fatal abnormal conditions
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Applications should not try to catch errors since they indicate
+ * abnormal conditions. An abnormal condition is something which should not
+ * occur, or which should not be recovered from. This latter category
+ * includes <code>ThreadDeath</code> and <code>AssertionError</code>.
+ *
+ * <p>A method is not required to declare any subclass of <code>Error</code> in
+ * its <code>throws</code> clause which might be thrown but not caught while
+ * executing the method.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Error extends Throwable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 4980196508277280342L;
+
+ /**
+ * Create an error without a message. The cause remains uninitialized.
+ *
+ * @see #initCause(Throwable)
+ */
+ public Error()
+ {
+ }
+
+ /**
+ * Create an error with a message. The cause remains uninitialized.
+ *
+ * @param s the message string
+ * @see #initCause(Throwable)
+ */
+ public Error(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an error with a message and a cause.
+ *
+ * @param s the message string
+ * @param cause the cause of this error
+ * @since 1.4
+ */
+ public Error(String s, Throwable cause)
+ {
+ super(s, cause);
+ }
+
+ /**
+ * Create an error with a given cause, and a message of
+ * <code>cause == null ? null : cause.toString()</code>.
+ *
+ * @param cause the cause of this error
+ * @since 1.4
+ */
+ public Error(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/libjava/classpath/java/lang/Exception.java b/libjava/classpath/java/lang/Exception.java
new file mode 100644
index 00000000000..42f7c640dd3
--- /dev/null
+++ b/libjava/classpath/java/lang/Exception.java
@@ -0,0 +1,104 @@
+/* Exception.java -- generic exception thrown to indicate an exceptional
+ condition has occurred.
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * The root class of all exceptions worth catching in a program. This
+ * includes the special category of <code>RuntimeException</code>, which
+ * does not need to be declared in a throws clause. Exceptions can be used
+ * to represent almost any exceptional behavior, such as programming errors,
+ * mouse movements, keyboard clicking, etc.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class Exception extends Throwable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -3387516993124229948L;
+
+ /**
+ * Create an exception without a message. The cause remains uninitialized.
+ *
+ * @see #initCause(Throwable)
+ */
+ public Exception()
+ {
+ }
+
+ /**
+ * Create an exception with a message. The cause remains uninitialized.
+ *
+ * @param s the message
+ * @see #initCause(Throwable)
+ */
+ public Exception(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message string
+ * @param cause the cause of this error
+ * @since 1.4
+ */
+ public Exception(String s, Throwable cause)
+ {
+ super(s, cause);
+ }
+
+ /**
+ * Create an exception with a given cause, and a message of
+ * <code>cause == null ? null : cause.toString()</code>.
+ *
+ * @param cause the cause of this exception
+ * @since 1.4
+ */
+ public Exception(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/libjava/classpath/java/lang/ExceptionInInitializerError.java b/libjava/classpath/java/lang/ExceptionInInitializerError.java
new file mode 100644
index 00000000000..1e580958054
--- /dev/null
+++ b/libjava/classpath/java/lang/ExceptionInInitializerError.java
@@ -0,0 +1,123 @@
+/* ExceptionInInitializerError.java -- thrown when class initialization fails
+ with an uncaught exception
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An <code>ExceptionInInitializerError</code> is thrown when an uncaught
+ * exception has occurred in a static initializer or the initializer for a
+ * static variable. In general, this wraps only RuntimeExceptions, since the
+ * compiler does not allow a checked exception to be uncaught in an
+ * initializer. This exception only occurs during reflection, when a class
+ * is initialized as part of another action.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ExceptionInInitializerError extends LinkageError
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ static final long serialVersionUID = 1521711792217232256L;
+
+ /**
+ * The cause of this exception (duplicates the one stored in Throwable).
+ *
+ * @serial the exception cause
+ */
+ private final Throwable exception;
+
+ /**
+ * Create an error without a message. The cause is initialized as null.
+ */
+ public ExceptionInInitializerError()
+ {
+ this((String) null);
+ }
+
+ /**
+ * Create an error with a message. The cause is initialized as null.
+ *
+ * @param s the message
+ */
+ public ExceptionInInitializerError(String s)
+ {
+ super(s);
+ exception = null;
+ }
+
+ /**
+ * Creates an error an saves a reference to the <code>Throwable</code>
+ * object. The message string is null.
+ *
+ * @param t the exception thrown
+ */
+ public ExceptionInInitializerError(Throwable t)
+ {
+ super(null);
+ initCause(t);
+ exception = t;
+ }
+
+ /**
+ * Return the exception that caused this error to be created. This is a
+ * legacy method; the preferred choice now is {@link Throwable#getCause()}.
+ *
+ * @return the cause, or null if unknown
+ */
+ public Throwable getException()
+ {
+ return exception;
+ }
+
+ /**
+ * Return the exception that cause this error to be created.
+ *
+ * @return the cause, or null if unknown
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return exception;
+ }
+}
diff --git a/libjava/classpath/java/lang/Float.java b/libjava/classpath/java/lang/Float.java
new file mode 100644
index 00000000000..e6200dabddc
--- /dev/null
+++ b/libjava/classpath/java/lang/Float.java
@@ -0,0 +1,527 @@
+/* Float.java -- object wrapper for float
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Instances of class <code>Float</code> represent primitive
+ * <code>float</code> values.
+ *
+ * Additionally, this class provides various helper functions and variables
+ * related to floats.
+ *
+ * @author Paul Fisher
+ * @author Andrew Haley (aph@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public final class Float extends Number implements Comparable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -2671257302660747028L;
+
+ /**
+ * The maximum positive value a <code>double</code> may represent
+ * is 3.4028235e+38f.
+ */
+ public static final float MAX_VALUE = 3.4028235e+38f;
+
+ /**
+ * The minimum positive value a <code>float</code> may represent
+ * is 1.4e-45.
+ */
+ public static final float MIN_VALUE = 1.4e-45f;
+
+ /**
+ * The value of a float representation -1.0/0.0, negative infinity.
+ */
+ public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
+
+ /**
+ * The value of a float representation 1.0/0.0, positive infinity.
+ */
+ public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
+
+ /**
+ * All IEEE 754 values of NaN have the same value in Java.
+ */
+ public static final float NaN = 0.0f / 0.0f;
+
+ /**
+ * The primitive type <code>float</code> is represented by this
+ * <code>Class</code> object.
+ * @since 1.1
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass('F');
+
+ /**
+ * The immutable value of this Float.
+ *
+ * @serial the wrapped float
+ */
+ private final float value;
+
+ /**
+ * Create a <code>Float</code> from the primitive <code>float</code>
+ * specified.
+ *
+ * @param value the <code>float</code> argument
+ */
+ public Float(float value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create a <code>Float</code> from the primitive <code>double</code>
+ * specified.
+ *
+ * @param value the <code>double</code> argument
+ */
+ public Float(double value)
+ {
+ this.value = (float) value;
+ }
+
+ /**
+ * Create a <code>Float</code> from the specified <code>String</code>.
+ * This method calls <code>Float.parseFloat()</code>.
+ *
+ * @param s the <code>String</code> to convert
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>float</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @see #parseFloat(String)
+ */
+ public Float(String s)
+ {
+ value = parseFloat(s);
+ }
+
+ /**
+ * Convert the <code>float</code> to a <code>String</code>.
+ * Floating-point string representation is fairly complex: here is a
+ * rundown of the possible values. "<code>[-]</code>" indicates that a
+ * negative sign will be printed if the value (or exponent) is negative.
+ * "<code>&lt;number&gt;</code>" means a string of digits ('0' to '9').
+ * "<code>&lt;digit&gt;</code>" means a single digit ('0' to '9').<br>
+ *
+ * <table border=1>
+ * <tr><th>Value of Float</th><th>String Representation</th></tr>
+ * <tr><td>[+-] 0</td> <td><code>[-]0.0</code></td></tr>
+ * <tr><td>Between [+-] 10<sup>-3</sup> and 10<sup>7</sup>, exclusive</td>
+ * <td><code>[-]number.number</code></td></tr>
+ * <tr><td>Other numeric value</td>
+ * <td><code>[-]&lt;digit&gt;.&lt;number&gt;
+ * E[-]&lt;number&gt;</code></td></tr>
+ * <tr><td>[+-] infinity</td> <td><code>[-]Infinity</code></td></tr>
+ * <tr><td>NaN</td> <td><code>NaN</code></td></tr>
+ * </table>
+ *
+ * Yes, negative zero <em>is</em> a possible value. Note that there is
+ * <em>always</em> a <code>.</code> and at least one digit printed after
+ * it: even if the number is 3, it will be printed as <code>3.0</code>.
+ * After the ".", all digits will be printed except trailing zeros. The
+ * result is rounded to the shortest decimal number which will parse back
+ * to the same float.
+ *
+ * <p>To create other output formats, use {@link java.text.NumberFormat}.
+ *
+ * @XXX specify where we are not in accord with the spec.
+ *
+ * @param f the <code>float</code> to convert
+ * @return the <code>String</code> representing the <code>float</code>
+ */
+ public static String toString(float f)
+ {
+ return VMDouble.toString(f, true);
+ }
+
+ /**
+ * Creates a new <code>Float</code> object using the <code>String</code>.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the new <code>Float</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>float</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @see #parseFloat(String)
+ */
+ public static Float valueOf(String s)
+ {
+ return new Float(parseFloat(s));
+ }
+
+ /**
+ * Parse the specified <code>String</code> as a <code>float</code>. The
+ * extended BNF grammar is as follows:<br>
+ * <pre>
+ * <em>DecodableString</em>:
+ * ( [ <code>-</code> | <code>+</code> ] <code>NaN</code> )
+ * | ( [ <code>-</code> | <code>+</code> ] <code>Infinity</code> )
+ * | ( [ <code>-</code> | <code>+</code> ] <em>FloatingPoint</em>
+ * [ <code>f</code> | <code>F</code> | <code>d</code>
+ * | <code>D</code>] )
+ * <em>FloatingPoint</em>:
+ * ( { <em>Digit</em> }+ [ <code>.</code> { <em>Digit</em> } ]
+ * [ <em>Exponent</em> ] )
+ * | ( <code>.</code> { <em>Digit</em> }+ [ <em>Exponent</em> ] )
+ * <em>Exponent</em>:
+ * ( ( <code>e</code> | <code>E</code> )
+ * [ <code>-</code> | <code>+</code> ] { <em>Digit</em> }+ )
+ * <em>Digit</em>: <em><code>'0'</code> through <code>'9'</code></em>
+ * </pre>
+ *
+ * <p>NaN and infinity are special cases, to allow parsing of the output
+ * of toString. Otherwise, the result is determined by calculating
+ * <em>n * 10<sup>exponent</sup></em> to infinite precision, then rounding
+ * to the nearest float. Remember that many numbers cannot be precisely
+ * represented in floating point. In case of overflow, infinity is used,
+ * and in case of underflow, signed zero is used. Unlike Integer.parseInt,
+ * this does not accept Unicode digits outside the ASCII range.
+ *
+ * <p>If an unexpected character is found in the <code>String</code>, a
+ * <code>NumberFormatException</code> will be thrown. Leading and trailing
+ * 'whitespace' is ignored via <code>String.trim()</code>, but spaces
+ * internal to the actual number are not allowed.
+ *
+ * <p>To parse numbers according to another format, consider using
+ * {@link java.text.NumberFormat}.
+ *
+ * @XXX specify where/how we are not in accord with the spec.
+ *
+ * @param str the <code>String</code> to convert
+ * @return the <code>float</code> value of <code>s</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>float</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @see #MIN_VALUE
+ * @see #MAX_VALUE
+ * @see #POSITIVE_INFINITY
+ * @see #NEGATIVE_INFINITY
+ * @since 1.2
+ */
+ public static float parseFloat(String str)
+ {
+ // XXX Rounding parseDouble() causes some errors greater than 1 ulp from
+ // the infinitely precise decimal.
+ return (float) Double.parseDouble(str);
+ }
+
+ /**
+ * Return <code>true</code> if the <code>float</code> has the same
+ * value as <code>NaN</code>, otherwise return <code>false</code>.
+ *
+ * @param v the <code>float</code> to compare
+ * @return whether the argument is <code>NaN</code>
+ */
+ public static boolean isNaN(float v)
+ {
+ // This works since NaN != NaN is the only reflexive inequality
+ // comparison which returns true.
+ return v != v;
+ }
+
+ /**
+ * Return <code>true</code> if the <code>float</code> has a value
+ * equal to either <code>NEGATIVE_INFINITY</code> or
+ * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>.
+ *
+ * @param v the <code>float</code> to compare
+ * @return whether the argument is (-/+) infinity
+ */
+ public static boolean isInfinite(float v)
+ {
+ return v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY;
+ }
+
+ /**
+ * Return <code>true</code> if the value of this <code>Float</code>
+ * is the same as <code>NaN</code>, otherwise return <code>false</code>.
+ *
+ * @return whether this <code>Float</code> is <code>NaN</code>
+ */
+ public boolean isNaN()
+ {
+ return isNaN(value);
+ }
+
+ /**
+ * Return <code>true</code> if the value of this <code>Float</code>
+ * is the same as <code>NEGATIVE_INFINITY</code> or
+ * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>.
+ *
+ * @return whether this <code>Float</code> is (-/+) infinity
+ */
+ public boolean isInfinite()
+ {
+ return isInfinite(value);
+ }
+
+ /**
+ * Convert the <code>float</code> value of this <code>Float</code>
+ * to a <code>String</code>. This method calls
+ * <code>Float.toString(float)</code> to do its dirty work.
+ *
+ * @return the <code>String</code> representation
+ * @see #toString(float)
+ */
+ public String toString()
+ {
+ return toString(value);
+ }
+
+ /**
+ * Return the value of this <code>Float</code> as a <code>byte</code>.
+ *
+ * @return the byte value
+ * @since 1.1
+ */
+ public byte byteValue()
+ {
+ return (byte) value;
+ }
+
+ /**
+ * Return the value of this <code>Float</code> as a <code>short</code>.
+ *
+ * @return the short value
+ * @since 1.1
+ */
+ public short shortValue()
+ {
+ return (short) value;
+ }
+
+ /**
+ * Return the value of this <code>Integer</code> as an <code>int</code>.
+ *
+ * @return the int value
+ */
+ public int intValue()
+ {
+ return (int) value;
+ }
+
+ /**
+ * Return the value of this <code>Integer</code> as a <code>long</code>.
+ *
+ * @return the long value
+ */
+ public long longValue()
+ {
+ return (long) value;
+ }
+
+ /**
+ * Return the value of this <code>Float</code>.
+ *
+ * @return the float value
+ */
+ public float floatValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Float</code> as a <code>double</code>
+ *
+ * @return the double value
+ */
+ public double doubleValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return a hashcode representing this Object. <code>Float</code>'s hash
+ * code is calculated by calling <code>floatToIntBits(floatValue())</code>.
+ *
+ * @return this Object's hash code
+ * @see #floatToIntBits(float)
+ */
+ public int hashCode()
+ {
+ return floatToIntBits(value);
+ }
+
+ /**
+ * Returns <code>true</code> if <code>obj</code> is an instance of
+ * <code>Float</code> and represents the same float value. Unlike comparing
+ * two floats with <code>==</code>, this treats two instances of
+ * <code>Float.NaN</code> as equal, but treats <code>0.0</code> and
+ * <code>-0.0</code> as unequal.
+ *
+ * <p>Note that <code>f1.equals(f2)</code> is identical to
+ * <code>floatToIntBits(f1.floatValue()) ==
+ * floatToIntBits(f2.floatValue())</code>.
+ *
+ * @param obj the object to compare
+ * @return whether the objects are semantically equal
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Float))
+ return false;
+
+ float f = ((Float) obj).value;
+
+ // Avoid call to native method. However, some implementations, like gcj,
+ // are better off using floatToIntBits(value) == floatToIntBits(f).
+ // Check common case first, then check NaN and 0.
+ if (value == f)
+ return (value != 0) || (1 / value == 1 / f);
+ return isNaN(value) && isNaN(f);
+ }
+
+ /**
+ * Convert the float to the IEEE 754 floating-point "single format" bit
+ * layout. Bit 31 (the most significant) is the sign bit, bits 30-23
+ * (masked by 0x7f800000) represent the exponent, and bits 22-0
+ * (masked by 0x007fffff) are the mantissa. This function collapses all
+ * versions of NaN to 0x7fc00000. The result of this function can be used
+ * as the argument to <code>Float.intBitsToFloat(int)</code> to obtain the
+ * original <code>float</code> value.
+ *
+ * @param value the <code>float</code> to convert
+ * @return the bits of the <code>float</code>
+ * @see #intBitsToFloat(int)
+ */
+ public static int floatToIntBits(float value)
+ {
+ return VMFloat.floatToIntBits(value);
+ }
+
+ /**
+ * Convert the float to the IEEE 754 floating-point "single format" bit
+ * layout. Bit 31 (the most significant) is the sign bit, bits 30-23
+ * (masked by 0x7f800000) represent the exponent, and bits 22-0
+ * (masked by 0x007fffff) are the mantissa. This function leaves NaN alone,
+ * rather than collapsing to a canonical value. The result of this function
+ * can be used as the argument to <code>Float.intBitsToFloat(int)</code> to
+ * obtain the original <code>float</code> value.
+ *
+ * @param value the <code>float</code> to convert
+ * @return the bits of the <code>float</code>
+ * @see #intBitsToFloat(int)
+ */
+ public static int floatToRawIntBits(float value)
+ {
+ return VMFloat.floatToRawIntBits(value);
+ }
+
+ /**
+ * Convert the argument in IEEE 754 floating-point "single format" bit
+ * layout to the corresponding float. Bit 31 (the most significant) is the
+ * sign bit, bits 30-23 (masked by 0x7f800000) represent the exponent, and
+ * bits 22-0 (masked by 0x007fffff) are the mantissa. This function leaves
+ * NaN alone, so that you can recover the bit pattern with
+ * <code>Float.floatToRawIntBits(float)</code>.
+ *
+ * @param bits the bits to convert
+ * @return the <code>float</code> represented by the bits
+ * @see #floatToIntBits(float)
+ * @see #floatToRawIntBits(float)
+ */
+ public static float intBitsToFloat(int bits)
+ {
+ return VMFloat.intBitsToFloat(bits);
+ }
+
+ /**
+ * Compare two Floats numerically by comparing their <code>float</code>
+ * values. The result is positive if the first is greater, negative if the
+ * second is greater, and 0 if the two are equal. However, this special
+ * cases NaN and signed zero as follows: NaN is considered greater than
+ * all other floats, including <code>POSITIVE_INFINITY</code>, and positive
+ * zero is considered greater than negative zero.
+ *
+ * @param f the Float to compare
+ * @return the comparison
+ * @since 1.2
+ */
+ public int compareTo(Float f)
+ {
+ return compare(value, f.value);
+ }
+
+ /**
+ * Behaves like <code>compareTo(Float)</code> unless the Object
+ * is not an <code>Float</code>.
+ *
+ * @param o the object to compare
+ * @return the comparison
+ * @throws ClassCastException if the argument is not a <code>Float</code>
+ * @see #compareTo(Float)
+ * @see Comparable
+ * @since 1.2
+ */
+ public int compareTo(Object o)
+ {
+ return compare(value, ((Float) o).value);
+ }
+
+ /**
+ * Behaves like <code>new Float(x).compareTo(new Float(y))</code>; in
+ * other words this compares two floats, special casing NaN and zero,
+ * without the overhead of objects.
+ *
+ * @param x the first float to compare
+ * @param y the second float to compare
+ * @return the comparison
+ * @since 1.4
+ */
+ public static int compare(float x, float y)
+ {
+ if (isNaN(x))
+ return isNaN(y) ? 0 : 1;
+ if (isNaN(y))
+ return -1;
+ // recall that 0.0 == -0.0, so we convert to infinities and try again
+ if (x == 0 && y == 0)
+ return (int) (1 / x - 1 / y);
+ if (x == y)
+ return 0;
+
+ return x > y ? 1 : -1;
+ }
+}
diff --git a/libjava/classpath/java/lang/IllegalAccessError.java b/libjava/classpath/java/lang/IllegalAccessError.java
new file mode 100644
index 00000000000..e4821606a41
--- /dev/null
+++ b/libjava/classpath/java/lang/IllegalAccessError.java
@@ -0,0 +1,76 @@
+/* IllegalAccessError.java -- thrown when linking to an inaccessible member
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An <code>IllegalAccessError</code> is thrown when an attempt is made to
+ * call a method, or access or modify a field that the application does not
+ * have access to. Because this error is usually caught by a compiler,
+ * the error only occurs at runtime when the definition of a class has
+ * changed in a way that is incompatible with the previously compiled
+ * application.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class IllegalAccessError extends IncompatibleClassChangeError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -8988904074992417891L;
+
+ /**
+ * Create an error without a message.
+ */
+ public IllegalAccessError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public IllegalAccessError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/IllegalAccessException.java b/libjava/classpath/java/lang/IllegalAccessException.java
new file mode 100644
index 00000000000..a352c8b1b31
--- /dev/null
+++ b/libjava/classpath/java/lang/IllegalAccessException.java
@@ -0,0 +1,99 @@
+/* IllegalAccessException.java -- thrown on attempt to reflect on
+ inaccessible data
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Thrown whenever a reflective method tries to do something that the
+ * compiler would not allow. For example, using reflection to set a private
+ * variable that belongs to a class in another package is bad.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see Class#newInstance()
+ * @see Field#set(Object, Object)
+ * @see Field#setBoolean(Object, boolean)
+ * @see Field#setByte(Object, byte)
+ * @see Field#setShort(Object, short)
+ * @see Field#setChar(Object, char)
+ * @see Field#setInt(Object, int)
+ * @see Field#setLong(Object, long)
+ * @see Field#setFloat(Object, float)
+ * @see Field#setDouble(Object, double)
+ * @see Field#get(Object)
+ * @see Field#getBoolean(Object)
+ * @see Field#getByte(Object)
+ * @see Field#getShort(Object)
+ * @see Field#getChar(Object)
+ * @see Field#getInt(Object)
+ * @see Field#getLong(Object)
+ * @see Field#getFloat(Object)
+ * @see Field#getDouble(Object)
+ * @see Method#invoke(Object, Object[])
+ * @see Constructor#newInstance(Object[])
+ * @status updated to 1.4
+ */
+public class IllegalAccessException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 6616958222490762034L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public IllegalAccessException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public IllegalAccessException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/IllegalArgumentException.java b/libjava/classpath/java/lang/IllegalArgumentException.java
new file mode 100644
index 00000000000..7b822b91665
--- /dev/null
+++ b/libjava/classpath/java/lang/IllegalArgumentException.java
@@ -0,0 +1,75 @@
+/* IllegalArgumentException.java -- thrown when a method is passed an
+ illegal or inappropriate argument
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+/**
+ * Thrown when a method is passed an illegal or inappropriate argument. For
+ * example:<br>
+ * <pre>
+ * wait(-1);
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class IllegalArgumentException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -5365630128856068164L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public IllegalArgumentException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public IllegalArgumentException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/IllegalMonitorStateException.java b/libjava/classpath/java/lang/IllegalMonitorStateException.java
new file mode 100644
index 00000000000..13b3f952bb5
--- /dev/null
+++ b/libjava/classpath/java/lang/IllegalMonitorStateException.java
@@ -0,0 +1,78 @@
+/* IllegalMonitorStateException.java -- thrown when trying to wait or
+ notify a monitor that is not owned
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when a thread attempts to wait or notify on a monitor that it
+ * does not own (ie. it has not synchronized on the object). For example:<br>
+ * <pre>
+ * void m() {
+ * notify();
+ * }
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class IllegalMonitorStateException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 3713306369498869069L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public IllegalMonitorStateException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public IllegalMonitorStateException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/IllegalStateException.java b/libjava/classpath/java/lang/IllegalStateException.java
new file mode 100644
index 00000000000..5c2bbad37a2
--- /dev/null
+++ b/libjava/classpath/java/lang/IllegalStateException.java
@@ -0,0 +1,80 @@
+/* IllegalStateException.java -- thrown when invoking a method at
+ an illegal or inappropriate time
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when a method is invoked at an illegal or inappropriate time. For
+ * example:<br>
+ * <pre>
+ * void m(Collecion c)
+ * {
+ * c.iterator().remove();
+ * }
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class IllegalStateException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -1848914673093119416L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public IllegalStateException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public IllegalStateException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/IllegalThreadStateException.java b/libjava/classpath/java/lang/IllegalThreadStateException.java
new file mode 100644
index 00000000000..e14385a3e83
--- /dev/null
+++ b/libjava/classpath/java/lang/IllegalThreadStateException.java
@@ -0,0 +1,75 @@
+/* IllegalThreadStateException.java -- thrown when trying to manipulate a
+ Thread when it is not in an appropriate state
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown When trying to manipulate a Thread which is in an inappropriate
+ * state. Since the documentation suggests that this can happen with
+ * <code>Thread.suspend</code> or <code>Thread.resume</code>, but these
+ * two methods are deprecated, this exception is likely very rare.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class IllegalThreadStateException extends IllegalArgumentException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -7626246362397460174L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public IllegalThreadStateException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public IllegalThreadStateException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/IncompatibleClassChangeError.java b/libjava/classpath/java/lang/IncompatibleClassChangeError.java
new file mode 100644
index 00000000000..637410a9009
--- /dev/null
+++ b/libjava/classpath/java/lang/IncompatibleClassChangeError.java
@@ -0,0 +1,73 @@
+/* IncompatibleClassChangeError.java -- thrown for binary incompatible classes
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An <code>IncompatibleClassChangeError</code> is thrown when the definition
+ * of a class used by the currently executing method has changed in an
+ * incompatible way.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class IncompatibleClassChangeError extends LinkageError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4914975503642802119L;
+
+ /**
+ * Create an error without a message.
+ */
+ public IncompatibleClassChangeError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public IncompatibleClassChangeError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/IndexOutOfBoundsException.java b/libjava/classpath/java/lang/IndexOutOfBoundsException.java
new file mode 100644
index 00000000000..c53c67e5574
--- /dev/null
+++ b/libjava/classpath/java/lang/IndexOutOfBoundsException.java
@@ -0,0 +1,75 @@
+/* IndexOutOfBoundsException.java -- thrown for an invalid index
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * This exception can be thrown to indicate an attempt to access an
+ * index which is out of bounds on objects like String, Array, or Vector.
+ * Usually any negative integer less than or equal to -1 and positive
+ * integer greater than or equal to the size of the object is an index
+ * which would be out of bounds.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class IndexOutOfBoundsException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 234122996006267687L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public IndexOutOfBoundsException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public IndexOutOfBoundsException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/InheritableThreadLocal.java b/libjava/classpath/java/lang/InheritableThreadLocal.java
new file mode 100644
index 00000000000..69ff6138dc6
--- /dev/null
+++ b/libjava/classpath/java/lang/InheritableThreadLocal.java
@@ -0,0 +1,116 @@
+/* InheritableThreadLocal -- a ThreadLocal which inherits values across threads
+ Copyright (C) 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.util.Iterator;
+import java.util.WeakHashMap;
+
+/**
+ * A ThreadLocal whose value is inherited by child Threads. The value of the
+ * InheritableThreadLocal associated with the (parent) Thread is copied to
+ * the new (child) Thread at the moment of creation.
+ *
+ * <p>It is possible to make the value associated with the child Thread a
+ * function of the value that is associated with the parent Thread by
+ * overriding the <code>childValue()</code> method. The utility of this class
+ * is in transferring items like User ID or Transaction ID across threads
+ * automatically.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see ThreadLocal
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InheritableThreadLocal extends ThreadLocal
+{
+ /**
+ * Creates a new InheritableThreadLocal that has no values associated
+ * with it yet.
+ */
+ public InheritableThreadLocal()
+ {
+ }
+
+ /**
+ * Determines the value associated with a newly created child Thread as a
+ * function of the value associated with the currently executing (parent)
+ * Thread. The default implementation just returns the parentValue.
+ *
+ * @param parentValue the value of this object in the parent thread at
+ * the moment of creation of the child
+ * @return the initial value for the child thread
+ */
+ protected Object childValue(Object parentValue)
+ {
+ return parentValue;
+ }
+
+ /**
+ * Generates the childValues of all <code>InheritableThreadLocal</code>s
+ * that are in the heritage of the current Thread for the newly created
+ * childThread. Should be called from the contructor Thread.
+ *
+ * @param childThread the newly created thread, to inherit from this thread
+ * @see Thread#Thread(ThreadGroup, Runnable, String)
+ */
+ static void newChildThread(Thread childThread)
+ {
+ // The currentThread is the parent of the new thread.
+ Thread parentThread = Thread.currentThread();
+ if (parentThread.locals != null)
+ {
+ Iterator keys = parentThread.locals.keySet().iterator();
+ while (keys.hasNext())
+ {
+ Key key = (Key)keys.next();
+ if (key.get() instanceof InheritableThreadLocal)
+ {
+ InheritableThreadLocal local = (InheritableThreadLocal)key.get();
+ Object parentValue = parentThread.locals.get(key);
+ Object childValue = local.childValue(parentValue == NULL
+ ? null : parentValue);
+ if (childThread.locals == null)
+ childThread.locals = new WeakHashMap();
+ childThread.locals.put(key, (childValue == null
+ ? NULL : childValue));
+ }
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/lang/InstantiationError.java b/libjava/classpath/java/lang/InstantiationError.java
new file mode 100644
index 00000000000..dd12b513a22
--- /dev/null
+++ b/libjava/classpath/java/lang/InstantiationError.java
@@ -0,0 +1,75 @@
+/* InstantiationError.java -- thrown when the linker cannot create an instance
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An <code>InstantiationError</code> is thrown when an attempt is made to
+ * create an instance of an abstract class or an interface. Because this
+ * error is usually caught by a compiler, the error only occurs at runtime
+ * when the definition of a class has changed in a way that is incompatible
+ * with the previously compiled application.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class InstantiationError extends IncompatibleClassChangeError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4885810657349421204L;
+
+ /**
+ * Create an error without a message.
+ */
+ public InstantiationError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public InstantiationError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/InstantiationException.java b/libjava/classpath/java/lang/InstantiationException.java
new file mode 100644
index 00000000000..367b14bd278
--- /dev/null
+++ b/libjava/classpath/java/lang/InstantiationException.java
@@ -0,0 +1,74 @@
+/* InstantiationException.java -- thrown when reflection cannot create an
+ instance
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when an attempt is made to use reflection to build a
+ * non-instantiable class (an interface or abstract class).
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see Class#newInstance()
+ * @status updated to 1.4
+ */
+public class InstantiationException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -8441929162975509110L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public InstantiationException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public InstantiationException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/Integer.java b/libjava/classpath/java/lang/Integer.java
new file mode 100644
index 00000000000..07be4e30728
--- /dev/null
+++ b/libjava/classpath/java/lang/Integer.java
@@ -0,0 +1,772 @@
+/* Integer.java -- object wrapper for int
+ Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Instances of class <code>Integer</code> represent primitive
+ * <code>int</code> values.
+ *
+ * Additionally, this class provides various helper functions and variables
+ * related to ints.
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Warren Levy
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @since 1.0
+ * @status largely updated to 1.5
+ */
+public final class Integer extends Number implements Comparable
+{
+ /**
+ * Compatible with JDK 1.0.2+.
+ */
+ private static final long serialVersionUID = 1360826667806852920L;
+
+ /**
+ * The minimum value an <code>int</code> can represent is -2147483648 (or
+ * -2<sup>31</sup>).
+ */
+ public static final int MIN_VALUE = 0x80000000;
+
+ /**
+ * The maximum value an <code>int</code> can represent is 2147483647 (or
+ * 2<sup>31</sup> - 1).
+ */
+ public static final int MAX_VALUE = 0x7fffffff;
+
+ /**
+ * The primitive type <code>int</code> is represented by this
+ * <code>Class</code> object.
+ * @since 1.1
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass('I');
+
+ /**
+ * The number of bits needed to represent an <code>int</code>.
+ * @since 1.5
+ */
+ public static final int SIZE = 32;
+
+ // This caches some Integer values, and is used by boxing
+ // conversions via valueOf(). We must cache at least -128..127;
+ // these constants control how much we actually cache.
+ private static final int MIN_CACHE = -128;
+ private static final int MAX_CACHE = 127;
+ private static Integer[] intCache = new Integer[MAX_CACHE - MIN_CACHE + 1];
+
+ /**
+ * The immutable value of this Integer.
+ *
+ * @serial the wrapped int
+ */
+ private final int value;
+
+ /**
+ * Create an <code>Integer</code> object representing the value of the
+ * <code>int</code> argument.
+ *
+ * @param value the value to use
+ */
+ public Integer(int value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create an <code>Integer</code> object representing the value of the
+ * argument after conversion to an <code>int</code>.
+ *
+ * @param s the string to convert
+ * @throws NumberFormatException if the String does not contain an int
+ * @see #valueOf(String)
+ */
+ public Integer(String s)
+ {
+ value = parseInt(s, 10, false);
+ }
+
+ /**
+ * Converts the <code>int</code> to a <code>String</code> using
+ * the specified radix (base). If the radix exceeds
+ * <code>Character.MIN_RADIX</code> or <code>Character.MAX_RADIX</code>, 10
+ * is used instead. If the result is negative, the leading character is
+ * '-' ('\\u002D'). The remaining characters come from
+ * <code>Character.forDigit(digit, radix)</code> ('0'-'9','a'-'z').
+ *
+ * @param num the <code>int</code> to convert to <code>String</code>
+ * @param radix the radix (base) to use in the conversion
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toString(int num, int radix)
+ {
+ if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
+ radix = 10;
+
+ // For negative numbers, print out the absolute value w/ a leading '-'.
+ // Use an array large enough for a binary number.
+ char[] buffer = new char[33];
+ int i = 33;
+ boolean isNeg = false;
+ if (num < 0)
+ {
+ isNeg = true;
+ num = -num;
+
+ // When the value is MIN_VALUE, it overflows when made positive
+ if (num < 0)
+ {
+ buffer[--i] = digits[(int) (-(num + radix) % radix)];
+ num = -(num / radix);
+ }
+ }
+
+ do
+ {
+ buffer[--i] = digits[num % radix];
+ num /= radix;
+ }
+ while (num > 0);
+
+ if (isNeg)
+ buffer[--i] = '-';
+
+ // Package constructor avoids an array copy.
+ return new String(buffer, i, 33 - i, true);
+ }
+
+ /**
+ * Converts the <code>int</code> to a <code>String</code> assuming it is
+ * unsigned in base 16.
+ *
+ * @param i the <code>int</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toHexString(int i)
+ {
+ return toUnsignedString(i, 4);
+ }
+
+ /**
+ * Converts the <code>int</code> to a <code>String</code> assuming it is
+ * unsigned in base 8.
+ *
+ * @param i the <code>int</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toOctalString(int i)
+ {
+ return toUnsignedString(i, 3);
+ }
+
+ /**
+ * Converts the <code>int</code> to a <code>String</code> assuming it is
+ * unsigned in base 2.
+ *
+ * @param i the <code>int</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toBinaryString(int i)
+ {
+ return toUnsignedString(i, 1);
+ }
+
+ /**
+ * Converts the <code>int</code> to a <code>String</code> and assumes
+ * a radix of 10.
+ *
+ * @param i the <code>int</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ * @see #toString(int, int)
+ */
+ public static String toString(int i)
+ {
+ // This is tricky: in libgcj, String.valueOf(int) is a fast native
+ // implementation. In Classpath it just calls back to
+ // Integer.toString(int, int).
+ return String.valueOf(i);
+ }
+
+ /**
+ * Converts the specified <code>String</code> into an <code>int</code>
+ * using the specified radix (base). The string must not be <code>null</code>
+ * or empty. It may begin with an optional '-', which will negate the answer,
+ * provided that there are also valid digits. Each digit is parsed as if by
+ * <code>Character.digit(d, radix)</code>, and must be in the range
+ * <code>0</code> to <code>radix - 1</code>. Finally, the result must be
+ * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive.
+ * Unlike Double.parseDouble, you may not have a leading '+'.
+ *
+ * @param str the <code>String</code> to convert
+ * @param radix the radix (base) to use in the conversion
+ * @return the <code>String</code> argument converted to <code>int</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as an
+ * <code>int</code>
+ */
+ public static int parseInt(String str, int radix)
+ {
+ return parseInt(str, radix, false);
+ }
+
+ /**
+ * Converts the specified <code>String</code> into an <code>int</code>.
+ * This function assumes a radix of 10.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the <code>int</code> value of <code>s</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as an
+ * <code>int</code>
+ * @see #parseInt(String, int)
+ */
+ public static int parseInt(String s)
+ {
+ return parseInt(s, 10, false);
+ }
+
+ /**
+ * Creates a new <code>Integer</code> object using the <code>String</code>
+ * and specified radix (base).
+ *
+ * @param s the <code>String</code> to convert
+ * @param radix the radix (base) to convert with
+ * @return the new <code>Integer</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as an
+ * <code>int</code>
+ * @see #parseInt(String, int)
+ */
+ public static Integer valueOf(String s, int radix)
+ {
+ return new Integer(parseInt(s, radix, false));
+ }
+
+ /**
+ * Creates a new <code>Integer</code> object using the <code>String</code>,
+ * assuming a radix of 10.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the new <code>Integer</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as an
+ * <code>int</code>
+ * @see #Integer(String)
+ * @see #parseInt(String)
+ */
+ public static Integer valueOf(String s)
+ {
+ return new Integer(parseInt(s, 10, false));
+ }
+
+ /**
+ * Returns an <code>Integer</code> object wrapping the value.
+ * In contrast to the <code>Integer</code> constructor, this method
+ * will cache some values. It is used by boxing conversion.
+ *
+ * @param val the value to wrap
+ * @return the <code>Integer</code>
+ */
+ public static Integer valueOf(int val)
+ {
+ if (val < MIN_CACHE || val > MAX_CACHE)
+ return new Integer(val);
+ synchronized (intCache)
+ {
+ if (intCache[val - MIN_CACHE] == null)
+ intCache[val - MIN_CACHE] = new Integer(val);
+ return intCache[val - MIN_CACHE];
+ }
+ }
+
+ /**
+ * Return the value of this <code>Integer</code> as a <code>byte</code>.
+ *
+ * @return the byte value
+ */
+ public byte byteValue()
+ {
+ return (byte) value;
+ }
+
+ /**
+ * Return the value of this <code>Integer</code> as a <code>short</code>.
+ *
+ * @return the short value
+ */
+ public short shortValue()
+ {
+ return (short) value;
+ }
+
+ /**
+ * Return the value of this <code>Integer</code>.
+ * @return the int value
+ */
+ public int intValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Integer</code> as a <code>long</code>.
+ *
+ * @return the long value
+ */
+ public long longValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Integer</code> as a <code>float</code>.
+ *
+ * @return the float value
+ */
+ public float floatValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Integer</code> as a <code>double</code>.
+ *
+ * @return the double value
+ */
+ public double doubleValue()
+ {
+ return value;
+ }
+
+ /**
+ * Converts the <code>Integer</code> value to a <code>String</code> and
+ * assumes a radix of 10.
+ *
+ * @return the <code>String</code> representation
+ */
+ public String toString()
+ {
+ return String.valueOf(value);
+ }
+
+ /**
+ * Return a hashcode representing this Object. <code>Integer</code>'s hash
+ * code is simply its value.
+ *
+ * @return this Object's hash code
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Returns <code>true</code> if <code>obj</code> is an instance of
+ * <code>Integer</code> and represents the same int value.
+ *
+ * @param obj the object to compare
+ * @return whether these Objects are semantically equal
+ */
+ public boolean equals(Object obj)
+ {
+ return obj instanceof Integer && value == ((Integer) obj).value;
+ }
+
+ /**
+ * Get the specified system property as an <code>Integer</code>. The
+ * <code>decode()</code> method will be used to interpret the value of
+ * the property.
+ *
+ * @param nm the name of the system property
+ * @return the system property as an <code>Integer</code>, or null if the
+ * property is not found or cannot be decoded
+ * @throws SecurityException if accessing the system property is forbidden
+ * @see System#getProperty(String)
+ * @see #decode(String)
+ */
+ public static Integer getInteger(String nm)
+ {
+ return getInteger(nm, null);
+ }
+
+ /**
+ * Get the specified system property as an <code>Integer</code>, or use a
+ * default <code>int</code> value if the property is not found or is not
+ * decodable. The <code>decode()</code> method will be used to interpret
+ * the value of the property.
+ *
+ * @param nm the name of the system property
+ * @param val the default value
+ * @return the value of the system property, or the default
+ * @throws SecurityException if accessing the system property is forbidden
+ * @see System#getProperty(String)
+ * @see #decode(String)
+ */
+ public static Integer getInteger(String nm, int val)
+ {
+ Integer result = getInteger(nm, null);
+ return result == null ? new Integer(val) : result;
+ }
+
+ /**
+ * Get the specified system property as an <code>Integer</code>, or use a
+ * default <code>Integer</code> value if the property is not found or is
+ * not decodable. The <code>decode()</code> method will be used to
+ * interpret the value of the property.
+ *
+ * @param nm the name of the system property
+ * @param def the default value
+ * @return the value of the system property, or the default
+ * @throws SecurityException if accessing the system property is forbidden
+ * @see System#getProperty(String)
+ * @see #decode(String)
+ */
+ public static Integer getInteger(String nm, Integer def)
+ {
+ if (nm == null || "".equals(nm))
+ return def;
+ nm = System.getProperty(nm);
+ if (nm == null)
+ return def;
+ try
+ {
+ return decode(nm);
+ }
+ catch (NumberFormatException e)
+ {
+ return def;
+ }
+ }
+
+ /**
+ * Convert the specified <code>String</code> into an <code>Integer</code>.
+ * The <code>String</code> may represent decimal, hexadecimal, or
+ * octal numbers.
+ *
+ * <p>The extended BNF grammar is as follows:<br>
+ * <pre>
+ * <em>DecodableString</em>:
+ * ( [ <code>-</code> ] <em>DecimalNumber</em> )
+ * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code>
+ * | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } )
+ * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } )
+ * <em>DecimalNumber</em>:
+ * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> }
+ * <em>DecimalDigit</em>:
+ * <em>Character.digit(d, 10) has value 0 to 9</em>
+ * <em>OctalDigit</em>:
+ * <em>Character.digit(d, 8) has value 0 to 7</em>
+ * <em>DecimalDigit</em>:
+ * <em>Character.digit(d, 16) has value 0 to 15</em>
+ * </pre>
+ * Finally, the value must be in the range <code>MIN_VALUE</code> to
+ * <code>MAX_VALUE</code>, or an exception is thrown.
+ *
+ * @param str the <code>String</code> to interpret
+ * @return the value of the String as an <code>Integer</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>int</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @since 1.2
+ */
+ public static Integer decode(String str)
+ {
+ return new Integer(parseInt(str, 10, true));
+ }
+
+ /**
+ * Compare two Integers numerically by comparing their <code>int</code>
+ * values. The result is positive if the first is greater, negative if the
+ * second is greater, and 0 if the two are equal.
+ *
+ * @param i the Integer to compare
+ * @return the comparison
+ * @since 1.2
+ */
+ public int compareTo(Integer i)
+ {
+ if (value == i.value)
+ return 0;
+ // Returns just -1 or 1 on inequality; doing math might overflow.
+ return value > i.value ? 1 : -1;
+ }
+
+ /**
+ * Behaves like <code>compareTo(Integer)</code> unless the Object
+ * is not an <code>Integer</code>.
+ *
+ * @param o the object to compare
+ * @return the comparison
+ * @throws ClassCastException if the argument is not an <code>Integer</code>
+ * @see #compareTo(Integer)
+ * @see Comparable
+ * @since 1.2
+ */
+ public int compareTo(Object o)
+ {
+ return compareTo((Integer) o);
+ }
+
+ /**
+ * Return the number of bits set in x.
+ * @param x value to examine
+ * @since 1.5
+ */
+ public static int bitCount(int x)
+ {
+ // Successively collapse alternating bit groups into a sum.
+ x = ((x >> 1) & 0x55555555) + (x & 0x55555555);
+ x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
+ x = ((x >> 4) & 0x0f0f0f0f) + (x & 0x0f0f0f0f);
+ x = ((x >> 8) & 0x00ff00ff) + (x & 0x00ff00ff);
+ return ((x >> 16) & 0x0000ffff) + (x & 0x0000ffff);
+ }
+
+ /**
+ * Rotate x to the left by distance bits.
+ * @param x the value to rotate
+ * @param distance the number of bits by which to rotate
+ * @since 1.5
+ */
+ public static int rotateLeft(int x, int distance)
+ {
+ // This trick works because the shift operators implicitly mask
+ // the shift count.
+ return (x << distance) | (x >>> - distance);
+ }
+
+ /**
+ * Rotate x to the right by distance bits.
+ * @param x the value to rotate
+ * @param distance the number of bits by which to rotate
+ * @since 1.5
+ */
+ public static int rotateRight(int x, int distance)
+ {
+ // This trick works because the shift operators implicitly mask
+ // the shift count.
+ return (x << - distance) | (x >>> distance);
+ }
+
+ /**
+ * Find the highest set bit in value, and return a new value
+ * with only that bit set.
+ * @param value the value to examine
+ * @since 1.5
+ */
+ public static int highestOneBit(int value)
+ {
+ value |= value >>> 1;
+ value |= value >>> 2;
+ value |= value >>> 4;
+ value |= value >>> 8;
+ value |= value >>> 16;
+ return value ^ (value >>> 1);
+ }
+
+ /**
+ * Return the number of leading zeros in value.
+ * @param value the value to examine
+ * @since 1.5
+ */
+ public static int numberOfLeadingZeros(int value)
+ {
+ value |= value >>> 1;
+ value |= value >>> 2;
+ value |= value >>> 4;
+ value |= value >>> 8;
+ value |= value >>> 16;
+ return bitCount(~value);
+ }
+
+ /**
+ * Find the lowest set bit in value, and return a new value
+ * with only that bit set.
+ * @param value the value to examine
+ * @since 1.5
+ */
+ public static int lowestOneBit(int value)
+ {
+ // Classic assembly trick.
+ return value & - value;
+ }
+
+ /**
+ * Find the number of trailing zeros in value.
+ * @param value the value to examine
+ * @since 1.5
+ */
+ public static int numberOfTrailingZeros(int value)
+ {
+ return bitCount((value & -value) - 1);
+ }
+
+ /**
+ * Return 1 if x is positive, -1 if it is negative, and 0 if it is
+ * zero.
+ * @param x the value to examine
+ * @since 1.5
+ */
+ public static int signum(int x)
+ {
+ return x < 0 ? -1 : (x > 0 ? 1 : 0);
+ }
+
+ /**
+ * Reverse the bytes in val.
+ * @since 1.5
+ */
+ public static int reverseBytes(int val)
+ {
+ return ( ((val >> 24) & 0xff)
+ | ((val >> 8) & 0xff00)
+ | ((val << 8) & 0xff0000)
+ | ((val << 24) & 0xff000000));
+ }
+
+ /**
+ * Reverse the bits in val.
+ * @since 1.5
+ */
+ public static int reverse(int val)
+ {
+ // Successively swap alternating bit groups.
+ val = ((val >> 1) & 0x55555555) + ((val << 1) & ~0x55555555);
+ val = ((val >> 2) & 0x33333333) + ((val << 2) & ~0x33333333);
+ val = ((val >> 4) & 0x0f0f0f0f) + ((val << 4) & ~0x0f0f0f0f);
+ val = ((val >> 8) & 0x00ff00ff) + ((val << 8) & ~0x00ff00ff);
+ return ((val >> 16) & 0x0000ffff) + ((val << 16) & ~0x0000ffff);
+ }
+
+ /**
+ * Helper for converting unsigned numbers to String.
+ *
+ * @param num the number
+ * @param exp log2(digit) (ie. 1, 3, or 4 for binary, oct, hex)
+ */
+ // Package visible for use by Long.
+ static String toUnsignedString(int num, int exp)
+ {
+ // Use an array large enough for a binary number.
+ int mask = (1 << exp) - 1;
+ char[] buffer = new char[32];
+ int i = 32;
+ do
+ {
+ buffer[--i] = digits[num & mask];
+ num >>>= exp;
+ }
+ while (num != 0);
+
+ // Package constructor avoids an array copy.
+ return new String(buffer, i, 32 - i, true);
+ }
+
+ /**
+ * Helper for parsing ints, used by Integer, Short, and Byte.
+ *
+ * @param str the string to parse
+ * @param radix the radix to use, must be 10 if decode is true
+ * @param decode if called from decode
+ * @return the parsed int value
+ * @throws NumberFormatException if there is an error
+ * @throws NullPointerException if decode is true and str if null
+ * @see #parseInt(String, int)
+ * @see #decode(String)
+ * @see Byte#parseInt(String, int)
+ * @see Short#parseInt(String, int)
+ */
+ static int parseInt(String str, int radix, boolean decode)
+ {
+ if (! decode && str == null)
+ throw new NumberFormatException();
+ int index = 0;
+ int len = str.length();
+ boolean isNeg = false;
+ if (len == 0)
+ throw new NumberFormatException();
+ int ch = str.charAt(index);
+ if (ch == '-')
+ {
+ if (len == 1)
+ throw new NumberFormatException();
+ isNeg = true;
+ ch = str.charAt(++index);
+ }
+ if (decode)
+ {
+ if (ch == '0')
+ {
+ if (++index == len)
+ return 0;
+ if ((str.charAt(index) & ~('x' ^ 'X')) == 'X')
+ {
+ radix = 16;
+ index++;
+ }
+ else
+ radix = 8;
+ }
+ else if (ch == '#')
+ {
+ radix = 16;
+ index++;
+ }
+ }
+ if (index == len)
+ throw new NumberFormatException();
+
+ int max = MAX_VALUE / radix;
+ // We can't directly write `max = (MAX_VALUE + 1) / radix'.
+ // So instead we fake it.
+ if (isNeg && MAX_VALUE % radix == radix - 1)
+ ++max;
+
+ int val = 0;
+ while (index < len)
+ {
+ if (val < 0 || val > max)
+ throw new NumberFormatException();
+
+ ch = Character.digit(str.charAt(index++), radix);
+ val = val * radix + ch;
+ if (ch < 0 || (val < 0 && (! isNeg || val != MIN_VALUE)))
+ throw new NumberFormatException();
+ }
+ return isNeg ? -val : val;
+ }
+}
diff --git a/libjava/classpath/java/lang/InternalError.java b/libjava/classpath/java/lang/InternalError.java
new file mode 100644
index 00000000000..3a95bbeaf57
--- /dev/null
+++ b/libjava/classpath/java/lang/InternalError.java
@@ -0,0 +1,72 @@
+/* InternalError.java -- thrown when the VM encounters an internal error
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An <code>InternalError</code> is thrown when a mystical error has
+ * occurred in the Java Virtual Machine.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class InternalError extends VirtualMachineError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -9062593416125562365L;
+
+ /**
+ * Create an error without a message.
+ */
+ public InternalError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public InternalError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/InterruptedException.java b/libjava/classpath/java/lang/InterruptedException.java
new file mode 100644
index 00000000000..da2173c8b4e
--- /dev/null
+++ b/libjava/classpath/java/lang/InterruptedException.java
@@ -0,0 +1,80 @@
+/* InterruptedException.java -- thrown when a thread is interrupted
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when a thread interrupts another thread which was previously
+ * sleeping, waiting, or paused in some other way. See the
+ * <code>interrupt</code> method of class <code>Thread</code>.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see Object#wait()
+ * @see Object#wait(long)
+ * @see Object#wait(long, int)
+ * @see Thread#sleep(long)
+ * @see Thread#interrupt()
+ * @see Thread#interrupted()
+ * @status updated to 1.4
+ */
+public class InterruptedException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 6700697376100628473L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public InterruptedException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ *
+ * @param s the message
+ */
+ public InterruptedException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/LinkageError.java b/libjava/classpath/java/lang/LinkageError.java
new file mode 100644
index 00000000000..028702081ba
--- /dev/null
+++ b/libjava/classpath/java/lang/LinkageError.java
@@ -0,0 +1,74 @@
+/* LinkageError.java -- thrown when classes valid at separate compile times
+ cannot be linked to each other
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Subclasses of <code>LinkageError</code> are thrown to indicate that two
+ * classes which were compatible at separate compilation times cannot be
+ * linked to one another.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class LinkageError extends Error
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 3579600108157160122L;
+
+ /**
+ * Create an error without a message.
+ */
+ public LinkageError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public LinkageError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/Long.java b/libjava/classpath/java/lang/Long.java
new file mode 100644
index 00000000000..703eab8a0f3
--- /dev/null
+++ b/libjava/classpath/java/lang/Long.java
@@ -0,0 +1,614 @@
+/* Long.java -- object wrapper for long
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Instances of class <code>Long</code> represent primitive
+ * <code>long</code> values.
+ *
+ * Additionally, this class provides various helper functions and variables
+ * related to longs.
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Warren Levy
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public final class Long extends Number implements Comparable
+{
+ /**
+ * Compatible with JDK 1.0.2+.
+ */
+ private static final long serialVersionUID = 4290774380558885855L;
+
+ /**
+ * The minimum value a <code>long</code> can represent is
+ * -9223372036854775808L (or -2<sup>63</sup>).
+ */
+ public static final long MIN_VALUE = 0x8000000000000000L;
+
+ /**
+ * The maximum value a <code>long</code> can represent is
+ * 9223372036854775807 (or 2<sup>63</sup> - 1).
+ */
+ public static final long MAX_VALUE = 0x7fffffffffffffffL;
+
+ /**
+ * The primitive type <code>long</code> is represented by this
+ * <code>Class</code> object.
+ * @since 1.1
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass ('J');
+
+ /**
+ * The immutable value of this Long.
+ *
+ * @serial the wrapped long
+ */
+ private final long value;
+
+ /**
+ * Create a <code>Long</code> object representing the value of the
+ * <code>long</code> argument.
+ *
+ * @param value the value to use
+ */
+ public Long(long value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create a <code>Long</code> object representing the value of the
+ * argument after conversion to a <code>long</code>.
+ *
+ * @param s the string to convert
+ * @throws NumberFormatException if the String does not contain a long
+ * @see #valueOf(String)
+ */
+ public Long(String s)
+ {
+ value = parseLong(s, 10, false);
+ }
+
+ /**
+ * Converts the <code>long</code> to a <code>String</code> using
+ * the specified radix (base). If the radix exceeds
+ * <code>Character.MIN_RADIX</code> or <code>Character.MAX_RADIX</code>, 10
+ * is used instead. If the result is negative, the leading character is
+ * '-' ('\\u002D'). The remaining characters come from
+ * <code>Character.forDigit(digit, radix)</code> ('0'-'9','a'-'z').
+ *
+ * @param num the <code>long</code> to convert to <code>String</code>
+ * @param radix the radix (base) to use in the conversion
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toString(long num, int radix)
+ {
+ // Use the Integer toString for efficiency if possible.
+ if ((int) num == num)
+ return Integer.toString((int) num, radix);
+
+ if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
+ radix = 10;
+
+ // For negative numbers, print out the absolute value w/ a leading '-'.
+ // Use an array large enough for a binary number.
+ char[] buffer = new char[65];
+ int i = 65;
+ boolean isNeg = false;
+ if (num < 0)
+ {
+ isNeg = true;
+ num = -num;
+
+ // When the value is MIN_VALUE, it overflows when made positive
+ if (num < 0)
+ {
+ buffer[--i] = digits[(int) (-(num + radix) % radix)];
+ num = -(num / radix);
+ }
+ }
+
+ do
+ {
+ buffer[--i] = digits[(int) (num % radix)];
+ num /= radix;
+ }
+ while (num > 0);
+
+ if (isNeg)
+ buffer[--i] = '-';
+
+ // Package constructor avoids an array copy.
+ return new String(buffer, i, 65 - i, true);
+ }
+
+ /**
+ * Converts the <code>long</code> to a <code>String</code> assuming it is
+ * unsigned in base 16.
+ *
+ * @param l the <code>long</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toHexString(long l)
+ {
+ return toUnsignedString(l, 4);
+ }
+
+ /**
+ * Converts the <code>long</code> to a <code>String</code> assuming it is
+ * unsigned in base 8.
+ *
+ * @param l the <code>long</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toOctalString(long l)
+ {
+ return toUnsignedString(l, 3);
+ }
+
+ /**
+ * Converts the <code>long</code> to a <code>String</code> assuming it is
+ * unsigned in base 2.
+ *
+ * @param l the <code>long</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toBinaryString(long l)
+ {
+ return toUnsignedString(l, 1);
+ }
+
+ /**
+ * Converts the <code>long</code> to a <code>String</code> and assumes
+ * a radix of 10.
+ *
+ * @param num the <code>long</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ * @see #toString(long, int)
+ */
+ public static String toString(long num)
+ {
+ return toString(num, 10);
+ }
+
+ /**
+ * Converts the specified <code>String</code> into an <code>int</code>
+ * using the specified radix (base). The string must not be <code>null</code>
+ * or empty. It may begin with an optional '-', which will negate the answer,
+ * provided that there are also valid digits. Each digit is parsed as if by
+ * <code>Character.digit(d, radix)</code>, and must be in the range
+ * <code>0</code> to <code>radix - 1</code>. Finally, the result must be
+ * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive.
+ * Unlike Double.parseDouble, you may not have a leading '+'; and 'l' or
+ * 'L' as the last character is only valid in radices 22 or greater, where
+ * it is a digit and not a type indicator.
+ *
+ * @param str the <code>String</code> to convert
+ * @param radix the radix (base) to use in the conversion
+ * @return the <code>String</code> argument converted to <code>long</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>long</code>
+ */
+ public static long parseLong(String str, int radix)
+ {
+ return parseLong(str, radix, false);
+ }
+
+ /**
+ * Converts the specified <code>String</code> into a <code>long</code>.
+ * This function assumes a radix of 10.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the <code>int</code> value of <code>s</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>long</code>
+ * @see #parseLong(String, int)
+ */
+ public static long parseLong(String s)
+ {
+ return parseLong(s, 10, false);
+ }
+
+ /**
+ * Creates a new <code>Long</code> object using the <code>String</code>
+ * and specified radix (base).
+ *
+ * @param s the <code>String</code> to convert
+ * @param radix the radix (base) to convert with
+ * @return the new <code>Long</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>long</code>
+ * @see #parseLong(String, int)
+ */
+ public static Long valueOf(String s, int radix)
+ {
+ return new Long(parseLong(s, radix, false));
+ }
+
+ /**
+ * Creates a new <code>Long</code> object using the <code>String</code>,
+ * assuming a radix of 10.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the new <code>Long</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>long</code>
+ * @see #Long(String)
+ * @see #parseLong(String)
+ */
+ public static Long valueOf(String s)
+ {
+ return new Long(parseLong(s, 10, false));
+ }
+
+ /**
+ * Convert the specified <code>String</code> into a <code>Long</code>.
+ * The <code>String</code> may represent decimal, hexadecimal, or
+ * octal numbers.
+ *
+ * <p>The extended BNF grammar is as follows:<br>
+ * <pre>
+ * <em>DecodableString</em>:
+ * ( [ <code>-</code> ] <em>DecimalNumber</em> )
+ * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code>
+ * | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } )
+ * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } )
+ * <em>DecimalNumber</em>:
+ * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> }
+ * <em>DecimalDigit</em>:
+ * <em>Character.digit(d, 10) has value 0 to 9</em>
+ * <em>OctalDigit</em>:
+ * <em>Character.digit(d, 8) has value 0 to 7</em>
+ * <em>DecimalDigit</em>:
+ * <em>Character.digit(d, 16) has value 0 to 15</em>
+ * </pre>
+ * Finally, the value must be in the range <code>MIN_VALUE</code> to
+ * <code>MAX_VALUE</code>, or an exception is thrown. Note that you cannot
+ * use a trailing 'l' or 'L', unlike in Java source code.
+ *
+ * @param str the <code>String</code> to interpret
+ * @return the value of the String as a <code>Long</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>long</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @since 1.2
+ */
+ public static Long decode(String str)
+ {
+ return new Long(parseLong(str, 10, true));
+ }
+
+ /**
+ * Return the value of this <code>Long</code> as a <code>byte</code>.
+ *
+ * @return the byte value
+ */
+ public byte byteValue()
+ {
+ return (byte) value;
+ }
+
+ /**
+ * Return the value of this <code>Long</code> as a <code>short</code>.
+ *
+ * @return the short value
+ */
+ public short shortValue()
+ {
+ return (short) value;
+ }
+
+ /**
+ * Return the value of this <code>Long</code> as an <code>int</code>.
+ *
+ * @return the int value
+ */
+ public int intValue()
+ {
+ return (int) value;
+ }
+
+ /**
+ * Return the value of this <code>Long</code>.
+ *
+ * @return the long value
+ */
+ public long longValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Long</code> as a <code>float</code>.
+ *
+ * @return the float value
+ */
+ public float floatValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Long</code> as a <code>double</code>.
+ *
+ * @return the double value
+ */
+ public double doubleValue()
+ {
+ return value;
+ }
+
+ /**
+ * Converts the <code>Long</code> value to a <code>String</code> and
+ * assumes a radix of 10.
+ *
+ * @return the <code>String</code> representation
+ */
+ public String toString()
+ {
+ return toString(value, 10);
+ }
+
+ /**
+ * Return a hashcode representing this Object. <code>Long</code>'s hash
+ * code is calculated by <code>(int) (value ^ (value &gt;&gt; 32))</code>.
+ *
+ * @return this Object's hash code
+ */
+ public int hashCode()
+ {
+ return (int) (value ^ (value >>> 32));
+ }
+
+ /**
+ * Returns <code>true</code> if <code>obj</code> is an instance of
+ * <code>Long</code> and represents the same long value.
+ *
+ * @param obj the object to compare
+ * @return whether these Objects are semantically equal
+ */
+ public boolean equals(Object obj)
+ {
+ return obj instanceof Long && value == ((Long) obj).value;
+ }
+
+ /**
+ * Get the specified system property as a <code>Long</code>. The
+ * <code>decode()</code> method will be used to interpret the value of
+ * the property.
+ *
+ * @param nm the name of the system property
+ * @return the system property as a <code>Long</code>, or null if the
+ * property is not found or cannot be decoded
+ * @throws SecurityException if accessing the system property is forbidden
+ * @see System#getProperty(String)
+ * @see #decode(String)
+ */
+ public static Long getLong(String nm)
+ {
+ return getLong(nm, null);
+ }
+
+ /**
+ * Get the specified system property as a <code>Long</code>, or use a
+ * default <code>long</code> value if the property is not found or is not
+ * decodable. The <code>decode()</code> method will be used to interpret
+ * the value of the property.
+ *
+ * @param nm the name of the system property
+ * @param val the default value
+ * @return the value of the system property, or the default
+ * @throws SecurityException if accessing the system property is forbidden
+ * @see System#getProperty(String)
+ * @see #decode(String)
+ */
+ public static Long getLong(String nm, long val)
+ {
+ Long result = getLong(nm, null);
+ return result == null ? new Long(val) : result;
+ }
+
+ /**
+ * Get the specified system property as a <code>Long</code>, or use a
+ * default <code>Long</code> value if the property is not found or is
+ * not decodable. The <code>decode()</code> method will be used to
+ * interpret the value of the property.
+ *
+ * @param nm the name of the system property
+ * @param def the default value
+ * @return the value of the system property, or the default
+ * @throws SecurityException if accessing the system property is forbidden
+ * @see System#getProperty(String)
+ * @see #decode(String)
+ */
+ public static Long getLong(String nm, Long def)
+ {
+ if (nm == null || "".equals(nm))
+ return def;
+ nm = System.getProperty(nm);
+ if (nm == null)
+ return def;
+ try
+ {
+ return decode(nm);
+ }
+ catch (NumberFormatException e)
+ {
+ return def;
+ }
+ }
+
+ /**
+ * Compare two Longs numerically by comparing their <code>long</code>
+ * values. The result is positive if the first is greater, negative if the
+ * second is greater, and 0 if the two are equal.
+ *
+ * @param l the Long to compare
+ * @return the comparison
+ * @since 1.2
+ */
+ public int compareTo(Long l)
+ {
+ if (value == l.value)
+ return 0;
+ // Returns just -1 or 1 on inequality; doing math might overflow the long.
+ return value > l.value ? 1 : -1;
+ }
+
+ /**
+ * Behaves like <code>compareTo(Long)</code> unless the Object
+ * is not a <code>Long</code>.
+ *
+ * @param o the object to compare
+ * @return the comparison
+ * @throws ClassCastException if the argument is not a <code>Long</code>
+ * @see #compareTo(Long)
+ * @see Comparable
+ * @since 1.2
+ */
+ public int compareTo(Object o)
+ {
+ return compareTo((Long) o);
+ }
+
+ /**
+ * Helper for converting unsigned numbers to String.
+ *
+ * @param num the number
+ * @param exp log2(digit) (ie. 1, 3, or 4 for binary, oct, hex)
+ */
+ private static String toUnsignedString(long num, int exp)
+ {
+ // Use the Integer toUnsignedString for efficiency if possible.
+ // If NUM<0 then this particular optimization doesn't work
+ // properly.
+ if (num >= 0 && (int) num == num)
+ return Integer.toUnsignedString((int) num, exp);
+
+ // Use an array large enough for a binary number.
+ int mask = (1 << exp) - 1;
+ char[] buffer = new char[64];
+ int i = 64;
+ do
+ {
+ buffer[--i] = digits[(int) num & mask];
+ num >>>= exp;
+ }
+ while (num != 0);
+
+ // Package constructor avoids an array copy.
+ return new String(buffer, i, 64 - i, true);
+ }
+
+ /**
+ * Helper for parsing longs.
+ *
+ * @param str the string to parse
+ * @param radix the radix to use, must be 10 if decode is true
+ * @param decode if called from decode
+ * @return the parsed long value
+ * @throws NumberFormatException if there is an error
+ * @throws NullPointerException if decode is true and str is null
+ * @see #parseLong(String, int)
+ * @see #decode(String)
+ */
+ private static long parseLong(String str, int radix, boolean decode)
+ {
+ if (! decode && str == null)
+ throw new NumberFormatException();
+ int index = 0;
+ int len = str.length();
+ boolean isNeg = false;
+ if (len == 0)
+ throw new NumberFormatException();
+ int ch = str.charAt(index);
+ if (ch == '-')
+ {
+ if (len == 1)
+ throw new NumberFormatException();
+ isNeg = true;
+ ch = str.charAt(++index);
+ }
+ if (decode)
+ {
+ if (ch == '0')
+ {
+ if (++index == len)
+ return 0;
+ if ((str.charAt(index) & ~('x' ^ 'X')) == 'X')
+ {
+ radix = 16;
+ index++;
+ }
+ else
+ radix = 8;
+ }
+ else if (ch == '#')
+ {
+ radix = 16;
+ index++;
+ }
+ }
+ if (index == len)
+ throw new NumberFormatException();
+
+ long max = MAX_VALUE / radix;
+ // We can't directly write `max = (MAX_VALUE + 1) / radix'.
+ // So instead we fake it.
+ if (isNeg && MAX_VALUE % radix == radix - 1)
+ ++max;
+
+ long val = 0;
+ while (index < len)
+ {
+ if (val < 0 || val > max)
+ throw new NumberFormatException();
+
+ ch = Character.digit(str.charAt(index++), radix);
+ val = val * radix + ch;
+ if (ch < 0 || (val < 0 && (! isNeg || val != MIN_VALUE)))
+ throw new NumberFormatException();
+ }
+ return isNeg ? -val : val;
+ }
+}
diff --git a/libjava/classpath/java/lang/Math.java b/libjava/classpath/java/lang/Math.java
new file mode 100644
index 00000000000..08081e2523a
--- /dev/null
+++ b/libjava/classpath/java/lang/Math.java
@@ -0,0 +1,650 @@
+/* java.lang.Math -- common mathematical functions, native allowed
+ Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.classpath.Configuration;
+
+import java.util.Random;
+
+/**
+ * Helper class containing useful mathematical functions and constants.
+ * <P>
+ *
+ * Note that angles are specified in radians. Conversion functions are
+ * provided for your convenience.
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ */
+public final class Math
+{
+ /**
+ * Math is non-instantiable
+ */
+ private Math()
+ {
+ }
+
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("javalang");
+ }
+ }
+
+ /**
+ * A random number generator, initialized on first use.
+ */
+ private static Random rand;
+
+ /**
+ * The most accurate approximation to the mathematical constant <em>e</em>:
+ * <code>2.718281828459045</code>. Used in natural log and exp.
+ *
+ * @see #log(double)
+ * @see #exp(double)
+ */
+ public static final double E = 2.718281828459045;
+
+ /**
+ * The most accurate approximation to the mathematical constant <em>pi</em>:
+ * <code>3.141592653589793</code>. This is the ratio of a circle's diameter
+ * to its circumference.
+ */
+ public static final double PI = 3.141592653589793;
+
+ /**
+ * Take the absolute value of the argument.
+ * (Absolute value means make it positive.)
+ * <P>
+ *
+ * Note that the the largest negative value (Integer.MIN_VALUE) cannot
+ * be made positive. In this case, because of the rules of negation in
+ * a computer, MIN_VALUE is what will be returned.
+ * This is a <em>negative</em> value. You have been warned.
+ *
+ * @param i the number to take the absolute value of
+ * @return the absolute value
+ * @see Integer#MIN_VALUE
+ */
+ public static int abs(int i)
+ {
+ return (i < 0) ? -i : i;
+ }
+
+ /**
+ * Take the absolute value of the argument.
+ * (Absolute value means make it positive.)
+ * <P>
+ *
+ * Note that the the largest negative value (Long.MIN_VALUE) cannot
+ * be made positive. In this case, because of the rules of negation in
+ * a computer, MIN_VALUE is what will be returned.
+ * This is a <em>negative</em> value. You have been warned.
+ *
+ * @param l the number to take the absolute value of
+ * @return the absolute value
+ * @see Long#MIN_VALUE
+ */
+ public static long abs(long l)
+ {
+ return (l < 0) ? -l : l;
+ }
+
+ /**
+ * Take the absolute value of the argument.
+ * (Absolute value means make it positive.)
+ * <P>
+ *
+ * This is equivalent, but faster than, calling
+ * <code>Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))</code>.
+ *
+ * @param f the number to take the absolute value of
+ * @return the absolute value
+ */
+ public static float abs(float f)
+ {
+ return (f <= 0) ? 0 - f : f;
+ }
+
+ /**
+ * Take the absolute value of the argument.
+ * (Absolute value means make it positive.)
+ *
+ * This is equivalent, but faster than, calling
+ * <code>Double.longBitsToDouble(Double.doubleToLongBits(a)
+ * &lt;&lt; 1) &gt;&gt;&gt; 1);</code>.
+ *
+ * @param d the number to take the absolute value of
+ * @return the absolute value
+ */
+ public static double abs(double d)
+ {
+ return (d <= 0) ? 0 - d : d;
+ }
+
+ /**
+ * Return whichever argument is smaller.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the smaller of the two numbers
+ */
+ public static int min(int a, int b)
+ {
+ return (a < b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is smaller.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the smaller of the two numbers
+ */
+ public static long min(long a, long b)
+ {
+ return (a < b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is smaller. If either argument is NaN, the
+ * result is NaN, and when comparing 0 and -0, -0 is always smaller.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the smaller of the two numbers
+ */
+ public static float min(float a, float b)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return a;
+ // no need to check if b is NaN; < will work correctly
+ // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
+ if (a == 0 && b == 0)
+ return -(-a - b);
+ return (a < b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is smaller. If either argument is NaN, the
+ * result is NaN, and when comparing 0 and -0, -0 is always smaller.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the smaller of the two numbers
+ */
+ public static double min(double a, double b)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return a;
+ // no need to check if b is NaN; < will work correctly
+ // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
+ if (a == 0 && b == 0)
+ return -(-a - b);
+ return (a < b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is larger.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the larger of the two numbers
+ */
+ public static int max(int a, int b)
+ {
+ return (a > b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is larger.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the larger of the two numbers
+ */
+ public static long max(long a, long b)
+ {
+ return (a > b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is larger. If either argument is NaN, the
+ * result is NaN, and when comparing 0 and -0, 0 is always larger.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the larger of the two numbers
+ */
+ public static float max(float a, float b)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return a;
+ // no need to check if b is NaN; > will work correctly
+ // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
+ if (a == 0 && b == 0)
+ return a - -b;
+ return (a > b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is larger. If either argument is NaN, the
+ * result is NaN, and when comparing 0 and -0, 0 is always larger.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the larger of the two numbers
+ */
+ public static double max(double a, double b)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return a;
+ // no need to check if b is NaN; > will work correctly
+ // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
+ if (a == 0 && b == 0)
+ return a - -b;
+ return (a > b) ? a : b;
+ }
+
+ /**
+ * The trigonometric function <em>sin</em>. The sine of NaN or infinity is
+ * NaN, and the sine of 0 retains its sign. This is accurate within 1 ulp,
+ * and is semi-monotonic.
+ *
+ * @param a the angle (in radians)
+ * @return sin(a)
+ */
+ public static native double sin(double a);
+
+ /**
+ * The trigonometric function <em>cos</em>. The cosine of NaN or infinity is
+ * NaN. This is accurate within 1 ulp, and is semi-monotonic.
+ *
+ * @param a the angle (in radians)
+ * @return cos(a)
+ */
+ public static native double cos(double a);
+
+ /**
+ * The trigonometric function <em>tan</em>. The tangent of NaN or infinity
+ * is NaN, and the tangent of 0 retains its sign. This is accurate within 1
+ * ulp, and is semi-monotonic.
+ *
+ * @param a the angle (in radians)
+ * @return tan(a)
+ */
+ public static native double tan(double a);
+
+ /**
+ * The trigonometric function <em>arcsin</em>. The range of angles returned
+ * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN or
+ * its absolute value is beyond 1, the result is NaN; and the arcsine of
+ * 0 retains its sign. This is accurate within 1 ulp, and is semi-monotonic.
+ *
+ * @param a the sin to turn back into an angle
+ * @return arcsin(a)
+ */
+ public static native double asin(double a);
+
+ /**
+ * The trigonometric function <em>arccos</em>. The range of angles returned
+ * is 0 to pi radians (0 to 180 degrees). If the argument is NaN or
+ * its absolute value is beyond 1, the result is NaN. This is accurate
+ * within 1 ulp, and is semi-monotonic.
+ *
+ * @param a the cos to turn back into an angle
+ * @return arccos(a)
+ */
+ public static native double acos(double a);
+
+ /**
+ * The trigonometric function <em>arcsin</em>. The range of angles returned
+ * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN, the
+ * result is NaN; and the arctangent of 0 retains its sign. This is accurate
+ * within 1 ulp, and is semi-monotonic.
+ *
+ * @param a the tan to turn back into an angle
+ * @return arcsin(a)
+ * @see #atan2(double, double)
+ */
+ public static native double atan(double a);
+
+ /**
+ * A special version of the trigonometric function <em>arctan</em>, for
+ * converting rectangular coordinates <em>(x, y)</em> to polar
+ * <em>(r, theta)</em>. This computes the arctangent of x/y in the range
+ * of -pi to pi radians (-180 to 180 degrees). Special cases:<ul>
+ * <li>If either argument is NaN, the result is NaN.</li>
+ * <li>If the first argument is positive zero and the second argument is
+ * positive, or the first argument is positive and finite and the second
+ * argument is positive infinity, then the result is positive zero.</li>
+ * <li>If the first argument is negative zero and the second argument is
+ * positive, or the first argument is negative and finite and the second
+ * argument is positive infinity, then the result is negative zero.</li>
+ * <li>If the first argument is positive zero and the second argument is
+ * negative, or the first argument is positive and finite and the second
+ * argument is negative infinity, then the result is the double value
+ * closest to pi.</li>
+ * <li>If the first argument is negative zero and the second argument is
+ * negative, or the first argument is negative and finite and the second
+ * argument is negative infinity, then the result is the double value
+ * closest to -pi.</li>
+ * <li>If the first argument is positive and the second argument is
+ * positive zero or negative zero, or the first argument is positive
+ * infinity and the second argument is finite, then the result is the
+ * double value closest to pi/2.</li>
+ * <li>If the first argument is negative and the second argument is
+ * positive zero or negative zero, or the first argument is negative
+ * infinity and the second argument is finite, then the result is the
+ * double value closest to -pi/2.</li>
+ * <li>If both arguments are positive infinity, then the result is the
+ * double value closest to pi/4.</li>
+ * <li>If the first argument is positive infinity and the second argument
+ * is negative infinity, then the result is the double value closest to
+ * 3*pi/4.</li>
+ * <li>If the first argument is negative infinity and the second argument
+ * is positive infinity, then the result is the double value closest to
+ * -pi/4.</li>
+ * <li>If both arguments are negative infinity, then the result is the
+ * double value closest to -3*pi/4.</li>
+ *
+ * </ul><p>This is accurate within 2 ulps, and is semi-monotonic. To get r,
+ * use sqrt(x*x+y*y).
+ *
+ * @param y the y position
+ * @param x the x position
+ * @return <em>theta</em> in the conversion of (x, y) to (r, theta)
+ * @see #atan(double)
+ */
+ public static native double atan2(double y, double x);
+
+ /**
+ * 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
+ * infinity, the result is positive zero. This is accurate within 1 ulp,
+ * and is semi-monotonic.
+ *
+ * @param a the number to raise to the power
+ * @return the number raised to the power of <em>e</em>
+ * @see #log(double)
+ * @see #pow(double, double)
+ */
+ public static native double exp(double a);
+
+ /**
+ * 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
+ * is either zero, the result is negative infinity. This is accurate within
+ * 1 ulp, and is semi-monotonic.
+ *
+ * <p>Note that the way to get log<sub>b</sub>(a) is to do this:
+ * <code>ln(a) / ln(b)</code>.
+ *
+ * @param a the number to take the natural log of
+ * @return the natural log of <code>a</code>
+ * @see #exp(double)
+ */
+ public static native double log(double a);
+
+ /**
+ * Take a square root. 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 result is either zero, the result is the same.
+ * This is accurate within the limits of doubles.
+ *
+ * <p>For other roots, use pow(a, 1 / rootNumber).
+ *
+ * @param a the numeric argument
+ * @return the square root of the argument
+ * @see #pow(double, double)
+ */
+ public static native double sqrt(double a);
+
+ /**
+ * Raise a number to a power. Special cases:<ul>
+ * <li>If the second argument is positive or negative zero, then the result
+ * is 1.0.</li>
+ * <li>If the second argument is 1.0, then the result is the same as the
+ * first argument.</li>
+ * <li>If the second argument is NaN, then the result is NaN.</li>
+ * <li>If the first argument is NaN and the second argument is nonzero,
+ * then the result is NaN.</li>
+ * <li>If the absolute value of the first argument is greater than 1 and
+ * the second argument is positive infinity, or the absolute value of the
+ * first argument is less than 1 and the second argument is negative
+ * infinity, then the result is positive infinity.</li>
+ * <li>If the absolute value of the first argument is greater than 1 and
+ * the second argument is negative infinity, or the absolute value of the
+ * first argument is less than 1 and the second argument is positive
+ * infinity, then the result is positive zero.</li>
+ * <li>If the absolute value of the first argument equals 1 and the second
+ * argument is infinite, then the result is NaN.</li>
+ * <li>If the first argument is positive zero and the second argument is
+ * greater than zero, or the first argument is positive infinity and the
+ * second argument is less than zero, then the result is positive zero.</li>
+ * <li>If the first argument is positive zero and the second argument is
+ * less than zero, or the first argument is positive infinity and the
+ * second argument is greater than zero, then the result is positive
+ * infinity.</li>
+ * <li>If the first argument is negative zero and the second argument is
+ * greater than zero but not a finite odd integer, or the first argument is
+ * negative infinity and the second argument is less than zero but not a
+ * finite odd integer, then the result is positive zero.</li>
+ * <li>If the first argument is negative zero and the second argument is a
+ * positive finite odd integer, or the first argument is negative infinity
+ * and the second argument is a negative finite odd integer, then the result
+ * is negative zero.</li>
+ * <li>If the first argument is negative zero and the second argument is
+ * less than zero but not a finite odd integer, or the first argument is
+ * negative infinity and the second argument is greater than zero but not a
+ * finite odd integer, then the result is positive infinity.</li>
+ * <li>If the first argument is negative zero and the second argument is a
+ * negative finite odd integer, or the first argument is negative infinity
+ * and the second argument is a positive finite odd integer, then the result
+ * is negative infinity.</li>
+ * <li>If the first argument is less than zero and the second argument is a
+ * finite even integer, then the result is equal to the result of raising
+ * the absolute value of the first argument to the power of the second
+ * argument.</li>
+ * <li>If the first argument is less than zero and the second argument is a
+ * finite odd integer, then the result is equal to the negative of the
+ * result of raising the absolute value of the first argument to the power
+ * of the second argument.</li>
+ * <li>If the first argument is finite and less than zero and the second
+ * argument is finite and not an integer, then the result is NaN.</li>
+ * <li>If both arguments are integers, then the result is exactly equal to
+ * the mathematical result of raising the first argument to the power of
+ * the second argument if that result can in fact be represented exactly as
+ * a double value.</li>
+ *
+ * </ul><p>(In the foregoing descriptions, a floating-point value is
+ * considered to be an integer if and only if it is a fixed point of the
+ * method {@link #ceil(double)} or, equivalently, a fixed point of the
+ * method {@link #floor(double)}. A value is a fixed point of a one-argument
+ * method if and only if the result of applying the method to the value is
+ * equal to the value.) This is accurate within 1 ulp, and is semi-monotonic.
+ *
+ * @param a the number to raise
+ * @param b the power to raise it to
+ * @return a<sup>b</sup>
+ */
+ public static native double pow(double a, double b);
+
+ /**
+ * Get the IEEE 754 floating point remainder on two numbers. This is the
+ * value of <code>x - y * <em>n</em></code>, where <em>n</em> is the closest
+ * double to <code>x / y</code> (ties go to the even n); for a zero
+ * remainder, the sign is that of <code>x</code>. If either argument is NaN,
+ * the first argument is infinite, or the second argument is zero, the result
+ * is NaN; if x is finite but y is infinite, the result is x. This is
+ * accurate within the limits of doubles.
+ *
+ * @param x the dividend (the top half)
+ * @param y the divisor (the bottom half)
+ * @return the IEEE 754-defined floating point remainder of x/y
+ * @see #rint(double)
+ */
+ public static native double IEEEremainder(double x, double y);
+
+ /**
+ * Take the nearest integer that is that is greater than or equal to the
+ * argument. If the argument is NaN, infinite, or zero, the result is the
+ * same; if the argument is between -1 and 0, the result is negative zero.
+ * Note that <code>Math.ceil(x) == -Math.floor(-x)</code>.
+ *
+ * @param a the value to act upon
+ * @return the nearest integer &gt;= <code>a</code>
+ */
+ public static native double ceil(double a);
+
+ /**
+ * Take the nearest integer that is that is less than or equal to the
+ * argument. If the argument is NaN, infinite, or zero, the result is the
+ * same. Note that <code>Math.ceil(x) == -Math.floor(-x)</code>.
+ *
+ * @param a the value to act upon
+ * @return the nearest integer &lt;= <code>a</code>
+ */
+ public static native double floor(double a);
+
+ /**
+ * Take the nearest integer to the argument. If it is exactly between
+ * two integers, the even integer is taken. If the argument is NaN,
+ * infinite, or zero, the result is the same.
+ *
+ * @param a the value to act upon
+ * @return the nearest integer to <code>a</code>
+ */
+ public static native double rint(double a);
+
+ /**
+ * Take the nearest integer to the argument. This is equivalent to
+ * <code>(int) Math.floor(a + 0.5f)</code>. If the argument is NaN, the result
+ * is 0; otherwise if the argument is outside the range of int, the result
+ * will be Integer.MIN_VALUE or Integer.MAX_VALUE, as appropriate.
+ *
+ * @param a the argument to round
+ * @return the nearest integer to the argument
+ * @see Integer#MIN_VALUE
+ * @see Integer#MAX_VALUE
+ */
+ public static int round(float a)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return 0;
+ return (int) floor(a + 0.5f);
+ }
+
+ /**
+ * Take the nearest long to the argument. This is equivalent to
+ * <code>(long) Math.floor(a + 0.5)</code>. If the argument is NaN, the
+ * result is 0; otherwise if the argument is outside the range of long, the
+ * result will be Long.MIN_VALUE or Long.MAX_VALUE, as appropriate.
+ *
+ * @param a the argument to round
+ * @return the nearest long to the argument
+ * @see Long#MIN_VALUE
+ * @see Long#MAX_VALUE
+ */
+ public static long round(double a)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return 0;
+ return (long) floor(a + 0.5d);
+ }
+
+ /**
+ * Get a random number. This behaves like Random.nextDouble(), seeded by
+ * System.currentTimeMillis() when first called. In other words, the number
+ * is from a pseudorandom sequence, and lies in the range [+0.0, 1.0).
+ * This random sequence is only used by this method, and is threadsafe,
+ * although you may want your own random number generator if it is shared
+ * among threads.
+ *
+ * @return a random number
+ * @see Random#nextDouble()
+ * @see System#currentTimeMillis()
+ */
+ public static synchronized double random()
+ {
+ if (rand == null)
+ rand = new Random();
+ return rand.nextDouble();
+ }
+
+ /**
+ * Convert from degrees to radians. The formula for this is
+ * radians = degrees * (pi/180); however it is not always exact given the
+ * limitations of floating point numbers.
+ *
+ * @param degrees an angle in degrees
+ * @return the angle in radians
+ * @since 1.2
+ */
+ public static double toRadians(double degrees)
+ {
+ return (degrees * PI) / 180;
+ }
+
+ /**
+ * Convert from radians to degrees. The formula for this is
+ * degrees = radians * (180/pi); however it is not always exact given the
+ * limitations of floating point numbers.
+ *
+ * @param rads an angle in radians
+ * @return the angle in degrees
+ * @since 1.2
+ */
+ public static double toDegrees(double rads)
+ {
+ return (rads * 180) / PI;
+ }
+}
diff --git a/libjava/classpath/java/lang/NegativeArraySizeException.java b/libjava/classpath/java/lang/NegativeArraySizeException.java
new file mode 100644
index 00000000000..fcfa52e475c
--- /dev/null
+++ b/libjava/classpath/java/lang/NegativeArraySizeException.java
@@ -0,0 +1,77 @@
+/* NegativeArraySizeException.java -- thrown on attempt to create array
+ with a negative size
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when an attempt is made to create an array with a negative
+ * size. For example:<br>
+ * <pre>
+ * int i = -1;
+ * int[] array = new int[i];
+ * </pre>
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class NegativeArraySizeException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -8960118058596991861L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public NegativeArraySizeException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NegativeArraySizeException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/NoClassDefFoundError.java b/libjava/classpath/java/lang/NoClassDefFoundError.java
new file mode 100644
index 00000000000..7e8e6caff80
--- /dev/null
+++ b/libjava/classpath/java/lang/NoClassDefFoundError.java
@@ -0,0 +1,76 @@
+/* NoClassDefFoundError.java -- thrown when a ClassLoader cannot find a class
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>NoClassDefFoundError</code> is thrown when a classloader or the
+ * Java Virtual Machine tries to load a class and no definition of the class
+ * can be found. This could happen when using the <code>new</code> expression
+ * or during a normal method call. The reason this would occur at runtime is
+ * because the missing class definition existed when the currently executing
+ * class was compiled, but now that definition cannot be found.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class NoClassDefFoundError extends LinkageError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 9095859863287012458L;
+
+ /**
+ * Create an error without a message.
+ */
+ public NoClassDefFoundError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public NoClassDefFoundError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/NoSuchFieldError.java b/libjava/classpath/java/lang/NoSuchFieldError.java
new file mode 100644
index 00000000000..af42e35dcf2
--- /dev/null
+++ b/libjava/classpath/java/lang/NoSuchFieldError.java
@@ -0,0 +1,74 @@
+/* NoSuchFieldError.java -- thrown when the linker does not find a field
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>NoSuchFieldError</code> is thrown if an application attempts
+ * to access a field of a class, and that class no longer has that field.
+ * This is normally detected by the compiler, so it signals that you are
+ * using binary incompatible class versions.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class NoSuchFieldError extends IncompatibleClassChangeError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -3456430195886129035L;
+
+ /**
+ * Create an error without a message.
+ */
+ public NoSuchFieldError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public NoSuchFieldError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/NoSuchFieldException.java b/libjava/classpath/java/lang/NoSuchFieldException.java
new file mode 100644
index 00000000000..74d52d137c4
--- /dev/null
+++ b/libjava/classpath/java/lang/NoSuchFieldException.java
@@ -0,0 +1,73 @@
+/* NoSuchFieldException.java -- thrown when reflecting a non-existant field
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown to indicate the class does not have the specified field. This is
+ * caused by a variety of reflection methods, when looking up a field by name.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class NoSuchFieldException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -6143714805279938260L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public NoSuchFieldException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NoSuchFieldException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/NoSuchMethodError.java b/libjava/classpath/java/lang/NoSuchMethodError.java
new file mode 100644
index 00000000000..2bda776e8e9
--- /dev/null
+++ b/libjava/classpath/java/lang/NoSuchMethodError.java
@@ -0,0 +1,74 @@
+/* NoSuchMethodError.java -- thrown when the linker does not find a method
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>NoSuchMethodError</code> is thrown if an application attempts
+ * to access a method of a class, and that class no longer has that method.
+ * This is normally detected by the compiler, so it signals that you are
+ * using binary incompatible class versions.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class NoSuchMethodError extends IncompatibleClassChangeError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ static final long serialVersionUID = -3765521442372831335L;
+
+ /**
+ * Create an error without a message.
+ */
+ public NoSuchMethodError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public NoSuchMethodError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/NoSuchMethodException.java b/libjava/classpath/java/lang/NoSuchMethodException.java
new file mode 100644
index 00000000000..e423efb79f6
--- /dev/null
+++ b/libjava/classpath/java/lang/NoSuchMethodException.java
@@ -0,0 +1,72 @@
+/* NoSuchMethodException.java -- thrown when reflecting a non-existant method
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown to indicate the class does not have the specified method. This is
+ * caused by a variety of reflection methods, when looking up a method by name.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class NoSuchMethodException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 5034388446362600923L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public NoSuchMethodException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NoSuchMethodException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/NullPointerException.java b/libjava/classpath/java/lang/NullPointerException.java
new file mode 100644
index 00000000000..29a4ee086c5
--- /dev/null
+++ b/libjava/classpath/java/lang/NullPointerException.java
@@ -0,0 +1,82 @@
+/* NullPointerException.java -- thrown when using null instead of an object
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when attempting to use <code>null</code> where an object
+ * is required. The Virtual Machine automatically throws this exception
+ * for the following:<br><ul>
+ * <li>Calling an instance method on a null object</li>
+ * <li>Accessing or modifying a field of a null object</li>
+ * <li>Taking the array length of a null array</li>
+ * <li>Accessing or modifying the slots of a null array</li>
+ * <li>Throwing a null Throwable</li>
+ * <li>Synchronizing on a null object</li>
+ * </ul>
+ * <p>Applications should also throw NullPointerExceptions whenever
+ * <code>null</code> is an inappropriate parameter to a method.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class NullPointerException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 5162710183389028792L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public NullPointerException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NullPointerException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/Number.java b/libjava/classpath/java/lang/Number.java
new file mode 100644
index 00000000000..eb81f78c86e
--- /dev/null
+++ b/libjava/classpath/java/lang/Number.java
@@ -0,0 +1,131 @@
+/* Number.java =- abstract superclass of numeric objects
+ Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import java.io.Serializable;
+
+/**
+ * Number is a generic superclass of all the numeric classes, including
+ * the wrapper classes {@link Byte}, {@link Short}, {@link Integer},
+ * {@link Long}, {@link Float}, and {@link Double}. Also worth mentioning
+ * are the classes in {@link java.math}.
+ *
+ * It provides ways to convert numeric objects to any primitive.
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Warren Levy
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class Number implements Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -8742448824652078965L;
+
+ /**
+ * Table for calculating digits, used in Character, Long, and Integer.
+ */
+ static final char[] digits = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ };
+
+ /**
+ * The basic constructor (often called implicitly).
+ */
+ public Number()
+ {
+ }
+
+ /**
+ * Return the value of this <code>Number</code> as an <code>int</code>.
+ *
+ * @return the int value
+ */
+ public abstract int intValue();
+
+ /**
+ * Return the value of this <code>Number</code> as a <code>long</code>.
+ *
+ * @return the long value
+ */
+ public abstract long longValue();
+
+ /**
+ * Return the value of this <code>Number</code> as a <code>float</code>.
+ *
+ * @return the float value
+ */
+ public abstract float floatValue();
+
+ /**
+ * Return the value of this <code>Number</code> as a <code>float</code>.
+ *
+ * @return the double value
+ */
+ public abstract double doubleValue();
+
+ /**
+ * Return the value of this <code>Number</code> as a <code>byte</code>.
+ *
+ * @return the byte value
+ * @since 1.1
+ */
+ public byte byteValue()
+ {
+ return (byte) intValue();
+ }
+
+ /**
+ * Return the value of this <code>Number</code> as a <code>short</code>.
+ *
+ * @return the short value
+ * @since 1.1
+ */
+ public short shortValue()
+ {
+ return (short) intValue();
+ }
+}
diff --git a/libjava/classpath/java/lang/NumberFormatException.java b/libjava/classpath/java/lang/NumberFormatException.java
new file mode 100644
index 00000000000..bf98156d13c
--- /dev/null
+++ b/libjava/classpath/java/lang/NumberFormatException.java
@@ -0,0 +1,73 @@
+/* NumberFormatException.java -- thrown when parsing a bad string as a number
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Can be thrown when attempting to convert a <code>String</code> to
+ * one of the numeric types, but the operation fails because the string
+ * has the wrong format.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class NumberFormatException extends IllegalArgumentException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -2848938806368998894L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public NumberFormatException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NumberFormatException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/Object.java b/libjava/classpath/java/lang/Object.java
new file mode 100644
index 00000000000..f8c389a57ee
--- /dev/null
+++ b/libjava/classpath/java/lang/Object.java
@@ -0,0 +1,530 @@
+/* java.lang.Object - The universal superclass in Java
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+
+/**
+ * Object is the ultimate superclass of every class
+ * (excepting interfaces). When you define a class that
+ * does not extend any other class, it implicitly extends
+ * java.lang.Object. Also, an anonymous class based on
+ * an interface will extend Object.
+ *
+ * <p>It provides general-purpose methods that every single
+ * Object, regardless of race, sex or creed, implements.
+ * All of the public methods may be invoked on arrays or
+ * interfaces. The protected methods <code>clone</code>
+ * and <code>finalize</code> are not accessible on arrays
+ * or interfaces, but all array types have a public version
+ * of <code>clone</code> which is accessible.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class Object
+{
+ // WARNING: Object is a CORE class in the bootstrap cycle. See the comments
+ // in vm/reference/java/lang/Runtime for implications of this fact.
+
+ // Many JVMs do not allow for static initializers in this class,
+ // hence we do not use them in the default implementation.
+
+ // Some VM's rely on the order that these methods appear when laying
+ // out their internal structure. Therefore, do not haphazardly
+ // rearrange these methods.
+
+ /**
+ * The basic constructor. Object is special, because it has no
+ * superclass, so there is no call to super().
+ *
+ * @throws OutOfMemoryError Technically, this constructor never
+ * throws an OutOfMemoryError, because the memory has
+ * already been allocated by this point. But as all
+ * instance creation expressions eventually trace back
+ * to this constructor, and creating an object allocates
+ * memory, we list that possibility here.
+ */
+ // This could be implicit, but then javadoc would not document it!
+ public Object() {}
+
+ /**
+ * Determine whether this Object is semantically equal
+ * to another Object.
+ *
+ * <p>There are some fairly strict requirements on this
+ * method which subclasses must follow:<br>
+ * <ul>
+ * <li>It must be transitive. If <code>a.equals(b)</code> and
+ * <code>b.equals(c)</code>, then <code>a.equals(c)</code>
+ * must be true as well.</li>
+ * <li>It must be symmetric. <code>a.equals(b)</code> and
+ * <code>b.equals(a)</code> must have the same value.</li>
+ * <li>It must be reflexive. <code>a.equals(a)</code> must
+ * always be true.</li>
+ * <li>It must be consistent. Whichever value a.equals(b)
+ * returns on the first invocation must be the value
+ * returned on all later invocations.</li>
+ * <li><code>a.equals(null)</code> must be false.</li>
+ * <li>It must be consistent with hashCode(). That is,
+ * <code>a.equals(b)</code> must imply
+ * <code>a.hashCode() == b.hashCode()</code>.
+ * The reverse is not true; two objects that are not
+ * equal may have the same hashcode, but that has
+ * the potential to harm hashing performance.</li>
+ * </ul>
+ *
+ * <p>This is typically overridden to throw a {@link ClassCastException}
+ * if the argument is not comparable to the class performing
+ * the comparison, but that is not a requirement. It is legal
+ * for <code>a.equals(b)</code> to be true even though
+ * <code>a.getClass() != b.getClass()</code>. Also, it
+ * is typical to never cause a {@link NullPointerException}.
+ *
+ * <p>In general, the Collections API ({@link java.util}) use the
+ * <code>equals</code> method rather than the <code>==</code>
+ * operator to compare objects. However, {@link java.util.IdentityHashMap}
+ * is an exception to this rule, for its own good reasons.
+ *
+ * <p>The default implementation returns <code>this == o</code>.
+ *
+ * @param obj the Object to compare to
+ * @return whether this Object is semantically equal to another
+ * @see #hashCode()
+ */
+ public boolean equals(Object obj)
+ {
+ return this == obj;
+ }
+
+ /**
+ * Get a value that represents this Object, as uniquely as
+ * possible within the confines of an int.
+ *
+ * <p>There are some requirements on this method which
+ * subclasses must follow:<br>
+ *
+ * <ul>
+ * <li>Semantic equality implies identical hashcodes. In other
+ * words, if <code>a.equals(b)</code> is true, then
+ * <code>a.hashCode() == b.hashCode()</code> must be as well.
+ * However, the reverse is not necessarily true, and two
+ * objects may have the same hashcode without being equal.</li>
+ * <li>It must be consistent. Whichever value o.hashCode()
+ * returns on the first invocation must be the value
+ * returned on all later invocations as long as the object
+ * exists. Notice, however, that the result of hashCode may
+ * change between separate executions of a Virtual Machine,
+ * because it is not invoked on the same object.</li>
+ * </ul>
+ *
+ * <p>Notice that since <code>hashCode</code> is used in
+ * {@link java.util.Hashtable} and other hashing classes,
+ * a poor implementation will degrade the performance of hashing
+ * (so don't blindly implement it as returning a constant!). Also,
+ * if calculating the hash is time-consuming, a class may consider
+ * caching the results.
+ *
+ * <p>The default implementation returns
+ * <code>System.identityHashCode(this)</code>
+ *
+ * @return the hash code for this Object
+ * @see #equals(Object)
+ * @see System#identityHashCode(Object)
+ */
+ public int hashCode()
+ {
+ return System.identityHashCode(this);
+ }
+
+ /**
+ * Convert this Object to a human-readable String.
+ * There are no limits placed on how long this String
+ * should be or what it should contain. We suggest you
+ * make it as intuitive as possible to be able to place
+ * it into {@link java.io.PrintStream#println() System.out.println()}
+ * and such.
+ *
+ * <p>It is typical, but not required, to ensure that this method
+ * never completes abruptly with a {@link RuntimeException}.
+ *
+ * <p>This method will be called when performing string
+ * concatenation with this object. If the result is
+ * <code>null</code>, string concatenation will instead
+ * use <code>"null"</code>.
+ *
+ * <p>The default implementation returns
+ * <code>getClass().getName() + "@" +
+ * Integer.toHexString(hashCode())</code>.
+ *
+ * @return the String representing this Object, which may be null
+ * @throws OutOfMemoryError The default implementation creates a new
+ * String object, therefore it must allocate memory
+ * @see #getClass()
+ * @see #hashCode()
+ * @see Class#getName()
+ * @see Integer#toHexString(int)
+ */
+ public String toString()
+ {
+ return getClass().getName() + '@' + Integer.toHexString(hashCode());
+ }
+
+ /**
+ * Called on an object by the Virtual Machine at most once,
+ * at some point after the Object is determined unreachable
+ * but before it is destroyed. You would think that this
+ * means it eventually is called on every Object, but this is
+ * not necessarily the case. If execution terminates
+ * abnormally, garbage collection does not always happen.
+ * Thus you cannot rely on this method to always work.
+ * For finer control over garbage collection, use references
+ * from the {@link java.lang.ref} package.
+ *
+ * <p>Virtual Machines are free to not call this method if
+ * they can determine that it does nothing important; for
+ * example, if your class extends Object and overrides
+ * finalize to do simply <code>super.finalize()</code>.
+ *
+ * <p>finalize() will be called by a {@link Thread} that has no
+ * locks on any Objects, and may be called concurrently.
+ * There are no guarantees on the order in which multiple
+ * objects are finalized. This means that finalize() is
+ * usually unsuited for performing actions that must be
+ * thread-safe, and that your implementation must be
+ * use defensive programming if it is to always work.
+ *
+ * <p>If an Exception is thrown from finalize() during garbage
+ * collection, it will be patently ignored and the Object will
+ * still be destroyed.
+ *
+ * <p>It is allowed, although not typical, for user code to call
+ * finalize() directly. User invocation does not affect whether
+ * automatic invocation will occur. It is also permitted,
+ * although not recommended, for a finalize() method to "revive"
+ * an object by making it reachable from normal code again.
+ *
+ * <p>Unlike constructors, finalize() does not get called
+ * for an object's superclass unless the implementation
+ * specifically calls <code>super.finalize()</code>.
+ *
+ * <p>The default implementation does nothing.
+ *
+ * @throws Throwable permits a subclass to throw anything in an
+ * overridden version; but the default throws nothing
+ * @see System#gc()
+ * @see System#runFinalizersOnExit(boolean)
+ * @see java.lang.ref
+ */
+ protected void finalize() throws Throwable
+ {
+ }
+
+ /**
+ * This method may be called to create a new copy of the
+ * Object. The typical behavior is as follows:<br>
+ * <ul>
+ * <li><code>o == o.clone()</code> is false</li>
+ * <li><code>o.getClass() == o.clone().getClass()</code>
+ * is true</li>
+ * <li><code>o.equals(o)</code> is true</li>
+ * </ul>
+ *
+ * <p>However, these are not strict requirements, and may
+ * be violated if necessary. Of the three requirements, the
+ * last is the most commonly violated, particularly if the
+ * subclass does not override {@link #equals(Object)}.
+ *
+ * <p>If the Object you call clone() on does not implement
+ * {@link Cloneable} (which is a placeholder interface), then
+ * a CloneNotSupportedException is thrown. Notice that
+ * Object does not implement Cloneable; this method exists
+ * as a convenience for subclasses that do.
+ *
+ * <p>Object's implementation of clone allocates space for the
+ * new Object using the correct class, without calling any
+ * constructors, and then fills in all of the new field values
+ * with the old field values. Thus, it is a shallow copy.
+ * However, subclasses are permitted to make a deep copy.
+ *
+ * <p>All array types implement Cloneable, and override
+ * this method as follows (it should never fail):<br>
+ * <pre>
+ * public Object clone()
+ * {
+ * try
+ * {
+ * super.clone();
+ * }
+ * catch (CloneNotSupportedException e)
+ * {
+ * throw new InternalError(e.getMessage());
+ * }
+ * }
+ * </pre>
+ *
+ * @return a copy of the Object
+ * @throws CloneNotSupportedException If this Object does not
+ * implement Cloneable
+ * @throws OutOfMemoryError Since cloning involves memory allocation,
+ * even though it may bypass constructors, you might run
+ * out of memory
+ * @see Cloneable
+ */
+ protected Object clone() throws CloneNotSupportedException
+ {
+ if (this instanceof Cloneable)
+ return VMObject.clone((Cloneable) this);
+ throw new CloneNotSupportedException("Object not cloneable");
+ }
+
+ /**
+ * Returns the runtime {@link Class} of this Object.
+ *
+ * <p>The class object can also be obtained without a runtime
+ * instance by using the class literal, as in:
+ * <code>Foo.class</code>. Notice that the class literal
+ * also works on primitive types, making it useful for
+ * reflection purposes.
+ *
+ * @return the class of this Object
+ */
+ public final Class getClass()
+ {
+ return VMObject.getClass(this);
+ }
+
+ /**
+ * Wakes up one of the {@link Thread}s that has called
+ * <code>wait</code> on this Object. Only the owner
+ * of a lock on this Object may call this method. This lock
+ * is obtained by a <code>synchronized</code> method or statement.
+ *
+ * <p>The Thread to wake up is chosen arbitrarily. The
+ * awakened thread is not guaranteed to be the next thread
+ * to actually obtain the lock on this object.
+ *
+ * <p>This thread still holds a lock on the object, so it is
+ * typical to release the lock by exiting the synchronized
+ * code, calling wait(), or calling {@link Thread#sleep()}, so
+ * that the newly awakened thread can actually resume. The
+ * awakened thread will most likely be awakened with an
+ * {@link InterruptedException}, but that is not guaranteed.
+ *
+ * @throws IllegalMonitorStateException if this Thread
+ * does not own the lock on the Object
+ * @see #notifyAll()
+ * @see #wait()
+ * @see #wait(long)
+ * @see #wait(long, int)
+ * @see Thread
+ */
+ public final void notify() throws IllegalMonitorStateException
+ {
+ VMObject.notify(this);
+ }
+
+ /**
+ * Wakes up all of the {@link Thread}s that have called
+ * <code>wait</code> on this Object. Only the owner
+ * of a lock on this Object may call this method. This lock
+ * is obtained by a <code>synchronized</code> method or statement.
+ *
+ * <p>There are no guarantees as to which thread will next
+ * obtain the lock on the object.
+ *
+ * <p>This thread still holds a lock on the object, so it is
+ * typical to release the lock by exiting the synchronized
+ * code, calling wait(), or calling {@link Thread#sleep()}, so
+ * that one of the newly awakened threads can actually resume.
+ * The resuming thread will most likely be awakened with an
+ * {@link InterruptedException}, but that is not guaranteed.
+ *
+ * @throws IllegalMonitorStateException if this Thread
+ * does not own the lock on the Object
+ * @see #notify()
+ * @see #wait()
+ * @see #wait(long)
+ * @see #wait(long, int)
+ * @see Thread
+ */
+ public final void notifyAll() throws IllegalMonitorStateException
+ {
+ VMObject.notifyAll(this);
+ }
+
+ /**
+ * Waits indefinitely for notify() or notifyAll() to be
+ * called on the Object in question. Implementation is
+ * identical to wait(0).
+ *
+ * <p>The Thread that calls wait must have a lock on this Object,
+ * obtained by a <code>synchronized</code> method or statement.
+ * After calling wait, the thread loses the lock on this
+ * object until the method completes (abruptly or normally),
+ * at which time it regains the lock. All locks held on
+ * other objects remain in force, even though the thread is
+ * inactive. Therefore, caution must be used to avoid deadlock.
+ *
+ * <p>While it is typical that this method will complete abruptly
+ * with an {@link InterruptedException}, it is not guaranteed. So,
+ * it is typical to call wait inside an infinite loop:<br>
+ *
+ * <pre>
+ * try
+ * {
+ * while (true)
+ * lock.wait();
+ * }
+ * catch (InterruptedException e)
+ * {
+ * }
+ * </pre>
+ *
+ * @throws IllegalMonitorStateException if this Thread
+ * does not own a lock on this Object
+ * @throws InterruptedException if some other Thread
+ * interrupts this Thread
+ * @see #notify()
+ * @see #notifyAll()
+ * @see #wait(long)
+ * @see #wait(long, int)
+ * @see Thread
+ */
+ public final void wait()
+ throws IllegalMonitorStateException, InterruptedException
+ {
+ VMObject.wait(this, 0, 0);
+ }
+
+ /**
+ * Waits a specified amount of time (or indefinitely if
+ * the time specified is 0) for someone to call notify()
+ * or notifyAll() on this Object, waking up this Thread.
+ *
+ * <p>The Thread that calls wait must have a lock on this Object,
+ * obtained by a <code>synchronized</code> method or statement.
+ * After calling wait, the thread loses the lock on this
+ * object until the method completes (abruptly or normally),
+ * at which time it regains the lock. All locks held on
+ * other objects remain in force, even though the thread is
+ * inactive. Therefore, caution must be used to avoid deadlock.
+ *
+ * <p>Usually, this call will complete normally if the time
+ * expires, or abruptly with {@link InterruptedException}
+ * if another thread called notify, but neither result
+ * is guaranteed.
+ *
+ * <p>The waiting period is only *roughly* the amount of time
+ * you requested. It cannot be exact because of the overhead
+ * of the call itself. Most Virtual Machiness treat the
+ * argument as a lower limit on the time spent waiting, but
+ * even that is not guaranteed. Besides, some other thread
+ * may hold the lock on the object when the time expires, so
+ * the current thread may still have to wait to reobtain the
+ * lock.
+ *
+ * @param ms the minimum number of milliseconds to wait (1000
+ * milliseconds = 1 second), or 0 for an indefinite wait
+ * @throws IllegalArgumentException if ms &lt; 0
+ * @throws IllegalMonitorStateException if this Thread
+ * does not own a lock on this Object
+ * @throws InterruptedException if some other Thread
+ * interrupts this Thread
+ * @see #notify()
+ * @see #notifyAll()
+ * @see #wait()
+ * @see #wait(long, int)
+ * @see Thread
+ */
+ public final void wait(long ms)
+ throws IllegalMonitorStateException, InterruptedException
+ {
+ wait(ms, 0);
+ }
+
+ /**
+ * Waits a specified amount of time (or indefinitely if
+ * the time specified is 0) for someone to call notify()
+ * or notifyAll() on this Object, waking up this Thread.
+ *
+ * <p>The Thread that calls wait must have a lock on this Object,
+ * obtained by a <code>synchronized</code> method or statement.
+ * After calling wait, the thread loses the lock on this
+ * object until the method completes (abruptly or normally),
+ * at which time it regains the lock. All locks held on
+ * other objects remain in force, even though the thread is
+ * inactive. Therefore, caution must be used to avoid deadlock.
+ *
+ * <p>Usually, this call will complete normally if the time
+ * expires, or abruptly with {@link InterruptedException}
+ * if another thread called notify, but neither result
+ * is guaranteed.
+ *
+ * <p>The waiting period is nowhere near as precise as
+ * nanoseconds; considering that even wait(int) is inaccurate,
+ * how much can you expect? But on supporting
+ * implementations, this offers somewhat more granularity
+ * than milliseconds.
+ *
+ * @param ms the number of milliseconds to wait (1,000
+ * milliseconds = 1 second)
+ * @param ns the number of nanoseconds to wait over and
+ * above ms (1,000,000 nanoseconds = 1 millisecond)
+ * @throws IllegalArgumentException if ms &lt; 0 or ns is not
+ * in the range 0 to 999,999
+ * @throws IllegalMonitorStateException if this Thread
+ * does not own a lock on this Object
+ * @throws InterruptedException if some other Thread
+ * interrupts this Thread
+ * @see #notify()
+ * @see #notifyAll()
+ * @see #wait()
+ * @see #wait(long)
+ * @see Thread
+ */
+ public final void wait(long ms, int ns)
+ throws IllegalMonitorStateException, InterruptedException
+ {
+ if (ms < 0 || ns < 0 || ns > 999999)
+ throw new IllegalArgumentException("argument out of range");
+ VMObject.wait(this, ms, ns);
+ }
+} // class Object
diff --git a/libjava/classpath/java/lang/OutOfMemoryError.java b/libjava/classpath/java/lang/OutOfMemoryError.java
new file mode 100644
index 00000000000..66da563a0fb
--- /dev/null
+++ b/libjava/classpath/java/lang/OutOfMemoryError.java
@@ -0,0 +1,73 @@
+/* OutOfMemoryError.java -- thrown when a memory allocation fails
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Thrown when the Java Virtual Machine is unable to allocate an object
+ * because it is out of memory and no more memory could be made available
+ * by the garbage collector.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class OutOfMemoryError extends VirtualMachineError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 8228564086184010517L;
+
+ /**
+ * Create an error without a message.
+ */
+ public OutOfMemoryError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public OutOfMemoryError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/Package.java b/libjava/classpath/java/lang/Package.java
new file mode 100644
index 00000000000..4cded0af304
--- /dev/null
+++ b/libjava/classpath/java/lang/Package.java
@@ -0,0 +1,318 @@
+/* Package.java -- information about a package
+ Copyright (C) 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import gnu.classpath.VMStackWalker;
+
+import java.net.URL;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+
+/**
+ * Everything you ever wanted to know about a package. This class makes it
+ * possible to attach specification and implementation information to a
+ * package as explained in the
+ * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersionSpecification">Package Versioning Specification</a>
+ * section of the
+ * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html">Product Versioning Specification</a>.
+ * It also allows packages to be sealed with respect to the originating URL.
+ *
+ * <p>The most useful method is the <code>isCompatibleWith()</code> method that
+ * compares a desired version of a specification with the version of the
+ * specification as implemented by a package. A package is considered
+ * compatible with another version if the version of the specification is
+ * equal or higher then the requested version. Version numbers are represented
+ * as strings of positive numbers separated by dots (e.g. "1.2.0").
+ * The first number is called the major number, the second the minor,
+ * the third the micro, etc. A version is considered higher then another
+ * version if it has a bigger major number then the another version or when
+ * the major numbers of the versions are equal if it has a bigger minor number
+ * then the other version, etc. (If a version has no minor, micro, etc numbers
+ * then they are considered the be 0.)
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @see ClassLoader#definePackage(String, String, String, String, String,
+ * String, String, URL)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class Package
+{
+ /** The name of the Package */
+ private final String name;
+
+ /** The name if the implementation */
+ private final String implTitle;
+
+ /** The vendor that wrote this implementation */
+ private final String implVendor;
+
+ /** The version of this implementation */
+ private final String implVersion;
+
+ /** The name of the specification */
+ private final String specTitle;
+
+ /** The name of the specification designer */
+ private final String specVendor;
+
+ /** The version of this specification */
+ private final String specVersion;
+
+ /** If sealed the origin of the package classes, otherwise null */
+ private final URL sealed;
+
+ /**
+ * A package local constructor for the Package class. All parameters except
+ * the <code>name</code> of the package may be <code>null</code>.
+ * There are no public constructors defined for Package; this is a package
+ * local constructor that is used by java.lang.Classloader.definePackage().
+ *
+ * @param name The name of the Package
+ * @param specTitle The name of the specification
+ * @param specVendor The name of the specification designer
+ * @param specVersion The version of this specification
+ * @param implTitle The name of the implementation
+ * @param implVendor The vendor that wrote this implementation
+ * @param implVersion The version of this implementation
+ * @param sealed If sealed the origin of the package classes
+ */
+ Package(String name,
+ String specTitle, String specVendor, String specVersion,
+ String implTitle, String implVendor, String implVersion, URL sealed)
+ {
+ if (name == null)
+ throw new IllegalArgumentException("null Package name");
+
+ this.name = name;
+ this.implTitle = implTitle;
+ this.implVendor = implVendor;
+ this.implVersion = implVersion;
+ this.specTitle = specTitle;
+ this.specVendor = specVendor;
+ this.specVersion = specVersion;
+ this.sealed = sealed;
+ }
+
+ /**
+ * Returns the Package name in dot-notation.
+ *
+ * @return the non-null package name
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns the name of the specification, or null if unknown.
+ *
+ * @return the specification title
+ */
+ public String getSpecificationTitle()
+ {
+ return specTitle;
+ }
+
+ /**
+ * Returns the version of the specification, or null if unknown.
+ *
+ * @return the specification version
+ */
+ public String getSpecificationVersion()
+ {
+ return specVersion;
+ }
+
+ /**
+ * Returns the name of the specification designer, or null if unknown.
+ *
+ * @return the specification vendor
+ */
+ public String getSpecificationVendor()
+ {
+ return specVendor;
+ }
+
+ /**
+ * Returns the name of the implementation, or null if unknown.
+ *
+ * @return the implementation title
+ */
+ public String getImplementationTitle()
+ {
+ return implTitle;
+ }
+
+ /**
+ * Returns the version of this implementation, or null if unknown.
+ *
+ * @return the implementation version
+ */
+ public String getImplementationVersion()
+ {
+ return implVersion;
+ }
+
+ /**
+ * Returns the vendor that wrote this implementation, or null if unknown.
+ *
+ * @return the implementation vendor
+ */
+ public String getImplementationVendor()
+ {
+ return implVendor;
+ }
+
+ /**
+ * Returns true if this Package is sealed.
+ *
+ * @return true if the package is sealed
+ */
+ public boolean isSealed()
+ {
+ return sealed != null;
+ }
+
+ /**
+ * Returns true if this Package is sealed and the origin of the classes is
+ * the given URL.
+ *
+ * @param url the URL to test
+ * @return true if the package is sealed by this URL
+ * @throws NullPointerException if url is null
+ */
+ public boolean isSealed(URL url)
+ {
+ return url.equals(sealed);
+ }
+
+ /**
+ * Checks if the version of the specification is higher or at least as high
+ * as the desired version. Comparison is done by sequentially comparing
+ * dotted decimal numbers from the parameter and from
+ * <code>getSpecificationVersion</code>.
+ *
+ * @param version the (minimal) desired version of the specification
+ *
+ * @return true if the version is compatible, false otherwise
+ *
+ * @Throws NumberFormatException if either version string is invalid
+ * @throws NullPointerException if either version string is null
+ */
+ public boolean isCompatibleWith(String version)
+ {
+ StringTokenizer versionTokens = new StringTokenizer(version, ".");
+ StringTokenizer specTokens = new StringTokenizer(specVersion, ".");
+ try
+ {
+ while (versionTokens.hasMoreElements())
+ {
+ int vers = Integer.parseInt(versionTokens.nextToken());
+ int spec = Integer.parseInt(specTokens.nextToken());
+ if (spec < vers)
+ return false;
+ else if (spec > vers)
+ return true;
+ // They must be equal, next Token please!
+ }
+ }
+ catch (NoSuchElementException e)
+ {
+ // This must have been thrown by spec.nextToken() so return false.
+ return false;
+ }
+ // They must have been exactly the same version.
+ // Or the specVersion has more subversions. That is also good.
+ return true;
+ }
+
+ /**
+ * Returns the named package if it is known by the callers class loader.
+ * It may return null if the package is unknown, when there is no
+ * information on that particular package available or when the callers
+ * classloader is null.
+ *
+ * @param name the name of the desired package
+ * @return the package by that name in the current ClassLoader
+ */
+ public static Package getPackage(String name)
+ {
+ // Get the caller's classloader
+ ClassLoader cl = VMStackWalker.getCallingClassLoader();
+ return cl != null ? cl.getPackage(name) : VMClassLoader.getPackage(name);
+ }
+
+ /**
+ * Returns all the packages that are known to the callers class loader.
+ * It may return an empty array if the classloader of the caller is null.
+ *
+ * @return an array of all known packages
+ */
+ public static Package[] getPackages()
+ {
+ // Get the caller's classloader
+ ClassLoader cl = VMStackWalker.getCallingClassLoader();
+ return cl != null ? cl.getPackages() : VMClassLoader.getPackages();
+ }
+
+ /**
+ * Returns the hashCode of the name of this package.
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return name.hashCode();
+ }
+
+ /**
+ * Returns a string representation of this package. It is specified to
+ * be <code>"package " + getName() + (getSpecificationTitle() == null
+ * ? "" : ", " + getSpecificationTitle()) + (getSpecificationVersion()
+ * == null ? "" : ", version " + getSpecificationVersion())</code>.
+ *
+ * @return the string representation of the package
+ */
+ public String toString()
+ {
+ return ("package " + name + (specTitle == null ? "" : ", " + specTitle)
+ + (specVersion == null ? "" : ", version " + specVersion));
+ }
+} // class Package
diff --git a/libjava/classpath/java/lang/Process.java b/libjava/classpath/java/lang/Process.java
new file mode 100644
index 00000000000..b6e18ca4df3
--- /dev/null
+++ b/libjava/classpath/java/lang/Process.java
@@ -0,0 +1,129 @@
+/* Process.java - Represent spawned system process
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * An instance of a subclass of <code>Process</code> is created by the
+ * <code>Runtime.exec</code> methods. Methods in <code>Process</code>
+ * provide a means to send input to a process, obtain the output from a
+ * subprocess, destroy a subprocess, obtain the exit value from a
+ * subprocess, and wait for a subprocess to complete.
+ *
+ * <p>This is dependent on the platform, and some processes (like native
+ * windowing processes, 16-bit processes in Windows, or shell scripts) may
+ * be limited in functionality. Because some platforms have limited buffers
+ * between processes, you may need to provide input and read output to prevent
+ * the process from blocking, or even deadlocking.
+ *
+ * <p>Even if all references to this object disapper, the process continues
+ * to execute to completion. There are no guarantees that the
+ * subprocess execute asynchronously or concurrently with the process which
+ * owns this object.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see Runtime#exec(String[], String[], File)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class Process
+{
+ /**
+ * Empty constructor does nothing.
+ */
+ public Process()
+ {
+ }
+
+ /**
+ * Obtain the output stream that sends data to the subprocess. This is
+ * the STDIN of the subprocess. When implementing, you should probably
+ * use a buffered stream.
+ *
+ * @return the output stream that pipes to the process input
+ */
+ public abstract OutputStream getOutputStream();
+
+ /**
+ * Obtain the input stream that receives data from the subprocess. This is
+ * the STDOUT of the subprocess. When implementing, you should probably
+ * use a buffered stream.
+ *
+ * @return the input stream that pipes data from the process output
+ */
+ public abstract InputStream getInputStream();
+
+ /**
+ * Obtain the input stream that receives data from the subprocess. This is
+ * the STDERR of the subprocess. When implementing, you should probably
+ * use a buffered stream.
+ *
+ * @return the input stream that pipes data from the process error output
+ */
+ public abstract InputStream getErrorStream();
+
+ /**
+ * The thread calling <code>waitFor</code> will block until the subprocess
+ * has terminated. If the process has already terminated then the method
+ * immediately returns with the exit value of the subprocess.
+ *
+ * @return the subprocess exit value; 0 conventionally denotes success
+ * @throws InterruptedException if another thread interrupts the blocked one
+ */
+ public abstract int waitFor() throws InterruptedException;
+
+ /**
+ * When a process terminates there is associated with that termination
+ * an exit value for the process to indicate why it terminated. A return
+ * of <code>0</code> denotes normal process termination by convention.
+ *
+ * @return the exit value of the subprocess
+ * @throws IllegalThreadStateException if the subprocess has not terminated
+ */
+ public abstract int exitValue();
+
+ /**
+ * Kills the subprocess and all of its children forcibly.
+ */
+ public abstract void destroy();
+} // class Process
diff --git a/libjava/classpath/java/lang/Readable.java b/libjava/classpath/java/lang/Readable.java
new file mode 100644
index 00000000000..efc1985d606
--- /dev/null
+++ b/libjava/classpath/java/lang/Readable.java
@@ -0,0 +1,71 @@
+/* Readable.java -- A character source
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.io.IOException;
+import java.nio.CharBuffer;
+
+/**
+ * A <code>Readable</code> object is simply a source for Unicode character
+ * data. On request, a <code>Readable</code> will provide its data in
+ * a supplied <code>CharBuffer</code>.
+ *
+ * @author Tom Tromey <tromey@redhat.com>
+ * @author Andrew John Hughes <gnu_andrew@member.fsf.org>
+ * @since 1.5
+ */
+public interface Readable
+{
+
+ /**
+ * Adds the character data supplied by this <code>Readable</code>
+ * to the specified character buffer. This method simply places
+ * each character into the buffer as supplied, using <code>put()</code>,
+ * without flipping or rewinding.
+ *
+ * @param buf the buffer to place the character data in.
+ * @return the number of <code>char</code> values placed in the buffer,
+ * or -1 if no more characters are available.
+ * @throws IOException if an I/O error occurs.
+ * @throws NullPointerException if buf is null.
+ * @throws ReadOnlyBufferException if buf is read only.
+ */
+ int read(CharBuffer buf)
+ throws IOException;
+
+}
diff --git a/libjava/classpath/java/lang/Runnable.java b/libjava/classpath/java/lang/Runnable.java
new file mode 100644
index 00000000000..32c52b94a05
--- /dev/null
+++ b/libjava/classpath/java/lang/Runnable.java
@@ -0,0 +1,62 @@
+/* Runnable -- interface for a method tied to an Object; often for Threads
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Runnable is an interface you implement to indicate that your class can be
+ * executed as the main part of a Thread, among other places. When you want
+ * an entry point to run a piece of code, implement this interface and
+ * override run.
+ *
+ * @author Paul Fisher
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see Thread
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface Runnable
+{
+ /**
+ * This method will be called by whoever wishes to run your class
+ * implementing Runnable. Note that there are no restrictions on what
+ * you are allowed to do in the run method, except that you cannot
+ * throw a checked exception.
+ */
+ void run();
+}
diff --git a/libjava/classpath/java/lang/Runtime.java b/libjava/classpath/java/lang/Runtime.java
new file mode 100644
index 00000000000..64ca5d912d9
--- /dev/null
+++ b/libjava/classpath/java/lang/Runtime.java
@@ -0,0 +1,796 @@
+/* Runtime.java -- access to the VM process
+ Copyright (C) 1998, 2002, 2003, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.classpath.SystemProperties;
+import gnu.classpath.VMStackWalker;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * Runtime represents the Virtual Machine.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Jeroen Frijters
+ */
+// No idea why this class isn't final, since you can't build a subclass!
+public class Runtime
+{
+ /**
+ * The library path, to search when loading libraries. We can also safely use
+ * this as a lock for synchronization.
+ */
+ private final String[] libpath;
+
+ /**
+ * The thread that started the exit sequence. Access to this field must
+ * be thread-safe; lock on libpath to avoid deadlock with user code.
+ * <code>runFinalization()</code> may want to look at this to see if ALL
+ * finalizers should be run, because the virtual machine is about to halt.
+ */
+ private Thread exitSequence;
+
+ /**
+ * All shutdown hooks. This is initialized lazily, and set to null once all
+ * shutdown hooks have run. Access to this field must be thread-safe; lock
+ * on libpath to avoid deadlock with user code.
+ */
+ private Set shutdownHooks;
+
+ /**
+ * The one and only runtime instance.
+ */
+ private static final Runtime current = new Runtime();
+
+ /**
+ * Not instantiable by a user, this should only create one instance.
+ */
+ private Runtime()
+ {
+ if (current != null)
+ throw new InternalError("Attempt to recreate Runtime");
+
+ // If used by underlying VM this contains the directories where Classpath's own
+ // native libraries are located.
+ String bootPath = SystemProperties.getProperty("gnu.classpath.boot.library.path", "");
+
+ // If properly set by the user this contains the directories where the application's
+ // native libraries are located. On operating systems where a LD_LIBRARY_PATH environment
+ // variable is available a VM should preset java.library.path with value of this
+ // variable.
+ String path = SystemProperties.getProperty("java.library.path", ".");
+ String pathSep = SystemProperties.getProperty("path.separator", ":");
+ String fileSep = SystemProperties.getProperty("file.separator", "/");
+
+ StringTokenizer t1 = new StringTokenizer(bootPath, pathSep);
+ StringTokenizer t2 = new StringTokenizer(path, pathSep);
+ libpath = new String[t1.countTokens() + t2.countTokens()];
+
+ int i = 0;
+ while(t1.hasMoreTokens()) {
+ String prefix = t1.nextToken();
+ if (! prefix.endsWith(fileSep))
+ prefix += fileSep;
+
+ libpath[i] = prefix;
+ i++;
+ }
+
+ while(t2.hasMoreTokens()) {
+ String prefix = t2.nextToken();
+ if (! prefix.endsWith(fileSep))
+ prefix += fileSep;
+
+ libpath[i] = prefix;
+ i++;
+ }
+ }
+
+ /**
+ * Get the current Runtime object for this JVM. This is necessary to access
+ * the many instance methods of this class.
+ *
+ * @return the current Runtime object
+ */
+ public static Runtime getRuntime()
+ {
+ return current;
+ }
+
+ /**
+ * Exit the Java runtime. This method will either throw a SecurityException
+ * or it will never return. The status code is returned to the system; often
+ * a non-zero status code indicates an abnormal exit. Of course, there is a
+ * security check, <code>checkExit(status)</code>.
+ *
+ * <p>First, all shutdown hooks are run, in unspecified order, and
+ * concurrently. Next, if finalization on exit has been enabled, all pending
+ * finalizers are run. Finally, the system calls <code>halt</code>.</p>
+ *
+ * <p>If this is run a second time after shutdown has already started, there
+ * are two actions. If shutdown hooks are still executing, it blocks
+ * indefinitely. Otherwise, if the status is nonzero it halts immediately;
+ * if it is zero, it blocks indefinitely. This is typically called by
+ * <code>System.exit</code>.</p>
+ *
+ * @param status the status to exit with
+ * @throws SecurityException if permission is denied
+ * @see #addShutdownHook(Thread)
+ * @see #runFinalizersOnExit(boolean)
+ * @see #runFinalization()
+ * @see #halt(int)
+ */
+ public void exit(int status)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkExit(status);
+
+ if (runShutdownHooks())
+ halt(status);
+
+ // Someone else already called runShutdownHooks().
+ // Make sure we are not/no longer in the shutdownHooks set.
+ // And wait till the thread that is calling runShutdownHooks() finishes.
+ synchronized (libpath)
+ {
+ if (shutdownHooks != null)
+ {
+ shutdownHooks.remove(Thread.currentThread());
+ // Interrupt the exit sequence thread, in case it was waiting
+ // inside a join on our thread.
+ exitSequence.interrupt();
+ // Shutdown hooks are still running, so we clear status to
+ // make sure we don't halt.
+ status = 0;
+ }
+ }
+
+ // If exit() is called again after the shutdown hooks have run, but
+ // while finalization for exit is going on and the status is non-zero
+ // we halt immediately.
+ if (status != 0)
+ halt(status);
+
+ while (true)
+ try
+ {
+ exitSequence.join();
+ }
+ catch (InterruptedException e)
+ {
+ // Ignore, we've suspended indefinitely to let all shutdown
+ // hooks complete, and to let any non-zero exits through, because
+ // this is a duplicate call to exit(0).
+ }
+ }
+
+ /**
+ * On first invocation, run all the shutdown hooks and return true.
+ * Any subsequent invocations will simply return false.
+ * Note that it is package accessible so that VMRuntime can call it
+ * when VM exit is not triggered by a call to Runtime.exit().
+ *
+ * @return was the current thread the first one to call this method?
+ */
+ boolean runShutdownHooks()
+ {
+ boolean first = false;
+ synchronized (libpath) // Synch on libpath, not this, to avoid deadlock.
+ {
+ if (exitSequence == null)
+ {
+ first = true;
+ exitSequence = Thread.currentThread();
+ if (shutdownHooks != null)
+ {
+ Iterator i = shutdownHooks.iterator();
+ while (i.hasNext()) // Start all shutdown hooks.
+ try
+ {
+ ((Thread) i.next()).start();
+ }
+ catch (IllegalThreadStateException e)
+ {
+ i.remove();
+ }
+ }
+ }
+ }
+ if (first)
+ {
+ if (shutdownHooks != null)
+ {
+ // Check progress of all shutdown hooks. As a hook completes,
+ // remove it from the set. If a hook calls exit, it removes
+ // itself from the set, then waits indefinitely on the
+ // exitSequence thread. Once the set is empty, set it to null to
+ // signal all finalizer threads that halt may be called.
+ while (true)
+ {
+ Thread[] hooks;
+ synchronized (libpath)
+ {
+ hooks = new Thread[shutdownHooks.size()];
+ shutdownHooks.toArray(hooks);
+ }
+ if (hooks.length == 0)
+ break;
+ for (int i = 0; i < hooks.length; i++)
+ {
+ try
+ {
+ synchronized (libpath)
+ {
+ if (!shutdownHooks.contains(hooks[i]))
+ continue;
+ }
+ hooks[i].join();
+ synchronized (libpath)
+ {
+ shutdownHooks.remove(hooks[i]);
+ }
+ }
+ catch (InterruptedException x)
+ {
+ // continue waiting on the next thread
+ }
+ }
+ }
+ synchronized (libpath)
+ {
+ shutdownHooks = null;
+ }
+ }
+ // Run finalization on all finalizable objects (even if they are
+ // still reachable).
+ VMRuntime.runFinalizationForExit();
+ }
+ return first;
+ }
+
+ /**
+ * Register a new shutdown hook. This is invoked when the program exits
+ * normally (because all non-daemon threads ended, or because
+ * <code>System.exit</code> was invoked), or when the user terminates
+ * the virtual machine (such as by typing ^C, or logging off). There is
+ * a security check to add hooks,
+ * <code>RuntimePermission("shutdownHooks")</code>.
+ *
+ * <p>The hook must be an initialized, but unstarted Thread. The threads
+ * are run concurrently, and started in an arbitrary order; and user
+ * threads or daemons may still be running. Once shutdown hooks have
+ * started, they must all complete, or else you must use <code>halt</code>,
+ * to actually finish the shutdown sequence. Attempts to modify hooks
+ * after shutdown has started result in IllegalStateExceptions.</p>
+ *
+ * <p>It is imperative that you code shutdown hooks defensively, as you
+ * do not want to deadlock, and have no idea what other hooks will be
+ * running concurrently. It is also a good idea to finish quickly, as the
+ * virtual machine really wants to shut down!</p>
+ *
+ * <p>There are no guarantees that such hooks will run, as there are ways
+ * to forcibly kill a process. But in such a drastic case, shutdown hooks
+ * would do little for you in the first place.</p>
+ *
+ * @param hook an initialized, unstarted Thread
+ * @throws IllegalArgumentException if the hook is already registered or run
+ * @throws IllegalStateException if the virtual machine is already in
+ * the shutdown sequence
+ * @throws SecurityException if permission is denied
+ * @since 1.3
+ * @see #removeShutdownHook(Thread)
+ * @see #exit(int)
+ * @see #halt(int)
+ */
+ public void addShutdownHook(Thread hook)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("shutdownHooks"));
+ if (hook.isAlive() || hook.getThreadGroup() == null)
+ throw new IllegalArgumentException("The hook thread " + hook + " must not have been already run or started");
+ synchronized (libpath)
+ {
+ if (exitSequence != null)
+ throw new IllegalStateException("The Virtual Machine is exiting. It is not possible anymore to add any hooks");
+ if (shutdownHooks == null)
+ {
+ VMRuntime.enableShutdownHooks();
+ shutdownHooks = new HashSet(); // Lazy initialization.
+ }
+ if (! shutdownHooks.add(hook))
+ throw new IllegalArgumentException(hook.toString() + " had already been inserted");
+ }
+ }
+
+ /**
+ * De-register a shutdown hook. As when you registered it, there is a
+ * security check to remove hooks,
+ * <code>RuntimePermission("shutdownHooks")</code>.
+ *
+ * @param hook the hook to remove
+ * @return true if the hook was successfully removed, false if it was not
+ * registered in the first place
+ * @throws IllegalStateException if the virtual machine is already in
+ * the shutdown sequence
+ * @throws SecurityException if permission is denied
+ * @since 1.3
+ * @see #addShutdownHook(Thread)
+ * @see #exit(int)
+ * @see #halt(int)
+ */
+ public boolean removeShutdownHook(Thread hook)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("shutdownHooks"));
+ synchronized (libpath)
+ {
+ if (exitSequence != null)
+ throw new IllegalStateException();
+ if (shutdownHooks != null)
+ return shutdownHooks.remove(hook);
+ }
+ return false;
+ }
+
+ /**
+ * Forcibly terminate the virtual machine. This call never returns. It is
+ * much more severe than <code>exit</code>, as it bypasses all shutdown
+ * hooks and initializers. Use caution in calling this! Of course, there is
+ * a security check, <code>checkExit(status)</code>.
+ *
+ * @param status the status to exit with
+ * @throws SecurityException if permission is denied
+ * @since 1.3
+ * @see #exit(int)
+ * @see #addShutdownHook(Thread)
+ */
+ public void halt(int status)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkExit(status);
+ VMRuntime.exit(status);
+ }
+
+ /**
+ * Tell the VM to run the finalize() method on every single Object before
+ * it exits. Note that the JVM may still exit abnormally and not perform
+ * this, so you still don't have a guarantee. And besides that, this is
+ * inherently unsafe in multi-threaded code, as it may result in deadlock
+ * as multiple threads compete to manipulate objects. This value defaults to
+ * <code>false</code>. There is a security check, <code>checkExit(0)</code>.
+ *
+ * @param finalizeOnExit whether to finalize all Objects on exit
+ * @throws SecurityException if permission is denied
+ * @see #exit(int)
+ * @see #gc()
+ * @since 1.1
+ * @deprecated never rely on finalizers to do a clean, thread-safe,
+ * mop-up from your code
+ */
+ public static void runFinalizersOnExit(boolean finalizeOnExit)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkExit(0);
+ VMRuntime.runFinalizersOnExit(finalizeOnExit);
+ }
+
+ /**
+ * Create a new subprocess with the specified command line. Calls
+ * <code>exec(cmdline, null, null)</code>. A security check is performed,
+ * <code>checkExec</code>.
+ *
+ * @param cmdline the command to call
+ * @return the Process object
+ * @throws SecurityException if permission is denied
+ * @throws IOException if an I/O error occurs
+ * @throws NullPointerException if cmdline is null
+ * @throws IndexOutOfBoundsException if cmdline is ""
+ */
+ public Process exec(String cmdline) throws IOException
+ {
+ return exec(cmdline, null, null);
+ }
+
+ /**
+ * Create a new subprocess with the specified command line and environment.
+ * If the environment is null, the process inherits the environment of
+ * this process. Calls <code>exec(cmdline, env, null)</code>. A security
+ * check is performed, <code>checkExec</code>.
+ *
+ * @param cmdline the command to call
+ * @param env the environment to use, in the format name=value
+ * @return the Process object
+ * @throws SecurityException if permission is denied
+ * @throws IOException if an I/O error occurs
+ * @throws NullPointerException if cmdline is null, or env has null entries
+ * @throws IndexOutOfBoundsException if cmdline is ""
+ */
+ public Process exec(String cmdline, String[] env) throws IOException
+ {
+ return exec(cmdline, env, null);
+ }
+
+ /**
+ * Create a new subprocess with the specified command line, environment, and
+ * working directory. If the environment is null, the process inherits the
+ * environment of this process. If the directory is null, the process uses
+ * the current working directory. This splits cmdline into an array, using
+ * the default StringTokenizer, then calls
+ * <code>exec(cmdArray, env, dir)</code>. A security check is performed,
+ * <code>checkExec</code>.
+ *
+ * @param cmdline the command to call
+ * @param env the environment to use, in the format name=value
+ * @param dir the working directory to use
+ * @return the Process object
+ * @throws SecurityException if permission is denied
+ * @throws IOException if an I/O error occurs
+ * @throws NullPointerException if cmdline is null, or env has null entries
+ * @throws IndexOutOfBoundsException if cmdline is ""
+ * @since 1.3
+ */
+ public Process exec(String cmdline, String[] env, File dir)
+ throws IOException
+ {
+ StringTokenizer t = new StringTokenizer(cmdline);
+ String[] cmd = new String[t.countTokens()];
+ for (int i = 0; i < cmd.length; i++)
+ cmd[i] = t.nextToken();
+ return exec(cmd, env, dir);
+ }
+
+ /**
+ * Create a new subprocess with the specified command line, already
+ * tokenized. Calls <code>exec(cmd, null, null)</code>. A security check
+ * is performed, <code>checkExec</code>.
+ *
+ * @param cmd the command to call
+ * @return the Process object
+ * @throws SecurityException if permission is denied
+ * @throws IOException if an I/O error occurs
+ * @throws NullPointerException if cmd is null, or has null entries
+ * @throws IndexOutOfBoundsException if cmd is length 0
+ */
+ public Process exec(String[] cmd) throws IOException
+ {
+ return exec(cmd, null, null);
+ }
+
+ /**
+ * Create a new subprocess with the specified command line, already
+ * tokenized, and specified environment. If the environment is null, the
+ * process inherits the environment of this process. Calls
+ * <code>exec(cmd, env, null)</code>. A security check is performed,
+ * <code>checkExec</code>.
+ *
+ * @param cmd the command to call
+ * @param env the environment to use, in the format name=value
+ * @return the Process object
+ * @throws SecurityException if permission is denied
+ * @throws IOException if an I/O error occurs
+ * @throws NullPointerException if cmd is null, or cmd or env has null
+ * entries
+ * @throws IndexOutOfBoundsException if cmd is length 0
+ */
+ public Process exec(String[] cmd, String[] env) throws IOException
+ {
+ return exec(cmd, env, null);
+ }
+
+ /**
+ * Create a new subprocess with the specified command line, already
+ * tokenized, and the specified environment and working directory. If the
+ * environment is null, the process inherits the environment of this
+ * process. If the directory is null, the process uses the current working
+ * directory. A security check is performed, <code>checkExec</code>.
+ *
+ * @param cmd the command to call
+ * @param env the environment to use, in the format name=value
+ * @param dir the working directory to use
+ * @return the Process object
+ * @throws SecurityException if permission is denied
+ * @throws IOException if an I/O error occurs
+ * @throws NullPointerException if cmd is null, or cmd or env has null
+ * entries
+ * @throws IndexOutOfBoundsException if cmd is length 0
+ * @since 1.3
+ */
+ public Process exec(String[] cmd, String[] env, File dir)
+ throws IOException
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkExec(cmd[0]);
+ return VMRuntime.exec(cmd, env, dir);
+ }
+
+ /**
+ * Returns the number of available processors currently available to the
+ * virtual machine. This number may change over time; so a multi-processor
+ * program want to poll this to determine maximal resource usage.
+ *
+ * @return the number of processors available, at least 1
+ */
+ public int availableProcessors()
+ {
+ return VMRuntime.availableProcessors();
+ }
+
+ /**
+ * Find out how much memory is still free for allocating Objects on the heap.
+ *
+ * @return the number of bytes of free memory for more Objects
+ */
+ public long freeMemory()
+ {
+ return VMRuntime.freeMemory();
+ }
+
+ /**
+ * Find out how much memory total is available on the heap for allocating
+ * Objects.
+ *
+ * @return the total number of bytes of memory for Objects
+ */
+ public long totalMemory()
+ {
+ return VMRuntime.totalMemory();
+ }
+
+ /**
+ * Returns the maximum amount of memory the virtual machine can attempt to
+ * use. This may be <code>Long.MAX_VALUE</code> if there is no inherent
+ * limit (or if you really do have a 8 exabyte memory!).
+ *
+ * @return the maximum number of bytes the virtual machine will attempt
+ * to allocate
+ */
+ public long maxMemory()
+ {
+ return VMRuntime.maxMemory();
+ }
+
+ /**
+ * Run the garbage collector. This method is more of a suggestion than
+ * anything. All this method guarantees is that the garbage collector will
+ * have "done its best" by the time it returns. Notice that garbage
+ * collection takes place even without calling this method.
+ */
+ public void gc()
+ {
+ VMRuntime.gc();
+ }
+
+ /**
+ * Run finalization on all Objects that are waiting to be finalized. Again,
+ * a suggestion, though a stronger one than {@link #gc()}. This calls the
+ * <code>finalize</code> method of all objects waiting to be collected.
+ *
+ * @see #finalize()
+ */
+ public void runFinalization()
+ {
+ VMRuntime.runFinalization();
+ }
+
+ /**
+ * Tell the VM to trace every bytecode instruction that executes (print out
+ * a trace of it). No guarantees are made as to where it will be printed,
+ * and the VM is allowed to ignore this request.
+ *
+ * @param on whether to turn instruction tracing on
+ */
+ public void traceInstructions(boolean on)
+ {
+ VMRuntime.traceInstructions(on);
+ }
+
+ /**
+ * Tell the VM to trace every method call that executes (print out a trace
+ * of it). No guarantees are made as to where it will be printed, and the
+ * VM is allowed to ignore this request.
+ *
+ * @param on whether to turn method tracing on
+ */
+ public void traceMethodCalls(boolean on)
+ {
+ VMRuntime.traceMethodCalls(on);
+ }
+
+ /**
+ * Load a native library using the system-dependent filename. This is similar
+ * to loadLibrary, except the only name mangling done is inserting "_g"
+ * before the final ".so" if the VM was invoked by the name "java_g". There
+ * may be a security check, of <code>checkLink</code>.
+ *
+ * <p>
+ * The library is loaded using the class loader associated with the
+ * class associated with the invoking method.
+ *
+ * @param filename the file to load
+ * @throws SecurityException if permission is denied
+ * @throws UnsatisfiedLinkError if the library is not found
+ */
+ public void load(String filename)
+ {
+ load(filename, VMStackWalker.getCallingClassLoader());
+ }
+
+ /**
+ * Same as <code>load(String)</code> but using the given loader.
+ *
+ * @param filename the file to load
+ * @param loader class loader, or <code>null</code> for the boot loader
+ * @throws SecurityException if permission is denied
+ * @throws UnsatisfiedLinkError if the library is not found
+ */
+ void load(String filename, ClassLoader loader)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkLink(filename);
+ if (loadLib(filename, loader) == 0)
+ throw new UnsatisfiedLinkError("Could not load library " + filename);
+ }
+
+ /**
+ * Do a security check on the filename and then load the native library.
+ *
+ * @param filename the file to load
+ * @param loader class loader, or <code>null</code> for the boot loader
+ * @return 0 on failure, nonzero on success
+ * @throws SecurityException if file read permission is denied
+ */
+ private static int loadLib(String filename, ClassLoader loader)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkRead(filename);
+ return VMRuntime.nativeLoad(filename, loader);
+ }
+
+ /**
+ * Load a native library using a system-independent "short name" for the
+ * library. It will be transformed to a correct filename in a
+ * system-dependent manner (for example, in Windows, "mylib" will be turned
+ * into "mylib.dll"). This is done as follows: if the context that called
+ * load has a ClassLoader cl, then <code>cl.findLibrary(libpath)</code> is
+ * used to convert the name. If that result was null, or there was no class
+ * loader, this searches each directory of the system property
+ * <code>java.library.path</code> for a file named
+ * <code>System.mapLibraryName(libname)</code>. There may be a security
+ * check, of <code>checkLink</code>.
+ *
+ * <p>Note: Besides <code>java.library.path</code> a VM may chose to search
+ * for native libraries in a path that is specified by the
+ * <code>gnu.classpath.boot.library.path</code> system property. However
+ * this is for internal usage or development of GNU Classpath only.
+ * <b>A Java application must not load a non-system library by changing
+ * this property otherwise it will break compatibility.</b></p>
+ *
+ * <p>
+ * The library is loaded using the class loader associated with the
+ * class associated with the invoking method.
+ *
+ * @param libname the library to load
+ *
+ * @throws SecurityException if permission is denied
+ * @throws UnsatisfiedLinkError if the library is not found
+ *
+ * @see System#mapLibraryName(String)
+ * @see ClassLoader#findLibrary(String)
+ */
+ public void loadLibrary(String libname)
+ {
+ loadLibrary(libname, VMStackWalker.getCallingClassLoader());
+ }
+
+ /**
+ * Same as <code>loadLibrary(String)</code> but using the given loader.
+ *
+ * @param libname the library to load
+ * @param loader class loader, or <code>null</code> for the boot loader
+ * @throws SecurityException if permission is denied
+ * @throws UnsatisfiedLinkError if the library is not found
+ */
+ void loadLibrary(String libname, ClassLoader loader)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkLink(libname);
+ String filename;
+ if (loader != null && (filename = loader.findLibrary(libname)) != null)
+ {
+ if (loadLib(filename, loader) != 0)
+ return;
+ }
+ else
+ {
+ filename = VMRuntime.mapLibraryName(libname);
+ for (int i = 0; i < libpath.length; i++)
+ if (loadLib(libpath[i] + filename, loader) != 0)
+ return;
+ }
+ throw new UnsatisfiedLinkError("Native library `" + libname
+ + "' not found (as file `" + filename + "') in gnu.classpath.boot.library.path and java.library.path");
+ }
+
+ /**
+ * Return a localized version of this InputStream, meaning all characters
+ * are localized before they come out the other end.
+ *
+ * @param in the stream to localize
+ * @return the localized stream
+ * @deprecated <code>InputStreamReader</code> is the preferred way to read
+ * local encodings
+ * @XXX This implementation does not localize, yet.
+ */
+ public InputStream getLocalizedInputStream(InputStream in)
+ {
+ return in;
+ }
+
+ /**
+ * Return a localized version of this OutputStream, meaning all characters
+ * are localized before they are sent to the other end.
+ *
+ * @param out the stream to localize
+ * @return the localized stream
+ * @deprecated <code>OutputStreamWriter</code> is the preferred way to write
+ * local encodings
+ * @XXX This implementation does not localize, yet.
+ */
+ public OutputStream getLocalizedOutputStream(OutputStream out)
+ {
+ return out;
+ }
+} // class Runtime
diff --git a/libjava/classpath/java/lang/RuntimeException.java b/libjava/classpath/java/lang/RuntimeException.java
new file mode 100644
index 00000000000..72cf0872bc7
--- /dev/null
+++ b/libjava/classpath/java/lang/RuntimeException.java
@@ -0,0 +1,102 @@
+/* RuntimeException.java -- root of all unchecked exceptions
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * All exceptions which are subclasses of <code>RuntimeException</code>
+ * can be thrown at any time during the execution of a Java virtual machine.
+ * Methods which throw these exceptions are not required to declare them
+ * in their throws clause.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class RuntimeException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -7034897190745766939L;
+
+ /**
+ * Create an exception without a message. The cause remains uninitialized.
+ *
+ * @see #initCause(Throwable)
+ */
+ public RuntimeException()
+ {
+ }
+
+ /**
+ * Create an exception with a message. The cause remains uninitialized.
+ *
+ * @param s the message string
+ * @see #initCause(Throwable)
+ */
+ public RuntimeException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message string
+ * @param cause the cause of this exception
+ * @since 1.4
+ */
+ public RuntimeException(String s, Throwable cause)
+ {
+ super(s, cause);
+ }
+
+ /**
+ * Create an exception with the given cause, and a message of
+ * <code>cause == null ? null : cause.toString()</code>.
+ *
+ * @param cause the cause of this exception
+ * @since 1.4
+ */
+ public RuntimeException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/libjava/classpath/java/lang/RuntimePermission.java b/libjava/classpath/java/lang/RuntimePermission.java
new file mode 100644
index 00000000000..ca33307d12b
--- /dev/null
+++ b/libjava/classpath/java/lang/RuntimePermission.java
@@ -0,0 +1,208 @@
+/* RuntimePermission.java -- permission for a secure runtime action
+ Copyright (C) 1998, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import java.security.BasicPermission;
+
+/**
+ * A <code>RuntimePermission</code> contains a permission name, but no
+ * actions list. This means you either have the permission or you don't.
+ *
+ * Permission names have the follow the hierarchial property naming
+ * convention. In addition, an asterisk may appear at the end of a
+ * name if following a period or by itself.
+ *
+ * <table border=1>
+ * <tr><th>Valid names</th><th>Invalid names</th></tr>
+ * <tr><td>"accessClassInPackage.*","*"</td>
+ * <td>"**", "*x", "*.a"</td></tr>
+ * </table>
+ * <br>
+ *
+ * The following table provides a list of all the possible RuntimePermission
+ * permission names with a description of what that permission allows.<br>
+ * <table border=1>
+ * <tr><th>Permission Name</th><th>Permission Allows</th><th>Risks</th</tr>
+ * <tr>
+ * <td><code>createClassLoader</code></td>
+ * <td>creation of a class loader</td>
+ * <td>a class loader can load rogue classes which bypass all security
+ * permissions</td></tr>
+ * <tr>
+ * <td><code>getClassLoader</code></td>
+ * <td>retrieval of the class loader for the calling class</td>
+ * <td>rogue code could load classes not otherwise available</td></tr>
+ * <tr>
+ * <td><code>setContextClassLoader</code></td>
+ * <td>allows the setting of the context class loader used by a thread</td>
+ * <td>rogue code could change the context class loader needed by system
+ * threads</td></tr>
+ * <tr>
+ * <td><code>setSecurityManager</code></td>
+ * <td>allows the application to replace the security manager</td>
+ * <td>the new manager may be less restrictive, so that rogue code can
+ * bypass existing security checks</td></tr>
+ * <tr>
+ * <td><code>createSecurityManager</code></td>
+ * <td>allows the application to create a new security manager</td>
+ * <td>rogue code can use the new security manager to discover information
+ * about the execution stack</td></tr>
+ * <tr>
+ * <td><code>exitVM</code></td>
+ * <td>allows the application to halt the virtual machine</td>
+ * <td>rogue code can mount a denial-of-service attack by killing the
+ * virtual machine</td></tr>
+ * <tr>
+ * <td><code>shutdownHooks</code></td>
+ * <td>allows registration and modification of shutdown hooks</td>
+ * <td>rogue code can add a hook that interferes with clean
+ * virtual machine shutdown</td></tr>
+ * <tr>
+ * <td><code>setFactory</code></td>
+ * <td>allows the application to set the socket factory for socket,
+ * server socket, stream handler, or RMI socket factory.</td>
+ * <td>rogue code can create a rogue network object which mangles or
+ * intercepts data</td></tr>
+ * <tr>
+ * <td><code>setIO</code></td>
+ * <td>allows the application to set System.out, System.in, and
+ * System.err</td>
+ * <td>rogue code could sniff user input and intercept or mangle
+ * output</td></tr>
+ * <tr>
+ * <td><code>modifyThread</code></td>
+ * <td>allows the application to modify any thread in the virtual machine
+ * using any of the methods <code>stop</code>, <code>resume</code>,
+ * <code>suspend</code>, <code>setPriority</code>, and
+ * <code>setName</code> of classs <code>Thread</code></td>
+ * <td>rogue code could adversely modify system or user threads</td></tr>
+ * <tr>
+ * <td><code>stopThread</code></td>
+ * <td>allows the application to <code>stop</code> any thread it has
+ * access to in the system</td>
+ * <td>rogue code can stop arbitrary threads</td></tr>
+ * <tr>
+ * <td><code>modifyThreadGroup</code></td>
+ * <td>allows the application to modify thread groups using any of the
+ * methods <code>destroy</code>, <code>resume</code>,
+ * <code>setDaemon</code>, <code>setMaxPriority</code>,
+ * <code>stop</code>, and <code>suspend</code> of the class
+ * <code>ThreadGroup</code></td>
+ * <td>rogue code can mount a denial-of-service attack by changing run
+ * priorities</td></tr>
+ * <tr>
+ * <td><code>getProtectionDomain</code></td>
+ * <td>retrieve a class's ProtectionDomain</td>
+ * <td>rogue code can gain information about the security policy, to
+ * prepare a better attack</td></tr>
+ * <tr>
+ * <td><code>readFileDescriptor</code></td>
+ * <td>read a file descriptor</td>
+ * <td>rogue code can read sensitive information</td></tr>
+ * <tr>
+ * <td><code>writeFileDescriptor</code></td>
+ * <td>write a file descriptor</td>
+ * <td>rogue code can write files, including viruses, and can modify the
+ * virtual machine binary; if not just fill up the disk</td></tr>
+ * <tr>
+ * <td><code>loadLibrary.</code><em>library name</em></td>
+ * <td>dynamic linking of the named library</td>
+ * <td>native code can bypass many security checks of pure Java</td></tr>
+ * <tr>
+ * <td><code>accessClassInPackage.</code><em>package name</em></td>
+ * <td>access to a package via a ClassLoader</td>
+ * <td>rogue code can access classes not normally available</td></tr>
+ * <tr>
+ * <td><code>defineClassInPackage.</code><em>package name</em></td>
+ * <td>define a class inside a given package</td>
+ * <td>rogue code can install rogue classes, including in trusted packages
+ * like java.security or java.lang</td></tr>
+ * <tr>
+ * <td><code>accessDeclaredMembers</code></td>
+ * <td>access declared class members via reflection</td>
+ * <td>rogue code can discover information, invoke methods, or modify fields
+ * that are not otherwise available</td></tr>
+ * <tr>
+ * <td><code>queuePrintJob</code></td>
+ * <td>initiate a print job</td>
+ * <td>rogue code could make a hard copy of sensitive information, or
+ * simply waste paper</td></tr>
+ * </table>
+ *
+ * @author Brian Jones
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see BasicPermission
+ * @see Permission
+ * @see SecurityManager
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class RuntimePermission extends BasicPermission
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 7399184964622342223L;
+
+ /**
+ * Create a new permission with the specified name.
+ *
+ * @param permissionName the name of the granted permission
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException thrown if name is empty or invalid
+ */
+ public RuntimePermission(String permissionName)
+ {
+ super(permissionName);
+ }
+
+ /**
+ * Create a new permission with the specified name. The actions argument
+ * is ignored, as runtime permissions have no actions.
+ *
+ * @param permissionName the name of the granted permission
+ * @param actions ignored
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException thrown if name is empty or invalid
+ */
+ public RuntimePermission(String permissionName, String actions)
+ {
+ super(permissionName);
+ }
+}
diff --git a/libjava/classpath/java/lang/SecurityException.java b/libjava/classpath/java/lang/SecurityException.java
new file mode 100644
index 00000000000..a95d797054f
--- /dev/null
+++ b/libjava/classpath/java/lang/SecurityException.java
@@ -0,0 +1,74 @@
+/* SecurityException.java -- thrown to indicate a security violation
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * The security manager will throw this exception to indicate a security
+ * violation. This can occur any time an operation is attempted which is
+ * deemed unsafe by the current security policies.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see SecurityManager
+ * @status updated to 1.4
+ */
+public class SecurityException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 6878364983674394167L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public SecurityException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public SecurityException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/SecurityManager.java b/libjava/classpath/java/lang/SecurityManager.java
new file mode 100644
index 00000000000..ef9e7597ddc
--- /dev/null
+++ b/libjava/classpath/java/lang/SecurityManager.java
@@ -0,0 +1,1062 @@
+/* SecurityManager.java -- security checks for privileged actions
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.classpath.VMStackWalker;
+
+import java.awt.AWTPermission;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FilePermission;
+import java.lang.reflect.Member;
+import java.net.InetAddress;
+import java.net.SocketPermission;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.security.SecurityPermission;
+import java.util.PropertyPermission;
+import java.util.StringTokenizer;
+
+/**
+ * SecurityManager is a class you can extend to create your own Java
+ * security policy. By default, there is no SecurityManager installed in
+ * 1.1, which means that all things are permitted to all people. The security
+ * manager, if set, is consulted before doing anything with potentially
+ * dangerous results, and throws a <code>SecurityException</code> if the
+ * action is forbidden.
+ *
+ * <p>A typical check is as follows, just before the dangerous operation:<br>
+ * <pre>
+ * SecurityManager sm = System.getSecurityManager();
+ * if (sm != null)
+ * sm.checkABC(<em>argument</em>, ...);
+ * </pre>
+ * Note that this is thread-safe, by caching the security manager in a local
+ * variable rather than risking a NullPointerException if the mangager is
+ * changed between the check for null and before the permission check.
+ *
+ * <p>The special method <code>checkPermission</code> is a catchall, and
+ * the default implementation calls
+ * <code>AccessController.checkPermission</code>. In fact, all the other
+ * methods default to calling checkPermission.
+ *
+ * <p>Sometimes, the security check needs to happen from a different context,
+ * such as when called from a worker thread. In such cases, use
+ * <code>getSecurityContext</code> to take a snapshot that can be passed
+ * to the worker thread:<br>
+ * <pre>
+ * Object context = null;
+ * SecurityManager sm = System.getSecurityManager();
+ * if (sm != null)
+ * context = sm.getSecurityContext(); // defaults to an AccessControlContext
+ * // now, in worker thread
+ * if (sm != null)
+ * sm.checkPermission(permission, context);
+ * </pre>
+ *
+ * <p>Permissions fall into these categories: File, Socket, Net, Security,
+ * Runtime, Property, AWT, Reflect, and Serializable. Each of these
+ * permissions have a property naming convention, that follows a hierarchical
+ * naming convention, to make it easy to grant or deny several permissions
+ * at once. Some permissions also take a list of permitted actions, such
+ * as "read" or "write", to fine-tune control even more. The permission
+ * <code>java.security.AllPermission</code> grants all permissions.
+ *
+ * <p>The default methods in this class deny all things to all people. You
+ * must explicitly grant permission for anything you want to be legal when
+ * subclassing this class.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see ClassLoader
+ * @see SecurityException
+ * @see #checkTopLevelWindow(Object)
+ * @see System#getSecurityManager()
+ * @see System#setSecurityManager(SecurityManager)
+ * @see AccessController
+ * @see AccessControlContext
+ * @see AccessControlException
+ * @see Permission
+ * @see BasicPermission
+ * @see java.io.FilePermission
+ * @see java.net.SocketPermission
+ * @see java.util.PropertyPermission
+ * @see RuntimePermission
+ * @see java.awt.AWTPermission
+ * @see Policy
+ * @see SecurityPermission
+ * @see ProtectionDomain
+ * @since 1.0
+ * @status still missing 1.4 functionality
+ */
+public class SecurityManager
+{
+ /**
+ * The current security manager. This is located here instead of in
+ * System, to avoid security problems, as well as bootstrap issues.
+ * Make sure to access it in a thread-safe manner; it is package visible
+ * to avoid overhead in java.lang.
+ */
+ static volatile SecurityManager current;
+
+ /**
+ * Tells whether or not the SecurityManager is currently performing a
+ * security check.
+ * @deprecated Use {@link #checkPermission(Permission)} instead.
+ */
+ protected boolean inCheck;
+
+ /**
+ * Construct a new security manager. There may be a security check, of
+ * <code>RuntimePermission("createSecurityManager")</code>.
+ *
+ * @throws SecurityException if permission is denied
+ */
+ public SecurityManager()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("createSecurityManager"));
+ }
+
+ /**
+ * Tells whether or not the SecurityManager is currently performing a
+ * security check.
+ *
+ * @return true if the SecurityManager is in a security check
+ * @see #inCheck
+ * @deprecated use {@link #checkPermission(Permission)} instead
+ */
+ public boolean getInCheck()
+ {
+ return inCheck;
+ }
+
+ /**
+ * Get a list of all the classes currently executing methods on the Java
+ * stack. getClassContext()[0] is the currently executing method (ie. the
+ * class that CALLED getClassContext, not SecurityManager).
+ *
+ * @return an array of classes on the Java execution stack
+ */
+ protected Class[] getClassContext()
+ {
+ Class[] stack1 = VMStackWalker.getClassContext();
+ Class[] stack2 = new Class[stack1.length - 1];
+ System.arraycopy(stack1, 1, stack2, 0, stack1.length - 1);
+ return stack2;
+ }
+
+ /**
+ * Find the ClassLoader of the first non-system class on the execution
+ * stack. A non-system class is one whose ClassLoader is not equal to
+ * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This
+ * will return null in three cases:
+ *
+ * <ul>
+ * <li>All methods on the stack are from system classes</li>
+ * <li>All methods on the stack up to the first "privileged" caller, as
+ * created by {@link AccessController.doPrivileged(PrivilegedAction)},
+ * are from system classes</li>
+ * <li>A check of <code>java.security.AllPermission</code> succeeds.</li>
+ * </ul>
+ *
+ * @return the most recent non-system ClassLoader on the execution stack
+ * @deprecated use {@link #checkPermission(Permission)} instead
+ */
+ protected ClassLoader currentClassLoader()
+ {
+ Class cl = currentLoadedClass();
+ return cl != null ? cl.getClassLoader() : null;
+ }
+
+ /**
+ * Find the first non-system class on the execution stack. A non-system
+ * class is one whose ClassLoader is not equal to
+ * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This
+ * will return null in three cases:
+ *
+ * <ul>
+ * <li>All methods on the stack are from system classes</li>
+ * <li>All methods on the stack up to the first "privileged" caller, as
+ * created by {@link AccessController.doPrivileged(PrivilegedAction)},
+ * are from system classes</li>
+ * <li>A check of <code>java.security.AllPermission</code> succeeds.</li>
+ * </ul>
+ *
+ * @return the most recent non-system Class on the execution stack
+ * @deprecated use {@link #checkPermission(Permission)} instead
+ */
+ protected Class currentLoadedClass()
+ {
+ int i = classLoaderDepth();
+ return i >= 0 ? getClassContext()[i] : null;
+ }
+
+ /**
+ * Get the depth of a particular class on the execution stack.
+ *
+ * @param className the fully-qualified name to search for
+ * @return the index of the class on the stack, or -1
+ * @deprecated use {@link #checkPermission(Permission)} instead
+ */
+ protected int classDepth(String className)
+ {
+ Class[] c = getClassContext();
+ for (int i = 0; i < c.length; i++)
+ if (className.equals(c[i].getName()))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Get the depth on the execution stack of the most recent non-system class.
+ * A non-system class is one whose ClassLoader is not equal to
+ * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This
+ * will return -1 in three cases:
+ *
+ * <ul>
+ * <li>All methods on the stack are from system classes</li>
+ * <li>All methods on the stack up to the first "privileged" caller, as
+ * created by {@link AccessController.doPrivileged(PrivilegedAction)},
+ * are from system classes</li>
+ * <li>A check of <code>java.security.AllPermission</code> succeeds.</li>
+ * </ul>
+ *
+ * @return the index of the most recent non-system Class on the stack
+ * @deprecated use {@link #checkPermission(Permission)} instead
+ */
+ protected int classLoaderDepth()
+ {
+ try
+ {
+ checkPermission(new AllPermission());
+ }
+ catch (SecurityException e)
+ {
+ Class[] c = getClassContext();
+ for (int i = 0; i < c.length; i++)
+ if (c[i].getClassLoader() != null)
+ // XXX Check if c[i] is AccessController, or a system class.
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Tell whether the specified class is on the execution stack.
+ *
+ * @param className the fully-qualified name of the class to find
+ * @return whether the specified class is on the execution stack
+ * @deprecated use {@link #checkPermission(Permission)} instead
+ */
+ protected boolean inClass(String className)
+ {
+ return classDepth(className) != -1;
+ }
+
+ /**
+ * Tell whether there is a class loaded with an explicit ClassLoader on
+ * the stack.
+ *
+ * @return whether a class with an explicit ClassLoader is on the stack
+ * @deprecated use {@link #checkPermission(Permission)} instead
+ */
+ protected boolean inClassLoader()
+ {
+ return classLoaderDepth() != -1;
+ }
+
+ /**
+ * Get an implementation-dependent Object that contains enough information
+ * about the current environment to be able to perform standard security
+ * checks later. This is used by trusted methods that need to verify that
+ * their callers have sufficient access to perform certain operations.
+ *
+ * <p>Currently the only methods that use this are checkRead() and
+ * checkConnect(). The default implementation returns an
+ * <code>AccessControlContext</code>.
+ *
+ * @return a security context
+ * @see #checkConnect(String, int, Object)
+ * @see #checkRead(String, Object)
+ * @see AccessControlContext
+ * @see AccessController#getContext()
+ */
+ public Object getSecurityContext()
+ {
+ return AccessController.getContext();
+ }
+
+ /**
+ * Check if the current thread is allowed to perform an operation that
+ * requires the specified <code>Permission</code>. This defaults to
+ * <code>AccessController.checkPermission</code>.
+ *
+ * @param perm the <code>Permission</code> required
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if perm is null
+ * @since 1.2
+ */
+ public void checkPermission(Permission perm)
+ {
+ AccessController.checkPermission(perm);
+ }
+
+ /**
+ * Check if the current thread is allowed to perform an operation that
+ * requires the specified <code>Permission</code>. This is done in a
+ * context previously returned by <code>getSecurityContext()</code>. The
+ * default implementation expects context to be an AccessControlContext,
+ * and it calls <code>AccessControlContext.checkPermission(perm)</code>.
+ *
+ * @param perm the <code>Permission</code> required
+ * @param context a security context
+ * @throws SecurityException if permission is denied, or if context is
+ * not an AccessControlContext
+ * @throws NullPointerException if perm is null
+ * @see #getSecurityContext()
+ * @see AccessControlContext#checkPermission(Permission)
+ * @since 1.2
+ */
+ public void checkPermission(Permission perm, Object context)
+ {
+ if (! (context instanceof AccessControlContext))
+ throw new SecurityException("Missing context");
+ ((AccessControlContext) context).checkPermission(perm);
+ }
+
+ /**
+ * Check if the current thread is allowed to create a ClassLoader. This
+ * method is called from ClassLoader.ClassLoader(), and checks
+ * <code>RuntimePermission("createClassLoader")</code>. If you override
+ * this, you should call <code>super.checkCreateClassLoader()</code> rather
+ * than throwing an exception.
+ *
+ * @throws SecurityException if permission is denied
+ * @see ClassLoader#ClassLoader()
+ */
+ public void checkCreateClassLoader()
+ {
+ checkPermission(new RuntimePermission("createClassLoader"));
+ }
+
+ /**
+ * Check if the current thread is allowed to modify another Thread. This is
+ * called by Thread.stop(), suspend(), resume(), interrupt(), destroy(),
+ * setPriority(), setName(), and setDaemon(). The default implementation
+ * checks <code>RuntimePermission("modifyThread")</code> on system threads
+ * (ie. threads in ThreadGroup with a null parent), and returns silently on
+ * other threads.
+ *
+ * <p>If you override this, you must do two things. First, call
+ * <code>super.checkAccess(t)</code>, to make sure you are not relaxing
+ * requirements. Second, if the calling thread has
+ * <code>RuntimePermission("modifyThread")</code>, return silently, so that
+ * core classes (the Classpath library!) can modify any thread.
+ *
+ * @param thread the other Thread to check
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if thread is null
+ * @see Thread#stop()
+ * @see Thread#suspend()
+ * @see Thread#resume()
+ * @see Thread#setPriority(int)
+ * @see Thread#setName(String)
+ * @see Thread#setDaemon(boolean)
+ */
+ public void checkAccess(Thread thread)
+ {
+ if (thread.getThreadGroup() != null
+ && thread.getThreadGroup().getParent() != null)
+ checkPermission(new RuntimePermission("modifyThread"));
+ }
+
+ /**
+ * Check if the current thread is allowed to modify a ThreadGroup. This is
+ * called by Thread.Thread() (to add a thread to the ThreadGroup),
+ * ThreadGroup.ThreadGroup() (to add this ThreadGroup to a parent),
+ * ThreadGroup.stop(), suspend(), resume(), interrupt(), destroy(),
+ * setDaemon(), and setMaxPriority(). The default implementation
+ * checks <code>RuntimePermission("modifyThread")</code> on the system group
+ * (ie. the one with a null parent), and returns silently on other groups.
+ *
+ * <p>If you override this, you must do two things. First, call
+ * <code>super.checkAccess(t)</code>, to make sure you are not relaxing
+ * requirements. Second, if the calling thread has
+ * <code>RuntimePermission("modifyThreadGroup")</code>, return silently,
+ * so that core classes (the Classpath library!) can modify any thread.
+ *
+ * @param g the ThreadGroup to check
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if g is null
+ * @see Thread#Thread()
+ * @see ThreadGroup#ThreadGroup()
+ * @see ThreadGroup#stop()
+ * @see ThreadGroup#suspend()
+ * @see ThreadGroup#resume()
+ * @see ThreadGroup#interrupt()
+ * @see ThreadGroup#setDaemon(boolean)
+ * @see ThreadGroup#setMaxPriority(int)
+ */
+ public void checkAccess(ThreadGroup g)
+ {
+ if (g.getParent() != null)
+ checkPermission(new RuntimePermission("modifyThreadGroup"));
+ }
+
+ /**
+ * Check if the current thread is allowed to exit the JVM with the given
+ * status. This method is called from Runtime.exit() and Runtime.halt().
+ * The default implementation checks
+ * <code>RuntimePermission("exitVM")</code>. If you override this, call
+ * <code>super.checkExit</code> rather than throwing an exception.
+ *
+ * @param status the status to exit with
+ * @throws SecurityException if permission is denied
+ * @see Runtime#exit(int)
+ * @see Runtime#halt(int)
+ */
+ public void checkExit(int status)
+ {
+ checkPermission(new RuntimePermission("exitVM"));
+ }
+
+ /**
+ * Check if the current thread is allowed to execute the given program. This
+ * method is called from Runtime.exec(). If the name is an absolute path,
+ * the default implementation checks
+ * <code>FilePermission(program, "execute")</code>, otherwise it checks
+ * <code>FilePermission("&lt;&lt;ALL FILES&gt;&gt;", "execute")</code>. If
+ * you override this, call <code>super.checkExec</code> rather than
+ * throwing an exception.
+ *
+ * @param program the name of the program to exec
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if program is null
+ * @see Runtime#exec(String[], String[], File)
+ */
+ public void checkExec(String program)
+ {
+ if (! program.equals(new File(program).getAbsolutePath()))
+ program = "<<ALL FILES>>";
+ checkPermission(new FilePermission(program, "execute"));
+ }
+
+ /**
+ * Check if the current thread is allowed to link in the given native
+ * library. This method is called from Runtime.load() (and hence, by
+ * loadLibrary() as well). The default implementation checks
+ * <code>RuntimePermission("loadLibrary." + filename)</code>. If you
+ * override this, call <code>super.checkLink</code> rather than throwing
+ * an exception.
+ *
+ * @param filename the full name of the library to load
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if filename is null
+ * @see Runtime#load(String)
+ */
+ public void checkLink(String filename)
+ {
+ // Use the toString() hack to do the null check.
+ checkPermission(new RuntimePermission("loadLibrary."
+ + filename.toString()));
+ }
+
+ /**
+ * Check if the current thread is allowed to read the given file using the
+ * FileDescriptor. This method is called from
+ * FileInputStream.FileInputStream(). The default implementation checks
+ * <code>RuntimePermission("readFileDescriptor")</code>. If you override
+ * this, call <code>super.checkRead</code> rather than throwing an
+ * exception.
+ *
+ * @param desc the FileDescriptor representing the file to access
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if desc is null
+ * @see FileInputStream#FileInputStream(FileDescriptor)
+ */
+ public void checkRead(FileDescriptor desc)
+ {
+ if (desc == null)
+ throw new NullPointerException();
+ checkPermission(new RuntimePermission("readFileDescriptor"));
+ }
+
+ /**
+ * Check if the current thread is allowed to read the given file. This
+ * method is called from FileInputStream.FileInputStream(),
+ * RandomAccessFile.RandomAccessFile(), File.exists(), canRead(), isFile(),
+ * isDirectory(), lastModified(), length() and list(). The default
+ * implementation checks <code>FilePermission(filename, "read")</code>. If
+ * you override this, call <code>super.checkRead</code> rather than
+ * throwing an exception.
+ *
+ * @param filename the full name of the file to access
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if filename is null
+ * @see File
+ * @see FileInputStream#FileInputStream(String)
+ * @see RandomAccessFile#RandomAccessFile(String)
+ */
+ public void checkRead(String filename)
+ {
+ checkPermission(new FilePermission(filename, "read"));
+ }
+
+ /**
+ * Check if the current thread is allowed to read the given file. using the
+ * given security context. The context must be a result of a previous call
+ * to <code>getSecurityContext()</code>. The default implementation checks
+ * <code>AccessControlContext.checkPermission(new FilePermission(filename,
+ * "read"))</code>. If you override this, call <code>super.checkRead</code>
+ * rather than throwing an exception.
+ *
+ * @param filename the full name of the file to access
+ * @param context the context to determine access for
+ * @throws SecurityException if permission is denied, or if context is
+ * not an AccessControlContext
+ * @throws NullPointerException if filename is null
+ * @see #getSecurityContext()
+ * @see AccessControlContext#checkPermission(Permission)
+ */
+ public void checkRead(String filename, Object context)
+ {
+ if (! (context instanceof AccessControlContext))
+ throw new SecurityException("Missing context");
+ AccessControlContext ac = (AccessControlContext) context;
+ ac.checkPermission(new FilePermission(filename, "read"));
+ }
+
+ /**
+ * Check if the current thread is allowed to write the given file using the
+ * FileDescriptor. This method is called from
+ * FileOutputStream.FileOutputStream(). The default implementation checks
+ * <code>RuntimePermission("writeFileDescriptor")</code>. If you override
+ * this, call <code>super.checkWrite</code> rather than throwing an
+ * exception.
+ *
+ * @param desc the FileDescriptor representing the file to access
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if desc is null
+ * @see FileOutputStream#FileOutputStream(FileDescriptor)
+ */
+ public void checkWrite(FileDescriptor desc)
+ {
+ if (desc == null)
+ throw new NullPointerException();
+ checkPermission(new RuntimePermission("writeFileDescriptor"));
+ }
+
+ /**
+ * Check if the current thread is allowed to write the given file. This
+ * method is called from FileOutputStream.FileOutputStream(),
+ * RandomAccessFile.RandomAccessFile(), File.canWrite(), mkdir(), and
+ * renameTo(). The default implementation checks
+ * <code>FilePermission(filename, "write")</code>. If you override this,
+ * call <code>super.checkWrite</code> rather than throwing an exception.
+ *
+ * @param filename the full name of the file to access
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if filename is null
+ * @see File
+ * @see File#canWrite()
+ * @see File#mkdir()
+ * @see File#renameTo()
+ * @see FileOutputStream#FileOutputStream(String)
+ * @see RandomAccessFile#RandomAccessFile(String)
+ */
+ public void checkWrite(String filename)
+ {
+ checkPermission(new FilePermission(filename, "write"));
+ }
+
+ /**
+ * Check if the current thread is allowed to delete the given file. This
+ * method is called from File.delete(). The default implementation checks
+ * <code>FilePermission(filename, "delete")</code>. If you override this,
+ * call <code>super.checkDelete</code> rather than throwing an exception.
+ *
+ * @param filename the full name of the file to delete
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if filename is null
+ * @see File#delete()
+ */
+ public void checkDelete(String filename)
+ {
+ checkPermission(new FilePermission(filename, "delete"));
+ }
+
+ /**
+ * Check if the current thread is allowed to connect to a given host on a
+ * given port. This method is called from Socket.Socket(). A port number
+ * of -1 indicates the caller is attempting to determine an IP address, so
+ * the default implementation checks
+ * <code>SocketPermission(host, "resolve")</code>. Otherwise, the default
+ * implementation checks
+ * <code>SocketPermission(host + ":" + port, "connect")</code>. If you
+ * override this, call <code>super.checkConnect</code> rather than throwing
+ * an exception.
+ *
+ * @param host the host to connect to
+ * @param port the port to connect on
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if host is null
+ * @see Socket#Socket()
+ */
+ public void checkConnect(String host, int port)
+ {
+ if (port == -1)
+ checkPermission(new SocketPermission(host, "resolve"));
+ else
+ // Use the toString() hack to do the null check.
+ checkPermission(new SocketPermission(host.toString() + ":" + port,
+ "connect"));
+ }
+
+ /**
+ * Check if the current thread is allowed to connect to a given host on a
+ * given port, using the given security context. The context must be a
+ * result of a previous call to <code>getSecurityContext</code>. A port
+ * number of -1 indicates the caller is attempting to determine an IP
+ * address, so the default implementation checks
+ * <code>AccessControlContext.checkPermission(new SocketPermission(host,
+ * "resolve"))</code>. Otherwise, the default implementation checks
+ * <code>AccessControlContext.checkPermission(new SocketPermission(host
+ * + ":" + port, "connect"))</code>. If you override this, call
+ * <code>super.checkConnect</code> rather than throwing an exception.
+ *
+ * @param host the host to connect to
+ * @param port the port to connect on
+ * @param context the context to determine access for
+ *
+ * @throws SecurityException if permission is denied, or if context is
+ * not an AccessControlContext
+ * @throws NullPointerException if host is null
+ *
+ * @see #getSecurityContext()
+ * @see AccessControlContext#checkPermission(Permission)
+ */
+ public void checkConnect(String host, int port, Object context)
+ {
+ if (! (context instanceof AccessControlContext))
+ throw new SecurityException("Missing context");
+ AccessControlContext ac = (AccessControlContext) context;
+ if (port == -1)
+ ac.checkPermission(new SocketPermission(host, "resolve"));
+ else
+ // Use the toString() hack to do the null check.
+ ac.checkPermission(new SocketPermission(host.toString() + ":" + port,
+ "connect"));
+ }
+
+ /**
+ * Check if the current thread is allowed to listen to a specific port for
+ * data. This method is called by ServerSocket.ServerSocket(). The default
+ * implementation checks
+ * <code>SocketPermission("localhost:" + (port == 0 ? "1024-" : "" + port),
+ * "listen")</code>. If you override this, call
+ * <code>super.checkListen</code> rather than throwing an exception.
+ *
+ * @param port the port to listen on
+ * @throws SecurityException if permission is denied
+ * @see ServerSocket#ServerSocket(int)
+ */
+ public void checkListen(int port)
+ {
+ checkPermission(new SocketPermission("localhost:"
+ + (port == 0 ? "1024-" : "" +port),
+ "listen"));
+ }
+
+ /**
+ * Check if the current thread is allowed to accept a connection from a
+ * particular host on a particular port. This method is called by
+ * ServerSocket.implAccept(). The default implementation checks
+ * <code>SocketPermission(host + ":" + port, "accept")</code>. If you
+ * override this, call <code>super.checkAccept</code> rather than throwing
+ * an exception.
+ *
+ * @param host the host which wishes to connect
+ * @param port the port the connection will be on
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if host is null
+ * @see ServerSocket#accept()
+ */
+ public void checkAccept(String host, int port)
+ {
+ // Use the toString() hack to do the null check.
+ checkPermission(new SocketPermission(host.toString() + ":" + port,
+ "accept"));
+ }
+
+ /**
+ * Check if the current thread is allowed to read and write multicast to
+ * a particular address. The default implementation checks
+ * <code>SocketPermission(addr.getHostAddress(), "accept,connect")</code>.
+ * If you override this, call <code>super.checkMulticast</code> rather than
+ * throwing an exception.
+ *
+ * @param addr the address to multicast to
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if host is null
+ * @since 1.1
+ */
+ public void checkMulticast(InetAddress addr)
+ {
+ checkPermission(new SocketPermission(addr.getHostAddress(),
+ "accept,connect"));
+ }
+
+ /**
+ *Check if the current thread is allowed to read and write multicast to
+ * a particular address with a particular ttl (time-to-live) value. The
+ * default implementation ignores ttl, and checks
+ * <code>SocketPermission(addr.getHostAddress(), "accept,connect")</code>.
+ * If you override this, call <code>super.checkMulticast</code> rather than
+ * throwing an exception.
+ *
+ * @param addr the address to multicast to
+ * @param ttl value in use for multicast send
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if host is null
+ * @since 1.1
+ * @deprecated use {@link #checkPermission(Permission)} instead
+ */
+ public void checkMulticast(InetAddress addr, byte ttl)
+ {
+ checkPermission(new SocketPermission(addr.getHostAddress(),
+ "accept,connect"));
+ }
+
+ /**
+ * Check if the current thread is allowed to read or write all the system
+ * properties at once. This method is called by System.getProperties()
+ * and setProperties(). The default implementation checks
+ * <code>PropertyPermission("*", "read,write")</code>. If you override
+ * this, call <code>super.checkPropertiesAccess</code> rather than
+ * throwing an exception.
+ *
+ * @throws SecurityException if permission is denied
+ * @see System#getProperties()
+ * @see System#setProperties(Properties)
+ */
+ public void checkPropertiesAccess()
+ {
+ checkPermission(new PropertyPermission("*", "read,write"));
+ }
+
+ /**
+ * Check if the current thread is allowed to read a particular system
+ * property (writes are checked directly via checkPermission). This method
+ * is called by System.getProperty() and setProperty(). The default
+ * implementation checks <code>PropertyPermission(key, "read")</code>. If
+ * you override this, call <code>super.checkPropertyAccess</code> rather
+ * than throwing an exception.
+ *
+ * @param key the key of the property to check
+ *
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if key is null
+ * @throws IllegalArgumentException if key is ""
+ *
+ * @see System#getProperty(String)
+ */
+ public void checkPropertyAccess(String key)
+ {
+ checkPermission(new PropertyPermission(key, "read"));
+ }
+
+ /**
+ * Check if the current thread is allowed to create a top-level window. If
+ * it is not, the operation should still go through, but some sort of
+ * nonremovable warning should be placed on the window to show that it
+ * is untrusted. This method is called by Window.Window(). The default
+ * implementation checks
+ * <code>AWTPermission("showWindowWithoutWarningBanner")</code>, and returns
+ * true if no exception was thrown. If you override this, use
+ * <code>return super.checkTopLevelWindow</code> rather than returning
+ * false.
+ *
+ * @param window the window to create
+ * @return true if there is permission to show the window without warning
+ * @throws NullPointerException if window is null
+ * @see Window#Window(Frame)
+ */
+ public boolean checkTopLevelWindow(Object window)
+ {
+ if (window == null)
+ throw new NullPointerException();
+ try
+ {
+ checkPermission(new AWTPermission("showWindowWithoutWarningBanner"));
+ return true;
+ }
+ catch (SecurityException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Check if the current thread is allowed to create a print job. This
+ * method is called by Toolkit.getPrintJob(). The default implementation
+ * checks <code>RuntimePermission("queuePrintJob")</code>. If you override
+ * this, call <code>super.checkPrintJobAccess</code> rather than throwing
+ * an exception.
+ *
+ * @throws SecurityException if permission is denied
+ * @see Toolkit#getPrintJob(Frame, String, Properties)
+ * @since 1.1
+ */
+ public void checkPrintJobAccess()
+ {
+ checkPermission(new RuntimePermission("queuePrintJob"));
+ }
+
+ /**
+ * Check if the current thread is allowed to use the system clipboard. This
+ * method is called by Toolkit.getSystemClipboard(). The default
+ * implementation checks <code>AWTPermission("accessClipboard")</code>. If
+ * you override this, call <code>super.checkSystemClipboardAccess</code>
+ * rather than throwing an exception.
+ *
+ * @throws SecurityException if permission is denied
+ * @see Toolkit#getSystemClipboard()
+ * @since 1.1
+ */
+ public void checkSystemClipboardAccess()
+ {
+ checkPermission(new AWTPermission("accessClipboard"));
+ }
+
+ /**
+ * Check if the current thread is allowed to use the AWT event queue. This
+ * method is called by Toolkit.getSystemEventQueue(). The default
+ * implementation checks <code>AWTPermission("accessEventQueue")</code>.
+ * you override this, call <code>super.checkAwtEventQueueAccess</code>
+ * rather than throwing an exception.
+ *
+ * @throws SecurityException if permission is denied
+ * @see Toolkit#getSystemEventQueue()
+ * @since 1.1
+ */
+ public void checkAwtEventQueueAccess()
+ {
+ checkPermission(new AWTPermission("accessEventQueue"));
+ }
+
+ /**
+ * Check if the current thread is allowed to access the specified package
+ * at all. This method is called by ClassLoader.loadClass() in user-created
+ * ClassLoaders. The default implementation gets a list of all restricted
+ * packages, via <code>Security.getProperty("package.access")</code>. Then,
+ * if packageName starts with or equals any restricted package, it checks
+ * <code>RuntimePermission("accessClassInPackage." + packageName)</code>.
+ * If you override this, you should call
+ * <code>super.checkPackageAccess</code> before doing anything else.
+ *
+ * @param packageName the package name to check access to
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if packageName is null
+ * @see ClassLoader#loadClass(String, boolean)
+ * @see Security#getProperty(String)
+ */
+ public void checkPackageAccess(String packageName)
+ {
+ checkPackageList(packageName, "package.access", "accessClassInPackage.");
+ }
+
+ /**
+ * Check if the current thread is allowed to define a class into the
+ * specified package. This method is called by ClassLoader.loadClass() in
+ * user-created ClassLoaders. The default implementation gets a list of all
+ * restricted packages, via
+ * <code>Security.getProperty("package.definition")</code>. Then, if
+ * packageName starts with or equals any restricted package, it checks
+ * <code>RuntimePermission("defineClassInPackage." + packageName)</code>.
+ * If you override this, you should call
+ * <code>super.checkPackageDefinition</code> before doing anything else.
+ *
+ * @param packageName the package name to check access to
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if packageName is null
+ * @see ClassLoader#loadClass(String, boolean)
+ * @see Security#getProperty(String)
+ */
+ public void checkPackageDefinition(String packageName)
+ {
+ checkPackageList(packageName, "package.definition", "defineClassInPackage.");
+ }
+
+ /**
+ * Check if the current thread is allowed to set the current socket factory.
+ * This method is called by Socket.setSocketImplFactory(),
+ * ServerSocket.setSocketFactory(), and URL.setURLStreamHandlerFactory().
+ * The default implementation checks
+ * <code>RuntimePermission("setFactory")</code>. If you override this, call
+ * <code>super.checkSetFactory</code> rather than throwing an exception.
+ *
+ * @throws SecurityException if permission is denied
+ * @see Socket#setSocketImplFactory(SocketImplFactory)
+ * @see ServerSocket#setSocketFactory(SocketImplFactory)
+ * @see URL#setURLStreamHandlerFactory(URLStreamHandlerFactory)
+ */
+ public void checkSetFactory()
+ {
+ checkPermission(new RuntimePermission("setFactory"));
+ }
+
+ /**
+ * Check if the current thread is allowed to get certain types of Methods,
+ * Fields and Constructors from a Class object. This method is called by
+ * Class.getMethod[s](), Class.getField[s](), Class.getConstructor[s],
+ * Class.getDeclaredMethod[s](), Class.getDeclaredField[s](), and
+ * Class.getDeclaredConstructor[s](). The default implementation allows
+ * PUBLIC access, and access to classes defined by the same classloader as
+ * the code performing the reflection. Otherwise, it checks
+ * <code>RuntimePermission("accessDeclaredMembers")</code>. If you override
+ * this, do not call <code>super.checkMemberAccess</code>, as this would
+ * mess up the stack depth check that determines the ClassLoader requesting
+ * the access.
+ *
+ * @param c the Class to check
+ * @param memberType either DECLARED or PUBLIC
+ * @throws SecurityException if permission is denied, including when
+ * memberType is not DECLARED or PUBLIC
+ * @throws NullPointerException if c is null
+ * @see Class
+ * @see Member#DECLARED
+ * @see Member#PUBLIC
+ * @since 1.1
+ */
+ public void checkMemberAccess(Class c, int memberType)
+ {
+ if (c == null)
+ throw new NullPointerException();
+ if (memberType == Member.PUBLIC)
+ return;
+ // XXX Allow access to classes created by same classloader before next
+ // check.
+ checkPermission(new RuntimePermission("accessDeclaredMembers"));
+ }
+
+ /**
+ * Test whether a particular security action may be taken. The default
+ * implementation checks <code>SecurityPermission(action)</code>. If you
+ * override this, call <code>super.checkSecurityAccess</code> rather than
+ * throwing an exception.
+ *
+ * @param action the desired action to take
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if action is null
+ * @throws IllegalArgumentException if action is ""
+ * @since 1.1
+ */
+ public void checkSecurityAccess(String action)
+ {
+ checkPermission(new SecurityPermission(action));
+ }
+
+ /**
+ * Get the ThreadGroup that a new Thread should belong to by default. Called
+ * by Thread.Thread(). The default implementation returns the current
+ * ThreadGroup of the current Thread. <STRONG>Spec Note:</STRONG> it is not
+ * clear whether the new Thread is guaranteed to pass the
+ * checkAccessThreadGroup() test when using this ThreadGroup, but I presume
+ * so.
+ *
+ * @return the ThreadGroup to put the new Thread into
+ * @since 1.1
+ */
+ public ThreadGroup getThreadGroup()
+ {
+ return Thread.currentThread().getThreadGroup();
+ }
+
+ /**
+ * Helper that checks a comma-separated list of restricted packages, from
+ * <code>Security.getProperty("package.definition")</code>, for the given
+ * package access permission. If packageName starts with or equals any
+ * restricted package, it checks
+ * <code>RuntimePermission(permission + packageName)</code>.
+ *
+ * @param packageName the package name to check access to
+ * @param restriction "package.access" or "package.definition"
+ * @param permission the base permission, including the '.'
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if packageName is null
+ * @see #checkPackageAccess(String)
+ * @see #checkPackageDefinition(String)
+ */
+ void checkPackageList(String packageName, final String restriction,
+ String permission)
+ {
+ if (packageName == null)
+ throw new NullPointerException();
+
+ String list = (String)AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return Security.getProperty(restriction);
+ }
+ });
+
+ if (list == null || list.equals(""))
+ return;
+
+ String packageNamePlusDot = packageName + ".";
+
+ StringTokenizer st = new StringTokenizer(list, ",");
+ while (st.hasMoreTokens())
+ {
+ if (packageNamePlusDot.startsWith(st.nextToken()))
+ {
+ Permission p = new RuntimePermission(permission + packageName);
+ checkPermission(p);
+ return;
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/lang/Short.java b/libjava/classpath/java/lang/Short.java
new file mode 100644
index 00000000000..fbeea915bd3
--- /dev/null
+++ b/libjava/classpath/java/lang/Short.java
@@ -0,0 +1,353 @@
+/* Short.java -- object wrapper for short
+ Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * Instances of class <code>Short</code> represent primitive
+ * <code>short</code> values.
+ *
+ * Additionally, this class provides various helper functions and variables
+ * related to shorts.
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Short extends Number implements Comparable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 7515723908773894738L;
+
+ /**
+ * The minimum value a <code>short</code> can represent is -32768 (or
+ * -2<sup>15</sup>).
+ */
+ public static final short MIN_VALUE = -32768;
+
+ /**
+ * The minimum value a <code>short</code> can represent is 32767 (or
+ * 2<sup>15</sup>).
+ */
+ public static final short MAX_VALUE = 32767;
+
+ /**
+ * The primitive type <code>short</code> is represented by this
+ * <code>Class</code> object.
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass('S');
+
+ /**
+ * The immutable value of this Short.
+ *
+ * @serial the wrapped short
+ */
+ private final short value;
+
+ /**
+ * Create a <code>Short</code> object representing the value of the
+ * <code>short</code> argument.
+ *
+ * @param value the value to use
+ */
+ public Short(short value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create a <code>Short</code> object representing the value of the
+ * argument after conversion to a <code>short</code>.
+ *
+ * @param s the string to convert
+ * @throws NumberFormatException if the String cannot be parsed
+ */
+ public Short(String s)
+ {
+ value = parseShort(s, 10);
+ }
+
+ /**
+ * Converts the <code>short</code> to a <code>String</code> and assumes
+ * a radix of 10.
+ *
+ * @param s the <code>short</code> to convert to <code>String</code>
+ * @return the <code>String</code> representation of the argument
+ */
+ public static String toString(short s)
+ {
+ return String.valueOf(s);
+ }
+
+ /**
+ * Converts the specified <code>String</code> into a <code>short</code>.
+ * This function assumes a radix of 10.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the <code>short</code> value of <code>s</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>short</code>
+ */
+ public static short parseShort(String s)
+ {
+ return parseShort(s, 10);
+ }
+
+ /**
+ * Converts the specified <code>String</code> into a <code>short</code>
+ * using the specified radix (base). The string must not be <code>null</code>
+ * or empty. It may begin with an optional '-', which will negate the answer,
+ * provided that there are also valid digits. Each digit is parsed as if by
+ * <code>Character.digit(d, radix)</code>, and must be in the range
+ * <code>0</code> to <code>radix - 1</code>. Finally, the result must be
+ * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive.
+ * Unlike Double.parseDouble, you may not have a leading '+'.
+ *
+ * @param s the <code>String</code> to convert
+ * @param radix the radix (base) to use in the conversion
+ * @return the <code>String</code> argument converted to <code>short</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>short</code>
+ */
+ public static short parseShort(String s, int radix)
+ {
+ int i = Integer.parseInt(s, radix, false);
+ if ((short) i != i)
+ throw new NumberFormatException();
+ return (short) i;
+ }
+
+ /**
+ * Creates a new <code>Short</code> object using the <code>String</code>
+ * and specified radix (base).
+ *
+ * @param s the <code>String</code> to convert
+ * @param radix the radix (base) to convert with
+ * @return the new <code>Short</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>short</code>
+ * @see #parseShort(String, int)
+ */
+ public static Short valueOf(String s, int radix)
+ {
+ return new Short(parseShort(s, radix));
+ }
+
+ /**
+ * Creates a new <code>Short</code> object using the <code>String</code>,
+ * assuming a radix of 10.
+ *
+ * @param s the <code>String</code> to convert
+ * @return the new <code>Short</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>short</code>
+ * @see #Short(String)
+ * @see #parseShort(String)
+ */
+ public static Short valueOf(String s)
+ {
+ return new Short(parseShort(s, 10));
+ }
+
+ /**
+ * Convert the specified <code>String</code> into a <code>Short</code>.
+ * The <code>String</code> may represent decimal, hexadecimal, or
+ * octal numbers.
+ *
+ * <p>The extended BNF grammar is as follows:<br>
+ * <pre>
+ * <em>DecodableString</em>:
+ * ( [ <code>-</code> ] <em>DecimalNumber</em> )
+ * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code>
+ * | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } )
+ * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } )
+ * <em>DecimalNumber</em>:
+ * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> }
+ * <em>DecimalDigit</em>:
+ * <em>Character.digit(d, 10) has value 0 to 9</em>
+ * <em>OctalDigit</em>:
+ * <em>Character.digit(d, 8) has value 0 to 7</em>
+ * <em>DecimalDigit</em>:
+ * <em>Character.digit(d, 16) has value 0 to 15</em>
+ * </pre>
+ * Finally, the value must be in the range <code>MIN_VALUE</code> to
+ * <code>MAX_VALUE</code>, or an exception is thrown.
+ *
+ * @param s the <code>String</code> to interpret
+ * @return the value of the String as a <code>Short</code>
+ * @throws NumberFormatException if <code>s</code> cannot be parsed as a
+ * <code>short</code>
+ * @throws NullPointerException if <code>s</code> is null
+ * @see Integer#decode(String)
+ */
+ public static Short decode(String s)
+ {
+ int i = Integer.parseInt(s, 10, true);
+ if ((short) i != i)
+ throw new NumberFormatException();
+ return new Short((short) i);
+ }
+
+ /**
+ * Return the value of this <code>Short</code> as a <code>byte</code>.
+ *
+ * @return the byte value
+ */
+ public byte byteValue()
+ {
+ return (byte) value;
+ }
+
+ /**
+ * Return the value of this <code>Short</code>.
+ *
+ * @return the short value
+ */
+ public short shortValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Short</code> as an <code>int</code>.
+ *
+ * @return the int value
+ */
+ public int intValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Short</code> as a <code>long</code>.
+ *
+ * @return the long value
+ */
+ public long longValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Short</code> as a <code>float</code>.
+ *
+ * @return the float value
+ */
+ public float floatValue()
+ {
+ return value;
+ }
+
+ /**
+ * Return the value of this <code>Short</code> as a <code>double</code>.
+ *
+ * @return the double value
+ */
+ public double doubleValue()
+ {
+ return value;
+ }
+
+ /**
+ * Converts the <code>Short</code> value to a <code>String</code> and
+ * assumes a radix of 10.
+ *
+ * @return the <code>String</code> representation of this <code>Short</code>
+ */
+ public String toString()
+ {
+ return String.valueOf(value);
+ }
+
+ /**
+ * Return a hashcode representing this Object. <code>Short</code>'s hash
+ * code is simply its value.
+ *
+ * @return this Object's hash code
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Returns <code>true</code> if <code>obj</code> is an instance of
+ * <code>Short</code> and represents the same short value.
+ *
+ * @param obj the object to compare
+ * @return whether these Objects are semantically equal
+ */
+ public boolean equals(Object obj)
+ {
+ return obj instanceof Short && value == ((Short) obj).value;
+ }
+
+ /**
+ * Compare two Shorts numerically by comparing their <code>short</code>
+ * values. The result is positive if the first is greater, negative if the
+ * second is greater, and 0 if the two are equal.
+ *
+ * @param s the Short to compare
+ * @return the comparison
+ * @since 1.2
+ */
+ public int compareTo(Short s)
+ {
+ return value - s.value;
+ }
+
+ /**
+ * Behaves like <code>compareTo(Short)</code> unless the Object
+ * is not a <code>Short</code>.
+ *
+ * @param o the object to compare
+ * @return the comparison
+ * @throws ClassCastException if the argument is not a <code>Short</code>
+ * @see #compareTo(Short)
+ * @see Comparable
+ * @since 1.2
+ */
+ public int compareTo(Object o)
+ {
+ return compareTo((Short)o);
+ }
+}
diff --git a/libjava/classpath/java/lang/StackOverflowError.java b/libjava/classpath/java/lang/StackOverflowError.java
new file mode 100644
index 00000000000..5188ddda159
--- /dev/null
+++ b/libjava/classpath/java/lang/StackOverflowError.java
@@ -0,0 +1,72 @@
+/* StackOverflowError.java -- thrown when the stack depth is exceeded
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>StackOverflowError</code> is thrown when the execution stack
+ * overflow occurs. This often occurs when a method enters infinit recursion.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class StackOverflowError extends VirtualMachineError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 8609175038441759607L;
+
+ /**
+ * Create an error without a message.
+ */
+ public StackOverflowError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public StackOverflowError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/StackTraceElement.java b/libjava/classpath/java/lang/StackTraceElement.java
new file mode 100644
index 00000000000..6dd4d8532e8
--- /dev/null
+++ b/libjava/classpath/java/lang/StackTraceElement.java
@@ -0,0 +1,259 @@
+/* StackTraceElement.java -- One function call or call stack element
+ Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import java.io.Serializable;
+
+/**
+ * One function call or stack trace element. Gives information about
+ * the execution point such as the source file name, the line number,
+ * the fully qualified class name, the method name and whether this method
+ * is native, if this information is known.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public final class StackTraceElement implements Serializable
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 6992337162326171013L;
+
+ /**
+ * The name of the file, null if unknown.
+ *
+ * @serial the source code filename, if known
+ */
+ private final String fileName;
+
+ /**
+ * The line number in the file, negative if unknown.
+ *
+ * @serial the source code line number, if known
+ */
+ private final int lineNumber;
+
+ /**
+ * The fully qualified class name, null if unknown.
+ *
+ * @serial the enclosing class, if known
+ */
+ private final String declaringClass;
+
+ /**
+ * The method name in the class, null if unknown.
+ *
+ * @serial the enclosing method, if known
+ */
+ private final String methodName;
+
+ /** Whether the method is native. */
+ private final transient boolean isNative;
+
+ /**
+ * A package local constructor for the StackTraceElement class, to be
+ * called by the Virtual Machine as part of Throwable.fillInStackTrace.
+ * There are no public constructors defined for this class. Creation
+ * of new elements is implementation specific.
+ *
+ * @param fileName the name of the file, null if unknown
+ * @param lineNumber the line in the file, negative if unknown
+ * @param className the fully qualified name of the class, null if unknown
+ * @param methodName the name of the method, null if unknown
+ * @param isNative true if native, false otherwise
+ */
+ StackTraceElement(String fileName, int lineNumber, String className,
+ String methodName, boolean isNative)
+ {
+ this.fileName = fileName;
+ this.lineNumber = lineNumber;
+ this.declaringClass = className;
+ this.methodName = methodName;
+ this.isNative = isNative;
+ }
+
+ /**
+ * Returns the name of the file, or null if unknown. This is usually
+ * obtained from the <code>SourceFile</code> attribute of the class file
+ * format, if present.
+ *
+ * @return the file name
+ */
+ public String getFileName()
+ {
+ return fileName;
+ }
+
+ /**
+ * Returns the line number in the file, or a negative number if unknown.
+ * This is usually obtained from the <code>LineNumberTable</code> attribute
+ * of the method in the class file format, if present.
+ *
+ * @return the line number
+ */
+ public int getLineNumber()
+ {
+ return lineNumber;
+ }
+
+ /**
+ * Returns the fully qualified class name, or null if unknown.
+ *
+ * @return the class name
+ */
+ public String getClassName()
+ {
+ return declaringClass;
+ }
+
+ /**
+ * Returns the method name in the class, or null if unknown. If the
+ * execution point is in a constructor, the name is
+ * <code>&lt;init&gt;</code>; if the execution point is in the class
+ * initializer, the name is <code>&lt;clinit&gt;</code>.
+ *
+ * @return the method name
+ */
+ public String getMethodName()
+ {
+ return methodName;
+ }
+
+ /**
+ * Returns true if the method is native, or false if it is not or unknown.
+ *
+ * @return whether the method is native
+ */
+ public boolean isNativeMethod()
+ {
+ return isNative;
+ }
+
+ /**
+ * Returns a string representation of this stack trace element. The
+ * returned String is implementation specific. This implementation
+ * returns the following String: "[class][.][method]([file][:line])".
+ * If the fully qualified class name or the method is unknown it is
+ * omitted including the point seperator. If the source file name is
+ * unknown it is replaced by "Unknown Source" if the method is not native
+ * or by "Native Method" if the method is native. If the line number
+ * is unknown it and the colon are omitted.
+ *
+ * @return a string representation of this execution point
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ if (declaringClass != null)
+ {
+ sb.append(declaringClass);
+ if (methodName != null)
+ sb.append('.');
+ }
+ if (methodName != null)
+ sb.append(methodName);
+ sb.append(" (");
+ if (fileName != null)
+ sb.append(fileName);
+ else
+ sb.append(isNative ? "Native Method" : "Unknown Source");
+ if (lineNumber >= 0)
+ sb.append(':').append(lineNumber);
+ sb.append(')');
+ return sb.toString();
+ }
+
+ /**
+ * Returns true if the given object is also a StackTraceElement and all
+ * attributes, except the native flag, are equal (either the same attribute
+ * between the two elments are null, or both satisfy Object.equals).
+ *
+ * @param o the object to compare
+ * @return true if the two are equal
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof StackTraceElement))
+ return false;
+ StackTraceElement e = (StackTraceElement) o;
+ return equals(fileName, e.fileName)
+ && lineNumber == e.lineNumber
+ && equals(declaringClass, e.declaringClass)
+ && equals(methodName, e.methodName);
+ }
+
+ /**
+ * Returns the hashCode of this StackTraceElement. This implementation
+ * computes the hashcode by xor-ing the hashcode of all attributes except
+ * the native flag.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ return hashCode(fileName) ^ lineNumber ^ hashCode(declaringClass)
+ ^ hashCode(methodName);
+ }
+
+ /**
+ * Compare two objects according to Collection semantics.
+ *
+ * @param o1 the first object
+ * @param o2 the second object
+ * @return o1 == null ? o2 == null : o1.equals(o2)
+ */
+ private static boolean equals(Object o1, Object o2)
+ {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ /**
+ * Hash an object according to Collection semantics.
+ *
+ * @param o the object to hash
+ * @return o1 == null ? 0 : o1.hashCode()
+ */
+ private static int hashCode(Object o)
+ {
+ return o == null ? 0 : o.hashCode();
+ }
+}
diff --git a/libjava/classpath/java/lang/StrictMath.java b/libjava/classpath/java/lang/StrictMath.java
new file mode 100644
index 00000000000..32bd3540d80
--- /dev/null
+++ b/libjava/classpath/java/lang/StrictMath.java
@@ -0,0 +1,1844 @@
+/* java.lang.StrictMath -- common mathematical functions, strict Java
+ Copyright (C) 1998, 2001, 2002, 2003 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. */
+
+/*
+ * Some of the algorithms in this class are in the public domain, as part
+ * of fdlibm (freely-distributable math library), available at
+ * http://www.netlib.org/fdlibm/, and carry the following copyright:
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+package java.lang;
+
+import gnu.classpath.Configuration;
+
+import java.util.Random;
+
+/**
+ * Helper class containing useful mathematical functions and constants.
+ * This class mirrors {@link Math}, but is 100% portable, because it uses
+ * no native methods whatsoever. Also, these algorithms are all accurate
+ * to less than 1 ulp, and execute in <code>strictfp</code> mode, while
+ * Math is allowed to vary in its results for some functions. Unfortunately,
+ * this usually means StrictMath has less efficiency and speed, as Math can
+ * use native methods.
+ *
+ * <p>The source of the various algorithms used is the fdlibm library, at:<br>
+ * <a href="http://www.netlib.org/fdlibm/">http://www.netlib.org/fdlibm/</a>
+ *
+ * Note that angles are specified in radians. Conversion functions are
+ * provided for your convenience.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ */
+public final strictfp class StrictMath
+{
+ /**
+ * StrictMath is non-instantiable.
+ */
+ private StrictMath()
+ {
+ }
+
+ /**
+ * A random number generator, initialized on first use.
+ *
+ * @see #random()
+ */
+ private static Random rand;
+
+ /**
+ * The most accurate approximation to the mathematical constant <em>e</em>:
+ * <code>2.718281828459045</code>. Used in natural log and exp.
+ *
+ * @see #log(double)
+ * @see #exp(double)
+ */
+ public static final double E
+ = 2.718281828459045; // Long bits 0x4005bf0z8b145769L.
+
+ /**
+ * The most accurate approximation to the mathematical constant <em>pi</em>:
+ * <code>3.141592653589793</code>. This is the ratio of a circle's diameter
+ * to its circumference.
+ */
+ public static final double PI
+ = 3.141592653589793; // Long bits 0x400921fb54442d18L.
+
+ /**
+ * Take the absolute value of the argument. (Absolute value means make
+ * it positive.)
+ *
+ * <p>Note that the the largest negative value (Integer.MIN_VALUE) cannot
+ * be made positive. In this case, because of the rules of negation in
+ * a computer, MIN_VALUE is what will be returned.
+ * This is a <em>negative</em> value. You have been warned.
+ *
+ * @param i the number to take the absolute value of
+ * @return the absolute value
+ * @see Integer#MIN_VALUE
+ */
+ public static int abs(int i)
+ {
+ return (i < 0) ? -i : i;
+ }
+
+ /**
+ * Take the absolute value of the argument. (Absolute value means make
+ * it positive.)
+ *
+ * <p>Note that the the largest negative value (Long.MIN_VALUE) cannot
+ * be made positive. In this case, because of the rules of negation in
+ * a computer, MIN_VALUE is what will be returned.
+ * This is a <em>negative</em> value. You have been warned.
+ *
+ * @param l the number to take the absolute value of
+ * @return the absolute value
+ * @see Long#MIN_VALUE
+ */
+ public static long abs(long l)
+ {
+ return (l < 0) ? -l : l;
+ }
+
+ /**
+ * Take the absolute value of the argument. (Absolute value means make
+ * it positive.)
+ *
+ * @param f the number to take the absolute value of
+ * @return the absolute value
+ */
+ public static float abs(float f)
+ {
+ return (f <= 0) ? 0 - f : f;
+ }
+
+ /**
+ * Take the absolute value of the argument. (Absolute value means make
+ * it positive.)
+ *
+ * @param d the number to take the absolute value of
+ * @return the absolute value
+ */
+ public static double abs(double d)
+ {
+ return (d <= 0) ? 0 - d : d;
+ }
+
+ /**
+ * Return whichever argument is smaller.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the smaller of the two numbers
+ */
+ public static int min(int a, int b)
+ {
+ return (a < b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is smaller.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the smaller of the two numbers
+ */
+ public static long min(long a, long b)
+ {
+ return (a < b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is smaller. If either argument is NaN, the
+ * result is NaN, and when comparing 0 and -0, -0 is always smaller.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the smaller of the two numbers
+ */
+ public static float min(float a, float b)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return a;
+ // no need to check if b is NaN; < will work correctly
+ // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
+ if (a == 0 && b == 0)
+ return -(-a - b);
+ return (a < b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is smaller. If either argument is NaN, the
+ * result is NaN, and when comparing 0 and -0, -0 is always smaller.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the smaller of the two numbers
+ */
+ public static double min(double a, double b)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return a;
+ // no need to check if b is NaN; < will work correctly
+ // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
+ if (a == 0 && b == 0)
+ return -(-a - b);
+ return (a < b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is larger.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the larger of the two numbers
+ */
+ public static int max(int a, int b)
+ {
+ return (a > b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is larger.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the larger of the two numbers
+ */
+ public static long max(long a, long b)
+ {
+ return (a > b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is larger. If either argument is NaN, the
+ * result is NaN, and when comparing 0 and -0, 0 is always larger.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the larger of the two numbers
+ */
+ public static float max(float a, float b)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return a;
+ // no need to check if b is NaN; > will work correctly
+ // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
+ if (a == 0 && b == 0)
+ return a - -b;
+ return (a > b) ? a : b;
+ }
+
+ /**
+ * Return whichever argument is larger. If either argument is NaN, the
+ * result is NaN, and when comparing 0 and -0, 0 is always larger.
+ *
+ * @param a the first number
+ * @param b a second number
+ * @return the larger of the two numbers
+ */
+ public static double max(double a, double b)
+ {
+ // this check for NaN, from JLS 15.21.1, saves a method call
+ if (a != a)
+ return a;
+ // no need to check if b is NaN; > will work correctly
+ // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
+ if (a == 0 && b == 0)
+ return a - -b;
+ return (a > b) ? a : b;
+ }
+
+ /**
+ * The trigonometric function <em>sin</em>. The sine of NaN or infinity is
+ * NaN, and the sine of 0 retains its sign.
+ *
+ * @param a the angle (in radians)
+ * @return sin(a)
+ */
+ public static double sin(double a)
+ {
+ if (a == Double.NEGATIVE_INFINITY || ! (a < Double.POSITIVE_INFINITY))
+ return Double.NaN;
+
+ if (abs(a) <= PI / 4)
+ return sin(a, 0);
+
+ // Argument reduction needed.
+ double[] y = new double[2];
+ int n = remPiOver2(a, y);
+ switch (n & 3)
+ {
+ case 0:
+ return sin(y[0], y[1]);
+ case 1:
+ return cos(y[0], y[1]);
+ case 2:
+ return -sin(y[0], y[1]);
+ default:
+ return -cos(y[0], y[1]);
+ }
+ }
+
+ /**
+ * The trigonometric function <em>cos</em>. The cosine of NaN or infinity is
+ * NaN.
+ *
+ * @param a the angle (in radians).
+ * @return cos(a).
+ */
+ public static double cos(double a)
+ {
+ if (a == Double.NEGATIVE_INFINITY || ! (a < Double.POSITIVE_INFINITY))
+ return Double.NaN;
+
+ if (abs(a) <= PI / 4)
+ return cos(a, 0);
+
+ // Argument reduction needed.
+ double[] y = new double[2];
+ int n = remPiOver2(a, y);
+ switch (n & 3)
+ {
+ case 0:
+ return cos(y[0], y[1]);
+ case 1:
+ return -sin(y[0], y[1]);
+ case 2:
+ return -cos(y[0], y[1]);
+ default:
+ return sin(y[0], y[1]);
+ }
+ }
+
+ /**
+ * The trigonometric function <em>tan</em>. The tangent of NaN or infinity
+ * is NaN, and the tangent of 0 retains its sign.
+ *
+ * @param a the angle (in radians)
+ * @return tan(a)
+ */
+ public static double tan(double a)
+ {
+ if (a == Double.NEGATIVE_INFINITY || ! (a < Double.POSITIVE_INFINITY))
+ return Double.NaN;
+
+ if (abs(a) <= PI / 4)
+ return tan(a, 0, false);
+
+ // Argument reduction needed.
+ double[] y = new double[2];
+ int n = remPiOver2(a, y);
+ return tan(y[0], y[1], (n & 1) == 1);
+ }
+
+ /**
+ * The trigonometric function <em>arcsin</em>. The range of angles returned
+ * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN or
+ * its absolute value is beyond 1, the result is NaN; and the arcsine of
+ * 0 retains its sign.
+ *
+ * @param x the sin to turn back into an angle
+ * @return arcsin(x)
+ */
+ public static double asin(double x)
+ {
+ boolean negative = x < 0;
+ if (negative)
+ x = -x;
+ if (! (x <= 1))
+ return Double.NaN;
+ if (x == 1)
+ return negative ? -PI / 2 : PI / 2;
+ if (x < 0.5)
+ {
+ if (x < 1 / TWO_27)
+ return negative ? -x : x;
+ double t = x * x;
+ double p = t * (PS0 + t * (PS1 + t * (PS2 + t * (PS3 + t
+ * (PS4 + t * PS5)))));
+ double q = 1 + t * (QS1 + t * (QS2 + t * (QS3 + t * QS4)));
+ return negative ? -x - x * (p / q) : x + x * (p / q);
+ }
+ double w = 1 - x; // 1>|x|>=0.5.
+ double t = w * 0.5;
+ double p = t * (PS0 + t * (PS1 + t * (PS2 + t * (PS3 + t
+ * (PS4 + t * PS5)))));
+ double q = 1 + t * (QS1 + t * (QS2 + t * (QS3 + t * QS4)));
+ double s = sqrt(t);
+ if (x >= 0.975)
+ {
+ w = p / q;
+ t = PI / 2 - (2 * (s + s * w) - PI_L / 2);
+ }
+ else
+ {
+ w = (float) s;
+ double c = (t - w * w) / (s + w);
+ p = 2 * s * (p / q) - (PI_L / 2 - 2 * c);
+ q = PI / 4 - 2 * w;
+ t = PI / 4 - (p - q);
+ }
+ return negative ? -t : t;
+ }
+
+ /**
+ * The trigonometric function <em>arccos</em>. The range of angles returned
+ * is 0 to pi radians (0 to 180 degrees). If the argument is NaN or
+ * its absolute value is beyond 1, the result is NaN.
+ *
+ * @param x the cos to turn back into an angle
+ * @return arccos(x)
+ */
+ public static double acos(double x)
+ {
+ boolean negative = x < 0;
+ if (negative)
+ x = -x;
+ if (! (x <= 1))
+ return Double.NaN;
+ if (x == 1)
+ return negative ? PI : 0;
+ if (x < 0.5)
+ {
+ if (x < 1 / TWO_57)
+ return PI / 2;
+ double z = x * x;
+ double p = z * (PS0 + z * (PS1 + z * (PS2 + z * (PS3 + z
+ * (PS4 + z * PS5)))));
+ double q = 1 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+ double r = x - (PI_L / 2 - x * (p / q));
+ return negative ? PI / 2 + r : PI / 2 - r;
+ }
+ if (negative) // x<=-0.5.
+ {
+ double z = (1 + x) * 0.5;
+ double p = z * (PS0 + z * (PS1 + z * (PS2 + z * (PS3 + z
+ * (PS4 + z * PS5)))));
+ double q = 1 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+ double s = sqrt(z);
+ double w = p / q * s - PI_L / 2;
+ return PI - 2 * (s + w);
+ }
+ double z = (1 - x) * 0.5; // x>0.5.
+ double s = sqrt(z);
+ double df = (float) s;
+ double c = (z - df * df) / (s + df);
+ double p = z * (PS0 + z * (PS1 + z * (PS2 + z * (PS3 + z
+ * (PS4 + z * PS5)))));
+ double q = 1 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+ double w = p / q * s + c;
+ return 2 * (df + w);
+ }
+
+ /**
+ * The trigonometric function <em>arcsin</em>. The range of angles returned
+ * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN, the
+ * result is NaN; and the arctangent of 0 retains its sign.
+ *
+ * @param x the tan to turn back into an angle
+ * @return arcsin(x)
+ * @see #atan2(double, double)
+ */
+ public static double atan(double x)
+ {
+ double lo;
+ double hi;
+ boolean negative = x < 0;
+ if (negative)
+ x = -x;
+ if (x >= TWO_66)
+ return negative ? -PI / 2 : PI / 2;
+ if (! (x >= 0.4375)) // |x|<7/16, or NaN.
+ {
+ if (! (x >= 1 / TWO_29)) // Small, or NaN.
+ return negative ? -x : x;
+ lo = hi = 0;
+ }
+ else if (x < 1.1875)
+ {
+ if (x < 0.6875) // 7/16<=|x|<11/16.
+ {
+ x = (2 * x - 1) / (2 + x);
+ hi = ATAN_0_5H;
+ lo = ATAN_0_5L;
+ }
+ else // 11/16<=|x|<19/16.
+ {
+ x = (x - 1) / (x + 1);
+ hi = PI / 4;
+ lo = PI_L / 4;
+ }
+ }
+ else if (x < 2.4375) // 19/16<=|x|<39/16.
+ {
+ x = (x - 1.5) / (1 + 1.5 * x);
+ hi = ATAN_1_5H;
+ lo = ATAN_1_5L;
+ }
+ else // 39/16<=|x|<2**66.
+ {
+ x = -1 / x;
+ hi = PI / 2;
+ lo = PI_L / 2;
+ }
+
+ // Break sum from i=0 to 10 ATi*z**(i+1) into odd and even poly.
+ double z = x * x;
+ double w = z * z;
+ double s1 = z * (AT0 + w * (AT2 + w * (AT4 + w * (AT6 + w
+ * (AT8 + w * AT10)))));
+ double s2 = w * (AT1 + w * (AT3 + w * (AT5 + w * (AT7 + w * AT9))));
+ if (hi == 0)
+ return negative ? x * (s1 + s2) - x : x - x * (s1 + s2);
+ z = hi - ((x * (s1 + s2) - lo) - x);
+ return negative ? -z : z;
+ }
+
+ /**
+ * A special version of the trigonometric function <em>arctan</em>, for
+ * converting rectangular coordinates <em>(x, y)</em> to polar
+ * <em>(r, theta)</em>. This computes the arctangent of x/y in the range
+ * of -pi to pi radians (-180 to 180 degrees). Special cases:<ul>
+ * <li>If either argument is NaN, the result is NaN.</li>
+ * <li>If the first argument is positive zero and the second argument is
+ * positive, or the first argument is positive and finite and the second
+ * argument is positive infinity, then the result is positive zero.</li>
+ * <li>If the first argument is negative zero and the second argument is
+ * positive, or the first argument is negative and finite and the second
+ * argument is positive infinity, then the result is negative zero.</li>
+ * <li>If the first argument is positive zero and the second argument is
+ * negative, or the first argument is positive and finite and the second
+ * argument is negative infinity, then the result is the double value
+ * closest to pi.</li>
+ * <li>If the first argument is negative zero and the second argument is
+ * negative, or the first argument is negative and finite and the second
+ * argument is negative infinity, then the result is the double value
+ * closest to -pi.</li>
+ * <li>If the first argument is positive and the second argument is
+ * positive zero or negative zero, or the first argument is positive
+ * infinity and the second argument is finite, then the result is the
+ * double value closest to pi/2.</li>
+ * <li>If the first argument is negative and the second argument is
+ * positive zero or negative zero, or the first argument is negative
+ * infinity and the second argument is finite, then the result is the
+ * double value closest to -pi/2.</li>
+ * <li>If both arguments are positive infinity, then the result is the
+ * double value closest to pi/4.</li>
+ * <li>If the first argument is positive infinity and the second argument
+ * is negative infinity, then the result is the double value closest to
+ * 3*pi/4.</li>
+ * <li>If the first argument is negative infinity and the second argument
+ * is positive infinity, then the result is the double value closest to
+ * -pi/4.</li>
+ * <li>If both arguments are negative infinity, then the result is the
+ * double value closest to -3*pi/4.</li>
+ *
+ * </ul><p>This returns theta, the angle of the point. To get r, albeit
+ * slightly inaccurately, use sqrt(x*x+y*y).
+ *
+ * @param y the y position
+ * @param x the x position
+ * @return <em>theta</em> in the conversion of (x, y) to (r, theta)
+ * @see #atan(double)
+ */
+ public static double atan2(double y, double x)
+ {
+ if (x != x || y != y)
+ return Double.NaN;
+ if (x == 1)
+ return atan(y);
+ if (x == Double.POSITIVE_INFINITY)
+ {
+ if (y == Double.POSITIVE_INFINITY)
+ return PI / 4;
+ if (y == Double.NEGATIVE_INFINITY)
+ return -PI / 4;
+ return 0 * y;
+ }
+ if (x == Double.NEGATIVE_INFINITY)
+ {
+ if (y == Double.POSITIVE_INFINITY)
+ return 3 * PI / 4;
+ if (y == Double.NEGATIVE_INFINITY)
+ return -3 * PI / 4;
+ return (1 / (0 * y) == Double.POSITIVE_INFINITY) ? PI : -PI;
+ }
+ if (y == 0)
+ {
+ if (1 / (0 * x) == Double.POSITIVE_INFINITY)
+ return y;
+ return (1 / y == Double.POSITIVE_INFINITY) ? PI : -PI;
+ }
+ if (y == Double.POSITIVE_INFINITY || y == Double.NEGATIVE_INFINITY
+ || x == 0)
+ return y < 0 ? -PI / 2 : PI / 2;
+
+ double z = abs(y / x); // Safe to do y/x.
+ if (z > TWO_60)
+ z = PI / 2 + 0.5 * PI_L;
+ else if (x < 0 && z < 1 / TWO_60)
+ z = 0;
+ else
+ z = atan(z);
+ if (x > 0)
+ return y > 0 ? z : -z;
+ return y > 0 ? PI - (z - PI_L) : z - PI_L - PI;
+ }
+
+ /**
+ * 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
+ * infinity, the result is positive zero.
+ *
+ * @param x the number to raise to the power
+ * @return the number raised to the power of <em>e</em>
+ * @see #log(double)
+ * @see #pow(double, double)
+ */
+ public static double exp(double x)
+ {
+ if (x != x)
+ return x;
+ if (x > EXP_LIMIT_H)
+ return Double.POSITIVE_INFINITY;
+ if (x < EXP_LIMIT_L)
+ return 0;
+
+ // Argument reduction.
+ double hi;
+ double lo;
+ int k;
+ double t = abs(x);
+ if (t > 0.5 * LN2)
+ {
+ if (t < 1.5 * LN2)
+ {
+ hi = t - LN2_H;
+ lo = LN2_L;
+ k = 1;
+ }
+ else
+ {
+ k = (int) (INV_LN2 * t + 0.5);
+ hi = t - k * LN2_H;
+ lo = k * LN2_L;
+ }
+ if (x < 0)
+ {
+ hi = -hi;
+ lo = -lo;
+ k = -k;
+ }
+ x = hi - lo;
+ }
+ else if (t < 1 / TWO_28)
+ return 1;
+ else
+ lo = hi = k = 0;
+
+ // Now x is in primary range.
+ t = x * x;
+ double c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+ if (k == 0)
+ return 1 - (x * c / (c - 2) - x);
+ double y = 1 - (lo - x * c / (2 - c) - hi);
+ return scale(y, k);
+ }
+
+ /**
+ * 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
+ * is either zero, the result is negative infinity.
+ *
+ * <p>Note that the way to get log<sub>b</sub>(a) is to do this:
+ * <code>ln(a) / ln(b)</code>.
+ *
+ * @param x the number to take the natural log of
+ * @return the natural log of <code>a</code>
+ * @see #exp(double)
+ */
+ public static double log(double x)
+ {
+ if (x == 0)
+ return Double.NEGATIVE_INFINITY;
+ if (x < 0)
+ return Double.NaN;
+ if (! (x < Double.POSITIVE_INFINITY))
+ return x;
+
+ // Normalize x.
+ long bits = Double.doubleToLongBits(x);
+ int exp = (int) (bits >> 52);
+ if (exp == 0) // Subnormal x.
+ {
+ x *= TWO_54;
+ bits = Double.doubleToLongBits(x);
+ exp = (int) (bits >> 52) - 54;
+ }
+ exp -= 1023; // Unbias exponent.
+ bits = (bits & 0x000fffffffffffffL) | 0x3ff0000000000000L;
+ x = Double.longBitsToDouble(bits);
+ if (x >= SQRT_2)
+ {
+ x *= 0.5;
+ exp++;
+ }
+ x--;
+ if (abs(x) < 1 / TWO_20)
+ {
+ if (x == 0)
+ return exp * LN2_H + exp * LN2_L;
+ double r = x * x * (0.5 - 1 / 3.0 * x);
+ if (exp == 0)
+ return x - r;
+ return exp * LN2_H - ((r - exp * LN2_L) - x);
+ }
+ double s = x / (2 + x);
+ double z = s * s;
+ double w = z * z;
+ double t1 = w * (LG2 + w * (LG4 + w * LG6));
+ double t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7)));
+ double r = t2 + t1;
+ if (bits >= 0x3ff6174a00000000L && bits < 0x3ff6b85200000000L)
+ {
+ double h = 0.5 * x * x; // Need more accuracy for x near sqrt(2).
+ if (exp == 0)
+ return x - (h - s * (h + r));
+ return exp * LN2_H - ((h - (s * (h + r) + exp * LN2_L)) - x);
+ }
+ if (exp == 0)
+ return x - s * (x - r);
+ return exp * LN2_H - ((s * (x - r) - exp * LN2_L) - x);
+ }
+
+ /**
+ * Take a square root. 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 result is either zero, the result is the same.
+ *
+ * <p>For other roots, use pow(x, 1/rootNumber).
+ *
+ * @param x the numeric argument
+ * @return the square root of the argument
+ * @see #pow(double, double)
+ */
+ public static double sqrt(double x)
+ {
+ if (x < 0)
+ return Double.NaN;
+ if (x == 0 || ! (x < Double.POSITIVE_INFINITY))
+ return x;
+
+ // Normalize x.
+ long bits = Double.doubleToLongBits(x);
+ int exp = (int) (bits >> 52);
+ if (exp == 0) // Subnormal x.
+ {
+ x *= TWO_54;
+ bits = Double.doubleToLongBits(x);
+ exp = (int) (bits >> 52) - 54;
+ }
+ exp -= 1023; // Unbias exponent.
+ bits = (bits & 0x000fffffffffffffL) | 0x0010000000000000L;
+ if ((exp & 1) == 1) // Odd exp, double x to make it even.
+ bits <<= 1;
+ exp >>= 1;
+
+ // Generate sqrt(x) bit by bit.
+ bits <<= 1;
+ long q = 0;
+ long s = 0;
+ long r = 0x0020000000000000L; // Move r right to left.
+ while (r != 0)
+ {
+ long t = s + r;
+ if (t <= bits)
+ {
+ s = t + r;
+ bits -= t;
+ q += r;
+ }
+ bits <<= 1;
+ r >>= 1;
+ }
+
+ // Use floating add to round correctly.
+ if (bits != 0)
+ q += q & 1;
+ return Double.longBitsToDouble((q >> 1) + ((exp + 1022L) << 52));
+ }
+
+ /**
+ * Raise a number to a power. Special cases:<ul>
+ * <li>If the second argument is positive or negative zero, then the result
+ * is 1.0.</li>
+ * <li>If the second argument is 1.0, then the result is the same as the
+ * first argument.</li>
+ * <li>If the second argument is NaN, then the result is NaN.</li>
+ * <li>If the first argument is NaN and the second argument is nonzero,
+ * then the result is NaN.</li>
+ * <li>If the absolute value of the first argument is greater than 1 and
+ * the second argument is positive infinity, or the absolute value of the
+ * first argument is less than 1 and the second argument is negative
+ * infinity, then the result is positive infinity.</li>
+ * <li>If the absolute value of the first argument is greater than 1 and
+ * the second argument is negative infinity, or the absolute value of the
+ * first argument is less than 1 and the second argument is positive
+ * infinity, then the result is positive zero.</li>
+ * <li>If the absolute value of the first argument equals 1 and the second
+ * argument is infinite, then the result is NaN.</li>
+ * <li>If the first argument is positive zero and the second argument is
+ * greater than zero, or the first argument is positive infinity and the
+ * second argument is less than zero, then the result is positive zero.</li>
+ * <li>If the first argument is positive zero and the second argument is
+ * less than zero, or the first argument is positive infinity and the
+ * second argument is greater than zero, then the result is positive
+ * infinity.</li>
+ * <li>If the first argument is negative zero and the second argument is
+ * greater than zero but not a finite odd integer, or the first argument is
+ * negative infinity and the second argument is less than zero but not a
+ * finite odd integer, then the result is positive zero.</li>
+ * <li>If the first argument is negative zero and the second argument is a
+ * positive finite odd integer, or the first argument is negative infinity
+ * and the second argument is a negative finite odd integer, then the result
+ * is negative zero.</li>
+ * <li>If the first argument is negative zero and the second argument is
+ * less than zero but not a finite odd integer, or the first argument is
+ * negative infinity and the second argument is greater than zero but not a
+ * finite odd integer, then the result is positive infinity.</li>
+ * <li>If the first argument is negative zero and the second argument is a
+ * negative finite odd integer, or the first argument is negative infinity
+ * and the second argument is a positive finite odd integer, then the result
+ * is negative infinity.</li>
+ * <li>If the first argument is less than zero and the second argument is a
+ * finite even integer, then the result is equal to the result of raising
+ * the absolute value of the first argument to the power of the second
+ * argument.</li>
+ * <li>If the first argument is less than zero and the second argument is a
+ * finite odd integer, then the result is equal to the negative of the
+ * result of raising the absolute value of the first argument to the power
+ * of the second argument.</li>
+ * <li>If the first argument is finite and less than zero and the second
+ * argument is finite and not an integer, then the result is NaN.</li>
+ * <li>If both arguments are integers, then the result is exactly equal to
+ * the mathematical result of raising the first argument to the power of
+ * the second argument if that result can in fact be represented exactly as
+ * a double value.</li>
+ *
+ * </ul><p>(In the foregoing descriptions, a floating-point value is
+ * considered to be an integer if and only if it is a fixed point of the
+ * method {@link #ceil(double)} or, equivalently, a fixed point of the
+ * method {@link #floor(double)}. A value is a fixed point of a one-argument
+ * method if and only if the result of applying the method to the value is
+ * equal to the value.)
+ *
+ * @param x the number to raise
+ * @param y the power to raise it to
+ * @return x<sup>y</sup>
+ */
+ public static double pow(double x, double y)
+ {
+ // Special cases first.
+ if (y == 0)
+ return 1;
+ if (y == 1)
+ return x;
+ if (y == -1)
+ return 1 / x;
+ if (x != x || y != y)
+ return Double.NaN;
+
+ // When x < 0, yisint tells if y is not an integer (0), even(1),
+ // or odd (2).
+ int yisint = 0;
+ if (x < 0 && floor(y) == y)
+ yisint = (y % 2 == 0) ? 2 : 1;
+ double ax = abs(x);
+ double ay = abs(y);
+
+ // More special cases, of y.
+ if (ay == Double.POSITIVE_INFINITY)
+ {
+ if (ax == 1)
+ return Double.NaN;
+ if (ax > 1)
+ return y > 0 ? y : 0;
+ return y < 0 ? -y : 0;
+ }
+ if (y == 2)
+ return x * x;
+ if (y == 0.5)
+ return sqrt(x);
+
+ // More special cases, of x.
+ if (x == 0 || ax == Double.POSITIVE_INFINITY || ax == 1)
+ {
+ if (y < 0)
+ ax = 1 / ax;
+ if (x < 0)
+ {
+ if (x == -1 && yisint == 0)
+ ax = Double.NaN;
+ else if (yisint == 1)
+ ax = -ax;
+ }
+ return ax;
+ }
+ if (x < 0 && yisint == 0)
+ return Double.NaN;
+
+ // Now we can start!
+ double t;
+ double t1;
+ double t2;
+ double u;
+ double v;
+ double w;
+ if (ay > TWO_31)
+ {
+ if (ay > TWO_64) // Automatic over/underflow.
+ return ((ax < 1) ? y < 0 : y > 0) ? Double.POSITIVE_INFINITY : 0;
+ // Over/underflow if x is not close to one.
+ if (ax < 0.9999995231628418)
+ return y < 0 ? Double.POSITIVE_INFINITY : 0;
+ if (ax >= 1.0000009536743164)
+ return y > 0 ? Double.POSITIVE_INFINITY : 0;
+ // Now |1-x| is <= 2**-20, sufficient to compute
+ // log(x) by x-x^2/2+x^3/3-x^4/4.
+ t = x - 1;
+ w = t * t * (0.5 - t * (1 / 3.0 - t * 0.25));
+ u = INV_LN2_H * t;
+ v = t * INV_LN2_L - w * INV_LN2;
+ t1 = (float) (u + v);
+ t2 = v - (t1 - u);
+ }
+ else
+ {
+ long bits = Double.doubleToLongBits(ax);
+ int exp = (int) (bits >> 52);
+ if (exp == 0) // Subnormal x.
+ {
+ ax *= TWO_54;
+ bits = Double.doubleToLongBits(ax);
+ exp = (int) (bits >> 52) - 54;
+ }
+ exp -= 1023; // Unbias exponent.
+ ax = Double.longBitsToDouble((bits & 0x000fffffffffffffL)
+ | 0x3ff0000000000000L);
+ boolean k;
+ if (ax < SQRT_1_5) // |x|<sqrt(3/2).
+ k = false;
+ else if (ax < SQRT_3) // |x|<sqrt(3).
+ k = true;
+ else
+ {
+ k = false;
+ ax *= 0.5;
+ exp++;
+ }
+
+ // Compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5).
+ u = ax - (k ? 1.5 : 1);
+ v = 1 / (ax + (k ? 1.5 : 1));
+ double s = u * v;
+ double s_h = (float) s;
+ double t_h = (float) (ax + (k ? 1.5 : 1));
+ double t_l = ax - (t_h - (k ? 1.5 : 1));
+ double s_l = v * ((u - s_h * t_h) - s_h * t_l);
+ // Compute log(ax).
+ double s2 = s * s;
+ double r = s_l * (s_h + s) + s2 * s2
+ * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6)))));
+ s2 = s_h * s_h;
+ t_h = (float) (3.0 + s2 + r);
+ t_l = r - (t_h - 3.0 - s2);
+ // u+v = s*(1+...).
+ u = s_h * t_h;
+ v = s_l * t_h + t_l * s;
+ // 2/(3log2)*(s+...).
+ double p_h = (float) (u + v);
+ double p_l = v - (p_h - u);
+ double z_h = CP_H * p_h;
+ double z_l = CP_L * p_h + p_l * CP + (k ? DP_L : 0);
+ // log2(ax) = (s+..)*2/(3*log2) = exp + dp_h + z_h + z_l.
+ t = exp;
+ t1 = (float) (z_h + z_l + (k ? DP_H : 0) + t);
+ t2 = z_l - (t1 - t - (k ? DP_H : 0) - z_h);
+ }
+
+ // Split up y into y1+y2 and compute (y1+y2)*(t1+t2).
+ boolean negative = x < 0 && yisint == 1;
+ double y1 = (float) y;
+ double p_l = (y - y1) * t1 + y * t2;
+ double p_h = y1 * t1;
+ double z = p_l + p_h;
+ if (z >= 1024) // Detect overflow.
+ {
+ if (z > 1024 || p_l + OVT > z - p_h)
+ return negative ? Double.NEGATIVE_INFINITY
+ : Double.POSITIVE_INFINITY;
+ }
+ else if (z <= -1075) // Detect underflow.
+ {
+ if (z < -1075 || p_l <= z - p_h)
+ return negative ? -0.0 : 0;
+ }
+
+ // Compute 2**(p_h+p_l).
+ int n = round((float) z);
+ p_h -= n;
+ t = (float) (p_l + p_h);
+ u = t * LN2_H;
+ v = (p_l - (t - p_h)) * LN2 + t * LN2_L;
+ z = u + v;
+ w = v - (z - u);
+ t = z * z;
+ t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+ double r = (z * t1) / (t1 - 2) - (w + z * w);
+ z = scale(1 - (r - z), n);
+ return negative ? -z : z;
+ }
+
+ /**
+ * Get the IEEE 754 floating point remainder on two numbers. This is the
+ * value of <code>x - y * <em>n</em></code>, where <em>n</em> is the closest
+ * double to <code>x / y</code> (ties go to the even n); for a zero
+ * remainder, the sign is that of <code>x</code>. If either argument is NaN,
+ * the first argument is infinite, or the second argument is zero, the result
+ * is NaN; if x is finite but y is infinite, the result is x.
+ *
+ * @param x the dividend (the top half)
+ * @param y the divisor (the bottom half)
+ * @return the IEEE 754-defined floating point remainder of x/y
+ * @see #rint(double)
+ */
+ public static double IEEEremainder(double x, double y)
+ {
+ // Purge off exception values.
+ if (x == Double.NEGATIVE_INFINITY || ! (x < Double.POSITIVE_INFINITY)
+ || y == 0 || y != y)
+ return Double.NaN;
+
+ boolean negative = x < 0;
+ x = abs(x);
+ y = abs(y);
+ if (x == y || x == 0)
+ return 0 * x; // Get correct sign.
+
+ // Achieve x < 2y, then take first shot at remainder.
+ if (y < TWO_1023)
+ x %= y + y;
+
+ // Now adjust x to get correct precision.
+ if (y < 4 / TWO_1023)
+ {
+ if (x + x > y)
+ {
+ x -= y;
+ if (x + x >= y)
+ x -= y;
+ }
+ }
+ else
+ {
+ y *= 0.5;
+ if (x > y)
+ {
+ x -= y;
+ if (x >= y)
+ x -= y;
+ }
+ }
+ return negative ? -x : x;
+ }
+
+ /**
+ * Take the nearest integer that is that is greater than or equal to the
+ * argument. If the argument is NaN, infinite, or zero, the result is the
+ * same; if the argument is between -1 and 0, the result is negative zero.
+ * Note that <code>Math.ceil(x) == -Math.floor(-x)</code>.
+ *
+ * @param a the value to act upon
+ * @return the nearest integer &gt;= <code>a</code>
+ */
+ public static double ceil(double a)
+ {
+ return -floor(-a);
+ }
+
+ /**
+ * Take the nearest integer that is that is less than or equal to the
+ * argument. If the argument is NaN, infinite, or zero, the result is the
+ * same. Note that <code>Math.ceil(x) == -Math.floor(-x)</code>.
+ *
+ * @param a the value to act upon
+ * @return the nearest integer &lt;= <code>a</code>
+ */
+ public static double floor(double a)
+ {
+ double x = abs(a);
+ if (! (x < TWO_52) || (long) a == a)
+ return a; // No fraction bits; includes NaN and infinity.
+ if (x < 1)
+ return a >= 0 ? 0 * a : -1; // Worry about signed zero.
+ return a < 0 ? (long) a - 1.0 : (long) a; // Cast to long truncates.
+ }
+
+ /**
+ * Take the nearest integer to the argument. If it is exactly between
+ * two integers, the even integer is taken. If the argument is NaN,
+ * infinite, or zero, the result is the same.
+ *
+ * @param a the value to act upon
+ * @return the nearest integer to <code>a</code>
+ */
+ public static double rint(double a)
+ {
+ double x = abs(a);
+ if (! (x < TWO_52))
+ return a; // No fraction bits; includes NaN and infinity.
+ if (x <= 0.5)
+ return 0 * a; // Worry about signed zero.
+ if (x % 2 <= 0.5)
+ return (long) a; // Catch round down to even.
+ return (long) (a + (a < 0 ? -0.5 : 0.5)); // Cast to long truncates.
+ }
+
+ /**
+ * Take the nearest integer to the argument. This is equivalent to
+ * <code>(int) Math.floor(f + 0.5f)</code>. If the argument is NaN, the
+ * result is 0; otherwise if the argument is outside the range of int, the
+ * result will be Integer.MIN_VALUE or Integer.MAX_VALUE, as appropriate.
+ *
+ * @param f the argument to round
+ * @return the nearest integer to the argument
+ * @see Integer#MIN_VALUE
+ * @see Integer#MAX_VALUE
+ */
+ public static int round(float f)
+ {
+ return (int) floor(f + 0.5f);
+ }
+
+ /**
+ * Take the nearest long to the argument. This is equivalent to
+ * <code>(long) Math.floor(d + 0.5)</code>. If the argument is NaN, the
+ * result is 0; otherwise if the argument is outside the range of long, the
+ * result will be Long.MIN_VALUE or Long.MAX_VALUE, as appropriate.
+ *
+ * @param d the argument to round
+ * @return the nearest long to the argument
+ * @see Long#MIN_VALUE
+ * @see Long#MAX_VALUE
+ */
+ public static long round(double d)
+ {
+ return (long) floor(d + 0.5);
+ }
+
+ /**
+ * Get a random number. This behaves like Random.nextDouble(), seeded by
+ * System.currentTimeMillis() when first called. In other words, the number
+ * is from a pseudorandom sequence, and lies in the range [+0.0, 1.0).
+ * This random sequence is only used by this method, and is threadsafe,
+ * although you may want your own random number generator if it is shared
+ * among threads.
+ *
+ * @return a random number
+ * @see Random#nextDouble()
+ * @see System#currentTimeMillis()
+ */
+ public static synchronized double random()
+ {
+ if (rand == null)
+ rand = new Random();
+ return rand.nextDouble();
+ }
+
+ /**
+ * Convert from degrees to radians. The formula for this is
+ * radians = degrees * (pi/180); however it is not always exact given the
+ * limitations of floating point numbers.
+ *
+ * @param degrees an angle in degrees
+ * @return the angle in radians
+ */
+ public static double toRadians(double degrees)
+ {
+ return (degrees * PI) / 180;
+ }
+
+ /**
+ * Convert from radians to degrees. The formula for this is
+ * degrees = radians * (180/pi); however it is not always exact given the
+ * limitations of floating point numbers.
+ *
+ * @param rads an angle in radians
+ * @return the angle in degrees
+ */
+ public static double toDegrees(double rads)
+ {
+ return (rads * 180) / PI;
+ }
+
+ /**
+ * Constants for scaling and comparing doubles by powers of 2. The compiler
+ * must automatically inline constructs like (1/TWO_54), so we don't list
+ * negative powers of two here.
+ */
+ private static final double
+ TWO_16 = 0x10000, // Long bits 0x40f0000000000000L.
+ TWO_20 = 0x100000, // Long bits 0x4130000000000000L.
+ TWO_24 = 0x1000000, // Long bits 0x4170000000000000L.
+ TWO_27 = 0x8000000, // Long bits 0x41a0000000000000L.
+ TWO_28 = 0x10000000, // Long bits 0x41b0000000000000L.
+ TWO_29 = 0x20000000, // Long bits 0x41c0000000000000L.
+ TWO_31 = 0x80000000L, // Long bits 0x41e0000000000000L.
+ TWO_49 = 0x2000000000000L, // Long bits 0x4300000000000000L.
+ TWO_52 = 0x10000000000000L, // Long bits 0x4330000000000000L.
+ TWO_54 = 0x40000000000000L, // Long bits 0x4350000000000000L.
+ TWO_57 = 0x200000000000000L, // Long bits 0x4380000000000000L.
+ TWO_60 = 0x1000000000000000L, // Long bits 0x43b0000000000000L.
+ TWO_64 = 1.8446744073709552e19, // Long bits 0x43f0000000000000L.
+ TWO_66 = 7.378697629483821e19, // Long bits 0x4410000000000000L.
+ TWO_1023 = 8.98846567431158e307; // Long bits 0x7fe0000000000000L.
+
+ /**
+ * Super precision for 2/pi in 24-bit chunks, for use in
+ * {@link #remPiOver2()}.
+ */
+ private static final int TWO_OVER_PI[] = {
+ 0xa2f983, 0x6e4e44, 0x1529fc, 0x2757d1, 0xf534dd, 0xc0db62,
+ 0x95993c, 0x439041, 0xfe5163, 0xabdebb, 0xc561b7, 0x246e3a,
+ 0x424dd2, 0xe00649, 0x2eea09, 0xd1921c, 0xfe1deb, 0x1cb129,
+ 0xa73ee8, 0x8235f5, 0x2ebb44, 0x84e99c, 0x7026b4, 0x5f7e41,
+ 0x3991d6, 0x398353, 0x39f49c, 0x845f8b, 0xbdf928, 0x3b1ff8,
+ 0x97ffde, 0x05980f, 0xef2f11, 0x8b5a0a, 0x6d1f6d, 0x367ecf,
+ 0x27cb09, 0xb74f46, 0x3f669e, 0x5fea2d, 0x7527ba, 0xc7ebe5,
+ 0xf17b3d, 0x0739f7, 0x8a5292, 0xea6bfb, 0x5fb11f, 0x8d5d08,
+ 0x560330, 0x46fc7b, 0x6babf0, 0xcfbc20, 0x9af436, 0x1da9e3,
+ 0x91615e, 0xe61b08, 0x659985, 0x5f14a0, 0x68408d, 0xffd880,
+ 0x4d7327, 0x310606, 0x1556ca, 0x73a8c9, 0x60e27b, 0xc08c6b,
+ };
+
+ /**
+ * Super precision for pi/2 in 24-bit chunks, for use in
+ * {@link #remPiOver2()}.
+ */
+ private static final double PI_OVER_TWO[] = {
+ 1.570796251296997, // Long bits 0x3ff921fb40000000L.
+ 7.549789415861596e-8, // Long bits 0x3e74442d00000000L.
+ 5.390302529957765e-15, // Long bits 0x3cf8469880000000L.
+ 3.282003415807913e-22, // Long bits 0x3b78cc5160000000L.
+ 1.270655753080676e-29, // Long bits 0x39f01b8380000000L.
+ 1.2293330898111133e-36, // Long bits 0x387a252040000000L.
+ 2.7337005381646456e-44, // Long bits 0x36e3822280000000L.
+ 2.1674168387780482e-51, // Long bits 0x3569f31d00000000L.
+ };
+
+ /**
+ * More constants related to pi, used in {@link #remPiOver2()} and
+ * elsewhere.
+ */
+ private static final double
+ PI_L = 1.2246467991473532e-16, // Long bits 0x3ca1a62633145c07L.
+ PIO2_1 = 1.5707963267341256, // Long bits 0x3ff921fb54400000L.
+ PIO2_1L = 6.077100506506192e-11, // Long bits 0x3dd0b4611a626331L.
+ PIO2_2 = 6.077100506303966e-11, // Long bits 0x3dd0b4611a600000L.
+ PIO2_2L = 2.0222662487959506e-21, // Long bits 0x3ba3198a2e037073L.
+ PIO2_3 = 2.0222662487111665e-21, // Long bits 0x3ba3198a2e000000L.
+ PIO2_3L = 8.4784276603689e-32; // Long bits 0x397b839a252049c1L.
+
+ /**
+ * Natural log and square root constants, for calculation of
+ * {@link #exp(double)}, {@link #log(double)} and
+ * {@link #power(double, double)}. CP is 2/(3*ln(2)).
+ */
+ private static final double
+ SQRT_1_5 = 1.224744871391589, // Long bits 0x3ff3988e1409212eL.
+ SQRT_2 = 1.4142135623730951, // Long bits 0x3ff6a09e667f3bcdL.
+ SQRT_3 = 1.7320508075688772, // Long bits 0x3ffbb67ae8584caaL.
+ EXP_LIMIT_H = 709.782712893384, // Long bits 0x40862e42fefa39efL.
+ EXP_LIMIT_L = -745.1332191019411, // Long bits 0xc0874910d52d3051L.
+ CP = 0.9617966939259756, // Long bits 0x3feec709dc3a03fdL.
+ CP_H = 0.9617967009544373, // Long bits 0x3feec709e0000000L.
+ CP_L = -7.028461650952758e-9, // Long bits 0xbe3e2fe0145b01f5L.
+ LN2 = 0.6931471805599453, // Long bits 0x3fe62e42fefa39efL.
+ LN2_H = 0.6931471803691238, // Long bits 0x3fe62e42fee00000L.
+ LN2_L = 1.9082149292705877e-10, // Long bits 0x3dea39ef35793c76L.
+ INV_LN2 = 1.4426950408889634, // Long bits 0x3ff71547652b82feL.
+ INV_LN2_H = 1.4426950216293335, // Long bits 0x3ff7154760000000L.
+ INV_LN2_L = 1.9259629911266175e-8; // Long bits 0x3e54ae0bf85ddf44L.
+
+ /**
+ * Constants for computing {@link #log(double)}.
+ */
+ private static final double
+ LG1 = 0.6666666666666735, // Long bits 0x3fe5555555555593L.
+ LG2 = 0.3999999999940942, // Long bits 0x3fd999999997fa04L.
+ LG3 = 0.2857142874366239, // Long bits 0x3fd2492494229359L.
+ LG4 = 0.22222198432149784, // Long bits 0x3fcc71c51d8e78afL.
+ LG5 = 0.1818357216161805, // Long bits 0x3fc7466496cb03deL.
+ LG6 = 0.15313837699209373, // Long bits 0x3fc39a09d078c69fL.
+ LG7 = 0.14798198605116586; // Long bits 0x3fc2f112df3e5244L.
+
+ /**
+ * Constants for computing {@link #pow(double, double)}. L and P are
+ * coefficients for series; OVT is -(1024-log2(ovfl+.5ulp)); and DP is ???.
+ * The P coefficients also calculate {@link #exp(double)}.
+ */
+ private static final double
+ L1 = 0.5999999999999946, // Long bits 0x3fe3333333333303L.
+ L2 = 0.4285714285785502, // Long bits 0x3fdb6db6db6fabffL.
+ L3 = 0.33333332981837743, // Long bits 0x3fd55555518f264dL.
+ L4 = 0.272728123808534, // Long bits 0x3fd17460a91d4101L.
+ L5 = 0.23066074577556175, // Long bits 0x3fcd864a93c9db65L.
+ L6 = 0.20697501780033842, // Long bits 0x3fca7e284a454eefL.
+ P1 = 0.16666666666666602, // Long bits 0x3fc555555555553eL.
+ P2 = -2.7777777777015593e-3, // Long bits 0xbf66c16c16bebd93L.
+ P3 = 6.613756321437934e-5, // Long bits 0x3f11566aaf25de2cL.
+ P4 = -1.6533902205465252e-6, // Long bits 0xbebbbd41c5d26bf1L.
+ P5 = 4.1381367970572385e-8, // Long bits 0x3e66376972bea4d0L.
+ DP_H = 0.5849624872207642, // Long bits 0x3fe2b80340000000L.
+ DP_L = 1.350039202129749e-8, // Long bits 0x3e4cfdeb43cfd006L.
+ OVT = 8.008566259537294e-17; // Long bits 0x3c971547652b82feL.
+
+ /**
+ * Coefficients for computing {@link #sin(double)}.
+ */
+ private static final double
+ S1 = -0.16666666666666632, // Long bits 0xbfc5555555555549L.
+ S2 = 8.33333333332249e-3, // Long bits 0x3f8111111110f8a6L.
+ S3 = -1.984126982985795e-4, // Long bits 0xbf2a01a019c161d5L.
+ S4 = 2.7557313707070068e-6, // Long bits 0x3ec71de357b1fe7dL.
+ S5 = -2.5050760253406863e-8, // Long bits 0xbe5ae5e68a2b9cebL.
+ S6 = 1.58969099521155e-10; // Long bits 0x3de5d93a5acfd57cL.
+
+ /**
+ * Coefficients for computing {@link #cos(double)}.
+ */
+ private static final double
+ C1 = 0.0416666666666666, // Long bits 0x3fa555555555554cL.
+ C2 = -1.388888888887411e-3, // Long bits 0xbf56c16c16c15177L.
+ C3 = 2.480158728947673e-5, // Long bits 0x3efa01a019cb1590L.
+ C4 = -2.7557314351390663e-7, // Long bits 0xbe927e4f809c52adL.
+ C5 = 2.087572321298175e-9, // Long bits 0x3e21ee9ebdb4b1c4L.
+ C6 = -1.1359647557788195e-11; // Long bits 0xbda8fae9be8838d4L.
+
+ /**
+ * Coefficients for computing {@link #tan(double)}.
+ */
+ private static final double
+ T0 = 0.3333333333333341, // Long bits 0x3fd5555555555563L.
+ T1 = 0.13333333333320124, // Long bits 0x3fc111111110fe7aL.
+ T2 = 0.05396825397622605, // Long bits 0x3faba1ba1bb341feL.
+ T3 = 0.021869488294859542, // Long bits 0x3f9664f48406d637L.
+ T4 = 8.8632398235993e-3, // Long bits 0x3f8226e3e96e8493L.
+ T5 = 3.5920791075913124e-3, // Long bits 0x3f6d6d22c9560328L.
+ T6 = 1.4562094543252903e-3, // Long bits 0x3f57dbc8fee08315L.
+ T7 = 5.880412408202641e-4, // Long bits 0x3f4344d8f2f26501L.
+ T8 = 2.464631348184699e-4, // Long bits 0x3f3026f71a8d1068L.
+ T9 = 7.817944429395571e-5, // Long bits 0x3f147e88a03792a6L.
+ T10 = 7.140724913826082e-5, // Long bits 0x3f12b80f32f0a7e9L.
+ T11 = -1.8558637485527546e-5, // Long bits 0xbef375cbdb605373L.
+ T12 = 2.590730518636337e-5; // Long bits 0x3efb2a7074bf7ad4L.
+
+ /**
+ * Coefficients for computing {@link #asin(double)} and
+ * {@link #acos(double)}.
+ */
+ private static final double
+ PS0 = 0.16666666666666666, // Long bits 0x3fc5555555555555L.
+ PS1 = -0.3255658186224009, // Long bits 0xbfd4d61203eb6f7dL.
+ PS2 = 0.20121253213486293, // Long bits 0x3fc9c1550e884455L.
+ PS3 = -0.04005553450067941, // Long bits 0xbfa48228b5688f3bL.
+ PS4 = 7.915349942898145e-4, // Long bits 0x3f49efe07501b288L.
+ PS5 = 3.479331075960212e-5, // Long bits 0x3f023de10dfdf709L.
+ QS1 = -2.403394911734414, // Long bits 0xc0033a271c8a2d4bL.
+ QS2 = 2.0209457602335057, // Long bits 0x40002ae59c598ac8L.
+ QS3 = -0.6882839716054533, // Long bits 0xbfe6066c1b8d0159L.
+ QS4 = 0.07703815055590194; // Long bits 0x3fb3b8c5b12e9282L.
+
+ /**
+ * Coefficients for computing {@link #atan(double)}.
+ */
+ private static final double
+ ATAN_0_5H = 0.4636476090008061, // Long bits 0x3fddac670561bb4fL.
+ ATAN_0_5L = 2.2698777452961687e-17, // Long bits 0x3c7a2b7f222f65e2L.
+ ATAN_1_5H = 0.982793723247329, // Long bits 0x3fef730bd281f69bL.
+ ATAN_1_5L = 1.3903311031230998e-17, // Long bits 0x3c7007887af0cbbdL.
+ AT0 = 0.3333333333333293, // Long bits 0x3fd555555555550dL.
+ AT1 = -0.19999999999876483, // Long bits 0xbfc999999998ebc4L.
+ AT2 = 0.14285714272503466, // Long bits 0x3fc24924920083ffL.
+ AT3 = -0.11111110405462356, // Long bits 0xbfbc71c6fe231671L.
+ AT4 = 0.09090887133436507, // Long bits 0x3fb745cdc54c206eL.
+ AT5 = -0.0769187620504483, // Long bits 0xbfb3b0f2af749a6dL.
+ AT6 = 0.06661073137387531, // Long bits 0x3fb10d66a0d03d51L.
+ AT7 = -0.058335701337905735, // Long bits 0xbfadde2d52defd9aL.
+ AT8 = 0.049768779946159324, // Long bits 0x3fa97b4b24760debL.
+ AT9 = -0.036531572744216916, // Long bits 0xbfa2b4442c6a6c2fL.
+ AT10 = 0.016285820115365782; // Long bits 0x3f90ad3ae322da11L.
+
+ /**
+ * Helper function for reducing an angle to a multiple of pi/2 within
+ * [-pi/4, pi/4].
+ *
+ * @param x the angle; not infinity or NaN, and outside pi/4
+ * @param y an array of 2 doubles modified to hold the remander x % pi/2
+ * @return the quadrant of the result, mod 4: 0: [-pi/4, pi/4],
+ * 1: [pi/4, 3*pi/4], 2: [3*pi/4, 5*pi/4], 3: [-3*pi/4, -pi/4]
+ */
+ private static int remPiOver2(double x, double[] y)
+ {
+ boolean negative = x < 0;
+ x = abs(x);
+ double z;
+ int n;
+ if (Configuration.DEBUG && (x <= PI / 4 || x != x
+ || x == Double.POSITIVE_INFINITY))
+ throw new InternalError("Assertion failure");
+ if (x < 3 * PI / 4) // If |x| is small.
+ {
+ z = x - PIO2_1;
+ if ((float) x != (float) (PI / 2)) // 33+53 bit pi is good enough.
+ {
+ y[0] = z - PIO2_1L;
+ y[1] = z - y[0] - PIO2_1L;
+ }
+ else // Near pi/2, use 33+33+53 bit pi.
+ {
+ z -= PIO2_2;
+ y[0] = z - PIO2_2L;
+ y[1] = z - y[0] - PIO2_2L;
+ }
+ n = 1;
+ }
+ else if (x <= TWO_20 * PI / 2) // Medium size.
+ {
+ n = (int) (2 / PI * x + 0.5);
+ z = x - n * PIO2_1;
+ double w = n * PIO2_1L; // First round good to 85 bits.
+ y[0] = z - w;
+ if (n >= 32 || (float) x == (float) (w))
+ {
+ if (x / y[0] >= TWO_16) // Second iteration, good to 118 bits.
+ {
+ double t = z;
+ w = n * PIO2_2;
+ z = t - w;
+ w = n * PIO2_2L - (t - z - w);
+ y[0] = z - w;
+ if (x / y[0] >= TWO_49) // Third iteration, 151 bits accuracy.
+ {
+ t = z;
+ w = n * PIO2_3;
+ z = t - w;
+ w = n * PIO2_3L - (t - z - w);
+ y[0] = z - w;
+ }
+ }
+ }
+ y[1] = z - y[0] - w;
+ }
+ else
+ {
+ // All other (large) arguments.
+ int e0 = (int) (Double.doubleToLongBits(x) >> 52) - 1046;
+ z = scale(x, -e0); // e0 = ilogb(z) - 23.
+ double[] tx = new double[3];
+ for (int i = 0; i < 2; i++)
+ {
+ tx[i] = (int) z;
+ z = (z - tx[i]) * TWO_24;
+ }
+ tx[2] = z;
+ int nx = 2;
+ while (tx[nx] == 0)
+ nx--;
+ n = remPiOver2(tx, y, e0, nx);
+ }
+ if (negative)
+ {
+ y[0] = -y[0];
+ y[1] = -y[1];
+ return -n;
+ }
+ return n;
+ }
+
+ /**
+ * Helper function for reducing an angle to a multiple of pi/2 within
+ * [-pi/4, pi/4].
+ *
+ * @param x the positive angle, broken into 24-bit chunks
+ * @param y an array of 2 doubles modified to hold the remander x % pi/2
+ * @param e0 the exponent of x[0]
+ * @param nx the last index used in x
+ * @return the quadrant of the result, mod 4: 0: [-pi/4, pi/4],
+ * 1: [pi/4, 3*pi/4], 2: [3*pi/4, 5*pi/4], 3: [-3*pi/4, -pi/4]
+ */
+ private static int remPiOver2(double[] x, double[] y, int e0, int nx)
+ {
+ int i;
+ int ih;
+ int n;
+ double fw;
+ double z;
+ int[] iq = new int[20];
+ double[] f = new double[20];
+ double[] q = new double[20];
+ boolean recompute = false;
+
+ // Initialize jk, jz, jv, q0; note that 3>q0.
+ int jk = 4;
+ int jz = jk;
+ int jv = max((e0 - 3) / 24, 0);
+ int q0 = e0 - 24 * (jv + 1);
+
+ // Set up f[0] to f[nx+jk] where f[nx+jk] = TWO_OVER_PI[jv+jk].
+ int j = jv - nx;
+ int m = nx + jk;
+ for (i = 0; i <= m; i++, j++)
+ f[i] = (j < 0) ? 0 : TWO_OVER_PI[j];
+
+ // Compute q[0],q[1],...q[jk].
+ for (i = 0; i <= jk; i++)
+ {
+ for (j = 0, fw = 0; j <= nx; j++)
+ fw += x[j] * f[nx + i - j];
+ q[i] = fw;
+ }
+
+ do
+ {
+ // Distill q[] into iq[] reversingly.
+ for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--)
+ {
+ fw = (int) (1 / TWO_24 * z);
+ iq[i] = (int) (z - TWO_24 * fw);
+ z = q[j - 1] + fw;
+ }
+
+ // Compute n.
+ z = scale(z, q0);
+ z -= 8 * floor(z * 0.125); // Trim off integer >= 8.
+ n = (int) z;
+ z -= n;
+ ih = 0;
+ if (q0 > 0) // Need iq[jz-1] to determine n.
+ {
+ i = iq[jz - 1] >> (24 - q0);
+ n += i;
+ iq[jz - 1] -= i << (24 - q0);
+ ih = iq[jz - 1] >> (23 - q0);
+ }
+ else if (q0 == 0)
+ ih = iq[jz - 1] >> 23;
+ else if (z >= 0.5)
+ ih = 2;
+
+ if (ih > 0) // If q > 0.5.
+ {
+ n += 1;
+ int carry = 0;
+ for (i = 0; i < jz; i++) // Compute 1-q.
+ {
+ j = iq[i];
+ if (carry == 0)
+ {
+ if (j != 0)
+ {
+ carry = 1;
+ iq[i] = 0x1000000 - j;
+ }
+ }
+ else
+ iq[i] = 0xffffff - j;
+ }
+ switch (q0)
+ {
+ case 1: // Rare case: chance is 1 in 12 for non-default.
+ iq[jz - 1] &= 0x7fffff;
+ break;
+ case 2:
+ iq[jz - 1] &= 0x3fffff;
+ }
+ if (ih == 2)
+ {
+ z = 1 - z;
+ if (carry != 0)
+ z -= scale(1, q0);
+ }
+ }
+
+ // Check if recomputation is needed.
+ if (z == 0)
+ {
+ j = 0;
+ for (i = jz - 1; i >= jk; i--)
+ j |= iq[i];
+ if (j == 0) // Need recomputation.
+ {
+ int k;
+ for (k = 1; iq[jk - k] == 0; k++); // k = no. of terms needed.
+
+ for (i = jz + 1; i <= jz + k; i++) // Add q[jz+1] to q[jz+k].
+ {
+ f[nx + i] = TWO_OVER_PI[jv + i];
+ for (j = 0, fw = 0; j <= nx; j++)
+ fw += x[j] * f[nx + i - j];
+ q[i] = fw;
+ }
+ jz += k;
+ recompute = true;
+ }
+ }
+ }
+ while (recompute);
+
+ // Chop off zero terms.
+ if (z == 0)
+ {
+ jz--;
+ q0 -= 24;
+ while (iq[jz] == 0)
+ {
+ jz--;
+ q0 -= 24;
+ }
+ }
+ else // Break z into 24-bit if necessary.
+ {
+ z = scale(z, -q0);
+ if (z >= TWO_24)
+ {
+ fw = (int) (1 / TWO_24 * z);
+ iq[jz] = (int) (z - TWO_24 * fw);
+ jz++;
+ q0 += 24;
+ iq[jz] = (int) fw;
+ }
+ else
+ iq[jz] = (int) z;
+ }
+
+ // Convert integer "bit" chunk to floating-point value.
+ fw = scale(1, q0);
+ for (i = jz; i >= 0; i--)
+ {
+ q[i] = fw * iq[i];
+ fw *= 1 / TWO_24;
+ }
+
+ // Compute PI_OVER_TWO[0,...,jk]*q[jz,...,0].
+ double[] fq = new double[20];
+ for (i = jz; i >= 0; i--)
+ {
+ fw = 0;
+ for (int k = 0; k <= jk && k <= jz - i; k++)
+ fw += PI_OVER_TWO[k] * q[i + k];
+ fq[jz - i] = fw;
+ }
+
+ // Compress fq[] into y[].
+ fw = 0;
+ for (i = jz; i >= 0; i--)
+ fw += fq[i];
+ y[0] = (ih == 0) ? fw : -fw;
+ fw = fq[0] - fw;
+ for (i = 1; i <= jz; i++)
+ fw += fq[i];
+ y[1] = (ih == 0) ? fw : -fw;
+ return n;
+ }
+
+ /**
+ * Helper method for scaling a double by a power of 2.
+ *
+ * @param x the double
+ * @param n the scale; |n| < 2048
+ * @return x * 2**n
+ */
+ private static double scale(double x, int n)
+ {
+ if (Configuration.DEBUG && abs(n) >= 2048)
+ throw new InternalError("Assertion failure");
+ if (x == 0 || x == Double.NEGATIVE_INFINITY
+ || ! (x < Double.POSITIVE_INFINITY) || n == 0)
+ return x;
+ long bits = Double.doubleToLongBits(x);
+ int exp = (int) (bits >> 52) & 0x7ff;
+ if (exp == 0) // Subnormal x.
+ {
+ x *= TWO_54;
+ exp = ((int) (Double.doubleToLongBits(x) >> 52) & 0x7ff) - 54;
+ }
+ exp += n;
+ if (exp > 0x7fe) // Overflow.
+ return Double.POSITIVE_INFINITY * x;
+ if (exp > 0) // Normal.
+ return Double.longBitsToDouble((bits & 0x800fffffffffffffL)
+ | ((long) exp << 52));
+ if (exp <= -54)
+ return 0 * x; // Underflow.
+ exp += 54; // Subnormal result.
+ x = Double.longBitsToDouble((bits & 0x800fffffffffffffL)
+ | ((long) exp << 52));
+ return x * (1 / TWO_54);
+ }
+
+ /**
+ * Helper trig function; computes sin in range [-pi/4, pi/4].
+ *
+ * @param x angle within about pi/4
+ * @param y tail of x, created by remPiOver2
+ * @return sin(x+y)
+ */
+ private static double sin(double x, double y)
+ {
+ if (Configuration.DEBUG && abs(x + y) > 0.7854)
+ throw new InternalError("Assertion failure");
+ if (abs(x) < 1 / TWO_27)
+ return x; // If |x| ~< 2**-27, already know answer.
+
+ double z = x * x;
+ double v = z * x;
+ double r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
+ if (y == 0)
+ return x + v * (S1 + z * r);
+ return x - ((z * (0.5 * y - v * r) - y) - v * S1);
+ }
+
+ /**
+ * Helper trig function; computes cos in range [-pi/4, pi/4].
+ *
+ * @param x angle within about pi/4
+ * @param y tail of x, created by remPiOver2
+ * @return cos(x+y)
+ */
+ private static double cos(double x, double y)
+ {
+ if (Configuration.DEBUG && abs(x + y) > 0.7854)
+ throw new InternalError("Assertion failure");
+ x = abs(x);
+ if (x < 1 / TWO_27)
+ return 1; // If |x| ~< 2**-27, already know answer.
+
+ double z = x * x;
+ double r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
+
+ if (x < 0.3)
+ return 1 - (0.5 * z - (z * r - x * y));
+
+ double qx = (x > 0.78125) ? 0.28125 : (x * 0.25);
+ return 1 - qx - ((0.5 * z - qx) - (z * r - x * y));
+ }
+
+ /**
+ * Helper trig function; computes tan in range [-pi/4, pi/4].
+ *
+ * @param x angle within about pi/4
+ * @param y tail of x, created by remPiOver2
+ * @param invert true iff -1/tan should be returned instead
+ * @return tan(x+y)
+ */
+ private static double tan(double x, double y, boolean invert)
+ {
+ // PI/2 is irrational, so no double is a perfect multiple of it.
+ if (Configuration.DEBUG && (abs(x + y) > 0.7854 || (x == 0 && invert)))
+ throw new InternalError("Assertion failure");
+ boolean negative = x < 0;
+ if (negative)
+ {
+ x = -x;
+ y = -y;
+ }
+ if (x < 1 / TWO_28) // If |x| ~< 2**-28, already know answer.
+ return (negative ? -1 : 1) * (invert ? -1 / x : x);
+
+ double z;
+ double w;
+ boolean large = x >= 0.6744;
+ if (large)
+ {
+ z = PI / 4 - x;
+ w = PI_L / 4 - y;
+ x = z + w;
+ y = 0;
+ }
+ z = x * x;
+ w = z * z;
+ // Break x**5*(T1+x**2*T2+...) into
+ // x**5(T1+x**4*T3+...+x**20*T11)
+ // + x**5(x**2*(T2+x**4*T4+...+x**22*T12)).
+ double r = T1 + w * (T3 + w * (T5 + w * (T7 + w * (T9 + w * T11))));
+ double v = z * (T2 + w * (T4 + w * (T6 + w * (T8 + w * (T10 + w * T12)))));
+ double s = z * x;
+ r = y + z * (s * (r + v) + y);
+ r += T0 * s;
+ w = x + r;
+ if (large)
+ {
+ v = invert ? -1 : 1;
+ return (negative ? -1 : 1) * (v - 2 * (x - (w * w / (w + v) - r)));
+ }
+ if (! invert)
+ return w;
+
+ // Compute -1.0/(x+r) accurately.
+ z = (float) w;
+ v = r - (z - x);
+ double a = -1 / w;
+ double t = (float) a;
+ return t + a * (1 + t * z + t * v);
+ }
+}
diff --git a/libjava/classpath/java/lang/String.java b/libjava/classpath/java/lang/String.java
new file mode 100644
index 00000000000..b4db8505051
--- /dev/null
+++ b/libjava/classpath/java/lang/String.java
@@ -0,0 +1,1750 @@
+/* String.java -- immutable character sequences; the object of string literals
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.java.lang.CharData;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.text.Collator;
+import java.util.Comparator;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * Strings represent an immutable set of characters. All String literals
+ * are instances of this class, and two string literals with the same contents
+ * refer to the same String object.
+ *
+ * <p>This class also includes a number of methods for manipulating the
+ * contents of strings (of course, creating a new object if there are any
+ * changes, as String is immutable). Case mapping relies on Unicode 3.0.0
+ * standards, where some character sequences have a different number of
+ * characters in the uppercase version than the lower case.
+ *
+ * <p>Strings are special, in that they are the only object with an overloaded
+ * operator. When you use '+' with at least one String argument, both
+ * arguments have String conversion performed on them, and another String (not
+ * guaranteed to be unique) results.
+ *
+ * <p>String is special-cased when doing data serialization - rather than
+ * listing the fields of this class, a String object is converted to a string
+ * literal in the object stream.
+ *
+ * @author Paul N. Fisher
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Per Bothner (bothner@cygnus.com)
+ * @since 1.0
+ * @status updated to 1.4; but could use better data sharing via offset field
+ */
+public final class String implements Serializable, Comparable, CharSequence
+{
+ // WARNING: String is a CORE class in the bootstrap cycle. See the comments
+ // in vm/reference/java/lang/Runtime for implications of this fact.
+
+ /**
+ * This is probably not necessary because this class is special cased already
+ * but it will avoid showing up as a discrepancy when comparing SUIDs.
+ */
+ private static final long serialVersionUID = -6849794470754667710L;
+
+ /**
+ * Stores unicode multi-character uppercase expansion table.
+ * @see #toUpperCase(char)
+ * @see CharData#UPPER_EXPAND
+ */
+ private static final char[] upperExpand
+ = zeroBasedStringValue(CharData.UPPER_EXPAND);
+
+ /**
+ * Stores unicode multi-character uppercase special casing table.
+ * @see #upperCaseExpansion(char)
+ * @see CharData#UPPER_SPECIAL
+ */
+ private static final char[] upperSpecial
+ = zeroBasedStringValue(CharData.UPPER_SPECIAL);
+
+ /**
+ * Characters which make up the String.
+ * Package access is granted for use by StringBuffer.
+ */
+ final char[] value;
+
+ /**
+ * Holds the number of characters in value. This number is generally
+ * the same as value.length, but can be smaller because substrings and
+ * StringBuffers can share arrays. Package visible for use by trusted code.
+ */
+ final int count;
+
+ /**
+ * Caches the result of hashCode(). If this value is zero, the hashcode
+ * is considered uncached (even if 0 is the correct hash value).
+ */
+ private int cachedHashCode;
+
+ /**
+ * Holds the starting position for characters in value[]. Since
+ * substring()'s are common, the use of offset allows the operation
+ * to perform in O(1). Package access is granted for use by StringBuffer.
+ */
+ final int offset;
+
+ /**
+ * An implementation for {@link CASE_INSENSITIVE_ORDER}.
+ * This must be {@link Serializable}. The class name is dictated by
+ * compatibility with Sun's JDK.
+ */
+ private static final class CaseInsensitiveComparator
+ implements Comparator, Serializable
+ {
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = 8575799808933029326L;
+
+ /**
+ * The default private constructor generates unnecessary overhead.
+ */
+ CaseInsensitiveComparator() {}
+
+ /**
+ * Compares to Strings, using
+ * <code>String.compareToIgnoreCase(String)</code>.
+ *
+ * @param o1 the first string
+ * @param o2 the second string
+ * @return &lt; 0, 0, or &gt; 0 depending on the case-insensitive
+ * comparison of the two strings.
+ * @throws NullPointerException if either argument is null
+ * @throws ClassCastException if either argument is not a String
+ * @see #compareToIgnoreCase(String)
+ */
+ public int compare(Object o1, Object o2)
+ {
+ return ((String) o1).compareToIgnoreCase((String) o2);
+ }
+ } // class CaseInsensitiveComparator
+
+ /**
+ * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>.
+ * This comparator is {@link Serializable}. Note that it ignores Locale,
+ * for that, you want a Collator.
+ *
+ * @see Collator#compare(String, String)
+ * @since 1.2
+ */
+ public static final Comparator CASE_INSENSITIVE_ORDER
+ = new CaseInsensitiveComparator();
+
+ /**
+ * Creates an empty String (length 0). Unless you really need a new object,
+ * consider using <code>""</code> instead.
+ */
+ public String()
+ {
+ value = "".value;
+ offset = 0;
+ count = 0;
+ }
+
+ /**
+ * Copies the contents of a String to a new String. Since Strings are
+ * immutable, only a shallow copy is performed.
+ *
+ * @param str String to copy
+ * @throws NullPointerException if value is null
+ */
+ public String(String str)
+ {
+ value = str.value;
+ offset = str.offset;
+ count = str.count;
+ cachedHashCode = str.cachedHashCode;
+ }
+
+ /**
+ * Creates a new String using the character sequence of the char array.
+ * Subsequent changes to data do not affect the String.
+ *
+ * @param data char array to copy
+ * @throws NullPointerException if data is null
+ */
+ public String(char[] data)
+ {
+ this(data, 0, data.length, false);
+ }
+
+ /**
+ * Creates a new String using the character sequence of a subarray of
+ * characters. The string starts at offset, and copies count chars.
+ * Subsequent changes to data do not affect the String.
+ *
+ * @param data char array to copy
+ * @param offset position (base 0) to start copying out of data
+ * @param count the number of characters from data to copy
+ * @throws NullPointerException if data is null
+ * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
+ * || offset + count &gt; data.length)
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public String(char[] data, int offset, int count)
+ {
+ this(data, offset, count, false);
+ }
+
+ /**
+ * Creates a new String using an 8-bit array of integer values, starting at
+ * an offset, and copying up to the count. Each character c, using
+ * corresponding byte b, is created in the new String as if by performing:
+ *
+ * <pre>
+ * c = (char) (((hibyte &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))
+ * </pre>
+ *
+ * @param ascii array of integer values
+ * @param hibyte top byte of each Unicode character
+ * @param offset position (base 0) to start copying out of ascii
+ * @param count the number of characters from ascii to copy
+ * @throws NullPointerException if ascii is null
+ * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
+ * || offset + count &gt; ascii.length)
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ * @see #String(byte[])
+ * @see #String(byte[], String)
+ * @see #String(byte[], int, int)
+ * @see #String(byte[], int, int, String)
+ * @deprecated use {@link #String(byte[], int, int, String)} to perform
+ * correct encoding
+ */
+ public String(byte[] ascii, int hibyte, int offset, int count)
+ {
+ if (offset < 0 || count < 0 || offset + count > ascii.length)
+ throw new StringIndexOutOfBoundsException();
+ value = new char[count];
+ this.offset = 0;
+ this.count = count;
+ hibyte <<= 8;
+ offset += count;
+ while (--count >= 0)
+ value[count] = (char) (hibyte | (ascii[--offset] & 0xff));
+ }
+
+ /**
+ * Creates a new String using an 8-bit array of integer values. Each
+ * character c, using corresponding byte b, is created in the new String
+ * as if by performing:
+ *
+ * <pre>
+ * c = (char) (((hibyte &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))
+ * </pre>
+ *
+ * @param ascii array of integer values
+ * @param hibyte top byte of each Unicode character
+ * @throws NullPointerException if ascii is null
+ * @see #String(byte[])
+ * @see #String(byte[], String)
+ * @see #String(byte[], int, int)
+ * @see #String(byte[], int, int, String)
+ * @see #String(byte[], int, int, int)
+ * @deprecated use {@link #String(byte[], String)} to perform
+ * correct encoding
+ */
+ public String(byte[] ascii, int hibyte)
+ {
+ this(ascii, hibyte, 0, ascii.length);
+ }
+
+ /**
+ * Creates a new String using the portion of the byte array starting at the
+ * offset and ending at offset + count. Uses the specified encoding type
+ * to decode the byte array, so the resulting string may be longer or
+ * shorter than the byte array. For more decoding control, use
+ * {@link java.nio.charset.CharsetDecoder}, and for valid character sets,
+ * see {@link java.nio.charset.Charset}. The behavior is not specified if
+ * the decoder encounters invalid characters; this implementation throws
+ * an Error.
+ *
+ * @param data byte array to copy
+ * @param offset the offset to start at
+ * @param count the number of bytes in the array to use
+ * @param encoding the name of the encoding to use
+ * @throws NullPointerException if data or encoding is null
+ * @throws IndexOutOfBoundsException if offset or count is incorrect
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ * @throws UnsupportedEncodingException if encoding is not found
+ * @throws Error if the decoding fails
+ * @since 1.1
+ */
+ public String(byte[] data, int offset, int count, String encoding)
+ throws UnsupportedEncodingException
+ {
+ if (offset < 0 || count < 0 || offset + count > data.length)
+ throw new StringIndexOutOfBoundsException();
+ try
+ {
+ CharsetDecoder csd = Charset.forName(encoding).newDecoder();
+ csd.onMalformedInput(CodingErrorAction.REPLACE);
+ csd.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count));
+ if(cbuf.hasArray())
+ {
+ value = cbuf.array();
+ this.offset = cbuf.position();
+ this.count = cbuf.remaining();
+ } else {
+ // Doubt this will happen. But just in case.
+ value = new char[cbuf.remaining()];
+ cbuf.get(value);
+ this.offset = 0;
+ this.count = value.length;
+ }
+ } catch(CharacterCodingException e){
+ throw new UnsupportedEncodingException("Encoding: "+encoding+
+ " not found.");
+ } catch(IllegalCharsetNameException e){
+ throw new UnsupportedEncodingException("Encoding: "+encoding+
+ " not found.");
+ } catch(UnsupportedCharsetException e){
+ throw new UnsupportedEncodingException("Encoding: "+encoding+
+ " not found.");
+ }
+ }
+
+ /**
+ * Creates a new String using the byte array. Uses the specified encoding
+ * type to decode the byte array, so the resulting string may be longer or
+ * shorter than the byte array. For more decoding control, use
+ * {@link java.nio.charset.CharsetDecoder}, and for valid character sets,
+ * see {@link java.nio.charset.Charset}. The behavior is not specified if
+ * the decoder encounters invalid characters; this implementation throws
+ * an Error.
+ *
+ * @param data byte array to copy
+ * @param encoding the name of the encoding to use
+ * @throws NullPointerException if data or encoding is null
+ * @throws UnsupportedEncodingException if encoding is not found
+ * @throws Error if the decoding fails
+ * @see #String(byte[], int, int, String)
+ * @since 1.1
+ */
+ public String(byte[] data, String encoding)
+ throws UnsupportedEncodingException
+ {
+ this(data, 0, data.length, encoding);
+ }
+
+ /**
+ * Creates a new String using the portion of the byte array starting at the
+ * offset and ending at offset + count. Uses the encoding of the platform's
+ * default charset, so the resulting string may be longer or shorter than
+ * the byte array. For more decoding control, use
+ * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified
+ * if the decoder encounters invalid characters; this implementation throws
+ * an Error.
+ *
+ * @param data byte array to copy
+ * @param offset the offset to start at
+ * @param count the number of bytes in the array to use
+ * @throws NullPointerException if data is null
+ * @throws IndexOutOfBoundsException if offset or count is incorrect
+ * @throws Error if the decoding fails
+ * @see #String(byte[], int, int, String)
+ * @since 1.1
+ */
+ public String(byte[] data, int offset, int count)
+ {
+ if (offset < 0 || count < 0 || offset + count > data.length)
+ throw new StringIndexOutOfBoundsException();
+ int o, c;
+ char[] v;
+ String encoding;
+ try
+ {
+ encoding = System.getProperty("file.encoding");
+ CharsetDecoder csd = Charset.forName(encoding).newDecoder();
+ csd.onMalformedInput(CodingErrorAction.REPLACE);
+ csd.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count));
+ if(cbuf.hasArray())
+ {
+ v = cbuf.array();
+ o = cbuf.position();
+ c = cbuf.remaining();
+ } else {
+ // Doubt this will happen. But just in case.
+ v = new char[cbuf.remaining()];
+ cbuf.get(v);
+ o = 0;
+ c = v.length;
+ }
+ } catch(Exception ex){
+ // If anything goes wrong (System property not set,
+ // NIO provider not available, etc)
+ // Default to the 'safe' encoding ISO8859_1
+ v = new char[count];
+ o = 0;
+ c = count;
+ for (int i=0;i<count;i++)
+ v[i] = (char)data[offset+i];
+ }
+ this.value = v;
+ this.offset = o;
+ this.count = c;
+ }
+
+ /**
+ * Creates a new String using the byte array. Uses the encoding of the
+ * platform's default charset, so the resulting string may be longer or
+ * shorter than the byte array. For more decoding control, use
+ * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified
+ * if the decoder encounters invalid characters; this implementation throws
+ * an Error.
+ *
+ * @param data byte array to copy
+ * @throws NullPointerException if data is null
+ * @throws Error if the decoding fails
+ * @see #String(byte[], int, int)
+ * @see #String(byte[], int, int, String)
+ * @since 1.1
+ */
+ public String(byte[] data)
+ {
+ this(data, 0, data.length);
+ }
+
+ /**
+ * Creates a new String using the character sequence represented by
+ * the StringBuffer. Subsequent changes to buf do not affect the String.
+ *
+ * @param buffer StringBuffer to copy
+ * @throws NullPointerException if buffer is null
+ */
+ public String(StringBuffer buffer)
+ {
+ synchronized (buffer)
+ {
+ offset = 0;
+ count = buffer.count;
+ // Share unless buffer is 3/4 empty.
+ if ((count << 2) < buffer.value.length)
+ {
+ value = new char[count];
+ VMSystem.arraycopy(buffer.value, 0, value, 0, count);
+ }
+ else
+ {
+ buffer.shared = true;
+ value = buffer.value;
+ }
+ }
+ }
+
+ /**
+ * Creates a new String using the character sequence represented by
+ * the StringBuilder. Subsequent changes to buf do not affect the String.
+ *
+ * @param buffer StringBuilder to copy
+ * @throws NullPointerException if buffer is null
+ */
+ public String(StringBuilder buffer)
+ {
+ this(buffer.value, 0, buffer.count);
+ }
+
+ /**
+ * Special constructor which can share an array when safe to do so.
+ *
+ * @param data the characters to copy
+ * @param offset the location to start from
+ * @param count the number of characters to use
+ * @param dont_copy true if the array is trusted, and need not be copied
+ * @throws NullPointerException if chars is null
+ * @throws StringIndexOutOfBoundsException if bounds check fails
+ */
+ String(char[] data, int offset, int count, boolean dont_copy)
+ {
+ if (offset < 0 || count < 0 || offset + count > data.length)
+ throw new StringIndexOutOfBoundsException();
+ if (dont_copy)
+ {
+ value = data;
+ this.offset = offset;
+ }
+ else
+ {
+ value = new char[count];
+ VMSystem.arraycopy(data, offset, value, 0, count);
+ this.offset = 0;
+ }
+ this.count = count;
+ }
+
+ /**
+ * Returns the number of characters contained in this String.
+ *
+ * @return the length of this String
+ */
+ public int length()
+ {
+ return count;
+ }
+
+ /**
+ * Returns the character located at the specified index within this String.
+ *
+ * @param index position of character to return (base 0)
+ * @return character located at position index
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= length()
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public char charAt(int index)
+ {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException(index);
+ return value[offset + index];
+ }
+
+ /**
+ * Copies characters from this String starting at a specified start index,
+ * ending at a specified stop index, to a character array starting at
+ * a specified destination begin index.
+ *
+ * @param srcBegin index to begin copying characters from this String
+ * @param srcEnd index after the last character to be copied from this String
+ * @param dst character array which this String is copied into
+ * @param dstBegin index to start writing characters into dst
+ * @throws NullPointerException if dst is null
+ * @throws IndexOutOfBoundsException if any indices are out of bounds
+ * (while unspecified, source problems cause a
+ * StringIndexOutOfBoundsException, and dst problems cause an
+ * ArrayIndexOutOfBoundsException)
+ */
+ public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
+ {
+ if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count)
+ throw new StringIndexOutOfBoundsException();
+ VMSystem.arraycopy(value, srcBegin + offset,
+ dst, dstBegin, srcEnd - srcBegin);
+ }
+
+ /**
+ * Copies the low byte of each character from this String starting at a
+ * specified start index, ending at a specified stop index, to a byte array
+ * starting at a specified destination begin index.
+ *
+ * @param srcBegin index to being copying characters from this String
+ * @param srcEnd index after the last character to be copied from this String
+ * @param dst byte array which each low byte of this String is copied into
+ * @param dstBegin index to start writing characters into dst
+ * @throws NullPointerException if dst is null and copy length is non-zero
+ * @throws IndexOutOfBoundsException if any indices are out of bounds
+ * (while unspecified, source problems cause a
+ * StringIndexOutOfBoundsException, and dst problems cause an
+ * ArrayIndexOutOfBoundsException)
+ * @see #getBytes()
+ * @see #getBytes(String)
+ * @deprecated use {@link #getBytes()}, which uses a char to byte encoder
+ */
+ public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin)
+ {
+ if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count)
+ throw new StringIndexOutOfBoundsException();
+ int i = srcEnd - srcBegin;
+ srcBegin += offset;
+ while (--i >= 0)
+ dst[dstBegin++] = (byte) value[srcBegin++];
+ }
+
+ /**
+ * Converts the Unicode characters in this String to a byte array. Uses the
+ * specified encoding method, so the result may be longer or shorter than
+ * the String. For more encoding control, use
+ * {@link java.nio.charset.CharsetEncoder}, and for valid character sets,
+ * see {@link java.nio.charset.Charset}. Unsupported characters get
+ * replaced by an encoding specific byte.
+ *
+ * @param enc encoding name
+ * @return the resulting byte array
+ * @throws NullPointerException if enc is null
+ * @throws UnsupportedEncodingException if encoding is not supported
+ * @since 1.1
+ */
+ public byte[] getBytes(String enc) throws UnsupportedEncodingException
+ {
+ try
+ {
+ CharsetEncoder cse = Charset.forName(enc).newEncoder();
+ cse.onMalformedInput(CodingErrorAction.REPLACE);
+ cse.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ ByteBuffer bbuf = cse.encode(CharBuffer.wrap(value, offset, count));
+ if(bbuf.hasArray())
+ return bbuf.array();
+
+ // Doubt this will happen. But just in case.
+ byte[] bytes = new byte[bbuf.remaining()];
+ bbuf.get(bytes);
+ return bytes;
+
+ } catch(IllegalCharsetNameException e){
+ throw new UnsupportedEncodingException("Encoding: "+enc+
+ " not found.");
+ } catch(UnsupportedCharsetException e){
+ throw new UnsupportedEncodingException("Encoding: "+enc+
+ " not found.");
+ } catch(CharacterCodingException e){
+ // XXX - Ignore coding exceptions? They shouldn't really happen.
+ return null;
+ }
+ }
+
+ /**
+ * Converts the Unicode characters in this String to a byte array. Uses the
+ * encoding of the platform's default charset, so the result may be longer
+ * or shorter than the String. For more encoding control, use
+ * {@link java.nio.charset.CharsetEncoder}. Unsupported characters get
+ * replaced by an encoding specific byte.
+ *
+ * @return the resulting byte array, or null on a problem
+ * @since 1.1
+ */
+ public byte[] getBytes()
+ {
+ try
+ {
+ return getBytes(System.getProperty("file.encoding"));
+ } catch(Exception e) {
+ // XXX - Throw an error here?
+ // For now, default to the 'safe' encoding.
+ byte[] bytes = new byte[count];
+ for(int i=0;i<count;i++)
+ bytes[i] = (byte)((value[offset+i] <= 0xFF)?
+ value[offset+i]:'?');
+ return bytes;
+ }
+ }
+
+ /**
+ * Predicate which compares anObject to this. This is true only for Strings
+ * with the same character sequence.
+ *
+ * @param anObject the object to compare
+ * @return true if anObject is semantically equal to this
+ * @see #compareTo(String)
+ * @see #equalsIgnoreCase(String)
+ */
+ public boolean equals(Object anObject)
+ {
+ if (! (anObject instanceof String))
+ return false;
+ String str2 = (String) anObject;
+ if (count != str2.count)
+ return false;
+ if (value == str2.value && offset == str2.offset)
+ return true;
+ int i = count;
+ int x = offset;
+ int y = str2.offset;
+ while (--i >= 0)
+ if (value[x++] != str2.value[y++])
+ return false;
+ return true;
+ }
+
+ /**
+ * Compares the given StringBuffer to this String. This is true if the
+ * StringBuffer has the same content as this String at this moment.
+ *
+ * @param buffer the StringBuffer to compare to
+ * @return true if StringBuffer has the same character sequence
+ * @throws NullPointerException if the given StringBuffer is null
+ * @since 1.4
+ */
+ public boolean contentEquals(StringBuffer buffer)
+ {
+ synchronized (buffer)
+ {
+ if (count != buffer.count)
+ return false;
+ if (value == buffer.value)
+ return true; // Possible if shared.
+ int i = count;
+ int x = offset + count;
+ while (--i >= 0)
+ if (value[--x] != buffer.value[i])
+ return false;
+ return true;
+ }
+ }
+
+ /**
+ * Compares a String to this String, ignoring case. This does not handle
+ * multi-character capitalization exceptions; instead the comparison is
+ * made on a character-by-character basis, and is true if:<br><ul>
+ * <li><code>c1 == c2</code></li>
+ * <li><code>Character.toUpperCase(c1)
+ * == Character.toUpperCase(c2)</code></li>
+ * <li><code>Character.toLowerCase(c1)
+ * == Character.toLowerCase(c2)</code></li>
+ * </ul>
+ *
+ * @param anotherString String to compare to this String
+ * @return true if anotherString is equal, ignoring case
+ * @see #equals(Object)
+ * @see Character#toUpperCase(char)
+ * @see Character#toLowerCase(char)
+ */
+ public boolean equalsIgnoreCase(String anotherString)
+ {
+ if (anotherString == null || count != anotherString.count)
+ return false;
+ int i = count;
+ int x = offset;
+ int y = anotherString.offset;
+ while (--i >= 0)
+ {
+ char c1 = value[x++];
+ char c2 = anotherString.value[y++];
+ // Note that checking c1 != c2 is redundant, but avoids method calls.
+ if (c1 != c2
+ && Character.toUpperCase(c1) != Character.toUpperCase(c2)
+ && Character.toLowerCase(c1) != Character.toLowerCase(c2))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares this String and another String (case sensitive,
+ * lexicographically). The result is less than 0 if this string sorts
+ * before the other, 0 if they are equal, and greater than 0 otherwise.
+ * After any common starting sequence is skipped, the result is
+ * <code>this.charAt(k) - anotherString.charAt(k)</code> if both strings
+ * have characters remaining, or
+ * <code>this.length() - anotherString.length()</code> if one string is
+ * a subsequence of the other.
+ *
+ * @param anotherString the String to compare against
+ * @return the comparison
+ * @throws NullPointerException if anotherString is null
+ */
+ public int compareTo(String anotherString)
+ {
+ int i = Math.min(count, anotherString.count);
+ int x = offset;
+ int y = anotherString.offset;
+ while (--i >= 0)
+ {
+ int result = value[x++] - anotherString.value[y++];
+ if (result != 0)
+ return result;
+ }
+ return count - anotherString.count;
+ }
+
+ /**
+ * Behaves like <code>compareTo(java.lang.String)</code> unless the Object
+ * is not a <code>String</code>. Then it throws a
+ * <code>ClassCastException</code>.
+ *
+ * @param o the object to compare against
+ * @return the comparison
+ * @throws NullPointerException if o is null
+ * @throws ClassCastException if o is not a <code>String</code>
+ * @since 1.2
+ */
+ public int compareTo(Object o)
+ {
+ return compareTo((String) o);
+ }
+
+ /**
+ * Compares this String and another String (case insensitive). This
+ * comparison is <em>similar</em> to equalsIgnoreCase, in that it ignores
+ * locale and multi-characater capitalization, and compares characters
+ * after performing
+ * <code>Character.toLowerCase(Character.toUpperCase(c))</code> on each
+ * character of the string. This is unsatisfactory for locale-based
+ * comparison, in which case you should use {@link java.text.Collator}.
+ *
+ * @param str the string to compare against
+ * @return the comparison
+ * @see Collator#compare(String, String)
+ * @since 1.2
+ */
+ public int compareToIgnoreCase(String str)
+ {
+ int i = Math.min(count, str.count);
+ int x = offset;
+ int y = str.offset;
+ while (--i >= 0)
+ {
+ int result = Character.toLowerCase(Character.toUpperCase(value[x++]))
+ - Character.toLowerCase(Character.toUpperCase(str.value[y++]));
+ if (result != 0)
+ return result;
+ }
+ return count - str.count;
+ }
+
+ /**
+ * Predicate which determines if this String matches another String
+ * starting at a specified offset for each String and continuing
+ * for a specified length. Indices out of bounds are harmless, and give
+ * a false result.
+ *
+ * @param toffset index to start comparison at for this String
+ * @param other String to compare region to this String
+ * @param ooffset index to start comparison at for other
+ * @param len number of characters to compare
+ * @return true if regions match (case sensitive)
+ * @throws NullPointerException if other is null
+ */
+ public boolean regionMatches(int toffset, String other, int ooffset, int len)
+ {
+ return regionMatches(false, toffset, other, ooffset, len);
+ }
+
+ /**
+ * Predicate which determines if this String matches another String
+ * starting at a specified offset for each String and continuing
+ * for a specified length, optionally ignoring case. Indices out of bounds
+ * are harmless, and give a false result. Case comparisons are based on
+ * <code>Character.toLowerCase()</code> and
+ * <code>Character.toUpperCase()</code>, not on multi-character
+ * capitalization expansions.
+ *
+ * @param ignoreCase true if case should be ignored in comparision
+ * @param toffset index to start comparison at for this String
+ * @param other String to compare region to this String
+ * @param ooffset index to start comparison at for other
+ * @param len number of characters to compare
+ * @return true if regions match, false otherwise
+ * @throws NullPointerException if other is null
+ */
+ public boolean regionMatches(boolean ignoreCase, int toffset,
+ String other, int ooffset, int len)
+ {
+ if (toffset < 0 || ooffset < 0 || toffset + len > count
+ || ooffset + len > other.count)
+ return false;
+ toffset += offset;
+ ooffset += other.offset;
+ while (--len >= 0)
+ {
+ char c1 = value[toffset++];
+ char c2 = other.value[ooffset++];
+ // Note that checking c1 != c2 is redundant when ignoreCase is true,
+ // but it avoids method calls.
+ if (c1 != c2
+ && (! ignoreCase
+ || (Character.toLowerCase(c1) != Character.toLowerCase(c2)
+ && (Character.toUpperCase(c1)
+ != Character.toUpperCase(c2)))))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Predicate which determines if this String contains the given prefix,
+ * beginning comparison at toffset. The result is false if toffset is
+ * negative or greater than this.length(), otherwise it is the same as
+ * <code>this.substring(toffset).startsWith(prefix)</code>.
+ *
+ * @param prefix String to compare
+ * @param toffset offset for this String where comparison starts
+ * @return true if this String starts with prefix
+ * @throws NullPointerException if prefix is null
+ * @see #regionMatches(boolean, int, String, int, int)
+ */
+ public boolean startsWith(String prefix, int toffset)
+ {
+ return regionMatches(false, toffset, prefix, 0, prefix.count);
+ }
+
+ /**
+ * Predicate which determines if this String starts with a given prefix.
+ * If the prefix is an empty String, true is returned.
+ *
+ * @param prefix String to compare
+ * @return true if this String starts with the prefix
+ * @throws NullPointerException if prefix is null
+ * @see #startsWith(String, int)
+ */
+ public boolean startsWith(String prefix)
+ {
+ return regionMatches(false, 0, prefix, 0, prefix.count);
+ }
+
+ /**
+ * Predicate which determines if this String ends with a given suffix.
+ * If the suffix is an empty String, true is returned.
+ *
+ * @param suffix String to compare
+ * @return true if this String ends with the suffix
+ * @throws NullPointerException if suffix is null
+ * @see #regionMatches(boolean, int, String, int, int)
+ */
+ public boolean endsWith(String suffix)
+ {
+ return regionMatches(false, count - suffix.count, suffix, 0, suffix.count);
+ }
+
+ /**
+ * Computes the hashcode for this String. This is done with int arithmetic,
+ * where ** represents exponentiation, by this formula:<br>
+ * <code>s[0]*31**(n-1) + s[1]*31**(n-2) + ... + s[n-1]</code>.
+ *
+ * @return hashcode value of this String
+ */
+ public int hashCode()
+ {
+ if (cachedHashCode != 0)
+ return cachedHashCode;
+
+ // Compute the hash code using a local variable to be reentrant.
+ int hashCode = 0;
+ int limit = count + offset;
+ for (int i = offset; i < limit; i++)
+ hashCode = hashCode * 31 + value[i];
+ return cachedHashCode = hashCode;
+ }
+
+ /**
+ * Finds the first instance of a character in this String.
+ *
+ * @param ch character to find
+ * @return location (base 0) of the character, or -1 if not found
+ */
+ public int indexOf(int ch)
+ {
+ return indexOf(ch, 0);
+ }
+
+ /**
+ * Finds the first instance of a character in this String, starting at
+ * a given index. If starting index is less than 0, the search
+ * starts at the beginning of this String. If the starting index
+ * is greater than the length of this String, -1 is returned.
+ *
+ * @param ch character to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the character, or -1 if not found
+ */
+ public int indexOf(int ch, int fromIndex)
+ {
+ if ((char) ch != ch)
+ return -1;
+ if (fromIndex < 0)
+ fromIndex = 0;
+ int i = fromIndex + offset;
+ for ( ; fromIndex < count; fromIndex++)
+ if (value[i++] == ch)
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Finds the last instance of a character in this String.
+ *
+ * @param ch character to find
+ * @return location (base 0) of the character, or -1 if not found
+ */
+ public int lastIndexOf(int ch)
+ {
+ return lastIndexOf(ch, count - 1);
+ }
+
+ /**
+ * Finds the last instance of a character in this String, starting at
+ * a given index. If starting index is greater than the maximum valid
+ * index, then the search begins at the end of this String. If the
+ * starting index is less than zero, -1 is returned.
+ *
+ * @param ch character to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the character, or -1 if not found
+ */
+ public int lastIndexOf(int ch, int fromIndex)
+ {
+ if ((char) ch != ch)
+ return -1;
+ if (fromIndex >= count)
+ fromIndex = count - 1;
+ int i = fromIndex + offset;
+ for ( ; fromIndex >= 0; fromIndex--)
+ if (value[i--] == ch)
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Finds the first instance of a String in this String.
+ *
+ * @param str String to find
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ */
+ public int indexOf(String str)
+ {
+ return indexOf(str, 0);
+ }
+
+ /**
+ * Finds the first instance of a String in this String, starting at
+ * a given index. If starting index is less than 0, the search
+ * starts at the beginning of this String. If the starting index
+ * is greater than the length of this String, -1 is returned.
+ *
+ * @param str String to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ */
+ public int indexOf(String str, int fromIndex)
+ {
+ if (fromIndex < 0)
+ fromIndex = 0;
+ int limit = count - str.count;
+ for ( ; fromIndex <= limit; fromIndex++)
+ if (regionMatches(fromIndex, str, 0, str.count))
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Finds the last instance of a String in this String.
+ *
+ * @param str String to find
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ */
+ public int lastIndexOf(String str)
+ {
+ return lastIndexOf(str, count - str.count);
+ }
+
+ /**
+ * Finds the last instance of a String in this String, starting at
+ * a given index. If starting index is greater than the maximum valid
+ * index, then the search begins at the end of this String. If the
+ * starting index is less than zero, -1 is returned.
+ *
+ * @param str String to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ */
+ public int lastIndexOf(String str, int fromIndex)
+ {
+ fromIndex = Math.min(fromIndex, count - str.count);
+ for ( ; fromIndex >= 0; fromIndex--)
+ if (regionMatches(fromIndex, str, 0, str.count))
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Creates a substring of this String, starting at a specified index
+ * and ending at the end of this String.
+ *
+ * @param begin index to start substring (base 0)
+ * @return new String which is a substring of this String
+ * @throws IndexOutOfBoundsException if begin &lt; 0 || begin &gt; length()
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public String substring(int begin)
+ {
+ return substring(begin, count);
+ }
+
+ /**
+ * Creates a substring of this String, starting at a specified index
+ * and ending at one character before a specified index.
+ *
+ * @param beginIndex index to start substring (inclusive, base 0)
+ * @param endIndex index to end at (exclusive)
+ * @return new String which is a substring of this String
+ * @throws IndexOutOfBoundsException if begin &lt; 0 || end &gt; length()
+ * || begin &gt; end (while unspecified, this is a
+ * StringIndexOutOfBoundsException)
+ */
+ public String substring(int beginIndex, int endIndex)
+ {
+ if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
+ throw new StringIndexOutOfBoundsException();
+ if (beginIndex == 0 && endIndex == count)
+ return this;
+ int len = endIndex - beginIndex;
+ // Package constructor avoids an array copy.
+ return new String(value, beginIndex + offset, len,
+ (len << 2) >= value.length);
+ }
+
+ /**
+ * Creates a substring of this String, starting at a specified index
+ * and ending at one character before a specified index. This behaves like
+ * <code>substring(begin, end)</code>.
+ *
+ * @param begin index to start substring (inclusive, base 0)
+ * @param end index to end at (exclusive)
+ * @return new String which is a substring of this String
+ * @throws IndexOutOfBoundsException if begin &lt; 0 || end &gt; length()
+ * || begin &gt; end
+ * @since 1.4
+ */
+ public CharSequence subSequence(int begin, int end)
+ {
+ return substring(begin, end);
+ }
+
+ /**
+ * Concatenates a String to this String. This results in a new string unless
+ * one of the two originals is "".
+ *
+ * @param str String to append to this String
+ * @return newly concatenated String
+ * @throws NullPointerException if str is null
+ */
+ public String concat(String str)
+ {
+ if (str.count == 0)
+ return this;
+ if (count == 0)
+ return str;
+ char[] newStr = new char[count + str.count];
+ VMSystem.arraycopy(value, offset, newStr, 0, count);
+ VMSystem.arraycopy(str.value, str.offset, newStr, count, str.count);
+ // Package constructor avoids an array copy.
+ return new String(newStr, 0, newStr.length, true);
+ }
+
+ /**
+ * Replaces every instance of a character in this String with a new
+ * character. If no replacements occur, this is returned.
+ *
+ * @param oldChar the old character to replace
+ * @param newChar the new character
+ * @return new String with all instances of oldChar replaced with newChar
+ */
+ public String replace(char oldChar, char newChar)
+ {
+ if (oldChar == newChar)
+ return this;
+ int i = count;
+ int x = offset - 1;
+ while (--i >= 0)
+ if (value[++x] == oldChar)
+ break;
+ if (i < 0)
+ return this;
+ char[] newStr = (char[]) value.clone();
+ newStr[x] = newChar;
+ while (--i >= 0)
+ if (value[++x] == oldChar)
+ newStr[x] = newChar;
+ // Package constructor avoids an array copy.
+ return new String(newStr, offset, count, true);
+ }
+
+ /**
+ * Test if this String matches a regular expression. This is shorthand for
+ * <code>{@link Pattern}.matches(regex, this)</code>.
+ *
+ * @param regex the pattern to match
+ * @return true if the pattern matches
+ * @throws NullPointerException if regex is null
+ * @throws PatternSyntaxException if regex is invalid
+ * @see Pattern#matches(String, CharSequence)
+ * @since 1.4
+ */
+ public boolean matches(String regex)
+ {
+ return Pattern.matches(regex, this);
+ }
+
+ /**
+ * Replaces the first substring match of the regular expression with a
+ * given replacement. This is shorthand for <code>{@link Pattern}
+ * .compile(regex).matcher(this).replaceFirst(replacement)</code>.
+ *
+ * @param regex the pattern to match
+ * @param replacement the replacement string
+ * @return the modified string
+ * @throws NullPointerException if regex or replacement is null
+ * @throws PatternSyntaxException if regex is invalid
+ * @see #replaceAll(String, String)
+ * @see Pattern#compile(String)
+ * @see Pattern#matcher(CharSequence)
+ * @see Matcher#replaceFirst(String)
+ * @since 1.4
+ */
+ public String replaceFirst(String regex, String replacement)
+ {
+ return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
+ }
+
+ /**
+ * Replaces all matching substrings of the regular expression with a
+ * given replacement. This is shorthand for <code>{@link Pattern}
+ * .compile(regex).matcher(this).replaceAll(replacement)</code>.
+ *
+ * @param regex the pattern to match
+ * @param replacement the replacement string
+ * @return the modified string
+ * @throws NullPointerException if regex or replacement is null
+ * @throws PatternSyntaxException if regex is invalid
+ * @see #replaceFirst(String, String)
+ * @see Pattern#compile(String)
+ * @see Pattern#matcher(CharSequence)
+ * @see Matcher#replaceAll(String)
+ * @since 1.4
+ */
+ public String replaceAll(String regex, String replacement)
+ {
+ return Pattern.compile(regex).matcher(this).replaceAll(replacement);
+ }
+
+ /**
+ * Split this string around the matches of a regular expression. Each
+ * element of the returned array is the largest block of characters not
+ * terminated by the regular expression, in the order the matches are found.
+ *
+ * <p>The limit affects the length of the array. If it is positive, the
+ * array will contain at most n elements (n - 1 pattern matches). If
+ * negative, the array length is unlimited, but there can be trailing empty
+ * entries. if 0, the array length is unlimited, and trailing empty entries
+ * are discarded.
+ *
+ * <p>For example, splitting "boo:and:foo" yields:<br>
+ * <table border=0>
+ * <th><td>Regex</td> <td>Limit</td> <td>Result</td></th>
+ * <tr><td>":"</td> <td>2</td> <td>{ "boo", "and:foo" }</td></tr>
+ * <tr><td>":"</td> <td>t</td> <td>{ "boo", "and", "foo" }</td></tr>
+ * <tr><td>":"</td> <td>-2</td> <td>{ "boo", "and", "foo" }</td></tr>
+ * <tr><td>"o"</td> <td>5</td> <td>{ "b", "", ":and:f", "", "" }</td></tr>
+ * <tr><td>"o"</td> <td>-2</td> <td>{ "b", "", ":and:f", "", "" }</td></tr>
+ * <tr><td>"o"</td> <td>0</td> <td>{ "b", "", ":and:f" }</td></tr>
+ * </table>
+ *
+ * <p>This is shorthand for
+ * <code>{@link Pattern}.compile(regex).split(this, limit)</code>.
+ *
+ * @param regex the pattern to match
+ * @param limit the limit threshold
+ * @return the array of split strings
+ * @throws NullPointerException if regex or replacement is null
+ * @throws PatternSyntaxException if regex is invalid
+ * @see Pattern#compile(String)
+ * @see Pattern#split(CharSequence, int)
+ * @since 1.4
+ */
+ public String[] split(String regex, int limit)
+ {
+ return Pattern.compile(regex).split(this, limit);
+ }
+
+ /**
+ * Split this string around the matches of a regular expression. Each
+ * element of the returned array is the largest block of characters not
+ * terminated by the regular expression, in the order the matches are found.
+ * The array length is unlimited, and trailing empty entries are discarded,
+ * as though calling <code>split(regex, 0)</code>.
+ *
+ * @param regex the pattern to match
+ * @return the array of split strings
+ * @throws NullPointerException if regex or replacement is null
+ * @throws PatternSyntaxException if regex is invalid
+ * @see #split(String, int)
+ * @see Pattern#compile(String)
+ * @see Pattern#split(CharSequence, int)
+ * @since 1.4
+ */
+ public String[] split(String regex)
+ {
+ return Pattern.compile(regex).split(this, 0);
+ }
+
+ /**
+ * Lowercases this String according to a particular locale. This uses
+ * Unicode's special case mappings, as applied to the given Locale, so the
+ * resulting string may be a different length.
+ *
+ * @param loc locale to use
+ * @return new lowercased String, or this if no characters were lowercased
+ * @throws NullPointerException if loc is null
+ * @see #toUpperCase(Locale)
+ * @since 1.1
+ */
+ public String toLowerCase(Locale loc)
+ {
+ // First, see if the current string is already lower case.
+ boolean turkish = "tr".equals(loc.getLanguage());
+ int i = count;
+ int x = offset - 1;
+ while (--i >= 0)
+ {
+ char ch = value[++x];
+ if ((turkish && ch == '\u0049')
+ || ch != Character.toLowerCase(ch))
+ break;
+ }
+ if (i < 0)
+ return this;
+
+ // Now we perform the conversion. Fortunately, there are no multi-character
+ // lowercase expansions in Unicode 3.0.0.
+ char[] newStr = (char[]) value.clone();
+ do
+ {
+ char ch = value[x];
+ // Hardcoded special case.
+ newStr[x++] = (turkish && ch == '\u0049') ? '\u0131'
+ : Character.toLowerCase(ch);
+ }
+ while (--i >= 0);
+ // Package constructor avoids an array copy.
+ return new String(newStr, offset, count, true);
+ }
+
+ /**
+ * Lowercases this String. This uses Unicode's special case mappings, as
+ * applied to the platform's default Locale, so the resulting string may
+ * be a different length.
+ *
+ * @return new lowercased String, or this if no characters were lowercased
+ * @see #toLowerCase(Locale)
+ * @see #toUpperCase()
+ */
+ public String toLowerCase()
+ {
+ return toLowerCase(Locale.getDefault());
+ }
+
+ /**
+ * Uppercases this String according to a particular locale. This uses
+ * Unicode's special case mappings, as applied to the given Locale, so the
+ * resulting string may be a different length.
+ *
+ * @param loc locale to use
+ * @return new uppercased String, or this if no characters were uppercased
+ * @throws NullPointerException if loc is null
+ * @see #toLowerCase(Locale)
+ * @since 1.1
+ */
+ public String toUpperCase(Locale loc)
+ {
+ // First, see how many characters we have to grow by, as well as if the
+ // current string is already upper case.
+ boolean turkish = "tr".equals(loc.getLanguage());
+ int expand = 0;
+ boolean unchanged = true;
+ int i = count;
+ int x = i + offset;
+ while (--i >= 0)
+ {
+ char ch = value[--x];
+ expand += upperCaseExpansion(ch);
+ unchanged = (unchanged && expand == 0
+ && ! (turkish && ch == '\u0069')
+ && ch == Character.toUpperCase(ch));
+ }
+ if (unchanged)
+ return this;
+
+ // Now we perform the conversion.
+ i = count;
+ if (expand == 0)
+ {
+ char[] newStr = (char[]) value.clone();
+ while (--i >= 0)
+ {
+ char ch = value[x];
+ // Hardcoded special case.
+ newStr[x++] = (turkish && ch == '\u0069') ? '\u0130'
+ : Character.toUpperCase(ch);
+ }
+ // Package constructor avoids an array copy.
+ return new String(newStr, offset, count, true);
+ }
+
+ // Expansion is necessary.
+ char[] newStr = new char[count + expand];
+ int j = 0;
+ while (--i >= 0)
+ {
+ char ch = value[x++];
+ // Hardcoded special case.
+ if (turkish && ch == '\u0069')
+ {
+ newStr[j++] = '\u0130';
+ continue;
+ }
+ expand = upperCaseExpansion(ch);
+ if (expand > 0)
+ {
+ int index = upperCaseIndex(ch);
+ while (expand-- >= 0)
+ newStr[j++] = upperExpand[index++];
+ }
+ else
+ newStr[j++] = Character.toUpperCase(ch);
+ }
+ // Package constructor avoids an array copy.
+ return new String(newStr, 0, newStr.length, true);
+ }
+
+ /**
+ * Uppercases this String. This uses Unicode's special case mappings, as
+ * applied to the platform's default Locale, so the resulting string may
+ * be a different length.
+ *
+ * @return new uppercased String, or this if no characters were uppercased
+ * @see #toUpperCase(Locale)
+ * @see #toLowerCase()
+ */
+ public String toUpperCase()
+ {
+ return toUpperCase(Locale.getDefault());
+ }
+
+ /**
+ * Trims all characters less than or equal to <code>'\u0020'</code>
+ * (<code>' '</code>) from the beginning and end of this String. This
+ * includes many, but not all, ASCII control characters, and all
+ * {@link Character#isWhitespace(char)}.
+ *
+ * @return new trimmed String, or this if nothing trimmed
+ */
+ public String trim()
+ {
+ int limit = count + offset;
+ if (count == 0 || (value[offset] > '\u0020'
+ && value[limit - 1] > '\u0020'))
+ return this;
+ int begin = offset;
+ do
+ if (begin == limit)
+ return "";
+ while (value[begin++] <= '\u0020');
+ int end = limit;
+ while (value[--end] <= '\u0020');
+ return substring(begin - offset - 1, end - offset + 1);
+ }
+
+ /**
+ * Returns this, as it is already a String!
+ *
+ * @return this
+ */
+ public String toString()
+ {
+ return this;
+ }
+
+ /**
+ * Copies the contents of this String into a character array. Subsequent
+ * changes to the array do not affect the String.
+ *
+ * @return character array copying the String
+ */
+ public char[] toCharArray()
+ {
+ if (count == value.length)
+ return (char[]) value.clone();
+
+ char[] copy = new char[count];
+ VMSystem.arraycopy(value, offset, copy, 0, count);
+ return copy;
+ }
+
+ /**
+ * Returns a String representation of an Object. This is "null" if the
+ * object is null, otherwise it is <code>obj.toString()</code> (which
+ * can be null).
+ *
+ * @param obj the Object
+ * @return the string conversion of obj
+ */
+ public static String valueOf(Object obj)
+ {
+ return obj == null ? "null" : obj.toString();
+ }
+
+ /**
+ * Returns a String representation of a character array. Subsequent
+ * changes to the array do not affect the String.
+ *
+ * @param data the character array
+ * @return a String containing the same character sequence as data
+ * @throws NullPointerException if data is null
+ * @see #valueOf(char[], int, int)
+ * @see #String(char[])
+ */
+ public static String valueOf(char[] data)
+ {
+ return valueOf (data, 0, data.length);
+ }
+
+ /**
+ * Returns a String representing the character sequence of the char array,
+ * starting at the specified offset, and copying chars up to the specified
+ * count. Subsequent changes to the array do not affect the String.
+ *
+ * @param data character array
+ * @param offset position (base 0) to start copying out of data
+ * @param count the number of characters from data to copy
+ * @return String containing the chars from data[offset..offset+count]
+ * @throws NullPointerException if data is null
+ * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
+ * || offset + count &gt; data.length)
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ * @see #String(char[], int, int)
+ */
+ public static String valueOf(char[] data, int offset, int count)
+ {
+ return new String(data, offset, count, false);
+ }
+
+ /**
+ * Returns a String representing the character sequence of the char array,
+ * starting at the specified offset, and copying chars up to the specified
+ * count. Subsequent changes to the array do not affect the String.
+ *
+ * @param data character array
+ * @param offset position (base 0) to start copying out of data
+ * @param count the number of characters from data to copy
+ * @return String containing the chars from data[offset..offset+count]
+ * @throws NullPointerException if data is null
+ * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
+ * || offset + count &gt; data.length)
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ * @see #String(char[], int, int)
+ */
+ public static String copyValueOf(char[] data, int offset, int count)
+ {
+ return new String(data, offset, count, false);
+ }
+
+ /**
+ * Returns a String representation of a character array. Subsequent
+ * changes to the array do not affect the String.
+ *
+ * @param data the character array
+ * @return a String containing the same character sequence as data
+ * @throws NullPointerException if data is null
+ * @see #copyValueOf(char[], int, int)
+ * @see #String(char[])
+ */
+ public static String copyValueOf(char[] data)
+ {
+ return copyValueOf (data, 0, data.length);
+ }
+
+ /**
+ * Returns a String representing a boolean.
+ *
+ * @param b the boolean
+ * @return "true" if b is true, else "false"
+ */
+ public static String valueOf(boolean b)
+ {
+ return b ? "true" : "false";
+ }
+
+ /**
+ * Returns a String representing a character.
+ *
+ * @param c the character
+ * @return String containing the single character c
+ */
+ public static String valueOf(char c)
+ {
+ // Package constructor avoids an array copy.
+ return new String(new char[] { c }, 0, 1, true);
+ }
+
+ /**
+ * Returns a String representing an integer.
+ *
+ * @param i the integer
+ * @return String containing the integer in base 10
+ * @see Integer#toString(int)
+ */
+ public static String valueOf(int i)
+ {
+ // See Integer to understand why we call the two-arg variant.
+ return Integer.toString(i, 10);
+ }
+
+ /**
+ * Returns a String representing a long.
+ *
+ * @param l the long
+ * @return String containing the long in base 10
+ * @see Long#toString(long)
+ */
+ public static String valueOf(long l)
+ {
+ return Long.toString(l);
+ }
+
+ /**
+ * Returns a String representing a float.
+ *
+ * @param f the float
+ * @return String containing the float
+ * @see Float#toString(float)
+ */
+ public static String valueOf(float f)
+ {
+ return Float.toString(f);
+ }
+
+ /**
+ * Returns a String representing a double.
+ *
+ * @param d the double
+ * @return String containing the double
+ * @see Double#toString(double)
+ */
+ public static String valueOf(double d)
+ {
+ return Double.toString(d);
+ }
+
+ /**
+ * If two Strings are considered equal, by the equals() method,
+ * then intern() will return the same String instance. ie.
+ * if (s1.equals(s2)) then (s1.intern() == s2.intern()).
+ * All string literals and string-valued constant expressions
+ * are already interned.
+ *
+ * @return the interned String
+ */
+ public String intern()
+ {
+ return VMString.intern(this);
+ }
+
+ /**
+ * Helper function used to detect which characters have a multi-character
+ * uppercase expansion. Note that this is only used in locations which
+ * track one-to-many capitalization (java.lang.Character does not do this).
+ * As of Unicode 3.0.0, the result is limited in the range 0 to 2, as the
+ * longest uppercase expansion is three characters (a growth of 2 from the
+ * lowercase character).
+ *
+ * @param ch the char to check
+ * @return the number of characters to add when converting to uppercase
+ * @see CharData#DIRECTION
+ * @see CharData#UPPER_SPECIAL
+ * @see #toUpperCase(Locale)
+ */
+ private static int upperCaseExpansion(char ch)
+ {
+ return Character.direction[Character.readChar(ch) >> 7] & 3;
+ }
+
+ /**
+ * Helper function used to locate the offset in upperExpand given a
+ * character with a multi-character expansion. The binary search is
+ * optimized under the assumption that this method will only be called on
+ * characters which exist in upperSpecial.
+ *
+ * @param ch the char to check
+ * @return the index where its expansion begins
+ * @see CharData#UPPER_SPECIAL
+ * @see CharData#UPPER_EXPAND
+ * @see #toUpperCase(Locale)
+ */
+ private static int upperCaseIndex(char ch)
+ {
+ // Simple binary search for the correct character.
+ int low = 0;
+ int hi = upperSpecial.length - 2;
+ int mid = ((low + hi) >> 2) << 1;
+ char c = upperSpecial[mid];
+ while (ch != c)
+ {
+ if (ch < c)
+ hi = mid - 2;
+ else
+ low = mid + 2;
+ mid = ((low + hi) >> 2) << 1;
+ c = upperSpecial[mid];
+ }
+ return upperSpecial[mid + 1];
+ }
+
+ /**
+ * Returns the value array of the given string if it is zero based or a
+ * copy of it that is zero based (stripping offset and making length equal
+ * to count). Used for accessing the char[]s of gnu.java.lang.CharData.
+ * Package private for use in Character.
+ */
+ static char[] zeroBasedStringValue(String s)
+ {
+ char[] value;
+
+ if (s.offset == 0 && s.count == s.value.length)
+ value = s.value;
+ else
+ {
+ int count = s.count;
+ value = new char[count];
+ VMSystem.arraycopy(s.value, s.offset, value, 0, count);
+ }
+
+ return value;
+ }
+}
diff --git a/libjava/classpath/java/lang/StringBuffer.java b/libjava/classpath/java/lang/StringBuffer.java
new file mode 100644
index 00000000000..94dec4878cb
--- /dev/null
+++ b/libjava/classpath/java/lang/StringBuffer.java
@@ -0,0 +1,931 @@
+/* StringBuffer.java -- Growable strings
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.io.Serializable;
+
+/**
+ * <code>StringBuffer</code> represents a changeable <code>String</code>.
+ * It provides the operations required to modify the
+ * <code>StringBuffer</code>, including insert, replace, delete, append,
+ * and reverse. It is thread-safe; meaning that all modifications to a buffer
+ * are in synchronized methods.
+ *
+ * <p><code>StringBuffer</code>s are variable-length in nature, so even if
+ * you initialize them to a certain size, they can still grow larger than
+ * that. <em>Capacity</em> indicates the number of characters the
+ * <code>StringBuffer</code> can have in it before it has to grow (growing
+ * the char array is an expensive operation involving <code>new</code>).
+ *
+ * <p>Incidentally, compilers often implement the String operator "+"
+ * by using a <code>StringBuffer</code> operation:<br>
+ * <code>a + b</code><br>
+ * is the same as<br>
+ * <code>new StringBuffer().append(a).append(b).toString()</code>.
+ *
+ * <p>Classpath's StringBuffer is capable of sharing memory with Strings for
+ * efficiency. This will help when a StringBuffer is converted to a String
+ * and the StringBuffer is not changed after that (quite common when performing
+ * string concatenation).
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Tom Tromey
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see String
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public final class StringBuffer implements Serializable, CharSequence
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 3388685877147921107L;
+
+ /**
+ * Index of next available character (and thus the size of the current
+ * string contents). Note that this has permissions set this way so that
+ * String can get the value.
+ *
+ * @serial the number of characters in the buffer
+ */
+ int count;
+
+ /**
+ * The buffer. Note that this has permissions set this way so that String
+ * can get the value.
+ *
+ * @serial the buffer
+ */
+ char[] value;
+
+ /**
+ * True if the buffer is shared with another object (StringBuffer or
+ * String); this means the buffer must be copied before writing to it again.
+ * Note that this has permissions set this way so that String can get the
+ * value.
+ *
+ * @serial whether the buffer is shared
+ */
+ boolean shared;
+
+ /**
+ * The default capacity of a buffer.
+ */
+ private static final int DEFAULT_CAPACITY = 16;
+
+ /**
+ * Create a new StringBuffer with default capacity 16.
+ */
+ public StringBuffer()
+ {
+ this(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * Create an empty <code>StringBuffer</code> with the specified initial
+ * capacity.
+ *
+ * @param capacity the initial capacity
+ * @throws NegativeArraySizeException if capacity is negative
+ */
+ public StringBuffer(int capacity)
+ {
+ value = new char[capacity];
+ }
+
+ /**
+ * Create a new <code>StringBuffer</code> with the characters in the
+ * specified <code>String</code>. Initial capacity will be the size of the
+ * String plus 16.
+ *
+ * @param str the <code>String</code> to convert
+ * @throws NullPointerException if str is null
+ */
+ public StringBuffer(String str)
+ {
+ // Unfortunately, because the size is 16 larger, we cannot share.
+ count = str.count;
+ value = new char[count + DEFAULT_CAPACITY];
+ str.getChars(0, count, value, 0);
+ }
+
+ /**
+ * Get the length of the <code>String</code> this <code>StringBuffer</code>
+ * would create. Not to be confused with the <em>capacity</em> of the
+ * <code>StringBuffer</code>.
+ *
+ * @return the length of this <code>StringBuffer</code>
+ * @see #capacity()
+ * @see #setLength(int)
+ */
+ public synchronized int length()
+ {
+ return count;
+ }
+
+ /**
+ * Get the total number of characters this <code>StringBuffer</code> can
+ * support before it must be grown. Not to be confused with <em>length</em>.
+ *
+ * @return the capacity of this <code>StringBuffer</code>
+ * @see #length()
+ * @see #ensureCapacity(int)
+ */
+ public synchronized int capacity()
+ {
+ return value.length;
+ }
+
+ /**
+ * Increase the capacity of this <code>StringBuffer</code>. This will
+ * ensure that an expensive growing operation will not occur until
+ * <code>minimumCapacity</code> is reached. The buffer is grown to the
+ * larger of <code>minimumCapacity</code> and
+ * <code>capacity() * 2 + 2</code>, if it is not already large enough.
+ *
+ * @param minimumCapacity the new capacity
+ * @see #capacity()
+ */
+ public synchronized void ensureCapacity(int minimumCapacity)
+ {
+ ensureCapacity_unsynchronized(minimumCapacity);
+ }
+
+ /**
+ * Set the length of this StringBuffer. If the new length is greater than
+ * the current length, all the new characters are set to '\0'. If the new
+ * length is less than the current length, the first <code>newLength</code>
+ * characters of the old array will be preserved, and the remaining
+ * characters are truncated.
+ *
+ * @param newLength the new length
+ * @throws IndexOutOfBoundsException if the new length is negative
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ * @see #length()
+ */
+ public synchronized void setLength(int newLength)
+ {
+ if (newLength < 0)
+ throw new StringIndexOutOfBoundsException(newLength);
+
+ int valueLength = value.length;
+
+ /* Always call ensureCapacity_unsynchronized in order to preserve
+ copy-on-write semantics. */
+ ensureCapacity_unsynchronized(newLength);
+
+ if (newLength < valueLength)
+ {
+ /* If the StringBuffer's value just grew, then we know that
+ value is newly allocated and the region between count and
+ newLength is filled with '\0'. */
+ count = newLength;
+ }
+ else
+ {
+ /* The StringBuffer's value doesn't need to grow. However,
+ we should clear out any cruft that may exist. */
+ while (count < newLength)
+ value[count++] = '\0';
+ }
+ }
+
+ /**
+ * Get the character at the specified index.
+ *
+ * @param index the index of the character to get, starting at 0
+ * @return the character at the specified index
+ * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public synchronized char charAt(int index)
+ {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException(index);
+ return value[index];
+ }
+
+ /**
+ * Get the specified array of characters. <code>srcOffset - srcEnd</code>
+ * characters will be copied into the array you pass in.
+ *
+ * @param srcOffset the index to start copying from (inclusive)
+ * @param srcEnd the index to stop copying from (exclusive)
+ * @param dst the array to copy into
+ * @param dstOffset the index to start copying into
+ * @throws NullPointerException if dst is null
+ * @throws IndexOutOfBoundsException if any source or target indices are
+ * out of range (while unspecified, source problems cause a
+ * StringIndexOutOfBoundsException, and dest problems cause an
+ * ArrayIndexOutOfBoundsException)
+ * @see System#arraycopy(Object, int, Object, int, int)
+ */
+ public synchronized void getChars(int srcOffset, int srcEnd,
+ char[] dst, int dstOffset)
+ {
+ if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
+ throw new StringIndexOutOfBoundsException();
+ VMSystem.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
+ }
+
+ /**
+ * Set the character at the specified index.
+ *
+ * @param index the index of the character to set starting at 0
+ * @param ch the value to set that character to
+ * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public synchronized void setCharAt(int index, char ch)
+ {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException(index);
+ // Call ensureCapacity to enforce copy-on-write.
+ ensureCapacity_unsynchronized(count);
+ value[index] = ch;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param obj the <code>Object</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(Object)
+ * @see #append(String)
+ */
+ public StringBuffer append(Object obj)
+ {
+ return append(obj == null ? "null" : obj.toString());
+ }
+
+ /**
+ * Append the <code>String</code> to this <code>StringBuffer</code>. If
+ * str is null, the String "null" is appended.
+ *
+ * @param str the <code>String</code> to append
+ * @return this <code>StringBuffer</code>
+ */
+ public synchronized StringBuffer append(String str)
+ {
+ if (str == null)
+ str = "null";
+ int len = str.count;
+ ensureCapacity_unsynchronized(count + len);
+ str.getChars(0, len, value, count);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Append the <code>StringBuffer</code> value of the argument to this
+ * <code>StringBuffer</code>. This behaves the same as
+ * <code>append((Object) stringBuffer)</code>, except it is more efficient.
+ *
+ * @param stringBuffer the <code>StringBuffer</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see #append(Object)
+ * @since 1.4
+ */
+ public synchronized StringBuffer append(StringBuffer stringBuffer)
+ {
+ if (stringBuffer == null)
+ return append("null");
+ synchronized (stringBuffer)
+ {
+ int len = stringBuffer.count;
+ ensureCapacity_unsynchronized(count + len);
+ VMSystem.arraycopy(stringBuffer.value, 0, value, count, len);
+ count += len;
+ }
+ return this;
+ }
+
+ /**
+ * Append the <code>char</code> array to this <code>StringBuffer</code>.
+ * This is similar (but more efficient) than
+ * <code>append(new String(data))</code>, except in the case of null.
+ *
+ * @param data the <code>char[]</code> to append
+ * @return this <code>StringBuffer</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @see #append(char[], int, int)
+ */
+ public StringBuffer append(char[] data)
+ {
+ return append(data, 0, data.length);
+ }
+
+ /**
+ * Append part of the <code>char</code> array to this
+ * <code>StringBuffer</code>. This is similar (but more efficient) than
+ * <code>append(new String(data, offset, count))</code>, except in the case
+ * of null.
+ *
+ * @param data the <code>char[]</code> to append
+ * @param offset the start location in <code>str</code>
+ * @param count the number of characters to get from <code>str</code>
+ * @return this <code>StringBuffer</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @throws IndexOutOfBoundsException if offset or count is out of range
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public synchronized StringBuffer append(char[] data, int offset, int count)
+ {
+ if (offset < 0 || count < 0 || offset > data.length - count)
+ throw new StringIndexOutOfBoundsException();
+ ensureCapacity_unsynchronized(this.count + count);
+ VMSystem.arraycopy(data, offset, value, this.count, count);
+ this.count += count;
+ return this;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param bool the <code>boolean</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(boolean)
+ */
+ public StringBuffer append(boolean bool)
+ {
+ return append(bool ? "true" : "false");
+ }
+
+ /**
+ * Append the <code>char</code> to this <code>StringBuffer</code>.
+ *
+ * @param ch the <code>char</code> to append
+ * @return this <code>StringBuffer</code>
+ */
+ public synchronized StringBuffer append(char ch)
+ {
+ ensureCapacity_unsynchronized(count + 1);
+ value[count++] = ch;
+ return this;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param inum the <code>int</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(int)
+ */
+ // This is native in libgcj, for efficiency.
+ public StringBuffer append(int inum)
+ {
+ return append(String.valueOf(inum));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param lnum the <code>long</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(long)
+ */
+ public StringBuffer append(long lnum)
+ {
+ return append(Long.toString(lnum, 10));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param fnum the <code>float</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(float)
+ */
+ public StringBuffer append(float fnum)
+ {
+ return append(Float.toString(fnum));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param dnum the <code>double</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(double)
+ */
+ public StringBuffer append(double dnum)
+ {
+ return append(Double.toString(dnum));
+ }
+
+ /**
+ * Delete characters from this <code>StringBuffer</code>.
+ * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
+ * harmless for end to be larger than length().
+ *
+ * @param start the first character to delete
+ * @param end the index after the last character to delete
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+ * @since 1.2
+ */
+ public synchronized StringBuffer delete(int start, int end)
+ {
+ if (start < 0 || start > count || start > end)
+ throw new StringIndexOutOfBoundsException(start);
+ if (end > count)
+ end = count;
+ // This will unshare if required.
+ ensureCapacity_unsynchronized(count);
+ if (count - end != 0)
+ VMSystem.arraycopy(value, end, value, start, count - end);
+ count -= end - start;
+ return this;
+ }
+
+ /**
+ * Delete a character from this <code>StringBuffer</code>.
+ *
+ * @param index the index of the character to delete
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if index is out of bounds
+ * @since 1.2
+ */
+ public StringBuffer deleteCharAt(int index)
+ {
+ return delete(index, index + 1);
+ }
+
+ /**
+ * Replace characters between index <code>start</code> (inclusive) and
+ * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
+ * is larger than the size of this StringBuffer, all characters after
+ * <code>start</code> are replaced.
+ *
+ * @param start the beginning index of characters to delete (inclusive)
+ * @param end the ending index of characters to delete (exclusive)
+ * @param str the new <code>String</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+ * @throws NullPointerException if str is null
+ * @since 1.2
+ */
+ public synchronized StringBuffer replace(int start, int end, String str)
+ {
+ if (start < 0 || start > count || start > end)
+ throw new StringIndexOutOfBoundsException(start);
+
+ int len = str.count;
+ // Calculate the difference in 'count' after the replace.
+ int delta = len - (end > count ? count : end) + start;
+ ensureCapacity_unsynchronized(count + delta);
+
+ if (delta != 0 && end < count)
+ VMSystem.arraycopy(value, end, value, end + delta, count - end);
+
+ str.getChars(0, len, value, start);
+ count += delta;
+ return this;
+ }
+
+ /**
+ * Creates a substring of this StringBuffer, starting at a specified index
+ * and ending at the end of this StringBuffer.
+ *
+ * @param beginIndex index to start substring (base 0)
+ * @return new String which is a substring of this StringBuffer
+ * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds
+ * @see #substring(int, int)
+ * @since 1.2
+ */
+ public String substring(int beginIndex)
+ {
+ return substring(beginIndex, count);
+ }
+
+ /**
+ * Creates a substring of this StringBuffer, starting at a specified index
+ * and ending at one character before a specified index. This is implemented
+ * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
+ * the CharSequence interface.
+ *
+ * @param beginIndex index to start at (inclusive, base 0)
+ * @param endIndex index to end at (exclusive)
+ * @return new String which is a substring of this StringBuffer
+ * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
+ * bounds
+ * @see #substring(int, int)
+ * @since 1.4
+ */
+ public CharSequence subSequence(int beginIndex, int endIndex)
+ {
+ return substring(beginIndex, endIndex);
+ }
+
+ /**
+ * Creates a substring of this StringBuffer, starting at a specified index
+ * and ending at one character before a specified index.
+ *
+ * @param beginIndex index to start at (inclusive, base 0)
+ * @param endIndex index to end at (exclusive)
+ * @return new String which is a substring of this StringBuffer
+ * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
+ * of bounds
+ * @since 1.2
+ */
+ public synchronized String substring(int beginIndex, int endIndex)
+ {
+ int len = endIndex - beginIndex;
+ if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
+ throw new StringIndexOutOfBoundsException();
+ if (len == 0)
+ return "";
+ // Don't copy unless substring is smaller than 1/4 of the buffer.
+ boolean share_buffer = ((len << 2) >= value.length);
+ if (share_buffer)
+ this.shared = true;
+ // Package constructor avoids an array copy.
+ return new String(value, beginIndex, len, share_buffer);
+ }
+
+ /**
+ * Insert a subarray of the <code>char[]</code> argument into this
+ * <code>StringBuffer</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param str the <code>char[]</code> to insert
+ * @param str_offset the index in <code>str</code> to start inserting from
+ * @param len the number of characters to insert
+ * @return this <code>StringBuffer</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @throws StringIndexOutOfBoundsException if any index is out of bounds
+ * @since 1.2
+ */
+ public synchronized StringBuffer insert(int offset,
+ char[] str, int str_offset, int len)
+ {
+ if (offset < 0 || offset > count || len < 0
+ || str_offset < 0 || str_offset > str.length - len)
+ throw new StringIndexOutOfBoundsException();
+ ensureCapacity_unsynchronized(count + len);
+ VMSystem.arraycopy(value, offset, value, offset + len, count - offset);
+ VMSystem.arraycopy(str, str_offset, value, offset, len);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param obj the <code>Object</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @exception StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(Object)
+ */
+ public StringBuffer insert(int offset, Object obj)
+ {
+ return insert(offset, obj == null ? "null" : obj.toString());
+ }
+
+ /**
+ * Insert the <code>String</code> argument into this
+ * <code>StringBuffer</code>. If str is null, the String "null" is used
+ * instead.
+ *
+ * @param offset the place to insert in this buffer
+ * @param str the <code>String</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ */
+ public synchronized StringBuffer insert(int offset, String str)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException(offset);
+ if (str == null)
+ str = "null";
+ int len = str.count;
+ ensureCapacity_unsynchronized(count + len);
+ VMSystem.arraycopy(value, offset, value, offset + len, count - offset);
+ str.getChars(0, len, value, offset);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Insert the <code>char[]</code> argument into this
+ * <code>StringBuffer</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param data the <code>char[]</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws NullPointerException if <code>data</code> is <code>null</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see #insert(int, char[], int, int)
+ */
+ public StringBuffer insert(int offset, char[] data)
+ {
+ return insert(offset, data, 0, data.length);
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param bool the <code>boolean</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(boolean)
+ */
+ public StringBuffer insert(int offset, boolean bool)
+ {
+ return insert(offset, bool ? "true" : "false");
+ }
+
+ /**
+ * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param ch the <code>char</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ */
+ public synchronized StringBuffer insert(int offset, char ch)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException(offset);
+ ensureCapacity_unsynchronized(count + 1);
+ VMSystem.arraycopy(value, offset, value, offset + 1, count - offset);
+ value[offset] = ch;
+ count++;
+ return this;
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param inum the <code>int</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(int)
+ */
+ public StringBuffer insert(int offset, int inum)
+ {
+ return insert(offset, String.valueOf(inum));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param lnum the <code>long</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(long)
+ */
+ public StringBuffer insert(int offset, long lnum)
+ {
+ return insert(offset, Long.toString(lnum, 10));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param fnum the <code>float</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(float)
+ */
+ public StringBuffer insert(int offset, float fnum)
+ {
+ return insert(offset, Float.toString(fnum));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param dnum the <code>double</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(double)
+ */
+ public StringBuffer insert(int offset, double dnum)
+ {
+ return insert(offset, Double.toString(dnum));
+ }
+
+ /**
+ * Finds the first instance of a substring in this StringBuffer.
+ *
+ * @param str String to find
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @see #indexOf(String, int)
+ * @since 1.4
+ */
+ public int indexOf(String str)
+ {
+ return indexOf(str, 0);
+ }
+
+ /**
+ * Finds the first instance of a String in this StringBuffer, starting at
+ * a given index. If starting index is less than 0, the search starts at
+ * the beginning of this String. If the starting index is greater than the
+ * length of this String, or the substring is not found, -1 is returned.
+ *
+ * @param str String to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @since 1.4
+ */
+ public synchronized int indexOf(String str, int fromIndex)
+ {
+ if (fromIndex < 0)
+ fromIndex = 0;
+ int limit = count - str.count;
+ for ( ; fromIndex <= limit; fromIndex++)
+ if (regionMatches(fromIndex, str))
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Finds the last instance of a substring in this StringBuffer.
+ *
+ * @param str String to find
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @see #lastIndexOf(String, int)
+ * @since 1.4
+ */
+ public int lastIndexOf(String str)
+ {
+ return lastIndexOf(str, count - str.count);
+ }
+
+ /**
+ * Finds the last instance of a String in this StringBuffer, starting at a
+ * given index. If starting index is greater than the maximum valid index,
+ * then the search begins at the end of this String. If the starting index
+ * is less than zero, or the substring is not found, -1 is returned.
+ *
+ * @param str String to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @since 1.4
+ */
+ public synchronized int lastIndexOf(String str, int fromIndex)
+ {
+ fromIndex = Math.min(fromIndex, count - str.count);
+ for ( ; fromIndex >= 0; fromIndex--)
+ if (regionMatches(fromIndex, str))
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Reverse the characters in this StringBuffer. The same sequence of
+ * characters exists, but in the reverse index ordering.
+ *
+ * @return this <code>StringBuffer</code>
+ */
+ public synchronized StringBuffer reverse()
+ {
+ // Call ensureCapacity to enforce copy-on-write.
+ ensureCapacity_unsynchronized(count);
+ for (int i = count >> 1, j = count - i; --i >= 0; ++j)
+ {
+ char c = value[i];
+ value[i] = value[j];
+ value[j] = c;
+ }
+ return this;
+ }
+
+ /**
+ * Convert this <code>StringBuffer</code> to a <code>String</code>. The
+ * String is composed of the characters currently in this StringBuffer. Note
+ * that the result is a copy, and that future modifications to this buffer
+ * do not affect the String.
+ *
+ * @return the characters in this StringBuffer
+ */
+ public String toString()
+ {
+ // The string will set this.shared = true.
+ return new String(this);
+ }
+
+ /**
+ * An unsynchronized version of ensureCapacity, used internally to avoid
+ * the cost of a second lock on the same object. This also has the side
+ * effect of duplicating the array, if it was shared (to form copy-on-write
+ * semantics).
+ *
+ * @param minimumCapacity the minimum capacity
+ * @see #ensureCapacity(int)
+ */
+ private void ensureCapacity_unsynchronized(int minimumCapacity)
+ {
+ if (shared || minimumCapacity > value.length)
+ {
+ // We don't want to make a larger vector when `shared' is
+ // set. If we do, then setLength becomes very inefficient
+ // when repeatedly reusing a StringBuffer in a loop.
+ int max = (minimumCapacity > value.length
+ ? value.length * 2 + 2
+ : value.length);
+ minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
+ char[] nb = new char[minimumCapacity];
+ VMSystem.arraycopy(value, 0, nb, 0, count);
+ value = nb;
+ shared = false;
+ }
+ }
+
+ /**
+ * Predicate which determines if a substring of this matches another String
+ * starting at a specified offset for each String and continuing for a
+ * specified length. This is more efficient than creating a String to call
+ * indexOf on.
+ *
+ * @param toffset index to start comparison at for this String
+ * @param other non-null String to compare to region of this
+ * @return true if regions match, false otherwise
+ * @see #indexOf(String, int)
+ * @see #lastIndexOf(String, int)
+ * @see String#regionMatches(boolean, int, String, int, int)
+ */
+ private boolean regionMatches(int toffset, String other)
+ {
+ int len = other.count;
+ int index = other.offset;
+ while (--len >= 0)
+ if (value[toffset++] != other.value[index++])
+ return false;
+ return true;
+ }
+}
diff --git a/libjava/classpath/java/lang/StringBuilder.java b/libjava/classpath/java/lang/StringBuilder.java
new file mode 100644
index 00000000000..b54c8ef7eb4
--- /dev/null
+++ b/libjava/classpath/java/lang/StringBuilder.java
@@ -0,0 +1,944 @@
+/* StringBuilder.java -- Unsynchronized growable strings
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.io.Serializable;
+
+/**
+ * <code>StringBuilder</code> represents a changeable <code>String</code>.
+ * It provides the operations required to modify the
+ * <code>StringBuilder</code>, including insert, replace, delete, append,
+ * and reverse. It like <code>StringBuffer</code>, but is not
+ * synchronized. It is ideal for use when it is known that the
+ * object will only be used from a single thread.
+ *
+ * <p><code>StringBuilder</code>s are variable-length in nature, so even if
+ * you initialize them to a certain size, they can still grow larger than
+ * that. <em>Capacity</em> indicates the number of characters the
+ * <code>StringBuilder</code> can have in it before it has to grow (growing
+ * the char array is an expensive operation involving <code>new</code>).
+ *
+ * <p>Incidentally, compilers often implement the String operator "+"
+ * by using a <code>StringBuilder</code> operation:<br>
+ * <code>a + b</code><br>
+ * is the same as<br>
+ * <code>new StringBuilder().append(a).append(b).toString()</code>.
+ *
+ * <p>Classpath's StringBuilder is capable of sharing memory with Strings for
+ * efficiency. This will help when a StringBuilder is converted to a String
+ * and the StringBuilder is not changed after that (quite common when
+ * performing string concatenation).
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Tom Tromey
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see String
+ * @see StringBuffer
+ *
+ * @since 1.5
+ */
+// FIX15: Implement Appendable when co-variant methods are available
+public final class StringBuilder
+ implements Serializable, CharSequence
+{
+ // Implementation note: if you change this class, you usually will
+ // want to change StringBuffer as well.
+
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = 4383685877147921099L;
+
+ /**
+ * Index of next available character (and thus the size of the current
+ * string contents). Note that this has permissions set this way so that
+ * String can get the value.
+ *
+ * @serial the number of characters in the buffer
+ */
+ int count;
+
+ /**
+ * The buffer. Note that this has permissions set this way so that String
+ * can get the value.
+ *
+ * @serial the buffer
+ */
+ char[] value;
+
+ /**
+ * The default capacity of a buffer.
+ */
+ private static final int DEFAULT_CAPACITY = 16;
+
+ /**
+ * Create a new StringBuilder with default capacity 16.
+ */
+ public StringBuilder()
+ {
+ this(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * Create an empty <code>StringBuilder</code> with the specified initial
+ * capacity.
+ *
+ * @param capacity the initial capacity
+ * @throws NegativeArraySizeException if capacity is negative
+ */
+ public StringBuilder(int capacity)
+ {
+ value = new char[capacity];
+ }
+
+ /**
+ * Create a new <code>StringBuilder</code> with the characters in the
+ * specified <code>String</code>. Initial capacity will be the size of the
+ * String plus 16.
+ *
+ * @param str the <code>String</code> to convert
+ * @throws NullPointerException if str is null
+ */
+ public StringBuilder(String str)
+ {
+ // Unfortunately, because the size is 16 larger, we cannot share.
+ count = str.count;
+ value = new char[count + DEFAULT_CAPACITY];
+ str.getChars(0, count, value, 0);
+ }
+
+ /**
+ * Create a new <code>StringBuilder</code> with the characters in the
+ * specified <code>CharSequence</code>. Initial capacity will be the
+ * length of the sequence plus 16; if the sequence reports a length
+ * less than or equal to 0, then the initial capacity will be 16.
+ *
+ * @param seq the initializing <code>CharSequence</code>
+ * @throws NullPointerException if str is null
+ */
+ public StringBuilder(CharSequence seq)
+ {
+ int len = seq.length();
+ count = len <= 0 ? 0 : len;
+ value = new char[count + DEFAULT_CAPACITY];
+ for (int i = 0; i < len; ++i)
+ value[i] = seq.charAt(i);
+ }
+
+ /**
+ * Get the length of the <code>String</code> this <code>StringBuilder</code>
+ * would create. Not to be confused with the <em>capacity</em> of the
+ * <code>StringBuilder</code>.
+ *
+ * @return the length of this <code>StringBuilder</code>
+ * @see #capacity()
+ * @see #setLength(int)
+ */
+ public int length()
+ {
+ return count;
+ }
+
+ /**
+ * Get the total number of characters this <code>StringBuilder</code> can
+ * support before it must be grown. Not to be confused with <em>length</em>.
+ *
+ * @return the capacity of this <code>StringBuilder</code>
+ * @see #length()
+ * @see #ensureCapacity(int)
+ */
+ public int capacity()
+ {
+ return value.length;
+ }
+
+ /**
+ * Increase the capacity of this <code>StringBuilder</code>. This will
+ * ensure that an expensive growing operation will not occur until
+ * <code>minimumCapacity</code> is reached. The buffer is grown to the
+ * larger of <code>minimumCapacity</code> and
+ * <code>capacity() * 2 + 2</code>, if it is not already large enough.
+ *
+ * @param minimumCapacity the new capacity
+ * @see #capacity()
+ */
+ public void ensureCapacity(int minimumCapacity)
+ {
+ if (minimumCapacity > value.length)
+ {
+ int max = value.length * 2 + 2;
+ minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
+ char[] nb = new char[minimumCapacity];
+ System.arraycopy(value, 0, nb, 0, count);
+ value = nb;
+ }
+ }
+
+ /**
+ * Set the length of this StringBuilder. If the new length is greater than
+ * the current length, all the new characters are set to '\0'. If the new
+ * length is less than the current length, the first <code>newLength</code>
+ * characters of the old array will be preserved, and the remaining
+ * characters are truncated.
+ *
+ * @param newLength the new length
+ * @throws IndexOutOfBoundsException if the new length is negative
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ * @see #length()
+ */
+ public void setLength(int newLength)
+ {
+ if (newLength < 0)
+ throw new StringIndexOutOfBoundsException(newLength);
+
+ int valueLength = value.length;
+
+ /* Always call ensureCapacity in order to preserve copy-on-write
+ semantics. */
+ ensureCapacity(newLength);
+
+ if (newLength < valueLength)
+ {
+ /* If the StringBuilder's value just grew, then we know that
+ value is newly allocated and the region between count and
+ newLength is filled with '\0'. */
+ count = newLength;
+ }
+ else
+ {
+ /* The StringBuilder's value doesn't need to grow. However,
+ we should clear out any cruft that may exist. */
+ while (count < newLength)
+ value[count++] = '\0';
+ }
+ }
+
+ /**
+ * Get the character at the specified index.
+ *
+ * @param index the index of the character to get, starting at 0
+ * @return the character at the specified index
+ * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public char charAt(int index)
+ {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException(index);
+ return value[index];
+ }
+
+ /**
+ * Get the specified array of characters. <code>srcOffset - srcEnd</code>
+ * characters will be copied into the array you pass in.
+ *
+ * @param srcOffset the index to start copying from (inclusive)
+ * @param srcEnd the index to stop copying from (exclusive)
+ * @param dst the array to copy into
+ * @param dstOffset the index to start copying into
+ * @throws NullPointerException if dst is null
+ * @throws IndexOutOfBoundsException if any source or target indices are
+ * out of range (while unspecified, source problems cause a
+ * StringIndexOutOfBoundsException, and dest problems cause an
+ * ArrayIndexOutOfBoundsException)
+ * @see System#arraycopy(Object, int, Object, int, int)
+ */
+ public void getChars(int srcOffset, int srcEnd,
+ char[] dst, int dstOffset)
+ {
+ if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
+ throw new StringIndexOutOfBoundsException();
+ System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
+ }
+
+ /**
+ * Set the character at the specified index.
+ *
+ * @param index the index of the character to set starting at 0
+ * @param ch the value to set that character to
+ * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public void setCharAt(int index, char ch)
+ {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException(index);
+ // Call ensureCapacity to enforce copy-on-write.
+ ensureCapacity(count);
+ value[index] = ch;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param obj the <code>Object</code> to convert and append
+ * @return this <code>StringBuilder</code>
+ * @see String#valueOf(Object)
+ * @see #append(String)
+ */
+ public StringBuilder append(Object obj)
+ {
+ return append(obj == null ? "null" : obj.toString());
+ }
+
+ /**
+ * Append the <code>String</code> to this <code>StringBuilder</code>. If
+ * str is null, the String "null" is appended.
+ *
+ * @param str the <code>String</code> to append
+ * @return this <code>StringBuilder</code>
+ */
+ public StringBuilder append(String str)
+ {
+ if (str == null)
+ str = "null";
+ int len = str.count;
+ ensureCapacity(count + len);
+ str.getChars(0, len, value, count);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Append the <code>StringBuilder</code> value of the argument to this
+ * <code>StringBuilder</code>. This behaves the same as
+ * <code>append((Object) stringBuffer)</code>, except it is more efficient.
+ *
+ * @param stringBuffer the <code>StringBuilder</code> to convert and append
+ * @return this <code>StringBuilder</code>
+ * @see #append(Object)
+ */
+ public StringBuilder append(StringBuffer stringBuffer)
+ {
+ if (stringBuffer == null)
+ return append("null");
+ synchronized (stringBuffer)
+ {
+ int len = stringBuffer.count;
+ ensureCapacity(count + len);
+ System.arraycopy(stringBuffer.value, 0, value, count, len);
+ count += len;
+ }
+ return this;
+ }
+
+ /**
+ * Append the <code>char</code> array to this <code>StringBuilder</code>.
+ * This is similar (but more efficient) than
+ * <code>append(new String(data))</code>, except in the case of null.
+ *
+ * @param data the <code>char[]</code> to append
+ * @return this <code>StringBuilder</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @see #append(char[], int, int)
+ */
+ public StringBuilder append(char[] data)
+ {
+ return append(data, 0, data.length);
+ }
+
+ /**
+ * Append part of the <code>char</code> array to this
+ * <code>StringBuilder</code>. This is similar (but more efficient) than
+ * <code>append(new String(data, offset, count))</code>, except in the case
+ * of null.
+ *
+ * @param data the <code>char[]</code> to append
+ * @param offset the start location in <code>str</code>
+ * @param count the number of characters to get from <code>str</code>
+ * @return this <code>StringBuilder</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @throws IndexOutOfBoundsException if offset or count is out of range
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public StringBuilder append(char[] data, int offset, int count)
+ {
+ if (offset < 0 || count < 0 || offset > data.length - count)
+ throw new StringIndexOutOfBoundsException();
+ ensureCapacity(this.count + count);
+ System.arraycopy(data, offset, value, this.count, count);
+ this.count += count;
+ return this;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param bool the <code>boolean</code> to convert and append
+ * @return this <code>StringBuilder</code>
+ * @see String#valueOf(boolean)
+ */
+ public StringBuilder append(boolean bool)
+ {
+ return append(bool ? "true" : "false");
+ }
+
+ /**
+ * Append the <code>char</code> to this <code>StringBuilder</code>.
+ *
+ * @param ch the <code>char</code> to append
+ * @return this <code>StringBuilder</code>
+ */
+ public StringBuilder append(char ch)
+ {
+ ensureCapacity(count + 1);
+ value[count++] = ch;
+ return this;
+ }
+
+ /**
+ * Append the characters in the <code>CharSequence</code> to this
+ * buffer.
+ *
+ * @param seq the <code>CharSequence</code> providing the characters
+ * @return this <code>StringBuilder</code>
+ */
+ public StringBuilder append(CharSequence seq)
+ {
+ return append(seq, 0, seq.length());
+ }
+
+ /**
+ * Append some characters from the <code>CharSequence</code> to this
+ * buffer. If the argument is null, the four characters "null" are
+ * appended.
+ *
+ * @param seq the <code>CharSequence</code> providing the characters
+ * @param start the starting index
+ * @param end one past the final index
+ * @return this <code>StringBuilder</code>
+ */
+ public StringBuilder append(CharSequence seq, int start,
+ int end)
+ {
+ if (seq == null)
+ return append("null");
+ if (end - start > 0)
+ {
+ ensureCapacity(count + end - start);
+ for (; start < end; ++start)
+ value[count++] = seq.charAt(start);
+ }
+ return this;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param inum the <code>int</code> to convert and append
+ * @return this <code>StringBuilder</code>
+ * @see String#valueOf(int)
+ */
+ // This is native in libgcj, for efficiency.
+ public StringBuilder append(int inum)
+ {
+ return append(String.valueOf(inum));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param lnum the <code>long</code> to convert and append
+ * @return this <code>StringBuilder</code>
+ * @see String#valueOf(long)
+ */
+ public StringBuilder append(long lnum)
+ {
+ return append(Long.toString(lnum, 10));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param fnum the <code>float</code> to convert and append
+ * @return this <code>StringBuilder</code>
+ * @see String#valueOf(float)
+ */
+ public StringBuilder append(float fnum)
+ {
+ return append(Float.toString(fnum));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param dnum the <code>double</code> to convert and append
+ * @return this <code>StringBuilder</code>
+ * @see String#valueOf(double)
+ */
+ public StringBuilder append(double dnum)
+ {
+ return append(Double.toString(dnum));
+ }
+
+ /**
+ * Delete characters from this <code>StringBuilder</code>.
+ * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
+ * harmless for end to be larger than length().
+ *
+ * @param start the first character to delete
+ * @param end the index after the last character to delete
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+ */
+ public StringBuilder delete(int start, int end)
+ {
+ if (start < 0 || start > count || start > end)
+ throw new StringIndexOutOfBoundsException(start);
+ if (end > count)
+ end = count;
+ // This will unshare if required.
+ ensureCapacity(count);
+ if (count - end != 0)
+ System.arraycopy(value, end, value, start, count - end);
+ count -= end - start;
+ return this;
+ }
+
+ /**
+ * Delete a character from this <code>StringBuilder</code>.
+ *
+ * @param index the index of the character to delete
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if index is out of bounds
+ */
+ public StringBuilder deleteCharAt(int index)
+ {
+ return delete(index, index + 1);
+ }
+
+ /**
+ * Replace characters between index <code>start</code> (inclusive) and
+ * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
+ * is larger than the size of this StringBuilder, all characters after
+ * <code>start</code> are replaced.
+ *
+ * @param start the beginning index of characters to delete (inclusive)
+ * @param end the ending index of characters to delete (exclusive)
+ * @param str the new <code>String</code> to insert
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+ * @throws NullPointerException if str is null
+ */
+ public StringBuilder replace(int start, int end, String str)
+ {
+ if (start < 0 || start > count || start > end)
+ throw new StringIndexOutOfBoundsException(start);
+
+ int len = str.count;
+ // Calculate the difference in 'count' after the replace.
+ int delta = len - (end > count ? count : end) + start;
+ ensureCapacity(count + delta);
+
+ if (delta != 0 && end < count)
+ System.arraycopy(value, end, value, end + delta, count - end);
+
+ str.getChars(0, len, value, start);
+ count += delta;
+ return this;
+ }
+
+ /**
+ * Creates a substring of this StringBuilder, starting at a specified index
+ * and ending at the end of this StringBuilder.
+ *
+ * @param beginIndex index to start substring (base 0)
+ * @return new String which is a substring of this StringBuilder
+ * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds
+ * @see #substring(int, int)
+ */
+ public String substring(int beginIndex)
+ {
+ return substring(beginIndex, count);
+ }
+
+ /**
+ * Creates a substring of this StringBuilder, starting at a specified index
+ * and ending at one character before a specified index. This is implemented
+ * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
+ * the CharSequence interface.
+ *
+ * @param beginIndex index to start at (inclusive, base 0)
+ * @param endIndex index to end at (exclusive)
+ * @return new String which is a substring of this StringBuilder
+ * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
+ * bounds
+ * @see #substring(int, int)
+ */
+ public CharSequence subSequence(int beginIndex, int endIndex)
+ {
+ return substring(beginIndex, endIndex);
+ }
+
+ /**
+ * Creates a substring of this StringBuilder, starting at a specified index
+ * and ending at one character before a specified index.
+ *
+ * @param beginIndex index to start at (inclusive, base 0)
+ * @param endIndex index to end at (exclusive)
+ * @return new String which is a substring of this StringBuilder
+ * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
+ * of bounds
+ */
+ public String substring(int beginIndex, int endIndex)
+ {
+ int len = endIndex - beginIndex;
+ if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
+ throw new StringIndexOutOfBoundsException();
+ if (len == 0)
+ return "";
+ return new String(value, beginIndex, len);
+ }
+
+ /**
+ * Insert a subarray of the <code>char[]</code> argument into this
+ * <code>StringBuilder</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param str the <code>char[]</code> to insert
+ * @param str_offset the index in <code>str</code> to start inserting from
+ * @param len the number of characters to insert
+ * @return this <code>StringBuilder</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @throws StringIndexOutOfBoundsException if any index is out of bounds
+ */
+ public StringBuilder insert(int offset,
+ char[] str, int str_offset, int len)
+ {
+ if (offset < 0 || offset > count || len < 0
+ || str_offset < 0 || str_offset > str.length - len)
+ throw new StringIndexOutOfBoundsException();
+ ensureCapacity(count + len);
+ System.arraycopy(value, offset, value, offset + len, count - offset);
+ System.arraycopy(str, str_offset, value, offset, len);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param obj the <code>Object</code> to convert and insert
+ * @return this <code>StringBuilder</code>
+ * @exception StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(Object)
+ */
+ public StringBuilder insert(int offset, Object obj)
+ {
+ return insert(offset, obj == null ? "null" : obj.toString());
+ }
+
+ /**
+ * Insert the <code>String</code> argument into this
+ * <code>StringBuilder</code>. If str is null, the String "null" is used
+ * instead.
+ *
+ * @param offset the place to insert in this buffer
+ * @param str the <code>String</code> to insert
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ */
+ public StringBuilder insert(int offset, String str)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException(offset);
+ if (str == null)
+ str = "null";
+ int len = str.count;
+ ensureCapacity(count + len);
+ System.arraycopy(value, offset, value, offset + len, count - offset);
+ str.getChars(0, len, value, offset);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Insert the <code>char[]</code> argument into this
+ * <code>StringBuilder</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param data the <code>char[]</code> to insert
+ * @return this <code>StringBuilder</code>
+ * @throws NullPointerException if <code>data</code> is <code>null</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see #insert(int, char[], int, int)
+ */
+ public StringBuilder insert(int offset, char[] data)
+ {
+ return insert(offset, data, 0, data.length);
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param bool the <code>boolean</code> to convert and insert
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(boolean)
+ */
+ public StringBuilder insert(int offset, boolean bool)
+ {
+ return insert(offset, bool ? "true" : "false");
+ }
+
+ /**
+ * Insert the <code>char</code> argument into this <code>StringBuilder</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param ch the <code>char</code> to insert
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ */
+ public StringBuilder insert(int offset, char ch)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException(offset);
+ ensureCapacity(count + 1);
+ System.arraycopy(value, offset, value, offset + 1, count - offset);
+ value[offset] = ch;
+ count++;
+ return this;
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param inum the <code>int</code> to convert and insert
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(int)
+ */
+ public StringBuilder insert(int offset, int inum)
+ {
+ return insert(offset, String.valueOf(inum));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param lnum the <code>long</code> to convert and insert
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(long)
+ */
+ public StringBuilder insert(int offset, long lnum)
+ {
+ return insert(offset, Long.toString(lnum, 10));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param fnum the <code>float</code> to convert and insert
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(float)
+ */
+ public StringBuilder insert(int offset, float fnum)
+ {
+ return insert(offset, Float.toString(fnum));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param dnum the <code>double</code> to convert and insert
+ * @return this <code>StringBuilder</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(double)
+ */
+ public StringBuilder insert(int offset, double dnum)
+ {
+ return insert(offset, Double.toString(dnum));
+ }
+
+ /**
+ * Finds the first instance of a substring in this StringBuilder.
+ *
+ * @param str String to find
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @see #indexOf(String, int)
+ */
+ public int indexOf(String str)
+ {
+ return indexOf(str, 0);
+ }
+
+ /**
+ * Finds the first instance of a String in this StringBuilder, starting at
+ * a given index. If starting index is less than 0, the search starts at
+ * the beginning of this String. If the starting index is greater than the
+ * length of this String, or the substring is not found, -1 is returned.
+ *
+ * @param str String to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ */
+ public int indexOf(String str, int fromIndex)
+ {
+ if (fromIndex < 0)
+ fromIndex = 0;
+ int limit = count - str.count;
+ for ( ; fromIndex <= limit; fromIndex++)
+ if (regionMatches(fromIndex, str))
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Finds the last instance of a substring in this StringBuilder.
+ *
+ * @param str String to find
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @see #lastIndexOf(String, int)
+ */
+ public int lastIndexOf(String str)
+ {
+ return lastIndexOf(str, count - str.count);
+ }
+
+ /**
+ * Finds the last instance of a String in this StringBuilder, starting at a
+ * given index. If starting index is greater than the maximum valid index,
+ * then the search begins at the end of this String. If the starting index
+ * is less than zero, or the substring is not found, -1 is returned.
+ *
+ * @param str String to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ */
+ public int lastIndexOf(String str, int fromIndex)
+ {
+ fromIndex = Math.min(fromIndex, count - str.count);
+ for ( ; fromIndex >= 0; fromIndex--)
+ if (regionMatches(fromIndex, str))
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Reverse the characters in this StringBuilder. The same sequence of
+ * characters exists, but in the reverse index ordering.
+ *
+ * @return this <code>StringBuilder</code>
+ */
+ public StringBuilder reverse()
+ {
+ // Call ensureCapacity to enforce copy-on-write.
+ ensureCapacity(count);
+ for (int i = count >> 1, j = count - i; --i >= 0; ++j)
+ {
+ char c = value[i];
+ value[i] = value[j];
+ value[j] = c;
+ }
+ return this;
+ }
+
+ /**
+ * Convert this <code>StringBuilder</code> to a <code>String</code>. The
+ * String is composed of the characters currently in this StringBuilder. Note
+ * that the result is a copy, and that future modifications to this buffer
+ * do not affect the String.
+ *
+ * @return the characters in this StringBuilder
+ */
+ public String toString()
+ {
+ return new String(this);
+ }
+
+ /**
+ * Predicate which determines if a substring of this matches another String
+ * starting at a specified offset for each String and continuing for a
+ * specified length. This is more efficient than creating a String to call
+ * indexOf on.
+ *
+ * @param toffset index to start comparison at for this String
+ * @param other non-null String to compare to region of this
+ * @return true if regions match, false otherwise
+ * @see #indexOf(String, int)
+ * @see #lastIndexOf(String, int)
+ * @see String#regionMatches(boolean, int, String, int, int)
+ */
+ private boolean regionMatches(int toffset, String other)
+ {
+ int len = other.count;
+ int index = other.offset;
+ while (--len >= 0)
+ if (value[toffset++] != other.value[index++])
+ return false;
+ return true;
+ }
+}
diff --git a/libjava/classpath/java/lang/StringIndexOutOfBoundsException.java b/libjava/classpath/java/lang/StringIndexOutOfBoundsException.java
new file mode 100644
index 00000000000..ebc4a04a391
--- /dev/null
+++ b/libjava/classpath/java/lang/StringIndexOutOfBoundsException.java
@@ -0,0 +1,85 @@
+/* StringIndexOutOfBoundsException.java -- thrown to indicate attempt to
+ exceed string bounds
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * This exception can be thrown to indicate an attempt to access an index
+ * which is out of bounds of a String. Any negative integer, and a positive
+ * integer greater than or equal to the size of the string, is an index
+ * which would be out of bounds.
+ *
+ * @author Brian Jones
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -6762910422159637258L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public StringIndexOutOfBoundsException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public StringIndexOutOfBoundsException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception noting the illegal index.
+ *
+ * @param index the invalid index
+ */
+ public StringIndexOutOfBoundsException(int index)
+ {
+ super("String index out of range: " + index);
+ }
+}
diff --git a/libjava/classpath/java/lang/System.java b/libjava/classpath/java/lang/System.java
new file mode 100644
index 00000000000..e466d3b8cfb
--- /dev/null
+++ b/libjava/classpath/java/lang/System.java
@@ -0,0 +1,528 @@
+/* System.java -- useful methods to interface with the system
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.classpath.SystemProperties;
+import gnu.classpath.VMStackWalker;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Properties;
+import java.util.PropertyPermission;
+
+/**
+ * System represents system-wide resources; things that represent the
+ * general environment. As such, all methods are static.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status still missing 1.4 functionality
+ */
+public final class System
+{
+ // WARNING: System is a CORE class in the bootstrap cycle. See the comments
+ // in vm/reference/java/lang/Runtime for implications of this fact.
+
+ /**
+ * The standard InputStream. This is assigned at startup and starts its
+ * life perfectly valid. Although it is marked final, you can change it
+ * using {@link #setIn(InputStream)} through some hefty VM magic.
+ *
+ * <p>This corresponds to the C stdin and C++ cin variables, which
+ * typically input from the keyboard, but may be used to pipe input from
+ * other processes or files. That should all be transparent to you,
+ * however.
+ */
+ public static final InputStream in = VMSystem.makeStandardInputStream();
+
+ /**
+ * The standard output PrintStream. This is assigned at startup and
+ * starts its life perfectly valid. Although it is marked final, you can
+ * change it using {@link #setOut(PrintStream)} through some hefty VM magic.
+ *
+ * <p>This corresponds to the C stdout and C++ cout variables, which
+ * typically output normal messages to the screen, but may be used to pipe
+ * output to other processes or files. That should all be transparent to
+ * you, however.
+ */
+ public static final PrintStream out = VMSystem.makeStandardOutputStream();
+
+ /**
+ * The standard output PrintStream. This is assigned at startup and
+ * starts its life perfectly valid. Although it is marked final, you can
+ * change it using {@link #setErr(PrintStream)} through some hefty VM magic.
+ *
+ * <p>This corresponds to the C stderr and C++ cerr variables, which
+ * typically output error messages to the screen, but may be used to pipe
+ * output to other processes or files. That should all be transparent to
+ * you, however.
+ */
+ public static final PrintStream err = VMSystem.makeStandardErrorStream();
+
+ /**
+ * This class is uninstantiable.
+ */
+ private System()
+ {
+ }
+
+ /**
+ * Set {@link #in} to a new InputStream. This uses some VM magic to change
+ * a "final" variable, so naturally there is a security check,
+ * <code>RuntimePermission("setIO")</code>.
+ *
+ * @param in the new InputStream
+ * @throws SecurityException if permission is denied
+ * @since 1.1
+ */
+ public static void setIn(InputStream in)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setIO"));
+ VMSystem.setIn(in);
+ }
+
+ /**
+ * Set {@link #out} to a new PrintStream. This uses some VM magic to change
+ * a "final" variable, so naturally there is a security check,
+ * <code>RuntimePermission("setIO")</code>.
+ *
+ * @param out the new PrintStream
+ * @throws SecurityException if permission is denied
+ * @since 1.1
+ */
+ public static void setOut(PrintStream out)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setIO"));
+
+ VMSystem.setOut(out);
+ }
+
+ /**
+ * Set {@link #err} to a new PrintStream. This uses some VM magic to change
+ * a "final" variable, so naturally there is a security check,
+ * <code>RuntimePermission("setIO")</code>.
+ *
+ * @param err the new PrintStream
+ * @throws SecurityException if permission is denied
+ * @since 1.1
+ */
+ public static void setErr(PrintStream err)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setIO"));
+ VMSystem.setErr(err);
+ }
+
+ /**
+ * Set the current SecurityManager. If a security manager already exists,
+ * then <code>RuntimePermission("setSecurityManager")</code> is checked
+ * first. Since this permission is denied by the default security manager,
+ * setting the security manager is often an irreversible action.
+ *
+ * <STRONG>Spec Note:</STRONG> Don't ask me, I didn't write it. It looks
+ * pretty vulnerable; whoever gets to the gate first gets to set the policy.
+ * There is probably some way to set the original security manager as a
+ * command line argument to the VM, but I don't know it.
+ *
+ * @param sm the new SecurityManager
+ * @throws SecurityException if permission is denied
+ */
+ public static synchronized void setSecurityManager(SecurityManager sm)
+ {
+ // Implementation note: the field lives in SecurityManager because of
+ // bootstrap initialization issues. This method is synchronized so that
+ // no other thread changes it to null before this thread makes the change.
+ if (SecurityManager.current != null)
+ SecurityManager.current.checkPermission
+ (new RuntimePermission("setSecurityManager"));
+ SecurityManager.current = sm;
+ }
+
+ /**
+ * Get the current SecurityManager. If the SecurityManager has not been
+ * set yet, then this method returns null.
+ *
+ * @return the current SecurityManager, or null
+ */
+ public static SecurityManager getSecurityManager()
+ {
+ return SecurityManager.current;
+ }
+
+ /**
+ * Get the current time, measured in the number of milliseconds from the
+ * beginning of Jan. 1, 1970. This is gathered from the system clock, with
+ * any attendant incorrectness (it may be timezone dependent).
+ *
+ * @return the current time
+ * @see java.util.Date
+ */
+ public static long currentTimeMillis()
+ {
+ return VMSystem.currentTimeMillis();
+ }
+
+ /**
+ * Copy one array onto another from <code>src[srcStart]</code> ...
+ * <code>src[srcStart+len-1]</code> to <code>dest[destStart]</code> ...
+ * <code>dest[destStart+len-1]</code>. First, the arguments are validated:
+ * neither array may be null, they must be of compatible types, and the
+ * start and length must fit within both arrays. Then the copying starts,
+ * and proceeds through increasing slots. If src and dest are the same
+ * array, this will appear to copy the data to a temporary location first.
+ * An ArrayStoreException in the middle of copying will leave earlier
+ * elements copied, but later elements unchanged.
+ *
+ * @param src the array to copy elements from
+ * @param srcStart the starting position in src
+ * @param dest the array to copy elements to
+ * @param destStart the starting position in dest
+ * @param len the number of elements to copy
+ * @throws NullPointerException if src or dest is null
+ * @throws ArrayStoreException if src or dest is not an array, if they are
+ * not compatible array types, or if an incompatible runtime type
+ * is stored in dest
+ * @throws IndexOutOfBoundsException if len is negative, or if the start or
+ * end copy position in either array is out of bounds
+ */
+ public static void arraycopy(Object src, int srcStart,
+ Object dest, int destStart, int len)
+ {
+ VMSystem.arraycopy(src, srcStart, dest, destStart, len);
+ }
+
+ /**
+ * Get a hash code computed by the VM for the Object. This hash code will
+ * be the same as Object's hashCode() method. It is usually some
+ * convolution of the pointer to the Object internal to the VM. It
+ * follows standard hash code rules, in that it will remain the same for a
+ * given Object for the lifetime of that Object.
+ *
+ * @param o the Object to get the hash code for
+ * @return the VM-dependent hash code for this Object
+ * @since 1.1
+ */
+ public static int identityHashCode(Object o)
+ {
+ return VMSystem.identityHashCode(o);
+ }
+
+ /**
+ * Get all the system properties at once. A security check may be performed,
+ * <code>checkPropertiesAccess</code>. Note that a security manager may
+ * allow getting a single property, but not the entire group.
+ *
+ * <p>The required properties include:
+ * <dl>
+ * <dt>java.version</dt> <dd>Java version number</dd>
+ * <dt>java.vendor</dt> <dd>Java vendor specific string</dd>
+ * <dt>java.vendor.url</dt> <dd>Java vendor URL</dd>
+ * <dt>java.home</dt> <dd>Java installation directory</dd>
+ * <dt>java.vm.specification.version</dt> <dd>VM Spec version</dd>
+ * <dt>java.vm.specification.vendor</dt> <dd>VM Spec vendor</dd>
+ * <dt>java.vm.specification.name</dt> <dd>VM Spec name</dd>
+ * <dt>java.vm.version</dt> <dd>VM implementation version</dd>
+ * <dt>java.vm.vendor</dt> <dd>VM implementation vendor</dd>
+ * <dt>java.vm.name</dt> <dd>VM implementation name</dd>
+ * <dt>java.specification.version</dt> <dd>Java Runtime Environment version</dd>
+ * <dt>java.specification.vendor</dt> <dd>Java Runtime Environment vendor</dd>
+ * <dt>java.specification.name</dt> <dd>Java Runtime Environment name</dd>
+ * <dt>java.class.version</dt> <dd>Java class version number</dd>
+ * <dt>java.class.path</dt> <dd>Java classpath</dd>
+ * <dt>java.library.path</dt> <dd>Path for finding Java libraries</dd>
+ * <dt>java.io.tmpdir</dt> <dd>Default temp file path</dd>
+ * <dt>java.compiler</dt> <dd>Name of JIT to use</dd>
+ * <dt>java.ext.dirs</dt> <dd>Java extension path</dd>
+ * <dt>os.name</dt> <dd>Operating System Name</dd>
+ * <dt>os.arch</dt> <dd>Operating System Architecture</dd>
+ * <dt>os.version</dt> <dd>Operating System Version</dd>
+ * <dt>file.separator</dt> <dd>File separator ("/" on Unix)</dd>
+ * <dt>path.separator</dt> <dd>Path separator (":" on Unix)</dd>
+ * <dt>line.separator</dt> <dd>Line separator ("\n" on Unix)</dd>
+ * <dt>user.name</dt> <dd>User account name</dd>
+ * <dt>user.home</dt> <dd>User home directory</dd>
+ * <dt>user.dir</dt> <dd>User's current working directory</dd>
+ * </dl>
+ *
+ * In addition, gnu defines several other properties, where ? stands for
+ * each character in '0' through '9':
+ * <dl>
+ * <dt>gnu.classpath.home</dt> <dd>Path to the classpath libraries.</dd>
+ * <dt>gnu.classpath.version</dt> <dd>Version of the classpath libraries.</dd>
+ * <dt>gnu.classpath.vm.shortname</dt> <dd>Succinct version of the VM name;
+ * used for finding property files in file system</dd>
+ * <dt>gnu.classpath.home.url</dt> <dd> Base URL; used for finding
+ * property files in file system</dd>
+ * <dt>gnu.cpu.endian</dt> <dd>big or little</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.iso-8859-?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.iso8859_?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.iso-latin-_?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.latin?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.utf-8</dt> <dd>UTF8</dd>
+ * </dl>
+ *
+ * @return the system properties, will never be null
+ * @throws SecurityException if permission is denied
+ */
+ public static Properties getProperties()
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPropertiesAccess();
+ return SystemProperties.getProperties();
+ }
+
+ /**
+ * Set all the system properties at once. A security check may be performed,
+ * <code>checkPropertiesAccess</code>. Note that a security manager may
+ * allow setting a single property, but not the entire group. An argument
+ * of null resets the properties to the startup default.
+ *
+ * @param properties the new set of system properties
+ * @throws SecurityException if permission is denied
+ */
+ public static void setProperties(Properties properties)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPropertiesAccess();
+ SystemProperties.setProperties(properties);
+ }
+
+ /**
+ * Get a single system property by name. A security check may be performed,
+ * <code>checkPropertyAccess(key)</code>.
+ *
+ * @param key the name of the system property to get
+ * @return the property, or null if not found
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if key is null
+ * @throws IllegalArgumentException if key is ""
+ */
+ public static String getProperty(String key)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPropertyAccess(key);
+ else if (key.length() == 0)
+ throw new IllegalArgumentException("key can't be empty");
+ return SystemProperties.getProperty(key);
+ }
+
+ /**
+ * Get a single system property by name. A security check may be performed,
+ * <code>checkPropertyAccess(key)</code>.
+ *
+ * @param key the name of the system property to get
+ * @param def the default
+ * @return the property, or def if not found
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if key is null
+ * @throws IllegalArgumentException if key is ""
+ */
+ public static String getProperty(String key, String def)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPropertyAccess(key);
+ return SystemProperties.getProperty(key, def);
+ }
+
+ /**
+ * Set a single system property by name. A security check may be performed,
+ * <code>checkPropertyAccess(key, "write")</code>.
+ *
+ * @param key the name of the system property to set
+ * @param value the new value
+ * @return the previous value, or null
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if key is null
+ * @throws IllegalArgumentException if key is ""
+ * @since 1.2
+ */
+ public static String setProperty(String key, String value)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(key, "write"));
+ return SystemProperties.setProperty(key, value);
+ }
+
+ /**
+ * Gets the value of an environment variable.
+ *
+ * @param name the name of the environment variable
+ * @return the string value of the variable or null when the
+ * environment variable is not defined.
+ * @throws NullPointerException
+ * @throws SecurityException if permission is denied
+ * @since 1.5
+ * @specnote This method was deprecated in some JDK releases, but
+ * was restored in 1.5.
+ */
+ public static String getenv(String name)
+ {
+ if (name == null)
+ throw new NullPointerException();
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("getenv." + name));
+ return VMSystem.getenv(name);
+ }
+
+ /**
+ * Terminate the Virtual Machine. This just calls
+ * <code>Runtime.getRuntime().exit(status)</code>, and never returns.
+ * Obviously, a security check is in order, <code>checkExit</code>.
+ *
+ * @param status the exit status; by convention non-zero is abnormal
+ * @throws SecurityException if permission is denied
+ * @see Runtime#exit(int)
+ */
+ public static void exit(int status)
+ {
+ Runtime.getRuntime().exit(status);
+ }
+
+ /**
+ * Calls the garbage collector. This is only a hint, and it is up to the
+ * implementation what this hint suggests, but it usually causes a
+ * best-effort attempt to reclaim unused memory from discarded objects.
+ * This calls <code>Runtime.getRuntime().gc()</code>.
+ *
+ * @see Runtime#gc()
+ */
+ public static void gc()
+ {
+ Runtime.getRuntime().gc();
+ }
+
+ /**
+ * Runs object finalization on pending objects. This is only a hint, and
+ * it is up to the implementation what this hint suggests, but it usually
+ * causes a best-effort attempt to run finalizers on all objects ready
+ * to be reclaimed. This calls
+ * <code>Runtime.getRuntime().runFinalization()</code>.
+ *
+ * @see Runtime#runFinalization()
+ */
+ public static void runFinalization()
+ {
+ Runtime.getRuntime().runFinalization();
+ }
+
+ /**
+ * Tell the Runtime whether to run finalization before exiting the
+ * JVM. This is inherently unsafe in multi-threaded applications,
+ * since it can force initialization on objects which are still in use
+ * by live threads, leading to deadlock; therefore this is disabled by
+ * default. There may be a security check, <code>checkExit(0)</code>. This
+ * calls <code>Runtime.runFinalizersOnExit()</code>.
+ *
+ * @param finalizeOnExit whether to run finalizers on exit
+ * @throws SecurityException if permission is denied
+ * @see Runtime#runFinalizersOnExit()
+ * @since 1.1
+ * @deprecated never rely on finalizers to do a clean, thread-safe,
+ * mop-up from your code
+ */
+ public static void runFinalizersOnExit(boolean finalizeOnExit)
+ {
+ Runtime.runFinalizersOnExit(finalizeOnExit);
+ }
+
+ /**
+ * Load a code file using its explicit system-dependent filename. A security
+ * check may be performed, <code>checkLink</code>. This just calls
+ * <code>Runtime.getRuntime().load(filename)</code>.
+ *
+ * <p>
+ * The library is loaded using the class loader associated with the
+ * class associated with the invoking method.
+ *
+ * @param filename the code file to load
+ * @throws SecurityException if permission is denied
+ * @throws UnsatisfiedLinkError if the file cannot be loaded
+ * @see Runtime#load(String)
+ */
+ public static void load(String filename)
+ {
+ Runtime.getRuntime().load(filename, VMStackWalker.getCallingClassLoader());
+ }
+
+ /**
+ * Load a library using its explicit system-dependent filename. A security
+ * check may be performed, <code>checkLink</code>. This just calls
+ * <code>Runtime.getRuntime().load(filename)</code>.
+ *
+ * <p>
+ * The library is loaded using the class loader associated with the
+ * class associated with the invoking method.
+ *
+ * @param libname the library file to load
+ * @throws SecurityException if permission is denied
+ * @throws UnsatisfiedLinkError if the file cannot be loaded
+ * @see Runtime#load(String)
+ */
+ public static void loadLibrary(String libname)
+ {
+ Runtime.getRuntime().loadLibrary(libname,
+ VMStackWalker.getCallingClassLoader());
+ }
+
+ /**
+ * Convert a library name to its platform-specific variant.
+ *
+ * @param libname the library name, as used in <code>loadLibrary</code>
+ * @return the platform-specific mangling of the name
+ * @since 1.2
+ */
+ public static String mapLibraryName(String libname)
+ {
+ return VMRuntime.mapLibraryName(libname);
+ }
+
+} // class System
diff --git a/libjava/classpath/java/lang/Thread.java b/libjava/classpath/java/lang/Thread.java
new file mode 100644
index 00000000000..37ca630b4ed
--- /dev/null
+++ b/libjava/classpath/java/lang/Thread.java
@@ -0,0 +1,999 @@
+/* Thread -- an independent thread of executable code
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete to version 1.4, with caveats. We do not
+ * implement the deprecated (and dangerous) stop, suspend, and resume
+ * methods. Security implementation is not complete.
+ */
+
+/**
+ * Thread represents a single thread of execution in the VM. When an
+ * application VM starts up, it creates a non-daemon Thread which calls the
+ * main() method of a particular class. There may be other Threads running,
+ * such as the garbage collection thread.
+ *
+ * <p>Threads have names to identify them. These names are not necessarily
+ * unique. Every Thread has a priority, as well, which tells the VM which
+ * Threads should get more running time. New threads inherit the priority
+ * and daemon status of the parent thread, by default.
+ *
+ * <p>There are two methods of creating a Thread: you may subclass Thread and
+ * implement the <code>run()</code> method, at which point you may start the
+ * Thread by calling its <code>start()</code> method, or you may implement
+ * <code>Runnable</code> in the class you want to use and then call new
+ * <code>Thread(your_obj).start()</code>.
+ *
+ * <p>The virtual machine runs until all non-daemon threads have died (either
+ * by returning from the run() method as invoked by start(), or by throwing
+ * an uncaught exception); or until <code>System.exit</code> is called with
+ * adequate permissions.
+ *
+ * <p>It is unclear at what point a Thread should be added to a ThreadGroup,
+ * and at what point it should be removed. Should it be inserted when it
+ * starts, or when it is created? Should it be removed when it is suspended
+ * or interrupted? The only thing that is clear is that the Thread should be
+ * removed when it is stopped.
+ *
+ * @author Tom Tromey
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Runnable
+ * @see Runtime#exit(int)
+ * @see #run()
+ * @see #start()
+ * @see ThreadLocal
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Thread implements Runnable
+{
+ /** The minimum priority for a Thread. */
+ public static final int MIN_PRIORITY = 1;
+
+ /** The priority a Thread gets by default. */
+ public static final int NORM_PRIORITY = 5;
+
+ /** The maximum priority for a Thread. */
+ public static final int MAX_PRIORITY = 10;
+
+ /** The underlying VM thread, only set when the thread is actually running.
+ */
+ volatile VMThread vmThread;
+
+ /**
+ * The group this thread belongs to. This is set to null by
+ * ThreadGroup.removeThread when the thread dies.
+ */
+ volatile ThreadGroup group;
+
+ /** The object to run(), null if this is the target. */
+ final Runnable runnable;
+
+ /** The thread name, non-null. */
+ volatile String name;
+
+ /** Whether the thread is a daemon. */
+ volatile boolean daemon;
+
+ /** The thread priority, 1 to 10. */
+ volatile int priority;
+
+ /** Native thread stack size. 0 = use default */
+ private long stacksize;
+
+ /** Was the thread stopped before it was started? */
+ Throwable stillborn;
+
+ /** The context classloader for this Thread. */
+ private ClassLoader contextClassLoader;
+
+ /** The next thread number to use. */
+ private static int numAnonymousThreadsCreated;
+
+ /** Thread local storage. Package accessible for use by
+ * InheritableThreadLocal.
+ */
+ WeakHashMap locals;
+
+ /**
+ * Allocates a new <code>Thread</code> object. This constructor has
+ * the same effect as <code>Thread(null, null,</code>
+ * <i>gname</i><code>)</code>, where <b><i>gname</i></b> is
+ * a newly generated name. Automatically generated names are of the
+ * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
+ * <p>
+ * Threads created this way must have overridden their
+ * <code>run()</code> method to actually do anything. An example
+ * illustrating this method being used follows:
+ * <p><blockquote><pre>
+ * import java.lang.*;
+ *
+ * class plain01 implements Runnable {
+ * String name;
+ * plain01() {
+ * name = null;
+ * }
+ * plain01(String s) {
+ * name = s;
+ * }
+ * public void run() {
+ * if (name == null)
+ * System.out.println("A new thread created");
+ * else
+ * System.out.println("A new thread with name " + name +
+ * " created");
+ * }
+ * }
+ * class threadtest01 {
+ * public static void main(String args[] ) {
+ * int failed = 0 ;
+ *
+ * <b>Thread t1 = new Thread();</b>
+ * if (t1 != null)
+ * System.out.println("new Thread() succeed");
+ * else {
+ * System.out.println("new Thread() failed");
+ * failed++;
+ * }
+ * }
+ * }
+ * </pre></blockquote>
+ *
+ * @see java.lang.Thread#Thread(java.lang.ThreadGroup,
+ * java.lang.Runnable, java.lang.String)
+ */
+ public Thread()
+ {
+ this(null, (Runnable) null);
+ }
+
+ /**
+ * Allocates a new <code>Thread</code> object. This constructor has
+ * the same effect as <code>Thread(null, target,</code>
+ * <i>gname</i><code>)</code>, where <i>gname</i> is
+ * a newly generated name. Automatically generated names are of the
+ * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
+ *
+ * @param target the object whose <code>run</code> method is called.
+ * @see java.lang.Thread#Thread(java.lang.ThreadGroup,
+ * java.lang.Runnable, java.lang.String)
+ */
+ public Thread(Runnable target)
+ {
+ this(null, target);
+ }
+
+ /**
+ * Allocates a new <code>Thread</code> object. This constructor has
+ * the same effect as <code>Thread(null, null, name)</code>.
+ *
+ * @param name the name of the new thread.
+ * @see java.lang.Thread#Thread(java.lang.ThreadGroup,
+ * java.lang.Runnable, java.lang.String)
+ */
+ public Thread(String name)
+ {
+ this(null, null, name, 0);
+ }
+
+ /**
+ * Allocates a new <code>Thread</code> object. This constructor has
+ * the same effect as <code>Thread(group, target,</code>
+ * <i>gname</i><code>)</code>, where <i>gname</i> is
+ * a newly generated name. Automatically generated names are of the
+ * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
+ *
+ * @param group the group to put the Thread into
+ * @param target the Runnable object to execute
+ * @throws SecurityException if this thread cannot access <code>group</code>
+ * @throws IllegalThreadStateException if group is destroyed
+ * @see #Thread(ThreadGroup, Runnable, String)
+ */
+ public Thread(ThreadGroup group, Runnable target)
+ {
+ this(group, target, "Thread-" + ++numAnonymousThreadsCreated, 0);
+ }
+
+ /**
+ * Allocates a new <code>Thread</code> object. This constructor has
+ * the same effect as <code>Thread(group, null, name)</code>
+ *
+ * @param group the group to put the Thread into
+ * @param name the name for the Thread
+ * @throws NullPointerException if name is null
+ * @throws SecurityException if this thread cannot access <code>group</code>
+ * @throws IllegalThreadStateException if group is destroyed
+ * @see #Thread(ThreadGroup, Runnable, String)
+ */
+ public Thread(ThreadGroup group, String name)
+ {
+ this(group, null, name, 0);
+ }
+
+ /**
+ * Allocates a new <code>Thread</code> object. This constructor has
+ * the same effect as <code>Thread(null, target, name)</code>.
+ *
+ * @param target the Runnable object to execute
+ * @param name the name for the Thread
+ * @throws NullPointerException if name is null
+ * @see #Thread(ThreadGroup, Runnable, String)
+ */
+ public Thread(Runnable target, String name)
+ {
+ this(null, target, name, 0);
+ }
+
+ /**
+ * Allocate a new Thread object, with the specified ThreadGroup and name, and
+ * using the specified Runnable object's <code>run()</code> method to
+ * execute. If the Runnable object is null, <code>this</code> (which is
+ * a Runnable) is used instead.
+ *
+ * <p>If the ThreadGroup is null, the security manager is checked. If a
+ * manager exists and returns a non-null object for
+ * <code>getThreadGroup</code>, that group is used; otherwise the group
+ * of the creating thread is used. Note that the security manager calls
+ * <code>checkAccess</code> if the ThreadGroup is not null.
+ *
+ * <p>The new Thread will inherit its creator's priority and daemon status.
+ * These can be changed with <code>setPriority</code> and
+ * <code>setDaemon</code>.
+ *
+ * @param group the group to put the Thread into
+ * @param target the Runnable object to execute
+ * @param name the name for the Thread
+ * @throws NullPointerException if name is null
+ * @throws SecurityException if this thread cannot access <code>group</code>
+ * @throws IllegalThreadStateException if group is destroyed
+ * @see Runnable#run()
+ * @see #run()
+ * @see #setDaemon(boolean)
+ * @see #setPriority(int)
+ * @see SecurityManager#checkAccess(ThreadGroup)
+ * @see ThreadGroup#checkAccess()
+ */
+ public Thread(ThreadGroup group, Runnable target, String name)
+ {
+ this(group, target, name, 0);
+ }
+
+ /**
+ * Allocate a new Thread object, as if by
+ * <code>Thread(group, null, name)</code>, and give it the specified stack
+ * size, in bytes. The stack size is <b>highly platform independent</b>,
+ * and the virtual machine is free to round up or down, or ignore it
+ * completely. A higher value might let you go longer before a
+ * <code>StackOverflowError</code>, while a lower value might let you go
+ * longer before an <code>OutOfMemoryError</code>. Or, it may do absolutely
+ * nothing! So be careful, and expect to need to tune this value if your
+ * virtual machine even supports it.
+ *
+ * @param group the group to put the Thread into
+ * @param target the Runnable object to execute
+ * @param name the name for the Thread
+ * @param size the stack size, in bytes; 0 to be ignored
+ * @throws NullPointerException if name is null
+ * @throws SecurityException if this thread cannot access <code>group</code>
+ * @throws IllegalThreadStateException if group is destroyed
+ * @since 1.4
+ */
+ public Thread(ThreadGroup group, Runnable target, String name, long size)
+ {
+ // Bypass System.getSecurityManager, for bootstrap efficiency.
+ SecurityManager sm = SecurityManager.current;
+ Thread current = currentThread();
+ if (group == null)
+ {
+ if (sm != null)
+ group = sm.getThreadGroup();
+ if (group == null)
+ group = current.group;
+ }
+ else if (sm != null)
+ sm.checkAccess(group);
+
+ this.group = group;
+ // Use toString hack to detect null.
+ this.name = name.toString();
+ this.runnable = target;
+ this.stacksize = size;
+
+ priority = current.priority;
+ daemon = current.daemon;
+ contextClassLoader = current.contextClassLoader;
+
+ group.addThread(this);
+ InheritableThreadLocal.newChildThread(this);
+ }
+
+ /**
+ * Used by the VM to create thread objects for threads started outside
+ * of Java. Note: caller is responsible for adding the thread to
+ * a group and InheritableThreadLocal.
+ *
+ * @param vmThread the native thread
+ * @param name the thread name or null to use the default naming scheme
+ * @param priority current priority
+ * @param daemon is the thread a background thread?
+ */
+ Thread(VMThread vmThread, String name, int priority, boolean daemon)
+ {
+ this.vmThread = vmThread;
+ this.runnable = null;
+ if (name == null)
+ name = "Thread-" + ++numAnonymousThreadsCreated;
+ this.name = name;
+ this.priority = priority;
+ this.daemon = daemon;
+ this.contextClassLoader = ClassLoader.getSystemClassLoader();
+ }
+
+ /**
+ * Get the number of active threads in the current Thread's ThreadGroup.
+ * This implementation calls
+ * <code>currentThread().getThreadGroup().activeCount()</code>.
+ *
+ * @return the number of active threads in the current ThreadGroup
+ * @see ThreadGroup#activeCount()
+ */
+ public static int activeCount()
+ {
+ return currentThread().group.activeCount();
+ }
+
+ /**
+ * Check whether the current Thread is allowed to modify this Thread. This
+ * passes the check on to <code>SecurityManager.checkAccess(this)</code>.
+ *
+ * @throws SecurityException if the current Thread cannot modify this Thread
+ * @see SecurityManager#checkAccess(Thread)
+ */
+ public final void checkAccess()
+ {
+ // Bypass System.getSecurityManager, for bootstrap efficiency.
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ sm.checkAccess(this);
+ }
+
+ /**
+ * Count the number of stack frames in this Thread. The Thread in question
+ * must be suspended when this occurs.
+ *
+ * @return the number of stack frames in this Thread
+ * @throws IllegalThreadStateException if this Thread is not suspended
+ * @deprecated pointless, since suspend is deprecated
+ */
+ public int countStackFrames()
+ {
+ VMThread t = vmThread;
+ if (t == null || group == null)
+ throw new IllegalThreadStateException();
+
+ return t.countStackFrames();
+ }
+
+ /**
+ * Get the currently executing Thread. In the situation that the
+ * currently running thread was created by native code and doesn't
+ * have an associated Thread object yet, a new Thread object is
+ * constructed and associated with the native thread.
+ *
+ * @return the currently executing Thread
+ */
+ public static Thread currentThread()
+ {
+ return VMThread.currentThread();
+ }
+
+ /**
+ * Originally intended to destroy this thread, this method was never
+ * implemented by Sun, and is hence a no-op.
+ */
+ public void destroy()
+ {
+ throw new NoSuchMethodError();
+ }
+
+ /**
+ * Print a stack trace of the current thread to stderr using the same
+ * format as Throwable's printStackTrace() method.
+ *
+ * @see Throwable#printStackTrace()
+ */
+ public static void dumpStack()
+ {
+ new Throwable().printStackTrace();
+ }
+
+ /**
+ * Copy every active thread in the current Thread's ThreadGroup into the
+ * array. Extra threads are silently ignored. This implementation calls
+ * <code>getThreadGroup().enumerate(array)</code>, which may have a
+ * security check, <code>checkAccess(group)</code>.
+ *
+ * @param array the array to place the Threads into
+ * @return the number of Threads placed into the array
+ * @throws NullPointerException if array is null
+ * @throws SecurityException if you cannot access the ThreadGroup
+ * @see ThreadGroup#enumerate(Thread[])
+ * @see #activeCount()
+ * @see SecurityManager#checkAccess(ThreadGroup)
+ */
+ public static int enumerate(Thread[] array)
+ {
+ return currentThread().group.enumerate(array);
+ }
+
+ /**
+ * Get this Thread's name.
+ *
+ * @return this Thread's name
+ */
+ public final String getName()
+ {
+ VMThread t = vmThread;
+ return t == null ? name : t.getName();
+ }
+
+ /**
+ * Get this Thread's priority.
+ *
+ * @return the Thread's priority
+ */
+ public final synchronized int getPriority()
+ {
+ VMThread t = vmThread;
+ return t == null ? priority : t.getPriority();
+ }
+
+ /**
+ * Get the ThreadGroup this Thread belongs to. If the thread has died, this
+ * returns null.
+ *
+ * @return this Thread's ThreadGroup
+ */
+ public final ThreadGroup getThreadGroup()
+ {
+ return group;
+ }
+
+ /**
+ * Checks whether the current thread holds the monitor on a given object.
+ * This allows you to do <code>assert Thread.holdsLock(obj)</code>.
+ *
+ * @param obj the object to test lock ownership on.
+ * @return true if the current thread is currently synchronized on obj
+ * @throws NullPointerException if obj is null
+ * @since 1.4
+ */
+ public static boolean holdsLock(Object obj)
+ {
+ return VMThread.holdsLock(obj);
+ }
+
+ /**
+ * Interrupt this Thread. First, there is a security check,
+ * <code>checkAccess</code>. Then, depending on the current state of the
+ * thread, various actions take place:
+ *
+ * <p>If the thread is waiting because of {@link #wait()},
+ * {@link #sleep(long)}, or {@link #join()}, its <i>interrupt status</i>
+ * will be cleared, and an InterruptedException will be thrown. Notice that
+ * this case is only possible if an external thread called interrupt().
+ *
+ * <p>If the thread is blocked in an interruptible I/O operation, in
+ * {@link java.nio.channels.InterruptibleChannel}, the <i>interrupt
+ * status</i> will be set, and ClosedByInterruptException will be thrown.
+ *
+ * <p>If the thread is blocked on a {@link java.nio.channels.Selector}, the
+ * <i>interrupt status</i> will be set, and the selection will return, with
+ * a possible non-zero value, as though by the wakeup() method.
+ *
+ * <p>Otherwise, the interrupt status will be set.
+ *
+ * @throws SecurityException if you cannot modify this Thread
+ */
+ public synchronized void interrupt()
+ {
+ checkAccess();
+ VMThread t = vmThread;
+ if (t != null)
+ t.interrupt();
+ }
+
+ /**
+ * Determine whether the current Thread has been interrupted, and clear
+ * the <i>interrupted status</i> in the process.
+ *
+ * @return whether the current Thread has been interrupted
+ * @see #isInterrupted()
+ */
+ public static boolean interrupted()
+ {
+ return VMThread.interrupted();
+ }
+
+ /**
+ * Determine whether the given Thread has been interrupted, but leave
+ * the <i>interrupted status</i> alone in the process.
+ *
+ * @return whether the Thread has been interrupted
+ * @see #interrupted()
+ */
+ public boolean isInterrupted()
+ {
+ VMThread t = vmThread;
+ return t != null && t.isInterrupted();
+ }
+
+ /**
+ * Determine whether this Thread is alive. A thread which is alive has
+ * started and not yet died.
+ *
+ * @return whether this Thread is alive
+ */
+ public final boolean isAlive()
+ {
+ return vmThread != null && group != null;
+ }
+
+ /**
+ * Tell whether this is a daemon Thread or not.
+ *
+ * @return whether this is a daemon Thread or not
+ * @see #setDaemon(boolean)
+ */
+ public final boolean isDaemon()
+ {
+ VMThread t = vmThread;
+ return t == null ? daemon : t.isDaemon();
+ }
+
+ /**
+ * Wait forever for the Thread in question to die.
+ *
+ * @throws InterruptedException if the Thread is interrupted; it's
+ * <i>interrupted status</i> will be cleared
+ */
+ public final void join() throws InterruptedException
+ {
+ join(0, 0);
+ }
+
+ /**
+ * Wait the specified amount of time for the Thread in question to die.
+ *
+ * @param ms the number of milliseconds to wait, or 0 for forever
+ * @throws InterruptedException if the Thread is interrupted; it's
+ * <i>interrupted status</i> will be cleared
+ */
+ public final void join(long ms) throws InterruptedException
+ {
+ join(ms, 0);
+ }
+
+ /**
+ * Wait the specified amount of time for the Thread in question to die.
+ *
+ * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
+ * not offer that fine a grain of timing resolution. Besides, there is
+ * no guarantee that this thread can start up immediately when time expires,
+ * because some other thread may be active. So don't expect real-time
+ * performance.
+ *
+ * @param ms the number of milliseconds to wait, or 0 for forever
+ * @param ns the number of extra nanoseconds to sleep (0-999999)
+ * @throws InterruptedException if the Thread is interrupted; it's
+ * <i>interrupted status</i> will be cleared
+ * @throws IllegalArgumentException if ns is invalid
+ */
+ public final void join(long ms, int ns) throws InterruptedException
+ {
+ if(ms < 0 || ns < 0 || ns > 999999)
+ throw new IllegalArgumentException();
+
+ VMThread t = vmThread;
+ if(t != null)
+ t.join(ms, ns);
+ }
+
+ /**
+ * Resume this Thread. If the thread is not suspended, this method does
+ * nothing. To mirror suspend(), there may be a security check:
+ * <code>checkAccess</code>.
+ *
+ * @throws SecurityException if you cannot resume the Thread
+ * @see #checkAccess()
+ * @see #suspend()
+ * @deprecated pointless, since suspend is deprecated
+ */
+ public final synchronized void resume()
+ {
+ checkAccess();
+ VMThread t = vmThread;
+ if (t != null)
+ t.resume();
+ }
+
+ /**
+ * The method of Thread that will be run if there is no Runnable object
+ * associated with the Thread. Thread's implementation does nothing at all.
+ *
+ * @see #start()
+ * @see #Thread(ThreadGroup, Runnable, String)
+ */
+ public void run()
+ {
+ if (runnable != null)
+ runnable.run();
+ }
+
+ /**
+ * Set the daemon status of this Thread. If this is a daemon Thread, then
+ * the VM may exit even if it is still running. This may only be called
+ * before the Thread starts running. There may be a security check,
+ * <code>checkAccess</code>.
+ *
+ * @param daemon whether this should be a daemon thread or not
+ * @throws SecurityException if you cannot modify this Thread
+ * @throws IllegalThreadStateException if the Thread is active
+ * @see #isDaemon()
+ * @see #checkAccess()
+ */
+ public final synchronized void setDaemon(boolean daemon)
+ {
+ if (vmThread != null)
+ throw new IllegalThreadStateException();
+ checkAccess();
+ this.daemon = daemon;
+ }
+
+ /**
+ * Returns the context classloader of this Thread. The context
+ * classloader can be used by code that want to load classes depending
+ * on the current thread. Normally classes are loaded depending on
+ * the classloader of the current class. There may be a security check
+ * for <code>RuntimePermission("getClassLoader")</code> if the caller's
+ * class loader is not null or an ancestor of this thread's context class
+ * loader.
+ *
+ * @return the context class loader
+ * @throws SecurityException when permission is denied
+ * @see setContextClassLoader(ClassLoader)
+ * @since 1.2
+ */
+ public synchronized ClassLoader getContextClassLoader()
+ {
+ // Bypass System.getSecurityManager, for bootstrap efficiency.
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ // XXX Don't check this if the caller's class loader is an ancestor.
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ return contextClassLoader;
+ }
+
+ /**
+ * Sets the context classloader for this Thread. When not explicitly set,
+ * the context classloader for a thread is the same as the context
+ * classloader of the thread that created this thread. The first thread has
+ * as context classloader the system classloader. There may be a security
+ * check for <code>RuntimePermission("setContextClassLoader")</code>.
+ *
+ * @param classloader the new context class loader
+ * @throws SecurityException when permission is denied
+ * @see getContextClassLoader()
+ * @since 1.2
+ */
+ public synchronized void setContextClassLoader(ClassLoader classloader)
+ {
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setContextClassLoader"));
+ this.contextClassLoader = classloader;
+ }
+
+ /**
+ * Set this Thread's name. There may be a security check,
+ * <code>checkAccess</code>.
+ *
+ * @param name the new name for this Thread
+ * @throws NullPointerException if name is null
+ * @throws SecurityException if you cannot modify this Thread
+ */
+ public final synchronized void setName(String name)
+ {
+ checkAccess();
+ // The Class Libraries book says ``threadName cannot be null''. I
+ // take this to mean NullPointerException.
+ if (name == null)
+ throw new NullPointerException();
+ VMThread t = vmThread;
+ if (t != null)
+ t.setName(name);
+ else
+ this.name = name;
+ }
+
+ /**
+ * Yield to another thread. The Thread will not lose any locks it holds
+ * during this time. There are no guarantees which thread will be
+ * next to run, and it could even be this one, but most VMs will choose
+ * the highest priority thread that has been waiting longest.
+ */
+ public static void yield()
+ {
+ VMThread.yield();
+ }
+
+ /**
+ * Suspend the current Thread's execution for the specified amount of
+ * time. The Thread will not lose any locks it has during this time. There
+ * are no guarantees which thread will be next to run, but most VMs will
+ * choose the highest priority thread that has been waiting longest.
+ *
+ * @param ms the number of milliseconds to sleep.
+ * @throws InterruptedException if the Thread is (or was) interrupted;
+ * it's <i>interrupted status</i> will be cleared
+ * @throws IllegalArgumentException if ms is negative
+ * @see #interrupt()
+ */
+ public static void sleep(long ms) throws InterruptedException
+ {
+ sleep(ms, 0);
+ }
+
+ /**
+ * Suspend the current Thread's execution for the specified amount of
+ * time. The Thread will not lose any locks it has during this time. There
+ * are no guarantees which thread will be next to run, but most VMs will
+ * choose the highest priority thread that has been waiting longest.
+ * <p>
+ * Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs
+ * do not offer that fine a grain of timing resolution. When ms is
+ * zero and ns is non-zero the Thread will sleep for at least one
+ * milli second. There is no guarantee that this thread can start up
+ * immediately when time expires, because some other thread may be
+ * active. So don't expect real-time performance.
+ *
+ * @param ms the number of milliseconds to sleep
+ * @param ns the number of extra nanoseconds to sleep (0-999999)
+ * @throws InterruptedException if the Thread is (or was) interrupted;
+ * it's <i>interrupted status</i> will be cleared
+ * @throws IllegalArgumentException if ms or ns is negative
+ * or ns is larger than 999999.
+ * @see #interrupt()
+ */
+ public static void sleep(long ms, int ns) throws InterruptedException
+ {
+
+ // Check parameters
+ if (ms < 0 || ns < 0 || ns > 999999)
+ throw new IllegalArgumentException();
+
+ // Really sleep
+ VMThread.sleep(ms, ns);
+ }
+
+ /**
+ * Start this Thread, calling the run() method of the Runnable this Thread
+ * was created with, or else the run() method of the Thread itself. This
+ * is the only way to start a new thread; calling run by yourself will just
+ * stay in the same thread. The virtual machine will remove the thread from
+ * its thread group when the run() method completes.
+ *
+ * @throws IllegalThreadStateException if the thread has already started
+ * @see #run()
+ */
+ public synchronized void start()
+ {
+ if (vmThread != null || group == null)
+ throw new IllegalThreadStateException();
+
+ VMThread.create(this, stacksize);
+ }
+
+ /**
+ * Cause this Thread to stop abnormally because of the throw of a ThreadDeath
+ * error. If you stop a Thread that has not yet started, it will stop
+ * immediately when it is actually started.
+ *
+ * <p>This is inherently unsafe, as it can interrupt synchronized blocks and
+ * leave data in bad states. Hence, there is a security check:
+ * <code>checkAccess(this)</code>, plus another one if the current thread
+ * is not this: <code>RuntimePermission("stopThread")</code>. If you must
+ * catch a ThreadDeath, be sure to rethrow it after you have cleaned up.
+ * ThreadDeath is the only exception which does not print a stack trace when
+ * the thread dies.
+ *
+ * @throws SecurityException if you cannot stop the Thread
+ * @see #interrupt()
+ * @see #checkAccess()
+ * @see #start()
+ * @see ThreadDeath
+ * @see ThreadGroup#uncaughtException(Thread, Throwable)
+ * @see SecurityManager#checkAccess(Thread)
+ * @see SecurityManager#checkPermission(Permission)
+ * @deprecated unsafe operation, try not to use
+ */
+ public final void stop()
+ {
+ stop(new ThreadDeath());
+ }
+
+ /**
+ * Cause this Thread to stop abnormally and throw the specified exception.
+ * If you stop a Thread that has not yet started, the stop is ignored
+ * (contrary to what the JDK documentation says).
+ * <b>WARNING</b>This bypasses Java security, and can throw a checked
+ * exception which the call stack is unprepared to handle. Do not abuse
+ * this power.
+ *
+ * <p>This is inherently unsafe, as it can interrupt synchronized blocks and
+ * leave data in bad states. Hence, there is a security check:
+ * <code>checkAccess(this)</code>, plus another one if the current thread
+ * is not this: <code>RuntimePermission("stopThread")</code>. If you must
+ * catch a ThreadDeath, be sure to rethrow it after you have cleaned up.
+ * ThreadDeath is the only exception which does not print a stack trace when
+ * the thread dies.
+ *
+ * @param t the Throwable to throw when the Thread dies
+ * @throws SecurityException if you cannot stop the Thread
+ * @throws NullPointerException in the calling thread, if t is null
+ * @see #interrupt()
+ * @see #checkAccess()
+ * @see #start()
+ * @see ThreadDeath
+ * @see ThreadGroup#uncaughtException(Thread, Throwable)
+ * @see SecurityManager#checkAccess(Thread)
+ * @see SecurityManager#checkPermission(Permission)
+ * @deprecated unsafe operation, try not to use
+ */
+ public final synchronized void stop(Throwable t)
+ {
+ if (t == null)
+ throw new NullPointerException();
+ // Bypass System.getSecurityManager, for bootstrap efficiency.
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ {
+ sm.checkAccess(this);
+ if (this != currentThread())
+ sm.checkPermission(new RuntimePermission("stopThread"));
+ }
+ VMThread vt = vmThread;
+ if (vt != null)
+ vt.stop(t);
+ else
+ stillborn = t;
+ }
+
+ /**
+ * Suspend this Thread. It will not come back, ever, unless it is resumed.
+ *
+ * <p>This is inherently unsafe, as the suspended thread still holds locks,
+ * and can potentially deadlock your program. Hence, there is a security
+ * check: <code>checkAccess</code>.
+ *
+ * @throws SecurityException if you cannot suspend the Thread
+ * @see #checkAccess()
+ * @see #resume()
+ * @deprecated unsafe operation, try not to use
+ */
+ public final synchronized void suspend()
+ {
+ checkAccess();
+ VMThread t = vmThread;
+ if (t != null)
+ t.suspend();
+ }
+
+ /**
+ * Set this Thread's priority. There may be a security check,
+ * <code>checkAccess</code>, then the priority is set to the smaller of
+ * priority and the ThreadGroup maximum priority.
+ *
+ * @param priority the new priority for this Thread
+ * @throws IllegalArgumentException if priority exceeds MIN_PRIORITY or
+ * MAX_PRIORITY
+ * @throws SecurityException if you cannot modify this Thread
+ * @see #getPriority()
+ * @see #checkAccess()
+ * @see ThreadGroup#getMaxPriority()
+ * @see #MIN_PRIORITY
+ * @see #MAX_PRIORITY
+ */
+ public final synchronized void setPriority(int priority)
+ {
+ checkAccess();
+ if (priority < MIN_PRIORITY || priority > MAX_PRIORITY)
+ throw new IllegalArgumentException("Invalid thread priority value "
+ + priority + ".");
+ priority = Math.min(priority, group.getMaxPriority());
+ VMThread t = vmThread;
+ if (t != null)
+ t.setPriority(priority);
+ else
+ this.priority = priority;
+ }
+
+ /**
+ * Returns a string representation of this thread, including the
+ * thread's name, priority, and thread group.
+ *
+ * @return a human-readable String representing this Thread
+ */
+ public String toString()
+ {
+ return ("Thread[" + name + "," + priority + ","
+ + (group == null ? "" : group.getName()) + "]");
+ }
+
+ /**
+ * Clean up code, called by VMThread when thread dies.
+ */
+ synchronized void die()
+ {
+ group.removeThread(this);
+ vmThread = null;
+ locals = null;
+ }
+
+ /**
+ * Returns the map used by ThreadLocal to store the thread local values.
+ */
+ static Map getThreadLocals()
+ {
+ Thread thread = currentThread();
+ Map locals = thread.locals;
+ if (locals == null)
+ {
+ locals = thread.locals = new WeakHashMap();
+ }
+ return locals;
+ }
+}
diff --git a/libjava/classpath/java/lang/ThreadDeath.java b/libjava/classpath/java/lang/ThreadDeath.java
new file mode 100644
index 00000000000..c7d88fb2a25
--- /dev/null
+++ b/libjava/classpath/java/lang/ThreadDeath.java
@@ -0,0 +1,68 @@
+/* ThreadDeath.java - special exception registering Thread death
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * ThreadDeath is thrown in a thread when someone calls <code>stop()</code>
+ * on that thread. <b>Important:</b> Make sure you rethrow this exception
+ * if you catch it. If you don't, the thread will not die.
+ *
+ * <p>This is an Error rather than an exception, so that normal code will
+ * not catch it. It is intended for asynchronous cleanup when using the
+ * deprecated Thread.stop() method.
+ *
+ * @author John Keiser
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see Thread#stop()
+ * @status updated to 1.4
+ */
+public class ThreadDeath extends Error
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4417128565033088268L;
+
+ /**
+ * Create an error without a message.
+ */
+ public ThreadDeath()
+ {
+ }
+}
diff --git a/libjava/classpath/java/lang/ThreadGroup.java b/libjava/classpath/java/lang/ThreadGroup.java
new file mode 100644
index 00000000000..6e4c27a7135
--- /dev/null
+++ b/libjava/classpath/java/lang/ThreadGroup.java
@@ -0,0 +1,749 @@
+/* ThreadGroup -- a group of Threads
+ Copyright (C) 1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.util.Vector;
+
+/**
+ * ThreadGroup allows you to group Threads together. There is a hierarchy
+ * of ThreadGroups, and only the initial ThreadGroup has no parent. A Thread
+ * may access information about its own ThreadGroup, but not its parents or
+ * others outside the tree.
+ *
+ * @author John Keiser
+ * @author Tom Tromey
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Thread
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class ThreadGroup
+{
+ /** The Initial, top-level ThreadGroup. */
+ static ThreadGroup root = new ThreadGroup();
+
+ /**
+ * This flag is set if an uncaught exception occurs. The runtime should
+ * check this and exit with an error status if it is set.
+ */
+ static boolean had_uncaught_exception;
+
+ /** The parent thread group. */
+ private final ThreadGroup parent;
+
+ /** The group name, non-null. */
+ final String name;
+
+ /** The threads in the group. */
+ private final Vector threads = new Vector();
+
+ /** Child thread groups, or null when this group is destroyed. */
+ private Vector groups = new Vector();
+
+ /** If all threads in the group are daemons. */
+ private boolean daemon_flag = false;
+
+ /** The maximum group priority. */
+ private int maxpri;
+
+ /**
+ * Hidden constructor to build the root node.
+ */
+ private ThreadGroup()
+ {
+ name = "main";
+ parent = null;
+ maxpri = Thread.MAX_PRIORITY;
+ }
+
+ /**
+ * Create a new ThreadGroup using the given name and the current thread's
+ * ThreadGroup as a parent. There may be a security check,
+ * <code>checkAccess</code>.
+ *
+ * @param name the name to use for the ThreadGroup
+ * @throws SecurityException if the current thread cannot create a group
+ * @see #checkAccess()
+ */
+ public ThreadGroup(String name)
+ {
+ this(Thread.currentThread().group, name);
+ }
+
+ /**
+ * Create a new ThreadGroup using the given name and parent group. The new
+ * group inherits the maximum priority and daemon status of its parent
+ * group. There may be a security check, <code>checkAccess</code>.
+ *
+ * @param name the name to use for the ThreadGroup
+ * @param parent the ThreadGroup to use as a parent
+ * @throws NullPointerException if parent is null
+ * @throws SecurityException if the current thread cannot create a group
+ * @throws IllegalThreadStateException if the parent is destroyed
+ * @see #checkAccess()
+ */
+ public ThreadGroup(ThreadGroup parent, String name)
+ {
+ parent.checkAccess();
+ this.parent = parent;
+ this.name = name;
+ maxpri = parent.maxpri;
+ daemon_flag = parent.daemon_flag;
+ synchronized (parent)
+ {
+ if (parent.groups == null)
+ throw new IllegalThreadStateException();
+ parent.groups.add(this);
+ }
+ }
+
+ /**
+ * Get the name of this ThreadGroup.
+ *
+ * @return the name of this ThreadGroup
+ */
+ public final String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Get the parent of this ThreadGroup. If the parent is not null, there
+ * may be a security check, <code>checkAccess</code>.
+ *
+ * @return the parent of this ThreadGroup
+ * @throws SecurityException if permission is denied
+ */
+ public final ThreadGroup getParent()
+ {
+ if (parent != null)
+ parent.checkAccess();
+ return parent;
+ }
+
+ /**
+ * Get the maximum priority of Threads in this ThreadGroup. Threads created
+ * after this call in this group may not exceed this priority.
+ *
+ * @return the maximum priority of Threads in this ThreadGroup
+ */
+ public final int getMaxPriority()
+ {
+ return maxpri;
+ }
+
+ /**
+ * Tell whether this ThreadGroup is a daemon group. A daemon group will
+ * be automatically destroyed when its last thread is stopped and
+ * its last thread group is destroyed.
+ *
+ * @return whether this ThreadGroup is a daemon group
+ */
+ public final boolean isDaemon()
+ {
+ return daemon_flag;
+ }
+
+ /**
+ * Tell whether this ThreadGroup has been destroyed or not.
+ *
+ * @return whether this ThreadGroup has been destroyed or not
+ * @since 1.1
+ */
+ public synchronized boolean isDestroyed()
+ {
+ return groups == null;
+ }
+
+ /**
+ * Set whether this ThreadGroup is a daemon group. A daemon group will be
+ * destroyed when its last thread is stopped and its last thread group is
+ * destroyed. There may be a security check, <code>checkAccess</code>.
+ *
+ * @param daemon whether this ThreadGroup should be a daemon group
+ * @throws SecurityException if you cannot modify this ThreadGroup
+ * @see #checkAccess()
+ */
+ public final void setDaemon(boolean daemon)
+ {
+ checkAccess();
+ daemon_flag = daemon;
+ }
+
+ /**
+ * Set the maximum priority for Threads in this ThreadGroup. setMaxPriority
+ * can only be used to reduce the current maximum. If maxpri is greater
+ * than the current Maximum of the parent group, the current value is not
+ * changed. Otherwise, all groups which belong to this have their priority
+ * adjusted as well. Calling this does not affect threads already in this
+ * ThreadGroup. There may be a security check, <code>checkAccess</code>.
+ *
+ * @param maxpri the new maximum priority for this ThreadGroup
+ * @throws SecurityException if you cannot modify this ThreadGroup
+ * @see #getMaxPriority()
+ * @see #checkAccess()
+ */
+ public final synchronized void setMaxPriority(int maxpri)
+ {
+ checkAccess();
+ if (maxpri < Thread.MIN_PRIORITY || maxpri > Thread.MAX_PRIORITY)
+ return;
+ if (parent != null && maxpri > parent.maxpri)
+ maxpri = parent.maxpri;
+ this.maxpri = maxpri;
+ if (groups == null)
+ return;
+ int i = groups.size();
+ while (--i >= 0)
+ ((ThreadGroup) groups.get(i)).setMaxPriority(maxpri);
+ }
+
+ /**
+ * Check whether this ThreadGroup is an ancestor of the specified
+ * ThreadGroup, or if they are the same.
+ *
+ * @param group the group to test on
+ * @return whether this ThreadGroup is a parent of the specified group
+ */
+ public final boolean parentOf(ThreadGroup group)
+ {
+ while (group != null)
+ {
+ if (group == this)
+ return true;
+ group = group.parent;
+ }
+ return false;
+ }
+
+ /**
+ * Find out if the current Thread can modify this ThreadGroup. This passes
+ * the check on to <code>SecurityManager.checkAccess(this)</code>.
+ *
+ * @throws SecurityException if the current Thread cannot modify this
+ * ThreadGroup
+ * @see SecurityManager#checkAccess(ThreadGroup)
+ */
+ public final void checkAccess()
+ {
+ // Bypass System.getSecurityManager, for bootstrap efficiency.
+ SecurityManager sm = SecurityManager.current;
+ if (sm != null)
+ sm.checkAccess(this);
+ }
+
+ /**
+ * Return an estimate of the total number of active threads in this
+ * ThreadGroup and all its descendants. This cannot return an exact number,
+ * since the status of threads may change after they were counted; but it
+ * should be pretty close. Based on a JDC bug,
+ * <a href="http://developer.java.sun.com/developer/bugParade/bugs/4089701.html">
+ * 4089701</a>, we take active to mean isAlive().
+ *
+ * @return count of active threads in this ThreadGroup and its descendants
+ */
+ public int activeCount()
+ {
+ int total = 0;
+ if (groups == null)
+ return total;
+ int i = threads.size();
+ while (--i >= 0)
+ if (((Thread) threads.get(i)).isAlive())
+ total++;
+ i = groups.size();
+ while (--i >= 0)
+ total += ((ThreadGroup) groups.get(i)).activeCount();
+ return total;
+ }
+
+ /**
+ * Copy all of the active Threads from this ThreadGroup and its descendants
+ * into the specified array. If the array is not big enough to hold all
+ * the Threads, extra Threads will simply not be copied. There may be a
+ * security check, <code>checkAccess</code>.
+ *
+ * @param array the array to put the threads into
+ * @return the number of threads put into the array
+ * @throws SecurityException if permission was denied
+ * @throws NullPointerException if array is null
+ * @throws ArrayStoreException if a thread does not fit in the array
+ * @see #activeCount()
+ * @see #checkAccess()
+ * @see #enumerate(Thread[], boolean)
+ */
+ public int enumerate(Thread[] array)
+ {
+ return enumerate(array, 0, true);
+ }
+
+ /**
+ * Copy all of the active Threads from this ThreadGroup and, if desired,
+ * from its descendants, into the specified array. If the array is not big
+ * enough to hold all the Threads, extra Threads will simply not be copied.
+ * There may be a security check, <code>checkAccess</code>.
+ *
+ * @param array the array to put the threads into
+ * @param recurse whether to recurse into descendent ThreadGroups
+ * @return the number of threads put into the array
+ * @throws SecurityException if permission was denied
+ * @throws NullPointerException if array is null
+ * @throws ArrayStoreException if a thread does not fit in the array
+ * @see #activeCount()
+ * @see #checkAccess()
+ */
+ public int enumerate(Thread[] array, boolean recurse)
+ {
+ return enumerate(array, 0, recurse);
+ }
+
+ /**
+ * Get the number of active groups in this ThreadGroup. This group itself
+ * is not included in the count. A sub-group is active if it has not been
+ * destroyed. This cannot return an exact number, since the status of
+ * threads may change after they were counted; but it should be pretty close.
+ *
+ * @return the number of active groups in this ThreadGroup
+ */
+ public int activeGroupCount()
+ {
+ if (groups == null)
+ return 0;
+ int total = groups.size();
+ int i = total;
+ while (--i >= 0)
+ total += ((ThreadGroup) groups.get(i)).activeGroupCount();
+ return total;
+ }
+
+ /**
+ * Copy all active ThreadGroups that are descendants of this ThreadGroup
+ * into the specified array. If the array is not large enough to hold all
+ * active ThreadGroups, extra ThreadGroups simply will not be copied. There
+ * may be a security check, <code>checkAccess</code>.
+ *
+ * @param array the array to put the ThreadGroups into
+ * @return the number of ThreadGroups copied into the array
+ * @throws SecurityException if permission was denied
+ * @throws NullPointerException if array is null
+ * @throws ArrayStoreException if a group does not fit in the array
+ * @see #activeCount()
+ * @see #checkAccess()
+ * @see #enumerate(ThreadGroup[], boolean)
+ */
+ public int enumerate(ThreadGroup[] array)
+ {
+ return enumerate(array, 0, true);
+ }
+
+ /**
+ * Copy all active ThreadGroups that are children of this ThreadGroup into
+ * the specified array, and if desired, also all descendents. If the array
+ * is not large enough to hold all active ThreadGroups, extra ThreadGroups
+ * simply will not be copied. There may be a security check,
+ * <code>checkAccess</code>.
+ *
+ * @param array the array to put the ThreadGroups into
+ * @param recurse whether to recurse into descendent ThreadGroups
+ * @return the number of ThreadGroups copied into the array
+ * @throws SecurityException if permission was denied
+ * @throws NullPointerException if array is null
+ * @throws ArrayStoreException if a group does not fit in the array
+ * @see #activeCount()
+ * @see #checkAccess()
+ */
+ public int enumerate(ThreadGroup[] array, boolean recurse)
+ {
+ return enumerate(array, 0, recurse);
+ }
+
+ /**
+ * Stop all Threads in this ThreadGroup and its descendants.
+ *
+ * <p>This is inherently unsafe, as it can interrupt synchronized blocks and
+ * leave data in bad states. Hence, there is a security check:
+ * <code>checkAccess()</code>, followed by further checks on each thread
+ * being stopped.
+ *
+ * @throws SecurityException if permission is denied
+ * @see #checkAccess()
+ * @see Thread#stop(Throwable)
+ * @deprecated unsafe operation, try not to use
+ */
+ public final synchronized void stop()
+ {
+ checkAccess();
+ if (groups == null)
+ return;
+ int i = threads.size();
+ while (--i >= 0)
+ ((Thread) threads.get(i)).stop();
+ i = groups.size();
+ while (--i >= 0)
+ ((ThreadGroup) groups.get(i)).stop();
+ }
+
+ /**
+ * Interrupt all Threads in this ThreadGroup and its sub-groups. There may
+ * be a security check, <code>checkAccess</code>.
+ *
+ * @throws SecurityException if permission is denied
+ * @see #checkAccess()
+ * @see Thread#interrupt()
+ * @since 1.2
+ */
+ public final synchronized void interrupt()
+ {
+ checkAccess();
+ if (groups == null)
+ return;
+ int i = threads.size();
+ while (--i >= 0)
+ ((Thread) threads.get(i)).interrupt();
+ i = groups.size();
+ while (--i >= 0)
+ ((ThreadGroup) groups.get(i)).interrupt();
+ }
+
+ /**
+ * Suspend all Threads in this ThreadGroup and its descendants.
+ *
+ * <p>This is inherently unsafe, as suspended threads still hold locks,
+ * which can lead to deadlock. Hence, there is a security check:
+ * <code>checkAccess()</code>, followed by further checks on each thread
+ * being suspended.
+ *
+ * @throws SecurityException if permission is denied
+ * @see #checkAccess()
+ * @see Thread#suspend()
+ * @deprecated unsafe operation, try not to use
+ */
+ public final synchronized void suspend()
+ {
+ checkAccess();
+ if (groups == null)
+ return;
+ int i = threads.size();
+ while (--i >= 0)
+ ((Thread) threads.get(i)).suspend();
+ i = groups.size();
+ while (--i >= 0)
+ ((ThreadGroup) groups.get(i)).suspend();
+ }
+
+ /**
+ * Resume all suspended Threads in this ThreadGroup and its descendants.
+ * To mirror suspend(), there is a security check:
+ * <code>checkAccess()</code>, followed by further checks on each thread
+ * being resumed.
+ *
+ * @throws SecurityException if permission is denied
+ * @see #checkAccess()
+ * @see Thread#suspend()
+ * @deprecated pointless, since suspend is deprecated
+ */
+ public final synchronized void resume()
+ {
+ checkAccess();
+ if (groups == null)
+ return;
+ int i = threads.size();
+ while (--i >= 0)
+ ((Thread) threads.get(i)).resume();
+ i = groups.size();
+ while (--i >= 0)
+ ((ThreadGroup) groups.get(i)).resume();
+ }
+
+ /**
+ * Destroy this ThreadGroup. The group must be empty, meaning that all
+ * threads and sub-groups have completed execution. Daemon groups are
+ * destroyed automatically. There may be a security check,
+ * <code>checkAccess</code>.
+ *
+ * @throws IllegalThreadStateException if the ThreadGroup is not empty, or
+ * was previously destroyed
+ * @throws SecurityException if permission is denied
+ * @see #checkAccess()
+ */
+ public final synchronized void destroy()
+ {
+ checkAccess();
+ if (! threads.isEmpty() || groups == null)
+ throw new IllegalThreadStateException();
+ int i = groups.size();
+ while (--i >= 0)
+ ((ThreadGroup) groups.get(i)).destroy();
+ groups = null;
+ if (parent != null)
+ parent.removeGroup(this);
+ }
+
+ /**
+ * Print out information about this ThreadGroup to System.out. This is
+ * meant for debugging purposes. <b>WARNING:</b> This method is not secure,
+ * and can print the name of threads to standard out even when you cannot
+ * otherwise get at such threads.
+ */
+ public void list()
+ {
+ list("");
+ }
+
+ /**
+ * When a Thread in this ThreadGroup does not catch an exception, the
+ * virtual machine calls this method. The default implementation simply
+ * passes the call to the parent; then in top ThreadGroup, it will
+ * ignore ThreadDeath and print the stack trace of any other throwable.
+ * Override this method if you want to handle the exception in a different
+ * manner.
+ *
+ * @param thread the thread that exited
+ * @param t the uncaught throwable
+ * @throws NullPointerException if t is null
+ * @see ThreadDeath
+ * @see System#err
+ * @see Throwable#printStackTrace()
+ */
+ public void uncaughtException(Thread thread, Throwable t)
+ {
+ if (parent != null)
+ parent.uncaughtException(thread, t);
+ else if (! (t instanceof ThreadDeath))
+ {
+ if (t == null)
+ throw new NullPointerException();
+ had_uncaught_exception = true;
+ try
+ {
+ if (thread != null)
+ System.err.print("Exception in thread \"" + thread.name + "\" ");
+ t.printStackTrace(System.err);
+ }
+ catch (Throwable x)
+ {
+ // This means that something is badly screwed up with the runtime,
+ // or perhaps someone overloaded the Throwable.printStackTrace to
+ // die. In any case, try to deal with it gracefully.
+ try
+ {
+ System.err.println(t);
+ System.err.println("*** Got " + x
+ + " while trying to print stack trace.");
+ }
+ catch (Throwable x2)
+ {
+ // Here, someone may have overloaded t.toString() or
+ // x.toString() to die. Give up all hope; we can't even chain
+ // the exception, because the chain would likewise die.
+ System.err.println("*** Catastrophic failure while handling "
+ + "uncaught exception.");
+ throw new InternalError();
+ }
+ }
+ }
+ }
+
+ /**
+ * Originally intended to tell the VM whether it may suspend Threads in
+ * low memory situations, this method was never implemented by Sun, and
+ * is hence a no-op.
+ *
+ * @param allow whether to allow low-memory thread suspension; ignored
+ * @return false
+ * @since 1.1
+ * @deprecated pointless, since suspend is deprecated
+ */
+ public boolean allowThreadSuspension(boolean allow)
+ {
+ return false;
+ }
+
+ /**
+ * Return a human-readable String representing this ThreadGroup. The format
+ * of the string is:<br>
+ * <code>getClass().getName() + "[name=" + getName() + ",maxpri="
+ * + getMaxPriority() + ']'</code>.
+ *
+ * @return a human-readable String representing this ThreadGroup
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[name=" + name + ",maxpri=" + maxpri + ']';
+ }
+
+ /**
+ * Implements enumerate.
+ *
+ * @param list the array to put the threads into
+ * @param next the next open slot in the array
+ * @param recurse whether to recurse into descendent ThreadGroups
+ * @return the number of threads put into the array
+ * @throws SecurityException if permission was denied
+ * @throws NullPointerException if list is null
+ * @throws ArrayStoreException if a thread does not fit in the array
+ * @see #enumerate(Thread[])
+ * @see #enumerate(Thread[], boolean)
+ */
+ private int enumerate(Thread[] list, int next, boolean recurse)
+ {
+ checkAccess();
+ if (groups == null)
+ return next;
+ int i = threads.size();
+ while (--i >= 0 && next < list.length)
+ {
+ Thread t = (Thread) threads.get(i);
+ if (t.isAlive())
+ list[next++] = t;
+ }
+ if (recurse)
+ {
+ i = groups.size();
+ while (--i >= 0 && next < list.length)
+ {
+ ThreadGroup g = (ThreadGroup) groups.get(i);
+ next = g.enumerate(list, next, true);
+ }
+ }
+ return next;
+ }
+
+ /**
+ * Implements enumerate.
+ *
+ * @param list the array to put the groups into
+ * @param next the next open slot in the array
+ * @param recurse whether to recurse into descendent ThreadGroups
+ * @return the number of groups put into the array
+ * @throws SecurityException if permission was denied
+ * @throws NullPointerException if list is null
+ * @throws ArrayStoreException if a group does not fit in the array
+ * @see #enumerate(ThreadGroup[])
+ * @see #enumerate(ThreadGroup[], boolean)
+ */
+ private int enumerate(ThreadGroup[] list, int next, boolean recurse)
+ {
+ checkAccess();
+ if (groups == null)
+ return next;
+ int i = groups.size();
+ while (--i >= 0 && next < list.length)
+ {
+ ThreadGroup g = (ThreadGroup) groups.get(i);
+ list[next++] = g;
+ if (recurse && next != list.length)
+ next = g.enumerate(list, next, true);
+ }
+ return next;
+ }
+
+ /**
+ * Implements list.
+ *
+ * @param indentation the current level of indentation
+ * @see #list()
+ */
+ private void list(String indentation)
+ {
+ if (groups == null)
+ return;
+ System.out.println(indentation + this);
+ indentation += " ";
+ int i = threads.size();
+ while (--i >= 0)
+ System.out.println(indentation + threads.get(i));
+ i = groups.size();
+ while (--i >= 0)
+ ((ThreadGroup) groups.get(i)).list(indentation);
+ }
+
+ /**
+ * Add a thread to the group. Called by Thread constructors.
+ *
+ * @param t the thread to add, non-null
+ * @throws IllegalThreadStateException if the group is destroyed
+ */
+ final synchronized void addThread(Thread t)
+ {
+ if (groups == null)
+ throw new IllegalThreadStateException("ThreadGroup is destroyed");
+ threads.add(t);
+ }
+
+ /**
+ * Called by the VM to remove a thread that has died.
+ *
+ * @param t the thread to remove, non-null
+ * @XXX A ThreadListener to call this might be nice.
+ */
+ final synchronized void removeThread(Thread t)
+ {
+ if (groups == null)
+ return;
+ threads.remove(t);
+ t.group = null;
+ // Daemon groups are automatically destroyed when all their threads die.
+ if (daemon_flag && groups.size() == 0 && threads.size() == 0)
+ {
+ // We inline destroy to avoid the access check.
+ groups = null;
+ if (parent != null)
+ parent.removeGroup(this);
+ }
+ }
+
+ /**
+ * Called when a group is destroyed, to remove it from its parent.
+ *
+ * @param g the destroyed group, non-null
+ */
+ final synchronized void removeGroup(ThreadGroup g)
+ {
+ groups.remove(g);
+ // Daemon groups are automatically destroyed when all their threads die.
+ if (daemon_flag && groups.size() == 0 && threads.size() == 0)
+ {
+ // We inline destroy to avoid the access check.
+ groups = null;
+ if (parent != null)
+ parent.removeGroup(this);
+ }
+ }
+} // class ThreadGroup
diff --git a/libjava/classpath/java/lang/ThreadLocal.java b/libjava/classpath/java/lang/ThreadLocal.java
new file mode 100644
index 00000000000..0b2b60867b9
--- /dev/null
+++ b/libjava/classpath/java/lang/ThreadLocal.java
@@ -0,0 +1,171 @@
+/* ThreadLocal -- a variable with a unique value per thread
+ Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+
+/**
+ * ThreadLocal objects have a different state associated with every
+ * Thread that accesses them. Every access to the ThreadLocal object
+ * (through the <code>get()</code> and <code>set()</code> methods)
+ * only affects the state of the object as seen by the currently
+ * executing Thread.
+ *
+ * <p>The first time a ThreadLocal object is accessed on a particular
+ * Thread, the state for that Thread's copy of the local variable is set by
+ * executing the method <code>initialValue()</code>.
+ * </p>
+ *
+ * <p>An example how you can use this:
+ * </p>
+ *
+ * <pre>
+ * class Connection
+ * {
+ * private static ThreadLocal owner = new ThreadLocal()
+ * {
+ * public Object initialValue()
+ * {
+ * return("nobody");
+ * }
+ * };
+ * ...
+ * }
+ * </pre>
+ *
+ * <p>Now all instances of connection can see who the owner of the currently
+ * executing Thread is by calling <code>owner.get()</code>. By default any
+ * Thread would be associated with 'nobody'. But the Connection object could
+ * offer a method that changes the owner associated with the Thread on
+ * which the method was called by calling <code>owner.put("somebody")</code>.
+ * (Such an owner changing method should then be guarded by security checks.)
+ * </p>
+ *
+ * <p>When a Thread is garbage collected all references to values of
+ * the ThreadLocal objects associated with that Thread are removed.
+ * </p>
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class ThreadLocal
+{
+ /**
+ * Placeholder to distinguish between uninitialized and null set by the
+ * user. Do not expose this to the public. Package visible for use by
+ * InheritableThreadLocal
+ */
+ static final Object NULL = new Object();
+
+ /**
+ * Serves as a key for the Thread.locals WeakHashMap.
+ * We can't use "this", because a subclass may override equals/hashCode
+ * and we need to use object identity for the map.
+ */
+ final Key key = new Key();
+
+ class Key
+ {
+ ThreadLocal get()
+ {
+ return ThreadLocal.this;
+ }
+ }
+
+ /**
+ * Creates a ThreadLocal object without associating any value to it yet.
+ */
+ public ThreadLocal()
+ {
+ }
+
+ /**
+ * Called once per thread on the first invocation of get(), if set() was
+ * not already called. The default implementation returns <code>null</code>.
+ * Often, this method is overridden to create the appropriate initial object
+ * for the current thread's view of the ThreadLocal.
+ *
+ * @return the initial value of the variable in this thread
+ */
+ protected Object initialValue()
+ {
+ return null;
+ }
+
+ /**
+ * Gets the value associated with the ThreadLocal object for the currently
+ * executing Thread. If this is the first time the current thread has called
+ * get(), and it has not already called set(), the value is obtained by
+ * <code>initialValue()</code>.
+ *
+ * @return the value of the variable in this thread
+ */
+ public Object get()
+ {
+ Map map = Thread.getThreadLocals();
+ // Note that we don't have to synchronize, as only this thread will
+ // ever modify the map.
+ Object value = map.get(key);
+ if (value == null)
+ {
+ value = initialValue();
+ map.put(key, value == null ? NULL : value);
+ }
+ return value == NULL ? null : value;
+ }
+
+ /**
+ * Sets the value associated with the ThreadLocal object for the currently
+ * executing Thread. This overrides any existing value associated with the
+ * current Thread and prevents <code>initialValue()</code> from being
+ * called if this is the first access to this ThreadLocal in this Thread.
+ *
+ * @param value the value to set this thread's view of the variable to
+ */
+ public void set(Object value)
+ {
+ Map map = Thread.getThreadLocals();
+ // Note that we don't have to synchronize, as only this thread will
+ // ever modify the map.
+ map.put(key, value == null ? NULL : value);
+ }
+}
diff --git a/libjava/classpath/java/lang/Throwable.java b/libjava/classpath/java/lang/Throwable.java
new file mode 100644
index 00000000000..c47a14bf040
--- /dev/null
+++ b/libjava/classpath/java/lang/Throwable.java
@@ -0,0 +1,563 @@
+/* java.lang.Throwable -- Root class for all Exceptions and Errors
+ Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import gnu.classpath.SystemProperties;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+
+/**
+ * Throwable is the superclass of all exceptions that can be raised.
+ *
+ * <p>There are two special cases: {@link Error} and {@link RuntimeException}:
+ * these two classes (and their subclasses) are considered unchecked
+ * exceptions, and are either frequent enough or catastrophic enough that you
+ * do not need to declare them in <code>throws</code> clauses. Everything
+ * else is a checked exception, and is ususally a subclass of
+ * {@link Exception}; these exceptions have to be handled or declared.
+ *
+ * <p>Instances of this class are usually created with knowledge of the
+ * execution context, so that you can get a stack trace of the problem spot
+ * in the code. Also, since JDK 1.4, Throwables participate in "exception
+ * chaining." This means that one exception can be caused by another, and
+ * preserve the information of the original.
+ *
+ * <p>One reason this is useful is to wrap exceptions to conform to an
+ * interface. For example, it would be bad design to require all levels
+ * of a program interface to be aware of the low-level exceptions thrown
+ * at one level of abstraction. Another example is wrapping a checked
+ * exception in an unchecked one, to communicate that failure occured
+ * while still obeying the method throws clause of a superclass.
+ *
+ * <p>A cause is assigned in one of two ways; but can only be assigned once
+ * in the lifetime of the Throwable. There are new constructors added to
+ * several classes in the exception hierarchy that directly initialize the
+ * cause, or you can use the <code>initCause</code> method. This second
+ * method is especially useful if the superclass has not been retrofitted
+ * with new constructors:<br>
+ * <pre>
+ * try
+ * {
+ * lowLevelOp();
+ * }
+ * catch (LowLevelException lle)
+ * {
+ * throw (HighLevelException) new HighLevelException().initCause(lle);
+ * }
+ * </pre>
+ * Notice the cast in the above example; without it, your method would need
+ * a throws clase that declared Throwable, defeating the purpose of chainig
+ * your exceptions.
+ *
+ * <p>By convention, exception classes have two constructors: one with no
+ * arguments, and one that takes a String for a detail message. Further,
+ * classes which are likely to be used in an exception chain also provide
+ * a constructor that takes a Throwable, with or without a detail message
+ * string.
+ *
+ * <p>Another 1.4 feature is the StackTrace, a means of reflection that
+ * allows the program to inspect the context of the exception, and which is
+ * serialized, so that remote procedure calls can correctly pass exceptions.
+ *
+ * @author Brian Jones
+ * @author John Keiser
+ * @author Mark Wielaard
+ * @author Tom Tromey
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Throwable implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -3042686055658047285L;
+
+ /**
+ * The detail message.
+ *
+ * @serial specific details about the exception, may be null
+ */
+ private final String detailMessage;
+
+ /**
+ * The cause of the throwable, including null for an unknown or non-chained
+ * cause. This may only be set once; so the field is set to
+ * <code>this</code> until initialized.
+ *
+ * @serial the cause, or null if unknown, or this if not yet set
+ * @since 1.4
+ */
+ private Throwable cause = this;
+
+ /**
+ * The stack trace, in a serialized form.
+ *
+ * @serial the elements of the stack trace; this is non-null, and has
+ * no null entries
+ * @since 1.4
+ */
+ private StackTraceElement[] stackTrace;
+
+ /**
+ * Instantiate this Throwable with an empty message. The cause remains
+ * uninitialized. {@link #fillInStackTrace()} will be called to set
+ * up the stack trace.
+ */
+ public Throwable()
+ {
+ this((String) null);
+ }
+
+ /**
+ * Instantiate this Throwable with the given message. The cause remains
+ * uninitialized. {@link #fillInStackTrace()} will be called to set
+ * up the stack trace.
+ *
+ * @param message the message to associate with the Throwable
+ */
+ public Throwable(String message)
+ {
+ fillInStackTrace();
+ detailMessage = message;
+ }
+
+ /**
+ * Instantiate this Throwable with the given message and cause. Note that
+ * the message is unrelated to the message of the cause.
+ * {@link #fillInStackTrace()} will be called to set up the stack trace.
+ *
+ * @param message the message to associate with the Throwable
+ * @param cause the cause, may be null
+ * @since 1.4
+ */
+ public Throwable(String message, Throwable cause)
+ {
+ this(message);
+ this.cause = cause;
+ }
+
+ /**
+ * Instantiate this Throwable with the given cause. The message is then
+ * built as <code>cause == null ? null : cause.toString()</code>.
+ * {@link #fillInStackTrace()} will be called to set up the stack trace.
+ *
+ * @param cause the cause, may be null
+ * @since 1.4
+ */
+ public Throwable(Throwable cause)
+ {
+ this(cause == null ? null : cause.toString(), cause);
+ }
+
+ /**
+ * Get the message associated with this Throwable.
+ *
+ * @return the error message associated with this Throwable, may be null
+ */
+ public String getMessage()
+ {
+ return detailMessage;
+ }
+
+ /**
+ * Get a localized version of this Throwable's error message.
+ * This method must be overridden in a subclass of Throwable
+ * to actually produce locale-specific methods. The Throwable
+ * implementation just returns getMessage().
+ *
+ * @return a localized version of this error message
+ * @see #getMessage()
+ * @since 1.1
+ */
+ public String getLocalizedMessage()
+ {
+ return getMessage();
+ }
+
+ /**
+ * Returns the cause of this exception, or null if the cause is not known
+ * or non-existant. This cause is initialized by the new constructors,
+ * or by calling initCause.
+ *
+ * @return the cause of this Throwable
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return cause == this ? null : cause;
+ }
+
+ /**
+ * Initialize the cause of this Throwable. This may only be called once
+ * during the object lifetime, including implicitly by chaining
+ * constructors.
+ *
+ * @param cause the cause of this Throwable, may be null
+ * @return this
+ * @throws IllegalArgumentException if cause is this (a Throwable can't be
+ * its own cause!)
+ * @throws IllegalStateException if the cause has already been set
+ * @since 1.4
+ */
+ public Throwable initCause(Throwable cause)
+ {
+ if (cause == this)
+ throw new IllegalArgumentException();
+ if (this.cause != this)
+ throw new IllegalStateException();
+ this.cause = cause;
+ return this;
+ }
+
+ /**
+ * Get a human-readable representation of this Throwable. The detail message
+ * is retrieved by getLocalizedMessage(). Then, with a null detail
+ * message, this string is simply the object's class name; otherwise
+ * the string is <code>getClass().getName() + ": " + message</code>.
+ *
+ * @return a human-readable String represting this Throwable
+ */
+ public String toString()
+ {
+ String msg = getLocalizedMessage();
+ return getClass().getName() + (msg == null ? "" : ": " + msg);
+ }
+
+ /**
+ * Print a stack trace to the standard error stream. This stream is the
+ * current contents of <code>System.err</code>. The first line of output
+ * is the result of {@link #toString()}, and the remaining lines represent
+ * the data created by {@link #fillInStackTrace()}. While the format is
+ * unspecified, this implementation uses the suggested format, demonstrated
+ * by this example:<br>
+ * <pre>
+ * public class Junk
+ * {
+ * public static void main(String args[])
+ * {
+ * try
+ * {
+ * a();
+ * }
+ * catch(HighLevelException e)
+ * {
+ * e.printStackTrace();
+ * }
+ * }
+ * static void a() throws HighLevelException
+ * {
+ * try
+ * {
+ * b();
+ * }
+ * catch(MidLevelException e)
+ * {
+ * throw new HighLevelException(e);
+ * }
+ * }
+ * static void b() throws MidLevelException
+ * {
+ * c();
+ * }
+ * static void c() throws MidLevelException
+ * {
+ * try
+ * {
+ * d();
+ * }
+ * catch(LowLevelException e)
+ * {
+ * throw new MidLevelException(e);
+ * }
+ * }
+ * static void d() throws LowLevelException
+ * {
+ * e();
+ * }
+ * static void e() throws LowLevelException
+ * {
+ * throw new LowLevelException();
+ * }
+ * }
+ * class HighLevelException extends Exception
+ * {
+ * HighLevelException(Throwable cause) { super(cause); }
+ * }
+ * class MidLevelException extends Exception
+ * {
+ * MidLevelException(Throwable cause) { super(cause); }
+ * }
+ * class LowLevelException extends Exception
+ * {
+ * }
+ * </pre>
+ * <p>
+ * <pre>
+ * HighLevelException: MidLevelException: LowLevelException
+ * at Junk.a(Junk.java:13)
+ * at Junk.main(Junk.java:4)
+ * Caused by: MidLevelException: LowLevelException
+ * at Junk.c(Junk.java:23)
+ * at Junk.b(Junk.java:17)
+ * at Junk.a(Junk.java:11)
+ * ... 1 more
+ * Caused by: LowLevelException
+ * at Junk.e(Junk.java:30)
+ * at Junk.d(Junk.java:27)
+ * at Junk.c(Junk.java:21)
+ * ... 3 more
+ * </pre>
+ */
+ public void printStackTrace()
+ {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Print a stack trace to the specified PrintStream. See
+ * {@link #printStackTrace()} for the sample format.
+ *
+ * @param s the PrintStream to write the trace to
+ */
+ public void printStackTrace(PrintStream s)
+ {
+ s.print(stackTraceString());
+ }
+
+ /**
+ * Prints the exception, the detailed message and the stack trace
+ * associated with this Throwable to the given <code>PrintWriter</code>.
+ * The actual output written is implemention specific. Use the result of
+ * <code>getStackTrace()</code> when more precise information is needed.
+ *
+ * <p>This implementation first prints a line with the result of this
+ * object's <code>toString()</code> method.
+ * <br>
+ * Then for all elements given by <code>getStackTrace</code> it prints
+ * a line containing three spaces, the string "at " and the result of calling
+ * the <code>toString()</code> method on the <code>StackTraceElement</code>
+ * object. If <code>getStackTrace()</code> returns an empty array it prints
+ * a line containing three spaces and the string
+ * "&lt;&lt;No stacktrace available&gt;&gt;".
+ * <br>
+ * Then if <code>getCause()</code> doesn't return null it adds a line
+ * starting with "Caused by: " and the result of calling
+ * <code>toString()</code> on the cause.
+ * <br>
+ * Then for every cause (of a cause, etc) the stacktrace is printed the
+ * same as for the top level <code>Throwable</code> except that as soon
+ * as all the remaining stack frames of the cause are the same as the
+ * the last stack frames of the throwable that the cause is wrapped in
+ * then a line starting with three spaces and the string "... X more" is
+ * printed, where X is the number of remaining stackframes.
+ *
+ * @param pw the PrintWriter to write the trace to
+ * @since 1.1
+ */
+ public void printStackTrace (PrintWriter pw)
+ {
+ pw.print(stackTraceString());
+ }
+
+ /*
+ * We use inner class to avoid a static initializer in this basic class.
+ */
+ private static class StaticData
+ {
+ static final String nl = SystemProperties.getProperty("line.separator");
+ }
+
+ // Create whole stack trace in a stringbuffer so we don't have to print
+ // it line by line. This prevents printing multiple stack traces from
+ // different threads to get mixed up when written to the same PrintWriter.
+ private String stackTraceString()
+ {
+ StringBuffer sb = new StringBuffer();
+
+ // Main stacktrace
+ StackTraceElement[] stack = getStackTrace();
+ stackTraceStringBuffer(sb, this.toString(), stack, 0);
+
+ // The cause(s)
+ Throwable cause = getCause();
+ while (cause != null)
+ {
+ // Cause start first line
+ sb.append("Caused by: ");
+
+ // Cause stacktrace
+ StackTraceElement[] parentStack = stack;
+ stack = cause.getStackTrace();
+ if (parentStack == null || parentStack.length == 0)
+ stackTraceStringBuffer(sb, cause.toString(), stack, 0);
+ else
+ {
+ int equal = 0; // Count how many of the last stack frames are equal
+ int frame = stack.length-1;
+ int parentFrame = parentStack.length-1;
+ while (frame > 0 && parentFrame > 0)
+ {
+ if (stack[frame].equals(parentStack[parentFrame]))
+ {
+ equal++;
+ frame--;
+ parentFrame--;
+ }
+ else
+ break;
+ }
+ stackTraceStringBuffer(sb, cause.toString(), stack, equal);
+ }
+ cause = cause.getCause();
+ }
+
+ return sb.toString();
+ }
+
+ // Adds to the given StringBuffer a line containing the name and
+ // all stacktrace elements minus the last equal ones.
+ private static void stackTraceStringBuffer(StringBuffer sb, String name,
+ StackTraceElement[] stack, int equal)
+ {
+ String nl = StaticData.nl;
+ // (finish) first line
+ sb.append(name);
+ sb.append(nl);
+
+ // The stacktrace
+ if (stack == null || stack.length == 0)
+ {
+ sb.append(" <<No stacktrace available>>");
+ sb.append(nl);
+ }
+ else
+ {
+ for (int i = 0; i < stack.length-equal; i++)
+ {
+ sb.append(" at ");
+ sb.append(stack[i] == null ? "<<Unknown>>" : stack[i].toString());
+ sb.append(nl);
+ }
+ if (equal > 0)
+ {
+ sb.append(" ...");
+ sb.append(equal);
+ sb.append(" more");
+ sb.append(nl);
+ }
+ }
+ }
+
+ /**
+ * Fill in the stack trace with the current execution stack.
+ *
+ * @return this same throwable
+ * @see #printStackTrace()
+ */
+ public Throwable fillInStackTrace()
+ {
+ vmState = VMThrowable.fillInStackTrace(this);
+ stackTrace = null; // Should be regenerated when used.
+
+ return this;
+ }
+
+ /**
+ * Provides access to the information printed in {@link #printStackTrace()}.
+ * The array is non-null, with no null entries, although the virtual
+ * machine is allowed to skip stack frames. If the array is not 0-length,
+ * then slot 0 holds the information on the stack frame where the Throwable
+ * was created (or at least where <code>fillInStackTrace()</code> was
+ * called).
+ *
+ * @return an array of stack trace information, as available from the VM
+ * @since 1.4
+ */
+ public StackTraceElement[] getStackTrace()
+ {
+ if (stackTrace == null)
+ if (vmState == null)
+ stackTrace = new StackTraceElement[0];
+ else
+ {
+ stackTrace = vmState.getStackTrace(this);
+ vmState = null; // No longer needed
+ }
+
+ return stackTrace;
+ }
+
+ /**
+ * Change the stack trace manually. This method is designed for remote
+ * procedure calls, which intend to alter the stack trace before or after
+ * serialization according to the context of the remote call.
+ * <p>
+ * The contents of the given stacktrace is copied so changes to the
+ * original array do not change the stack trace elements of this
+ * throwable.
+ *
+ * @param stackTrace the new trace to use
+ * @throws NullPointerException if stackTrace is null or has null elements
+ * @since 1.4
+ */
+ public void setStackTrace(StackTraceElement[] stackTrace)
+ {
+ int i = stackTrace.length;
+ StackTraceElement[] st = new StackTraceElement[i];
+
+ while (--i >= 0)
+ {
+ st[i] = stackTrace[i];
+ if (st[i] == null)
+ throw new NullPointerException("Element " + i + " null");
+ }
+
+ this.stackTrace = st;
+ }
+
+ /**
+ * VM state when fillInStackTrace was called.
+ * Used by getStackTrace() to get an array of StackTraceElements.
+ * Cleared when no longer needed.
+ */
+ private transient VMThrowable vmState;
+}
diff --git a/libjava/classpath/java/lang/TypeNotPresentException.java b/libjava/classpath/java/lang/TypeNotPresentException.java
new file mode 100644
index 00000000000..3010c968b6d
--- /dev/null
+++ b/libjava/classpath/java/lang/TypeNotPresentException.java
@@ -0,0 +1,97 @@
+/* TypeNotPresentException.java -- Thrown when a string-based type is missing
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * <p>
+ * Thrown when a type is accessed using a <code>String</code>-based
+ * representation, but no definition of the supplied type is found.
+ * This is effectively an unchecked equivalent of the existing
+ * <code>ClassNotFound</code> exception.
+ * </p>
+ * <p>
+ * It may occur due to an attempt to load a missing class, interface or
+ * annotation, or when an undefined type variable is accessed.
+ * </p>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @see ClassNotFoundException
+ * @since 1.5
+ */
+public class TypeNotPresentException
+ extends RuntimeException
+{
+
+ /**
+ * Constructs a <code>TypeNotPresentException</code> for
+ * the supplied type. The specified cause <code>Throwable</code>
+ * may be used to provide additional history, with regards to the
+ * root of the problem. It is perfectly valid for this to be null,
+ * if the cause of the problem is unknown.
+ *
+ * @param typeName the name of the missing type.
+ * @param cause the cause of this exception, or null if the cause
+ * is unknown.
+ */
+ public TypeNotPresentException(String typeName, Throwable cause)
+ {
+ super("type \"" + typeName + "\" not found", cause);
+ this.typeName = typeName;
+ }
+
+ /**
+ * Returns the name of the missing type.
+ *
+ * @return the missing type's name.
+ */
+ public String typeName()
+ {
+ return typeName;
+ }
+
+ /**
+ * The name of the missing type.
+ *
+ * @serial the missing type's name.
+ */
+ // Name fixed by serialization.
+ private String typeName;
+
+}
diff --git a/libjava/classpath/java/lang/UnknownError.java b/libjava/classpath/java/lang/UnknownError.java
new file mode 100644
index 00000000000..7b317bd2aa2
--- /dev/null
+++ b/libjava/classpath/java/lang/UnknownError.java
@@ -0,0 +1,72 @@
+/* UnknownError.java -- thrown when the VM cannot provide more information
+ about a catastrophic error
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An <code>UnknownError</code> is thrown when a serious but unknown
+ * problem has occurred in the Java Virtual Machine.
+ *
+ * @author Brian Jones
+ * @status updated to 1.4
+ */
+public class UnknownError extends VirtualMachineError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 2524784860676771849L;
+
+ /**
+ * Create an error without a message.
+ */
+ public UnknownError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public UnknownError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/UnsatisfiedLinkError.java b/libjava/classpath/java/lang/UnsatisfiedLinkError.java
new file mode 100644
index 00000000000..0d513d8e0ca
--- /dev/null
+++ b/libjava/classpath/java/lang/UnsatisfiedLinkError.java
@@ -0,0 +1,74 @@
+/* UnsatisfiedLinkError.java -- thrown when a native method cannot be loaded
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>UnsatisfiedLinkError</code> is thrown if an appropriate
+ * native language definition of a method declared <code>native</code>
+ * cannot be found by the Java Virtual Machine.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see Runtime
+ * @status updated to 1.4
+ */
+public class UnsatisfiedLinkError extends LinkageError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4019343241616879428L;
+
+ /**
+ * Create an error without a message.
+ */
+ public UnsatisfiedLinkError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public UnsatisfiedLinkError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/UnsupportedClassVersionError.java b/libjava/classpath/java/lang/UnsupportedClassVersionError.java
new file mode 100644
index 00000000000..d6974b7694d
--- /dev/null
+++ b/libjava/classpath/java/lang/UnsupportedClassVersionError.java
@@ -0,0 +1,74 @@
+/* UnsupportedClassVersionError.java -- thrown when a class file version
+ exceeds the capability of the virtual machine
+ Copyright (C) 1998, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * An <code>UnsupportedClassVersionError</code> is thrown when the
+ * Java Virtual Machine determines it does not support the major and minor
+ * version numbers in the class file it is attempting to read.
+ *
+ * @author Brian Jones
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class UnsupportedClassVersionError extends ClassFormatError
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -7123279212883497373L;
+
+ /**
+ * Create an error without a message.
+ */
+ public UnsupportedClassVersionError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public UnsupportedClassVersionError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/UnsupportedOperationException.java b/libjava/classpath/java/lang/UnsupportedOperationException.java
new file mode 100644
index 00000000000..0387d0ee29d
--- /dev/null
+++ b/libjava/classpath/java/lang/UnsupportedOperationException.java
@@ -0,0 +1,73 @@
+/* UnsupportedOperationException.java -- thrown when an operation is not
+ supported
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * This exception is thrown by an object when an operation is
+ * requested of it that it does not support.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class UnsupportedOperationException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -1242599979055084673L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public UnsupportedOperationException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public UnsupportedOperationException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/VerifyError.java b/libjava/classpath/java/lang/VerifyError.java
new file mode 100644
index 00000000000..350ceaa5e95
--- /dev/null
+++ b/libjava/classpath/java/lang/VerifyError.java
@@ -0,0 +1,72 @@
+/* VerifyError.java -- thrown when a class fails verification
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>VerifyError</code> is thrown if there is a security problem or
+ * internal inconsistency in a class file as detected by the "verifier."
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public class VerifyError extends LinkageError
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 7001962396098498785L;
+
+ /**
+ * Create an error without a message.
+ */
+ public VerifyError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public VerifyError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/VirtualMachineError.java b/libjava/classpath/java/lang/VirtualMachineError.java
new file mode 100644
index 00000000000..3062c4fe800
--- /dev/null
+++ b/libjava/classpath/java/lang/VirtualMachineError.java
@@ -0,0 +1,73 @@
+/* VirtualMachineError.java -- thrown when the Virtual Machine has a problem
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+/**
+ * A <code>VirtualMachineError</code> or its subclasses are thrown to
+ * indicate there is something wrong with the Java Virtual Machine or that
+ * it does not have the resources needed for it to continue execution.
+ *
+ * @author Brian Jones
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @status updated to 1.4
+ */
+public abstract class VirtualMachineError extends Error
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 4161983926571568670L;
+
+ /**
+ * Create an error without a message.
+ */
+ public VirtualMachineError()
+ {
+ }
+
+ /**
+ * Create an error with a message.
+ *
+ * @param s the message
+ */
+ public VirtualMachineError(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/lang/Void.java b/libjava/classpath/java/lang/Void.java
new file mode 100644
index 00000000000..15035426830
--- /dev/null
+++ b/libjava/classpath/java/lang/Void.java
@@ -0,0 +1,68 @@
+/* Void.class - defines void.class
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+
+/**
+ * Void is a placeholder class so that the variable <code>Void.TYPE</code>
+ * (also available as <code>void.class</code>) can be supported for
+ * reflection return types.
+ *
+ * <p>This class could be Serializable, but that is up to Sun.</p>
+ *
+ * @author Paul Fisher
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Void
+{
+ /**
+ * The return type <code>void</code> is represented by this
+ * <code>Class</code> object.
+ */
+ public static final Class TYPE = VMClassLoader.getPrimitiveClass('V');
+
+ /**
+ * Void is non-instantiable.
+ */
+ private Void()
+ {
+ }
+}
diff --git a/libjava/classpath/java/lang/annotation/AnnotationFormatError.java b/libjava/classpath/java/lang/annotation/AnnotationFormatError.java
new file mode 100644
index 00000000000..40ce3ca10f7
--- /dev/null
+++ b/libjava/classpath/java/lang/annotation/AnnotationFormatError.java
@@ -0,0 +1,104 @@
+/* AnnotationFormatError.java - Thrown when an binary annotation is malformed
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.annotation;
+
+/**
+ * Thrown when an annotation found in a class file is
+ * malformed. When the virtual machine finds a class file
+ * containing annotations, it attempts to parse them.
+ * This error is thrown if this operation fails.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class AnnotationFormatError extends Error
+{
+
+ /**
+ * Constructs a new <code>AnnotationFormatError</code>
+ * using the specified message to give details of the error.
+ *
+ * @param message the message to use in the error output.
+ */
+ public AnnotationFormatError(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * <p>
+ * Constructs a new <code>AnnotationFormatError</code>
+ * using the specified message to give details of the error.
+ * The supplied cause <code>Throwable</code> is used to
+ * provide additional history, with regards to the root
+ * of the problem. It is perfectly valid for this to be null, if
+ * the cause is unknown.
+ * </p>
+ * <p>
+ * <strong>Note</strong>: if a cause is supplied, the error
+ * message from this cause is not automatically included in the
+ * error message given by this error.
+ * </p>
+ *
+ * @param message the message to use in the error output
+ * @param cause the cause of this error, or null if the cause
+ * is unknown.
+ */
+ public AnnotationFormatError(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new <code>AnnotationFormatError</code> using
+ * the supplied cause <code>Throwable</code> to
+ * provide additional history, with regards to the root
+ * of the problem. It is perfectly valid for this to be null, if
+ * the cause is unknown. If the cause is not null, the error
+ * message from this cause will also be used as the message
+ * for this error.
+ *
+ * @param cause the cause of the error.
+ */
+ public AnnotationFormatError(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
diff --git a/libjava/classpath/java/lang/annotation/AnnotationTypeMismatchException.java b/libjava/classpath/java/lang/annotation/AnnotationTypeMismatchException.java
new file mode 100644
index 00000000000..653305d632a
--- /dev/null
+++ b/libjava/classpath/java/lang/annotation/AnnotationTypeMismatchException.java
@@ -0,0 +1,116 @@
+/* AnnotationTypeMismatchException.java - Thrown when annotation has changed
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.annotation;
+
+import java.lang.reflect.Method;
+
+/**
+ * Thrown when accessing an element within an annotation for
+ * which the type has changed, since compilation or serialization
+ * took place. The mismatch between the compiled or serialized
+ * type and the current type causes this exception to be thrown.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class AnnotationTypeMismatchException extends RuntimeException
+{
+
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = 8125925355765570191L;
+
+ /**
+ * Constructs an <code>AnnotationTypeMismatchException</code>
+ * which is due to a mismatched type in the annotation
+ * element, <code>m</code>. The erroneous type used for the
+ * data in <code>m</code> is represented by the string,
+ * <code>type</code>. This string is of an undefined format,
+ * and may contain the value as well as the type.
+ *
+ * @param m the element from the annotation.
+ * @param type the name of the erroneous type found in <code>m</code>.
+ */
+ public AnnotationTypeMismatchException(Method m, String type)
+ {
+ this.element = m;
+ this.foundType = type;
+ }
+
+ /**
+ * Returns the element from the annotation, for which a
+ * mismatch occurred.
+ *
+ * @return the element with the mismatched type.
+ */
+ public Method element()
+ {
+ return element;
+ }
+
+ /**
+ * Returns the erroneous type used by the element,
+ * represented as a <code>String</code>. The format
+ * of this <code>String</code> is not explicitly specified,
+ * and may contain the value as well as the type.
+ *
+ * @return the type found in the element.
+ */
+ public String foundType()
+ {
+ return foundType;
+ }
+
+ // Names are chosen from serialization spec.
+ /**
+ * The element from the annotation.
+ *
+ * @serial the element with the mismatched type.
+ */
+ private Method element;
+
+ /**
+ * The erroneous type used by the element.
+ *
+ * @serial the type found in the element.
+ */
+ private String foundType;
+
+}
diff --git a/libjava/classpath/java/lang/annotation/package.html b/libjava/classpath/java/lang/annotation/package.html
new file mode 100644
index 00000000000..ee70daf9ea9
--- /dev/null
+++ b/libjava/classpath/java/lang/annotation/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.lang.annotation package.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.lang.annotation</title></head>
+
+<body>
+<p>Classes to handle annotations.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/lang/class-dependencies.conf b/libjava/classpath/java/lang/class-dependencies.conf
new file mode 100644
index 00000000000..4fbf75eb1ce
--- /dev/null
+++ b/libjava/classpath/java/lang/class-dependencies.conf
@@ -0,0 +1,58 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+# end of file
diff --git a/libjava/classpath/java/lang/package.html b/libjava/classpath/java/lang/package.html
new file mode 100644
index 00000000000..715418dbd69
--- /dev/null
+++ b/libjava/classpath/java/lang/package.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.lang package.
+ Copyright (C) 2002 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 - java.lang</title></head>
+
+<body>
+<p>Core classes including wrappers for primitive types, classes, packages
+and class loaders, representations of the system, processes, threads and
+the core exception hierarchy.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/lang/ref/PhantomReference.java b/libjava/classpath/java/lang/ref/PhantomReference.java
new file mode 100644
index 00000000000..4d929c29c58
--- /dev/null
+++ b/libjava/classpath/java/lang/ref/PhantomReference.java
@@ -0,0 +1,73 @@
+/* java.lang.ref.PhantomReference
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.ref;
+
+/**
+ * A phantom reference is useful, to get notified, when an object got
+ * finalized. You can't access that object though, since it is
+ * finalized. This is the reason, why <code>get()</code> always
+ * returns null.
+ *
+ * @author Jochen Hoenicke
+ */
+public class PhantomReference
+ extends Reference
+{
+ /**
+ * Creates a new phantom reference.
+ * @param referent the object that should be watched.
+ * @param q the queue that should be notified, if the referent was
+ * finalized. This mustn't be <code>null</code>.
+ * @exception NullPointerException if q is null.
+ */
+ public PhantomReference(Object referent, ReferenceQueue q)
+ {
+ super(referent, q);
+ }
+
+ /**
+ * Returns the object, this reference refers to.
+ * @return <code>null</code>, since the refered object may be
+ * finalized and thus not accessible.
+ */
+ public Object get()
+ {
+ return null;
+ }
+}
diff --git a/libjava/classpath/java/lang/ref/Reference.java b/libjava/classpath/java/lang/ref/Reference.java
new file mode 100644
index 00000000000..1ec72438198
--- /dev/null
+++ b/libjava/classpath/java/lang/ref/Reference.java
@@ -0,0 +1,177 @@
+/* java.lang.ref.Reference
+ Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.ref;
+
+/**
+ * This is the base class of all references. A reference allows
+ * refering to an object without preventing the garbage collector to
+ * collect it. The only way to get the referred object is via the
+ * <code>get()</code>-method. This method will return
+ * <code>null</code> if the object was collected. <br>
+ *
+ * A reference may be registered with a queue. When a referred
+ * element gets collected the reference will be put on the queue, so
+ * that you will be notified. <br>
+ *
+ * There are currently three types of references: soft reference,
+ * weak reference and phantom reference. <br>
+ *
+ * Soft references will be cleared if the garbage collector is told
+ * to free some memory and there are no unreferenced or weakly referenced
+ * objects. It is useful for caches. <br>
+ *
+ * Weak references will be cleared as soon as the garbage collector
+ * determines that the refered object is only weakly reachable. They
+ * are useful as keys in hashtables (see <code>WeakHashtable</code>) as
+ * you get notified when nobody has the key anymore.
+ *
+ * Phantom references don't prevent finalization. If an object is only
+ * phantom reachable, it will be finalized, and the reference will be
+ * enqueued, but not cleared. Since you mustn't access an finalized
+ * object, the <code>get</code> method of a phantom reference will never
+ * work. It is useful to keep track, when an object is finalized.
+ *
+ * @author Jochen Hoenicke
+ * @see java.util.WeakHashtable
+ */
+public abstract class Reference
+{
+ /**
+ * The underlying object. This field is handled in a special way by
+ * the garbage collector.
+ */
+ Object referent;
+
+ /**
+ * The queue this reference is registered on. This is null, if this
+ * wasn't registered to any queue or reference was already enqueued.
+ */
+ ReferenceQueue queue;
+
+ /**
+ * Link to the next entry on the queue. If this is null, this
+ * reference is not enqueued. Otherwise it points to the next
+ * reference. The last reference on a queue will point to itself
+ * (not to null, that value is used to mark a not enqueued
+ * reference).
+ */
+ Reference nextOnQueue;
+
+ /**
+ * This lock should be taken by the garbage collector, before
+ * determining reachability. It will prevent the get()-method to
+ * return the reference so that reachability doesn't change.
+ */
+ static Object lock = new Object();
+
+ /**
+ * Creates a new reference that is not registered to any queue.
+ * Since it is package private, it is not possible to overload this
+ * class in a different package.
+ * @param referent the object we refer to.
+ */
+ Reference(Object ref)
+ {
+ referent = ref;
+ }
+
+ /**
+ * Creates a reference that is registered to a queue. Since this is
+ * package private, it is not possible to overload this class in a
+ * different package.
+ * @param referent the object we refer to.
+ * @param q the reference queue to register on.
+ * @exception NullPointerException if q is null.
+ */
+ Reference(Object ref, ReferenceQueue q)
+ {
+ if (q == null)
+ throw new NullPointerException();
+ referent = ref;
+ queue = q;
+ }
+
+ /**
+ * Returns the object, this reference refers to.
+ * @return the object, this reference refers to, or null if the
+ * reference was cleared.
+ */
+ public Object get()
+ {
+ synchronized (lock)
+ {
+ return referent;
+ }
+ }
+
+ /**
+ * Clears the reference, so that it doesn't refer to its object
+ * anymore. For soft and weak references this is called by the
+ * garbage collector. For phantom references you should call
+ * this when enqueuing the reference.
+ */
+ public void clear()
+ {
+ referent = null;
+ }
+
+ /**
+ * Tells if the object is enqueued on a reference queue.
+ * @return true if it is enqueued, false otherwise.
+ */
+ public boolean isEnqueued()
+ {
+ return nextOnQueue != null;
+ }
+
+ /**
+ * Enqueue an object on a reference queue. This is normally executed
+ * by the garbage collector.
+ */
+ public boolean enqueue()
+ {
+ if (queue != null && nextOnQueue == null)
+ {
+ queue.enqueue(this);
+ queue = null;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/libjava/classpath/java/lang/ref/ReferenceQueue.java b/libjava/classpath/java/lang/ref/ReferenceQueue.java
new file mode 100644
index 00000000000..f4729f282be
--- /dev/null
+++ b/libjava/classpath/java/lang/ref/ReferenceQueue.java
@@ -0,0 +1,145 @@
+/* java.lang.ref.ReferenceQueue
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.ref;
+
+/**
+ * This is the queue, where references can enqueue themselve on. Each
+ * reference may be registered to a queue at initialization time and
+ * will be appended to the queue, when the enqueue method is called.
+ *
+ * The enqueue method may be automatically called by the garbage
+ * collector if it detects, that the object is only reachable through
+ * the Reference objects.
+ *
+ * @author Jochen Hoenicke
+ * @see Reference#enqueue()
+ */
+public class ReferenceQueue
+{
+ /**
+ * This is a linked list of references. If this is null, the list is
+ * empty. Otherwise this points to the first reference on the queue.
+ * The first reference will point to the next reference via the
+ * <code>nextOnQueue</code> field. The last reference will point to
+ * itself (not to null, since <code>nextOnQueue</code> is used to
+ * determine if a reference is enqueued).
+ */
+ private Reference first;
+
+ /**
+ * Creates a new empty reference queue.
+ */
+ public ReferenceQueue()
+ {
+ }
+
+ /**
+ * Checks if there is a reference on the queue, returning it
+ * immediately. The reference will be dequeued.
+ *
+ * @return a reference on the queue, if there is one,
+ * <code>null</code> otherwise.
+ */
+ public synchronized Reference poll()
+ {
+ return dequeue();
+ }
+
+ /**
+ * This is called by reference to enqueue itself on this queue.
+ * @param ref the reference that should be enqueued.
+ */
+ synchronized void enqueue(Reference ref)
+ {
+ /* last reference will point to itself */
+ ref.nextOnQueue = first == null ? ref : first;
+ first = ref;
+ /* this wakes only one remove thread. */
+ notify();
+ }
+
+ /**
+ * Remove a reference from the queue, if there is one.
+ * @return the first element of the queue, or null if there isn't any.
+ */
+ private Reference dequeue()
+ {
+ if (first == null)
+ return null;
+
+ Reference result = first;
+ first = (first == first.nextOnQueue) ? null : first.nextOnQueue;
+ result.nextOnQueue = null;
+ return result;
+ }
+
+ /**
+ * Removes a reference from the queue, blocking for <code>timeout</code>
+ * until a reference is enqueued.
+ * @param timeout the timeout period in milliseconds, <code>0</code> means
+ * wait forever.
+ * @return the reference removed from the queue, or
+ * <code>null</code> if timeout period expired.
+ * @exception InterruptedException if the wait was interrupted.
+ */
+ public synchronized Reference remove(long timeout)
+ throws InterruptedException
+ {
+ if (first == null)
+ {
+ wait(timeout);
+ }
+
+ return dequeue();
+ }
+
+
+ /**
+ * Removes a reference from the queue, blocking until a reference is
+ * enqueued.
+ *
+ * @return the reference removed from the queue.
+ * @exception InterruptedException if the wait was interrupted.
+ */
+ public Reference remove()
+ throws InterruptedException
+ {
+ return remove(0L);
+ }
+}
diff --git a/libjava/classpath/java/lang/ref/SoftReference.java b/libjava/classpath/java/lang/ref/SoftReference.java
new file mode 100644
index 00000000000..97395eacdfa
--- /dev/null
+++ b/libjava/classpath/java/lang/ref/SoftReference.java
@@ -0,0 +1,84 @@
+/* java.lang.ref.SoftReference
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.ref;
+
+/**
+ * A soft reference will be cleared, if the object is only softly
+ * reachable and the garbage collection needs more memory. The garbage
+ * collection will use an intelligent strategy to determine which soft
+ * references it should clear. This makes a soft reference ideal for
+ * caches.<br>
+ *
+ * @author Jochen Hoenicke
+ */
+public class SoftReference
+ extends Reference
+{
+ /**
+ * Create a new soft reference, that is not registered to any queue.
+ * @param referent the object we refer to.
+ */
+ public SoftReference(Object referent)
+ {
+ super(referent);
+ }
+
+ /**
+ * Create a new soft reference.
+ * @param referent the object we refer to.
+ * @param q the reference queue to register on.
+ * @exception NullPointerException if q is null.
+ */
+ public SoftReference(Object referent, ReferenceQueue q)
+ {
+ super(referent, q);
+ }
+
+ /**
+ * Returns the object, this reference refers to.
+ * @return the object, this reference refers to, or null if the
+ * reference was cleared.
+ */
+ public Object get()
+ {
+ /* Why is this overloaded???
+ * Maybe for a kind of LRU strategy. */
+ return super.get();
+ }
+}
diff --git a/libjava/classpath/java/lang/ref/WeakReference.java b/libjava/classpath/java/lang/ref/WeakReference.java
new file mode 100644
index 00000000000..9f758ca1eab
--- /dev/null
+++ b/libjava/classpath/java/lang/ref/WeakReference.java
@@ -0,0 +1,79 @@
+/* java.lang.ref.WeakReference
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.ref;
+
+/**
+ * A weak reference will be cleared, if the object is only weakly
+ * reachable. It is useful for lookup tables, where you aren't
+ * interested in an entry, if the key isn't reachable anymore.
+ * <code>WeakHashtable</code> is a complete implementation of such a
+ * table. <br>
+ *
+ * It is also useful to make objects unique: You create a set of weak
+ * references to those objects, and when you create a new object you
+ * look in this set, if the object already exists and return it. If
+ * an object is not referenced anymore, the reference will
+ * automatically cleared, and you may remove it from the set. <br>
+ *
+ * @author Jochen Hoenicke
+ * @see java.util.WeakHashtable
+ */
+public class WeakReference
+ extends Reference
+{
+ /**
+ * Create a new weak reference, that is not registered to any queue.
+ * @param referent the object we refer to.
+ */
+ public WeakReference(Object referent)
+ {
+ super(referent);
+ }
+
+ /**
+ * Create a new weak reference.
+ * @param referent the object we refer to.
+ * @param q the reference queue to register on.
+ * @exception NullPointerException if q is null.
+ */
+ public WeakReference(Object referent, ReferenceQueue q)
+ {
+ super(referent, q);
+ }
+}
diff --git a/libjava/classpath/java/lang/ref/package.html b/libjava/classpath/java/lang/ref/package.html
new file mode 100644
index 00000000000..d3d176280fb
--- /dev/null
+++ b/libjava/classpath/java/lang/ref/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.lang.ref package.
+ Copyright (C) 2002 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 - java.lang.ref</title></head>
+
+<body>
+<p>Low level manipulation and monitoring of object references.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/lang/reflect/AccessibleObject.java b/libjava/classpath/java/lang/reflect/AccessibleObject.java
new file mode 100644
index 00000000000..24418c971c7
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/AccessibleObject.java
@@ -0,0 +1,159 @@
+/* java.lang.reflect.AccessibleObject
+ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * This class is the superclass of various reflection classes, and
+ * allows sufficiently trusted code to bypass normal restrictions to
+ * do necessary things like invoke private methods outside of the
+ * class during Serialization. If you don't have a good reason
+ * to mess with this, don't try. Fortunately, there are adequate
+ * security checks before you can set a reflection object as accessible.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Field
+ * @see Constructor
+ * @see Method
+ * @see ReflectPermission
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class AccessibleObject
+{
+ /**
+ * True if this object is marked accessible, which means the reflected
+ * object bypasses normal security checks.
+ */
+ // default visibility for use by inherited classes
+ boolean flag = false;
+
+ /**
+ * Only the three reflection classes that extend this can create an
+ * accessible object. This is not serializable for security reasons.
+ */
+ protected AccessibleObject()
+ {
+ }
+
+ /**
+ * Return the accessibility status of this object.
+ *
+ * @return true if this object bypasses security checks
+ */
+ public boolean isAccessible()
+ {
+ return flag;
+ }
+
+ /**
+ * Convenience method to set the flag on a number of objects with a single
+ * security check. If a security manager exists, it is checked for
+ * <code>ReflectPermission("suppressAccessChecks")</code>.<p>
+ *
+ * It is forbidden to set the accessibility flag to true on any constructor
+ * for java.lang.Class. This will result in a SecurityException. If the
+ * SecurityException is thrown for any of the passed AccessibleObjects,
+ * the accessibility flag will be set on AccessibleObjects in the array prior
+ * to the one which resulted in the exception.
+ *
+ * @param array the array of accessible objects
+ * @param flag the desired state of accessibility, true to bypass security
+ * @throws NullPointerException if array is null
+ * @throws SecurityException if the request is denied
+ * @see SecurityManager#checkPermission(java.security.Permission)
+ * @see RuntimePermission
+ */
+ public static void setAccessible(AccessibleObject[] array, boolean flag)
+ {
+ checkPermission();
+ for (int i = 0; i < array.length; i++)
+ array[i].secureSetAccessible(flag);
+ }
+
+ /**
+ * Sets the accessibility flag for this reflection object. If a security
+ * manager exists, it is checked for
+ * <code>ReflectPermission("suppressAccessChecks")</code>.<p>
+ *
+ * It is forbidden to set the accessibility flag to true on any constructor for
+ * java.lang.Class. This will result in a SecurityException.
+ *
+ * @param flag the desired state of accessibility, true to bypass security
+ * @throws NullPointerException if array is null
+ * @throws SecurityException if the request is denied
+ * @see SecurityManager#checkPermission(java.security.Permission)
+ * @see RuntimePermission
+ */
+ public void setAccessible(boolean flag)
+ {
+ checkPermission();
+ secureSetAccessible(flag);
+ }
+
+ /**
+ * Performs the specified security check, for
+ * <code>ReflectPermission("suppressAccessChecks")</code>.
+ *
+ * @throws SecurityException if permission is denied
+ */
+ private static void checkPermission()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
+ }
+
+ /**
+ * Performs the actual accessibility change, this must always be invoked
+ * after calling checkPermission.
+ *
+ * @param flag the desired status
+ * @throws SecurityException if flag is true and this is a constructor
+ * for <code>java.lang.Class</code>.
+ */
+ private void secureSetAccessible(boolean flag)
+ {
+ if (flag &&
+ (this instanceof Constructor
+ && ((Constructor) this).getDeclaringClass() == Class.class))
+ throw new SecurityException("Cannot make object accessible: " + this);
+ this.flag = flag;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/Array.java b/libjava/classpath/java/lang/reflect/Array.java
new file mode 100644
index 00000000000..35c77da369a
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Array.java
@@ -0,0 +1,675 @@
+/* java.lang.reflect.Array - manipulate arrays by reflection
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import gnu.classpath.Configuration;
+
+/**
+ * Array holds static helper functions that allow you to create and
+ * manipulate arrays by reflection. Operations know how to perform widening
+ * conversions, but throw {@link IllegalArgumentException} if you attempt
+ * a narrowing conversion. Also, when accessing primitive arrays, this
+ * class performs object wrapping and unwrapping as necessary.<p>
+ *
+ * <B>Note:</B> This class returns and accepts types as Classes, even
+ * primitive types; there are Class types defined that represent each
+ * different primitive type. They are <code>java.lang.Boolean.TYPE,
+ * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
+ * byte.class</code>, etc. These are not to be confused with the
+ * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
+ * real classes. Note also that the shorthand <code>Object[].class</code>
+ * is a convenient way to get array Classes.<p>
+ *
+ * <B>Performance note:</B> This class performs best when it does not have
+ * to convert primitive types. The further along the chain it has to convert,
+ * the worse performance will be. You're best off using the array as whatever
+ * type it already is, and then converting the result. You will do even
+ * worse if you do this and use the generic set() function.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Per Bothner (bothner@cygnus.com)
+ * @see java.lang.Boolean#TYPE
+ * @see java.lang.Byte#TYPE
+ * @see java.lang.Short#TYPE
+ * @see java.lang.Character#TYPE
+ * @see java.lang.Integer#TYPE
+ * @see java.lang.Long#TYPE
+ * @see java.lang.Float#TYPE
+ * @see java.lang.Double#TYPE
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Array
+{
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("javalangreflect");
+ }
+ }
+
+ /**
+ * This class is uninstantiable.
+ */
+ private Array()
+ {
+ }
+
+ /**
+ * Creates a new single-dimensioned array.
+ * @param componentType the type of the array to create
+ * @param length the length of the array to create
+ * @return the created array, cast to an Object
+ * @throws NullPointerException if <code>componentType</code> is null
+ * @throws IllegalArgumentException if <code>componentType</code> is
+ * <code>Void.TYPE</code>
+ * @throws NegativeArraySizeException when length is less than 0
+ * @throws OutOfMemoryError if memory allocation fails
+ */
+ public static Object newInstance(Class componentType, int length)
+ {
+ if (! componentType.isPrimitive())
+ return createObjectArray(componentType, length);
+ if (componentType == boolean.class)
+ return new boolean[length];
+ if (componentType == byte.class)
+ return new byte[length];
+ if (componentType == char.class)
+ return new char[length];
+ if (componentType == short.class)
+ return new short[length];
+ if (componentType == int.class)
+ return new int[length];
+ if (componentType == long.class)
+ return new long[length];
+ if (componentType == float.class)
+ return new float[length];
+ if (componentType == double.class)
+ return new double[length];
+ // assert componentType == void.class
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Creates a new multi-dimensioned array. The new array has the same
+ * component type as the argument class, and the number of dimensions
+ * in the new array is the sum of the dimensions of the argument class
+ * and the length of the argument dimensions. Virtual Machine limitations
+ * forbid too many dimensions (usually 255 is the maximum); but even
+ * 50 dimensions of 2 elements in each dimension would exceed your memory
+ * long beforehand!
+ *
+ * @param componentType the type of the array to create.
+ * @param dimensions the dimensions of the array to create. Each element
+ * in <code>dimensions</code> makes another dimension of the new
+ * array. Thus, <code>Array.newInstance(java.lang.Boolean,
+ * new int[]{1,2,3})</code> is the same as
+ * <code>new java.lang.Boolean[1][2][3]</code>
+ * @return the created array, cast to an Object
+ * @throws NullPointerException if componentType or dimension is null
+ * @throws IllegalArgumentException if the the size of
+ * <code>dimensions</code> is 0 or exceeds the maximum number of
+ * array dimensions in the VM; or if componentType is Void.TYPE
+ * @throws NegativeArraySizeException when any of the dimensions is less
+ * than 0
+ * @throws OutOfMemoryError if memory allocation fails
+ */
+ public static Object newInstance(Class componentType, int[] dimensions)
+ {
+ if (dimensions.length <= 0)
+ throw new IllegalArgumentException ("Empty dimensions array.");
+ return createMultiArray(componentType, dimensions,
+ dimensions.length - 1);
+ }
+
+ /**
+ * Gets the array length.
+ * @param array the array
+ * @return the length of the array
+ * @throws IllegalArgumentException if <code>array</code> is not an array
+ * @throws NullPointerException if <code>array</code> is null
+ */
+ public static int getLength(Object array)
+ {
+ if (array instanceof Object[])
+ return ((Object[]) array).length;
+ if (array instanceof boolean[])
+ return ((boolean[]) array).length;
+ if (array instanceof byte[])
+ return ((byte[]) array). length;
+ if (array instanceof char[])
+ return ((char[]) array).length;
+ if (array instanceof short[])
+ return ((short[]) array).length;
+ if (array instanceof int[])
+ return ((int[]) array).length;
+ if (array instanceof long[])
+ return ((long[]) array).length;
+ if (array instanceof float[])
+ return ((float[]) array).length;
+ if (array instanceof double[])
+ return ((double[]) array).length;
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of an array. Primitive elements will be wrapped in
+ * the corresponding class type.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not an array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #getBoolean(Object, int)
+ * @see #getByte(Object, int)
+ * @see #getChar(Object, int)
+ * @see #getShort(Object, int)
+ * @see #getInt(Object, int)
+ * @see #getLong(Object, int)
+ * @see #getFloat(Object, int)
+ * @see #getDouble(Object, int)
+ */
+ public static Object get(Object array, int index)
+ {
+ if (array instanceof Object[])
+ return ((Object[]) array)[index];
+ if (array instanceof boolean[])
+ return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE;
+ if (array instanceof byte[])
+ return new Byte(((byte[]) array)[index]);
+ if (array instanceof char[])
+ return new Character(((char[]) array)[index]);
+ if (array instanceof short[])
+ return new Short(((short[]) array)[index]);
+ if (array instanceof int[])
+ return new Integer(((int[]) array)[index]);
+ if (array instanceof long[])
+ return new Long(((long[]) array)[index]);
+ if (array instanceof float[])
+ return new Float(((float[]) array)[index]);
+ if (array instanceof double[])
+ return new Double(((double[]) array)[index]);
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of a boolean array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the boolean element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a boolean
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static boolean getBoolean(Object array, int index)
+ {
+ if (array instanceof boolean[])
+ return ((boolean[]) array)[index];
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of a byte array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the byte element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static byte getByte(Object array, int index)
+ {
+ if (array instanceof byte[])
+ return ((byte[]) array)[index];
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of a char array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the char element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a char
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static char getChar(Object array, int index)
+ {
+ if (array instanceof char[])
+ return ((char[]) array)[index];
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of a short array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the short element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte
+ * or char array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static short getShort(Object array, int index)
+ {
+ if (array instanceof short[])
+ return ((short[]) array)[index];
+ return getByte(array, index);
+ }
+
+ /**
+ * Gets an element of an int array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the int element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * char, short, or int array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static int getInt(Object array, int index)
+ {
+ if (array instanceof int[])
+ return ((int[]) array)[index];
+ if (array instanceof char[])
+ return ((char[]) array)[index];
+ return getShort(array, index);
+ }
+
+ /**
+ * Gets an element of a long array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the long element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * char, short, int, or long array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static long getLong(Object array, int index)
+ {
+ if (array instanceof long[])
+ return ((long[]) array)[index];
+ return getInt(array, index);
+ }
+
+ /**
+ * Gets an element of a float array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the float element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * char, short, int, long, or float array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static float getFloat(Object array, int index)
+ {
+ if (array instanceof float[])
+ return ((float[]) array)[index];
+ return getLong(array, index);
+ }
+
+ /**
+ * Gets an element of a double array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the double element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * char, short, int, long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static double getDouble(Object array, int index)
+ {
+ if (array instanceof double[])
+ return ((double[]) array)[index];
+ return getFloat(array, index);
+ }
+
+ /**
+ * Sets an element of an array. If the array is primitive, then the new
+ * value is unwrapped and widened.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not an array,
+ * or the array is primitive and unwrapping value fails, or the
+ * value is not assignable to the array component type
+ * @throws NullPointerException if array is null, or if array is primitive
+ * and value is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #setBoolean(Object, int, boolean)
+ * @see #setByte(Object, int, byte)
+ * @see #setChar(Object, int, char)
+ * @see #setShort(Object, int, short)
+ * @see #setInt(Object, int, int)
+ * @see #setLong(Object, int, long)
+ * @see #setFloat(Object, int, float)
+ * @see #setDouble(Object, int, double)
+ */
+ public static void set(Object array, int index, Object value)
+ {
+ if (array instanceof Object[])
+ {
+ // Too bad the API won't let us throw the easier ArrayStoreException!
+ if (value != null
+ && ! array.getClass().getComponentType().isInstance(value))
+ throw new IllegalArgumentException();
+ ((Object[]) array)[index] = value;
+ }
+ else if (value instanceof Byte)
+ setByte(array, index, ((Byte) value).byteValue());
+ else if (value instanceof Short)
+ setShort(array, index, ((Short) value).shortValue());
+ else if (value instanceof Integer)
+ setInt(array, index, ((Integer) value).intValue());
+ else if (value instanceof Long)
+ setLong(array, index, ((Long) value).longValue());
+ else if (value instanceof Float)
+ setFloat(array, index, ((Float) value).floatValue());
+ else if (value instanceof Double)
+ setDouble(array, index, ((Double) value).doubleValue());
+ else if (value instanceof Character)
+ setChar(array, index, ((Character) value).charValue());
+ else if (value instanceof Boolean)
+ setBoolean(array, index, ((Boolean) value).booleanValue());
+ else if (array == null)
+ throw new NullPointerException();
+ else
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Sets an element of a boolean array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a boolean
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setBoolean(Object array, int index, boolean value)
+ {
+ if (array instanceof boolean[])
+ ((boolean[]) array)[index] = value;
+ else if (array == null)
+ throw new NullPointerException();
+ else
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Sets an element of a byte array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * short, int, long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setByte(Object array, int index, byte value)
+ {
+ if (array instanceof byte[])
+ ((byte[]) array)[index] = value;
+ else
+ setShort(array, index, value);
+ }
+
+ /**
+ * Sets an element of a char array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a char,
+ * int, long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setChar(Object array, int index, char value)
+ {
+ if (array instanceof char[])
+ ((char[]) array)[index] = value;
+ else
+ setInt(array, index, value);
+ }
+
+ /**
+ * Sets an element of a short array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a short,
+ * int, long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setShort(Object array, int index, short value)
+ {
+ if (array instanceof short[])
+ ((short[]) array)[index] = value;
+ else
+ setInt(array, index, value);
+ }
+
+ /**
+ * Sets an element of an int array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not an int,
+ * long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setInt(Object array, int index, int value)
+ {
+ if (array instanceof int[])
+ ((int[]) array)[index] = value;
+ else
+ setLong(array, index, value);
+ }
+
+ /**
+ * Sets an element of a long array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a long,
+ * float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setLong(Object array, int index, long value)
+ {
+ if (array instanceof long[])
+ ((long[]) array)[index] = value;
+ else
+ setFloat(array, index, value);
+ }
+
+ /**
+ * Sets an element of a float array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a float
+ * or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setFloat(Object array, int index, float value)
+ {
+ if (array instanceof float[])
+ ((float[]) array)[index] = value;
+ else
+ setDouble(array, index, value);
+ }
+
+ /**
+ * Sets an element of a double array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a double
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setDouble(Object array, int index, double value)
+ {
+ if (array instanceof double[])
+ ((double[]) array)[index] = value;
+ else if (array == null)
+ throw new NullPointerException();
+ else
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Dynamically and recursively create a multi-dimensioned array of objects.
+ *
+ * @param type guaranteed to be a valid object type
+ * @param dimensions the dimensions of the array
+ * @param index index of the current dimension to build
+ * @return the new multi-dimensioned array
+ * @throws NegativeArraySizeException if any entry of dimensions is negative
+ * @throws OutOfMemoryError if memory allocation fails
+ */
+ // This would be faster if implemented natively, using the multianewarray
+ // bytecode instead of this recursive call
+ private static Object createMultiArray(Class type, int[] dimensions,
+ int index)
+ {
+ if (index == 0)
+ return newInstance(type, dimensions[0]);
+
+ Object toAdd = createMultiArray(type, dimensions, index - 1);
+ Class thisType = toAdd.getClass();
+ Object[] retval
+ = (Object[]) createObjectArray(thisType, dimensions[index]);
+ if (dimensions[index] > 0)
+ retval[0] = toAdd;
+ int i = dimensions[index];
+ while (--i > 0)
+ retval[i] = createMultiArray(type, dimensions, index - 1);
+ return retval;
+ }
+
+ /**
+ * Dynamically create an array of objects.
+ *
+ * @param type guaranteed to be a valid object type
+ * @param dim the length of the array
+ * @return the new array
+ * @throws NegativeArraySizeException if dim is negative
+ * @throws OutOfMemoryError if memory allocation fails
+ */
+ private static native Object createObjectArray(Class type, int dim);
+}
diff --git a/libjava/classpath/java/lang/reflect/GenericArrayType.java b/libjava/classpath/java/lang/reflect/GenericArrayType.java
new file mode 100644
index 00000000000..8dc33a796c5
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/GenericArrayType.java
@@ -0,0 +1,61 @@
+/* GenericArrayType.java - Represent an array type with a generic component
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * Represents the type of an array's components, which may be
+ * either a parameterized type or a type variable.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface GenericArrayType
+ extends Type
+{
+
+ /**
+ * Returns the <code>Type</code> of the components within the array.
+ *
+ * @return a <code>Type</code> instance representing the type of
+ * the array's components.
+ */
+ Type getGenericComponentType();
+
+}
diff --git a/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java b/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java
new file mode 100644
index 00000000000..ab6928de6c0
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java
@@ -0,0 +1,62 @@
+/* GenericSignatureFormatError.java - Thrown when a signature is malformed.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * Thrown on encountering a syntactically malformed signature in
+ * a reflective method. During reflection, the generic type signature
+ * of a type, method or constructor may be interpreted by the virtual
+ * machine. This error is thrown if this operation fails.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class GenericSignatureFormatError
+ extends ClassFormatError
+{
+
+ /**
+ * Constructs a new <code>GenericSignatureFormatError</code>.
+ */
+ public GenericSignatureFormatError()
+ {
+ }
+
+}
diff --git a/libjava/classpath/java/lang/reflect/InvocationHandler.java b/libjava/classpath/java/lang/reflect/InvocationHandler.java
new file mode 100644
index 00000000000..208e621eedc
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/InvocationHandler.java
@@ -0,0 +1,137 @@
+/* java.lang.reflect.InvocationHandler - dynamically executes methods in
+ proxy instances
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * This interface defines an invocation handler. Suppose you are using
+ * reflection, and found a method that requires that its parameter
+ * be an object of a given interface. You want to call this method,
+ * but have no idea what classes implement that interface. So, you can
+ * create a {@link Proxy} instance, a convenient way to dynamically
+ * generate a class that meets all the necessary properties of that
+ * interface. But in order for the proxy instance to do any good, it
+ * needs to know what to do when interface methods are invoked! So,
+ * this interface is basically a cool wrapper that provides runtime
+ * code generation needed by proxy instances.
+ *
+ * <p>While this interface was designed for use by Proxy, it will also
+ * work on any object in general.</p>
+ *
+ * <p>Hints for implementing this class:</p>
+ *
+ * <ul>
+ * <li>Don't forget that Object.equals, Object.hashCode, and
+ * Object.toString will call this handler. In particular,
+ * a naive call to proxy.equals, proxy.hashCode, or proxy.toString
+ * will put you in an infinite loop. And remember that string
+ * concatenation also invokes toString.</li>
+ * <li>Obey the contract of the Method object you are handling, or
+ * the proxy instance will be forced to throw a
+ * {@link NullPointerException}, {@link ClassCastException},
+ * or {@link UndeclaredThrowableException}.</li>
+ * <li>Be prepared to wrap/unwrap primitives as necessary.</li>
+ * <li>The Method object may be owned by a different interface than
+ * what was actually used as the qualifying type of the method
+ * invocation in the Java source code. This means that it might
+ * not always be safe to throw an exception listed as belonging
+ * to the method's throws clause.</li>
+ * </ul>
+ *
+ * <p><small>For a fun time, create an InvocationHandler that handles the
+ * methods of a proxy instance of the InvocationHandler interface!</small></p>
+ *
+ * @see Proxy
+ * @see UndeclaredThrowableException
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface InvocationHandler
+{
+ /**
+ * When a method is invoked on a proxy instance, it is wrapped and
+ * this method is called instead, so that you may decide at runtime
+ * how the original method should behave.
+ *
+ * @param proxy the instance that the wrapped method should be
+ * invoked on. When this method is called by a Proxy object,
+ * `proxy' will be an instance of {@link Proxy}, and oddly enough,
+ * <code>Proxy.getInvocationHandler(proxy)</code> will return
+ * <code>this</code>!
+ * @param method the reflected method to invoke on the proxy.
+ * When this method is called by a Proxy object, 'method'
+ * will be the reflection object owned by the declaring
+ * class or interface, which may be a supertype of the
+ * interfaces the proxy directly implements.
+ * @param args the arguments passed to the original method, or
+ * <code>null</code> if the method takes no arguments.
+ * (But also be prepared to handle a 0-length array).
+ * Arguments of primitive type, such as <code>boolean</code>
+ * or <code>int</code>, are wrapped in the appropriate
+ * class such as {@link Boolean} or {@link Integer}.
+ * @return whatever is necessary to return from the wrapped method.
+ * If the wrapped method is <code>void</code>, the proxy
+ * instance will ignore it. If the wrapped method returns
+ * a primitive, this must be the correct wrapper type whose value
+ * is exactly assignable to the appropriate type (no widening
+ * will be performed); a null object in this case causes a
+ * {@link NullPointerException}. In all remaining cases, if
+ * the returned object is not assignment compatible to the
+ * declared type of the original method, the proxy instance
+ * will generate a {@link ClassCastException}.
+ * @throws Throwable this interface is listed as throwing anything,
+ * but the implementation should only throw unchecked
+ * exceptions and exceptions listed in the throws clause of
+ * all methods being overridden by the proxy instance. If
+ * something is thrown that is not compatible with the throws
+ * clause of all overridden methods, the proxy instance will
+ * wrap the exception in an UndeclaredThrowableException.
+ * Note that an exception listed in the throws clause of the
+ * `method' parameter might not be declared in additional
+ * interfaces also implemented by the proxy object.
+ *
+ * @see Proxy
+ * @see UndeclaredThrowableException
+ */
+ Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable;
+
+}
diff --git a/libjava/classpath/java/lang/reflect/InvocationTargetException.java b/libjava/classpath/java/lang/reflect/InvocationTargetException.java
new file mode 100644
index 00000000000..af79d3a199d
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/InvocationTargetException.java
@@ -0,0 +1,123 @@
+/* InvocationTargetException.java -- Wrapper exception for reflection
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * InvocationTargetException is sort of a way to "wrap" whatever exception
+ * comes up when a method or constructor is called via Reflection. As of
+ * JDK 1.4, it was retrofitted to match the exception chaining of all other
+ * exceptions, but <code>getTargetException()</code> still works.
+ *
+ * @author John Keiser
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Method#invoke(Object,Object[])
+ * @see Constructor#newInstance(Object[])
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class InvocationTargetException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4085088731926701167L;
+
+ /**
+ * The chained exception. This field is only around for serial compatibility.
+ *
+ * @serial the chained exception
+ */
+ private final Throwable target;
+
+ /**
+ * Construct an exception with null as the cause. The cause is initialized
+ * to null.
+ */
+ protected InvocationTargetException()
+ {
+ this(null, null);
+ }
+
+ /**
+ * Create an <code>InvocationTargetException</code> using another
+ * exception.
+ *
+ * @param targetException the exception to wrap
+ */
+ public InvocationTargetException(Throwable targetException)
+ {
+ this(targetException, null);
+ }
+
+ /**
+ * Create an <code>InvocationTargetException</code> using another
+ * exception and an error message.
+ *
+ * @param targetException the exception to wrap
+ * @param err an extra reason for the exception-throwing
+ */
+ public InvocationTargetException(Throwable targetException, String err)
+ {
+ super(err, targetException);
+ target = targetException;
+ }
+
+ /**
+ * Get the wrapped (targeted) exception.
+ *
+ * @return the targeted exception
+ * @see #getCause()
+ */
+ public Throwable getTargetException()
+ {
+ return target;
+ }
+
+ /**
+ * Returns the cause of this exception (which may be null).
+ *
+ * @return the cause
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return target;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/Member.java b/libjava/classpath/java/lang/reflect/Member.java
new file mode 100644
index 00000000000..9983b275a94
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Member.java
@@ -0,0 +1,100 @@
+/* java.lang.reflect.Member - common query methods in reflection
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * Member is an interface that represents any member of a class (field or
+ * method) or a constructor. You can get information about the declaring
+ * class, name or modifiers of the member with this interface.
+ *
+ * @author John Keiser
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Class
+ * @see Field
+ * @see Method
+ * @see Constructor
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Member
+{
+ /**
+ * Represents all members, whether public, private, protected or
+ * package-protected, but only which are declared in this class.
+ * Used in SecurityManager.checkMemberAccess() to determine the
+ * type of members to access.
+ * @see SecurityManager#checkMemberAccess()
+ */
+ int DECLARED = 1;
+
+ /**
+ * Represents public members only, but includes all inherited members.
+ * Used in SecurityManager.checkMemberAccess() to determine the type of
+ * members to access.
+ * @see SecurityManager#checkMemberAccess()
+ */
+ int PUBLIC = 0;
+
+ /**
+ * Gets the class that declared this member. This is not the class where
+ * this method was called, or even the class where this Member object
+ * came to life, but the class that declares the member this represents.
+ *
+ * @return the class that declared this member
+ */
+ Class getDeclaringClass();
+
+ /**
+ * Gets the simple name of this member. This will be a valid Java
+ * identifier, with no qualification.
+ *
+ * @return the name of this member
+ */
+ String getName();
+
+ /**
+ * Gets the modifiers this member uses. Use the <code>Modifier</code>
+ * class to interpret the values.
+ *
+ * @return an integer representing the modifiers to this Member
+ * @see Modifier
+ */
+ int getModifiers();
+}
diff --git a/libjava/classpath/java/lang/reflect/Modifier.java b/libjava/classpath/java/lang/reflect/Modifier.java
new file mode 100644
index 00000000000..efc88c941db
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Modifier.java
@@ -0,0 +1,332 @@
+/* java.lang.reflect.Modifier
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * Modifier is a helper class with static methods to determine whether an
+ * int returned from getModifiers() represents static, public, protected,
+ * native, final, etc... and provides an additional method to print
+ * out all of the modifiers in an int in order.
+ * <p>
+ * The methods in this class use the bitmask values in the VM spec to
+ * determine the modifiers of an int. This means that a VM must return a
+ * standard mask, conformant with the VM spec. I don't know if this is how
+ * Sun does it, but I'm willing to bet money that it is.
+ *
+ * @author John Keiser
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Member#getModifiers()
+ * @see Method#getModifiers()
+ * @see Field#getModifiers()
+ * @see Constructor#getModifiers()
+ * @see Class#getModifiers()
+ * @since 1.1
+ */
+public class Modifier
+{
+ /** <STRONG>This constructor really shouldn't be here ... there are no
+ * instance methods or variables of this class, so instantiation is
+ * worthless. However, this function is in the 1.1 spec, so it is added
+ * for completeness.</STRONG>
+ */
+ public Modifier()
+ {
+ }
+
+ /**
+ * Public: accessible from any other class.
+ */
+ public static final int PUBLIC = 0x0001;
+
+ /**
+ * Private: accessible only from the same enclosing class.
+ */
+ public static final int PRIVATE = 0x0002;
+
+ /**
+ * Protected: accessible only to subclasses, or within the package.
+ */
+ public static final int PROTECTED = 0x0004;
+
+ /**
+ * Static:<br><ul>
+ * <li>Class: no enclosing instance for nested class.</li>
+ * <li>Field or Method: can be accessed or invoked without an
+ * instance of the declaring class.</li>
+ * </ul>
+ */
+ public static final int STATIC = 0x0008;
+
+ /**
+ * Final:<br><ul>
+ * <li>Class: no subclasses allowed.</li>
+ * <li>Field: cannot be changed.</li>
+ * <li>Method: cannot be overriden.</li>
+ * </ul>
+ */
+ public static final int FINAL = 0x0010;
+
+ /**
+ * Synchronized: Method: lock the class while calling this method.
+ */
+ public static final int SYNCHRONIZED = 0x0020;
+
+ /**
+ * Volatile: Field: cannot be cached.
+ */
+ public static final int VOLATILE = 0x0040;
+
+ /**
+ * Transient: Field: not serialized or deserialized.
+ */
+ public static final int TRANSIENT = 0x0080;
+
+ /**
+ * Native: Method: use JNI to call this method.
+ */
+ public static final int NATIVE = 0x0100;
+
+ /**
+ * Interface: Class: is an interface.
+ */
+ public static final int INTERFACE = 0x0200;
+
+ /**
+ * Abstract:<br><ul>
+ * <li>Class: may not be instantiated.</li>
+ * <li>Method: may not be called.</li>
+ * </ul>
+ */
+ public static final int ABSTRACT = 0x0400;
+
+ /**
+ * Strictfp: Method: expressions are FP-strict.<p>
+ * Also used as a modifier for classes, to mean that all initializers
+ * and constructors are FP-strict, but does not show up in
+ * Class.getModifiers.
+ */
+ public static final int STRICT = 0x0800;
+
+
+ /**
+ * Super - treat invokespecial as polymorphic so that super.foo() works
+ * according to the JLS. This is a reuse of the synchronized constant
+ * to patch a hole in JDK 1.0. *shudder*.
+ */
+ static final int SUPER = 0x0020;
+
+ /**
+ * All the flags, only used by code in this package.
+ */
+ static final int ALL_FLAGS = 0xfff;
+
+ /**
+ * Check whether the given modifier is abstract.
+ * @param mod the modifier.
+ * @return <code>true</code> if abstract, <code>false</code> otherwise.
+ */
+ public static boolean isAbstract(int mod)
+ {
+ return (mod & ABSTRACT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is final.
+ * @param mod the modifier.
+ * @return <code>true</code> if final, <code>false</code> otherwise.
+ */
+ public static boolean isFinal(int mod)
+ {
+ return (mod & FINAL) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is an interface.
+ * @param mod the modifier.
+ * @return <code>true</code> if an interface, <code>false</code> otherwise.
+ */
+ public static boolean isInterface(int mod)
+ {
+ return (mod & INTERFACE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is native.
+ * @param mod the modifier.
+ * @return <code>true</code> if native, <code>false</code> otherwise.
+ */
+ public static boolean isNative(int mod)
+ {
+ return (mod & NATIVE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is private.
+ * @param mod the modifier.
+ * @return <code>true</code> if private, <code>false</code> otherwise.
+ */
+ public static boolean isPrivate(int mod)
+ {
+ return (mod & PRIVATE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is protected.
+ * @param mod the modifier.
+ * @return <code>true</code> if protected, <code>false</code> otherwise.
+ */
+ public static boolean isProtected(int mod)
+ {
+ return (mod & PROTECTED) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is public.
+ * @param mod the modifier.
+ * @return <code>true</code> if public, <code>false</code> otherwise.
+ */
+ public static boolean isPublic(int mod)
+ {
+ return (mod & PUBLIC) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is static.
+ * @param mod the modifier.
+ * @return <code>true</code> if static, <code>false</code> otherwise.
+ */
+ public static boolean isStatic(int mod)
+ {
+ return (mod & STATIC) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is strictfp.
+ * @param mod the modifier.
+ * @return <code>true</code> if strictfp, <code>false</code> otherwise.
+ */
+ public static boolean isStrict(int mod)
+ {
+ return (mod & STRICT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is synchronized.
+ * @param mod the modifier.
+ * @return <code>true</code> if synchronized, <code>false</code> otherwise.
+ */
+ public static boolean isSynchronized(int mod)
+ {
+ return (mod & SYNCHRONIZED) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is transient.
+ * @param mod the modifier.
+ * @return <code>true</code> if transient, <code>false</code> otherwise.
+ */
+ public static boolean isTransient(int mod)
+ {
+ return (mod & TRANSIENT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is volatile.
+ * @param mod the modifier.
+ * @return <code>true</code> if volatile, <code>false</code> otherwise.
+ */
+ public static boolean isVolatile(int mod)
+ {
+ return (mod & VOLATILE) != 0;
+ }
+
+ /**
+ * Get a string representation of all the modifiers represented by the
+ * given int. The keywords are printed in this order:
+ * <code>&lt;public|protected|private&gt; abstract static final transient
+ * volatile synchronized native strictfp interface</code>.
+ *
+ * @param mod the modifier.
+ * @return the String representing the modifiers.
+ */
+ public static String toString(int mod)
+ {
+ return toString(mod, new StringBuffer()).toString();
+ }
+
+ /**
+ * Package helper method that can take a StringBuffer.
+ * @param mod the modifier
+ * @param r the StringBuffer to which the String representation is appended
+ * @return r, with information appended
+ */
+ static StringBuffer toString(int mod, StringBuffer r)
+ {
+ if (isPublic(mod))
+ r.append("public ");
+ if (isProtected(mod))
+ r.append("protected ");
+ if (isPrivate(mod))
+ r.append("private ");
+ if (isAbstract(mod))
+ r.append("abstract ");
+ if (isStatic(mod))
+ r.append("static ");
+ if (isFinal(mod))
+ r.append("final ");
+ if (isTransient(mod))
+ r.append("transient ");
+ if (isVolatile(mod))
+ r.append("volatile ");
+ if (isSynchronized(mod))
+ r.append("synchronized ");
+ if (isNative(mod))
+ r.append("native ");
+ if (isStrict(mod))
+ r.append("strictfp ");
+ if (isInterface(mod))
+ r.append("interface ");
+
+ // Trim trailing space.
+ if ((mod & ALL_FLAGS) != 0)
+ r.setLength(r.length() - 1);
+ return r;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/ParameterizedType.java b/libjava/classpath/java/lang/reflect/ParameterizedType.java
new file mode 100644
index 00000000000..61081c962db
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/ParameterizedType.java
@@ -0,0 +1,122 @@
+/* ParameterizedType.java -- Represents parameterized types e.g. List<String>
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * <p>
+ * Represents a type which is parameterized over one or more other
+ * types. For example, <code>List&lt;Integer&gt;</code> is a parameterized
+ * type, with <code>List</code> parameterized over the type
+ * <code>Integer</code>.
+ * </p>
+ * <p>
+ * Instances of this classes are created as needed, during reflection.
+ * On creating a parameterized type, <code>p</code>, the
+ * <code>GenericTypeDeclaration</code> corresponding to <code>p</code>
+ * is created and resolved. Each type argument of <code>p</code>
+ * is then created recursively; details of this process are availble
+ * in the documentation of <code>TypeVariable</code>. This creation
+ * process only happens once; repetition has no effect.
+ * </p>
+ * <p>
+ * Implementors of this interface must implement an appropriate
+ * <code>equals()</code> method. This method should equate any
+ * two instances of the implementing class that have the same
+ * <code>GenericTypeDeclaration</code> and <code>Type</code>
+ * parameters.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @see GenericTypeDeclaration
+ * @see TypeVariable
+ * @since 1.5
+ */
+public interface ParameterizedType
+ extends Type
+{
+
+ /**
+ * <p>
+ * Returns an array of <code>Type</code> objects, which gives
+ * the parameters of this type.
+ * </p>
+ * <p>
+ * <strong>Note</code>: the returned array may be empty. This
+ * occurs if the supposed <code>ParameterizedType</code> is simply
+ * a normal type wrapped inside a parameterized type.
+ * </p>
+ *
+ * @return an array of <code>Type</code>s, representing the arguments
+ * of this type.
+ * @throws TypeNotPresentException if any of the types referred to by
+ * the parameters of this type do not actually exist.
+ * @throws MalformedParameterizedTypeException if any of the types
+ * refer to a type which can not be instantiated.
+ */
+ Type[] getActualTypeArguments();
+
+ /**
+ * Returns the type of which this type is a member. For example,
+ * in <code>Top&lt;String&gt;.Bottom&lt;Integer&gt;</code>,
+ * <code>Bottom&lt;Integer&gt;</code> is a member of
+ * <code>Top&lt;String&gt;</code>, and so the latter is returned
+ * by this method. Calling this method on top-level types (such as
+ * <code>Top&lt;String&gt;</code>) returns null.
+ *
+ * @return the type which owns this type.
+ * @throws TypeNotPresentException if the owner type referred to by
+ * this type do not actually exist.
+ * @throws MalformedParameterizedTypeException if the owner type
+ * referred to by this type can not be instantiated.
+ */
+ Type getOwnerType();
+
+ /**
+ * Returns a version of this type without parameters, which corresponds
+ * to the class or interface which declared the type. For example,
+ * the raw type corresponding to <code>List&lt;Double&gt;</code>
+ * is <code>List</code>, which was declared by the <code>List</code>
+ * class.
+ *
+ * @return the raw variant of this type (i.e. the type without
+ * parameters).
+ */
+ Type getRawType();
+
+}
diff --git a/libjava/classpath/java/lang/reflect/Proxy.java b/libjava/classpath/java/lang/reflect/Proxy.java
new file mode 100644
index 00000000000..dc1ac87e4e1
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Proxy.java
@@ -0,0 +1,1615 @@
+/* Proxy.java -- build a proxy class that implements reflected interfaces
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import gnu.classpath.Configuration;
+import gnu.java.lang.reflect.TypeSignature;
+
+import java.io.Serializable;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class allows you to dynamically create an instance of any (or
+ * even multiple) interfaces by reflection, and decide at runtime
+ * how that instance will behave by giving it an appropriate
+ * {@link InvocationHandler}. Proxy classes serialize specially, so
+ * that the proxy object can be reused between VMs, without requiring
+ * a persistent copy of the generated class code.
+ *
+ * <h3>Creation</h3>
+ * To create a proxy for some interface Foo:
+ *
+ * <pre>
+ * InvocationHandler handler = new MyInvocationHandler(...);
+ * Class proxyClass = Proxy.getProxyClass(
+ * Foo.class.getClassLoader(), new Class[] { Foo.class });
+ * Foo f = (Foo) proxyClass
+ * .getConstructor(new Class[] { InvocationHandler.class })
+ * .newInstance(new Object[] { handler });
+ * </pre>
+ * or more simply:
+ * <pre>
+ * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
+ * new Class[] { Foo.class },
+ * handler);
+ * </pre>
+ *
+ * <h3>Dynamic Proxy Classes</h3>
+ * A dynamic proxy class is created at runtime, and has the following
+ * properties:
+ * <ul>
+ * <li>The class is <code>public</code> and <code>final</code>,
+ * and is neither <code>abstract</code> nor an inner class.</li>
+ * <li>The class has no canonical name (there is no formula you can use
+ * to determine or generate its name), but begins with the
+ * sequence "$Proxy". Abuse this knowledge at your own peril.
+ * (For now, '$' in user identifiers is legal, but it may not
+ * be that way forever. You weren't using '$' in your
+ * identifiers, were you?)</li>
+ * <li>The class extends Proxy, and explicitly implements all the
+ * interfaces specified at creation, in order (this is important
+ * for determining how method invocation is resolved). Note that
+ * a proxy class implements {@link Serializable}, at least
+ * implicitly, since Proxy does, but true serial behavior
+ * depends on using a serializable invocation handler as well.</li>
+ * <li>If at least one interface is non-public, the proxy class
+ * will be in the same package. Otherwise, the package is
+ * unspecified. This will work even if the package is sealed
+ * from user-generated classes, because Proxy classes are
+ * generated by a trusted source. Meanwhile, the proxy class
+ * belongs to the classloader you designated.</li>
+ * <li>Reflection works as expected: {@link Class#getInterfaces()} and
+ * {@link Class#getMethods()} work as they do on normal classes.</li>
+ * <li>The method {@link #isProxyClass()} will distinguish between
+ * true proxy classes and user extensions of this class. It only
+ * returns true for classes created by {@link #getProxyClass}.</li>
+ * <li>The {@link ProtectionDomain} of a proxy class is the same as for
+ * bootstrap classes, such as Object or Proxy, since it is created by
+ * a trusted source. This protection domain will typically be granted
+ * {@link java.security.AllPermission}. But this is not a security
+ * risk, since there are adequate permissions on reflection, which is
+ * the only way to create an instance of the proxy class.</li>
+ * <li>The proxy class contains a single constructor, which takes as
+ * its only argument an {@link InvocationHandler}. The method
+ * {@link #newInstance} is shorthand to do the necessary
+ * reflection.</li>
+ * </ul>
+ *
+ * <h3>Proxy Instances</h3>
+ * A proxy instance is an instance of a proxy class. It has the
+ * following properties, many of which follow from the properties of a
+ * proxy class listed above:
+ * <ul>
+ * <li>For a proxy class with Foo listed as one of its interfaces, the
+ * expression <code>proxy instanceof Foo</code> will return true,
+ * and the expression <code>(Foo) proxy</code> will succeed without
+ * a {@link ClassCastException}.</li>
+ * <li>Each proxy instance has an invocation handler, which can be
+ * accessed by {@link #getInvocationHandler(Object)}. Any call
+ * to an interface method, including {@link Object#hashcode()},
+ * {@link Object#equals(Object)}, or {@link Object#toString()},
+ * but excluding the public final methods of Object, will be
+ * encoded and passed to the {@link InvocationHandler#invoke}
+ * method of this handler.</li>
+ * </ul>
+ *
+ * <h3>Inheritance Issues</h3>
+ * A proxy class may inherit a method from more than one interface.
+ * The order in which interfaces are listed matters, because it determines
+ * which reflected {@link Method} object will be passed to the invocation
+ * handler. This means that the dynamically generated class cannot
+ * determine through which interface a method is being invoked.<p>
+ *
+ * In short, if a method is declared in Object (namely, hashCode,
+ * equals, or toString), then Object will be used; otherwise, the
+ * leftmost interface that inherits or declares a method will be used,
+ * even if it has a more permissive throws clause than what the proxy
+ * class is allowed. Thus, in the invocation handler, it is not always
+ * safe to assume that every class listed in the throws clause of the
+ * passed Method object can safely be thrown; fortunately, the Proxy
+ * instance is robust enough to wrap all illegal checked exceptions in
+ * {@link UndeclaredThrowableException}.
+ *
+ * @see InvocationHandler
+ * @see UndeclaredThrowableException
+ * @see Class
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4, except for the use of ProtectionDomain
+ */
+public class Proxy implements Serializable
+{
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = -2222568056686623797L;
+
+ /**
+ * Map of ProxyType to proxy class.
+ *
+ * @XXX This prevents proxy classes from being garbage collected.
+ * java.util.WeakHashSet is not appropriate, because that collects the
+ * keys, but we are interested in collecting the elements.
+ */
+ private static final Map proxyClasses = new HashMap();
+
+ /**
+ * The invocation handler for this proxy instance. For Proxy, this
+ * field is unused, but it appears here in order to be serialized in all
+ * proxy classes.
+ *
+ * <em>NOTE</em>: This implementation is more secure for proxy classes
+ * than what Sun specifies. Sun does not require h to be immutable, but
+ * this means you could change h after the fact by reflection. However,
+ * by making h immutable, we may break non-proxy classes which extend
+ * Proxy.
+ * @serial invocation handler associated with this proxy instance
+ */
+ protected InvocationHandler h;
+
+ /**
+ * Constructs a new Proxy from a subclass (usually a proxy class),
+ * with the specified invocation handler.
+ *
+ * <em>NOTE</em>: This throws a NullPointerException if you attempt
+ * to create a proxy instance with a null handler using reflection.
+ * This behavior is not yet specified by Sun; see Sun Bug 4487672.
+ *
+ * @param handler the invocation handler, may be null if the subclass
+ * is not a proxy class
+ * @throws NullPointerException if handler is null and this is a proxy
+ * instance
+ */
+ protected Proxy(InvocationHandler handler)
+ {
+ if (handler == null && isProxyClass(getClass()))
+ throw new NullPointerException("invalid handler");
+ h = handler;
+ }
+
+ /**
+ * Returns the proxy {@link Class} for the given ClassLoader and array
+ * of interfaces, dynamically generating it if necessary.
+ *
+ * <p>There are several restrictions on this method, the violation of
+ * which will result in an IllegalArgumentException or
+ * NullPointerException:</p>
+ *
+ * <ul>
+ * <li>All objects in `interfaces' must represent distinct interfaces.
+ * Classes, primitive types, null, and duplicates are forbidden.</li>
+ * <li>The interfaces must be visible in the specified ClassLoader.
+ * In other words, for each interface i:
+ * <code>Class.forName(i.getName(), false, loader) == i</code>
+ * must be true.</li>
+ * <li>All non-public interfaces (if any) must reside in the same
+ * package, or the proxy class would be non-instantiable. If
+ * there are no non-public interfaces, the package of the proxy
+ * class is unspecified.</li>
+ * <li>All interfaces must be compatible - if two declare a method
+ * with the same name and parameters, the return type must be
+ * the same and the throws clause of the proxy class will be
+ * the maximal subset of subclasses of the throws clauses for
+ * each method that is overridden.</li>
+ * <li>VM constraints limit the number of interfaces a proxy class
+ * may directly implement (however, the indirect inheritance
+ * of {@link Serializable} does not count against this limit).
+ * Even though most VMs can theoretically have 65535
+ * superinterfaces for a class, the actual limit is smaller
+ * because a class's constant pool is limited to 65535 entries,
+ * and not all entries can be interfaces.</li>
+ * </ul>
+ *
+ * <p>Note that different orders of interfaces produce distinct classes.</p>
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the array of interfaces the proxy class implements,
+ * may be empty, but not null
+ * @return the Class object of the proxy class
+ * @throws IllegalArgumentException if the constraints above were
+ * violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry
+ */
+ // synchronized so that we aren't trying to build the same class
+ // simultaneously in two threads
+ public static synchronized Class getProxyClass(ClassLoader loader,
+ Class[] interfaces)
+ {
+ interfaces = (Class[]) interfaces.clone();
+ ProxyType pt = new ProxyType(loader, interfaces);
+ Class clazz = (Class) proxyClasses.get(pt);
+ if (clazz == null)
+ {
+ if (Configuration.HAVE_NATIVE_GET_PROXY_CLASS)
+ clazz = getProxyClass0(loader, interfaces);
+ else
+ {
+ ProxyData data = (Configuration.HAVE_NATIVE_GET_PROXY_DATA
+ ? getProxyData0(loader, interfaces)
+ : ProxyData.getProxyData(pt));
+
+ clazz = (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS
+ ? generateProxyClass0(loader, data)
+ : new ClassFactory(data).generate(loader));
+ }
+
+ Object check = proxyClasses.put(pt, clazz);
+ // assert check == null && clazz != null;
+ if (check != null || clazz == null)
+ throw new InternalError(/*"Fatal flaw in getProxyClass"*/);
+ }
+ return clazz;
+ }
+
+ /**
+ * Combines several methods into one. This is equivalent to:
+ * <pre>
+ * Proxy.getProxyClass(loader, interfaces)
+ * .getConstructor(new Class[] {InvocationHandler.class})
+ * .newInstance(new Object[] {handler});
+ * </pre>
+ * except that it will not fail with the normal problems caused
+ * by reflection. It can still fail for the same reasons documented
+ * in getProxyClass, or if handler is null.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the array of interfaces the proxy class implements,
+ * may be empty, but not null
+ * @param handler the invocation handler, may not be null
+ * @return a proxy instance implementing the specified interfaces
+ * @throws IllegalArgumentException if the constraints for getProxyClass
+ * were violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry, or if handler is null
+ * @see #getProxyClass(ClassLoader, Class[])
+ * @see Class#getConstructor(Class[])
+ * @see Constructor#newInstance(Object[])
+ */
+ public static Object newProxyInstance(ClassLoader loader,
+ Class[] interfaces,
+ InvocationHandler handler)
+ {
+ try
+ {
+ // getProxyClass() and Proxy() throw the necessary exceptions
+ return getProxyClass(loader, interfaces)
+ .getConstructor(new Class[] {InvocationHandler.class})
+ .newInstance(new Object[] {handler});
+ }
+ catch (RuntimeException e)
+ {
+ // Let IllegalArgumentException, NullPointerException escape.
+ // assert e instanceof IllegalArgumentException
+ // || e instanceof NullPointerException;
+ throw e;
+ }
+ catch (InvocationTargetException e)
+ {
+ // Let wrapped NullPointerException escape.
+ // assert e.getTargetException() instanceof NullPointerException
+ throw (NullPointerException) e.getCause();
+ }
+ catch (Exception e)
+ {
+ // Covers InstantiationException, IllegalAccessException,
+ // NoSuchMethodException, none of which should be generated
+ // if the proxy class was generated correctly.
+ // assert false;
+ throw (Error) new InternalError("Unexpected: " + e).initCause(e);
+ }
+ }
+
+ /**
+ * Returns true if and only if the Class object is a dynamically created
+ * proxy class (created by <code>getProxyClass</code> or by the
+ * syntactic sugar of <code>newProxyInstance</code>).
+ *
+ * <p>This check is secure (in other words, it is not simply
+ * <code>clazz.getSuperclass() == Proxy.class</code>), it will not
+ * be spoofed by non-proxy classes that extend Proxy.
+ *
+ * @param clazz the class to check, must not be null
+ * @return true if the class represents a proxy class
+ * @throws NullPointerException if clazz is null
+ */
+ // This is synchronized on the off chance that another thread is
+ // trying to add a class to the map at the same time we read it.
+ public static synchronized boolean isProxyClass(Class clazz)
+ {
+ if (! Proxy.class.isAssignableFrom(clazz))
+ return false;
+ // This is a linear search, even though we could do an O(1) search
+ // using new ProxyType(clazz.getClassLoader(), clazz.getInterfaces()).
+ return proxyClasses.containsValue(clazz);
+ }
+
+ /**
+ * Returns the invocation handler for the given proxy instance.<p>
+ *
+ * <em>NOTE</em>: We guarantee a non-null result if successful,
+ * but Sun allows the creation of a proxy instance with a null
+ * handler. See the comments for {@link #Proxy(InvocationHandler)}.
+ *
+ * @param proxy the proxy instance, must not be null
+ * @return the invocation handler, guaranteed non-null.
+ * @throws IllegalArgumentException if
+ * <code>Proxy.isProxyClass(proxy.getClass())</code> returns false.
+ * @throws NullPointerException if proxy is null
+ */
+ public static InvocationHandler getInvocationHandler(Object proxy)
+ {
+ if (! isProxyClass(proxy.getClass()))
+ throw new IllegalArgumentException("not a proxy instance");
+ return ((Proxy) proxy).h;
+ }
+
+ /**
+ * Optional native method to replace (and speed up) the pure Java
+ * implementation of getProxyClass. Only needed if
+ * Configuration.HAVE_NATIVE_GET_PROXY_CLASS is true, this does the
+ * work of both getProxyData0 and generateProxyClass0 with no
+ * intermediate form in Java. The native code may safely assume that
+ * this class must be created, and does not already exist.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the interfaces the class will extend
+ * @return the generated proxy class
+ * @throws IllegalArgumentException if the constraints for getProxyClass
+ * were violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry, or if handler is null
+ * @see Configuration#HAVE_NATIVE_GET_PROXY_CLASS
+ * @see #getProxyClass(ClassLoader, Class[])
+ * @see #getProxyData0(ClassLoader, Class[])
+ * @see #generateProxyClass0(ProxyData)
+ */
+ private static native Class getProxyClass0(ClassLoader loader,
+ Class[] interfaces);
+
+ /**
+ * Optional native method to replace (and speed up) the pure Java
+ * implementation of getProxyData. Only needed if
+ * Configuration.HAVE_NATIVE_GET_PROXY_DATA is true. The native code
+ * may safely assume that a new ProxyData object must be created which
+ * does not duplicate any existing ones.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the interfaces the class will extend
+ * @return all data that is required to make this proxy class
+ * @throws IllegalArgumentException if the constraints for getProxyClass
+ * were violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry, or if handler is null
+ * @see Configuration.HAVE_NATIVE_GET_PROXY_DATA
+ * @see #getProxyClass(ClassLoader, Class[])
+ * @see #getProxyClass0(ClassLoader, Class[])
+ * @see ProxyType#getProxyData()
+ */
+ private static native ProxyData getProxyData0(ClassLoader loader,
+ Class[] interfaces);
+
+ /**
+ * Optional native method to replace (and speed up) the pure Java
+ * implementation of generateProxyClass. Only needed if
+ * Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS is true. The native
+ * code may safely assume that a new Class must be created, and that
+ * the ProxyData object does not describe any existing class.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param data the struct of information to convert to a Class. This
+ * has already been verified for all problems except exceeding
+ * VM limitations
+ * @return the newly generated class
+ * @throws IllegalArgumentException if VM limitations are exceeded
+ * @see #getProxyClass(ClassLoader, Class[])
+ * @see #getProxyClass0(ClassLoader, Class[])
+ * @see ProxyData#generateProxyClass(ClassLoader)
+ */
+ private static native Class generateProxyClass0(ClassLoader loader,
+ ProxyData data);
+
+ /**
+ * Helper class for mapping unique ClassLoader and interface combinations
+ * to proxy classes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ProxyType
+ {
+ /**
+ * Store the class loader (may be null)
+ */
+ final ClassLoader loader;
+
+ /**
+ * Store the interfaces (never null, all elements are interfaces)
+ */
+ final Class[] interfaces;
+
+ /**
+ * Construct the helper object.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces an array of interfaces
+ */
+ ProxyType(ClassLoader loader, Class[] interfaces)
+ {
+ if (loader == null)
+ loader = ClassLoader.getSystemClassLoader();
+ this.loader = loader;
+ this.interfaces = interfaces;
+ }
+
+ /**
+ * Calculates the hash code.
+ *
+ * @return a combination of the classloader and interfaces hashcodes.
+ */
+ public int hashCode()
+ {
+ //loader is always not null
+ int hash = loader.hashCode();
+ for (int i = 0; i < interfaces.length; i++)
+ hash = hash * 31 + interfaces[i].hashCode();
+ return hash;
+ }
+
+ // A more comprehensive comparison of two arrays,
+ // ignore array element order, and
+ // ignore redundant elements
+ private static boolean sameTypes(Class arr1[], Class arr2[]) {
+ if (arr1.length == 1 && arr2.length == 1) {
+ return arr1[0] == arr2[0];
+ }
+
+ // total occurrance of elements of arr1 in arr2
+ int total_occ_of_arr1_in_arr2 = 0;
+ each_type:
+ for (int i = arr1.length; --i >= 0; )
+ {
+ Class t = arr1[i];
+ for (int j = i; --j >= 0; )
+ {
+ if (t == arr1[j])
+ { //found duplicate type
+ continue each_type;
+ }
+ }
+
+ // count c(a unique element of arr1)'s
+ // occurrences in arr2
+ int occ_in_arr2 = 0;
+ for (int j = arr2.length; --j >= 0; )
+ {
+ if (t == arr2[j])
+ {
+ ++occ_in_arr2;
+ }
+ }
+ if (occ_in_arr2 == 0)
+ { // t does not occur in arr2
+ return false;
+ }
+
+ total_occ_of_arr1_in_arr2 += occ_in_arr2;
+ }
+ // now, each element of arr2 must have been visited
+ return total_occ_of_arr1_in_arr2 == arr2.length;
+ }
+
+ /**
+ * Calculates equality.
+ *
+ * @param the object to compare to
+ * @return true if it is a ProxyType with same data
+ */
+ public boolean equals(Object other)
+ {
+ ProxyType pt = (ProxyType) other;
+ if (loader != pt.loader || interfaces.length != pt.interfaces.length)
+ return false;
+ return sameTypes(interfaces, pt.interfaces);
+ }
+ } // class ProxyType
+
+ /**
+ * Helper class which allows hashing of a method name and signature
+ * without worrying about return type, declaring class, or throws clause,
+ * and which reduces the maximally common throws clause between two methods
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ProxySignature
+ {
+ /**
+ * The core signatures which all Proxy instances handle.
+ */
+ static final HashMap coreMethods = new HashMap();
+ static
+ {
+ try
+ {
+ ProxySignature sig
+ = new ProxySignature(Object.class
+ .getMethod("equals",
+ new Class[] {Object.class}));
+ coreMethods.put(sig, sig);
+ sig = new ProxySignature(Object.class.getMethod("hashCode", null));
+ coreMethods.put(sig, sig);
+ sig = new ProxySignature(Object.class.getMethod("toString", null));
+ coreMethods.put(sig, sig);
+ }
+ catch (Exception e)
+ {
+ // assert false;
+ throw (Error) new InternalError("Unexpected: " + e).initCause(e);
+ }
+ }
+
+ /**
+ * The underlying Method object, never null
+ */
+ final Method method;
+
+ /**
+ * The set of compatible thrown exceptions, may be empty
+ */
+ final Set exceptions = new HashSet();
+
+ /**
+ * Construct a signature
+ *
+ * @param method the Method this signature is based on, never null
+ */
+ ProxySignature(Method method)
+ {
+ this.method = method;
+ Class[] exc = method.getExceptionTypes();
+ int i = exc.length;
+ while (--i >= 0)
+ {
+ // discard unchecked exceptions
+ if (Error.class.isAssignableFrom(exc[i])
+ || RuntimeException.class.isAssignableFrom(exc[i]))
+ continue;
+ exceptions.add(exc[i]);
+ }
+ }
+
+ /**
+ * Given a method, make sure it's return type is identical
+ * to this, and adjust this signature's throws clause appropriately
+ *
+ * @param other the signature to merge in
+ * @throws IllegalArgumentException if the return types conflict
+ */
+ void checkCompatibility(ProxySignature other)
+ {
+ if (method.getReturnType() != other.method.getReturnType())
+ throw new IllegalArgumentException("incompatible return types: "
+ + method + ", " + other.method);
+
+ // if you can think of a more efficient way than this O(n^2) search,
+ // implement it!
+ int size1 = exceptions.size();
+ int size2 = other.exceptions.size();
+ boolean[] valid1 = new boolean[size1];
+ boolean[] valid2 = new boolean[size2];
+ Iterator itr = exceptions.iterator();
+ int pos = size1;
+ while (--pos >= 0)
+ {
+ Class c1 = (Class) itr.next();
+ Iterator itr2 = other.exceptions.iterator();
+ int pos2 = size2;
+ while (--pos2 >= 0)
+ {
+ Class c2 = (Class) itr2.next();
+ if (c2.isAssignableFrom(c1))
+ valid1[pos] = true;
+ if (c1.isAssignableFrom(c2))
+ valid2[pos2] = true;
+ }
+ }
+ pos = size1;
+ itr = exceptions.iterator();
+ while (--pos >= 0)
+ {
+ itr.next();
+ if (! valid1[pos])
+ itr.remove();
+ }
+ pos = size2;
+ itr = other.exceptions.iterator();
+ while (--pos >= 0)
+ {
+ itr.next();
+ if (! valid2[pos])
+ itr.remove();
+ }
+ exceptions.addAll(other.exceptions);
+ }
+
+ /**
+ * Calculates the hash code.
+ *
+ * @return a combination of name and parameter types
+ */
+ public int hashCode()
+ {
+ int hash = method.getName().hashCode();
+ Class[] types = method.getParameterTypes();
+ for (int i = 0; i < types.length; i++)
+ hash = hash * 31 + types[i].hashCode();
+ return hash;
+ }
+
+ /**
+ * Calculates equality.
+ *
+ * @param the object to compare to
+ * @return true if it is a ProxySignature with same data
+ */
+ public boolean equals(Object other)
+ {
+ ProxySignature ps = (ProxySignature) other;
+ Class[] types1 = method.getParameterTypes();
+ Class[] types2 = ps.method.getParameterTypes();
+ if (! method.getName().equals(ps.method.getName())
+ || types1.length != types2.length)
+ return false;
+ int i = types1.length;
+ while (--i >= 0)
+ if (types1[i] != types2[i])
+ return false;
+ return true;
+ }
+ } // class ProxySignature
+
+ /**
+ * A flat representation of all data needed to generate bytecode/instantiate
+ * a proxy class. This is basically a struct.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ProxyData
+ {
+ /**
+ * The package this class is in <b>including the trailing dot</b>
+ * or an empty string for the unnamed (aka default) package.
+ */
+ String pack;
+
+ /**
+ * The interfaces this class implements. Non-null, but possibly empty.
+ */
+ Class[] interfaces;
+
+ /**
+ * The Method objects this class must pass as the second argument to
+ * invoke (also useful for determining what methods this class has).
+ * Non-null, non-empty (includes at least Object.hashCode, Object.equals,
+ * and Object.toString).
+ */
+ Method[] methods;
+
+ /**
+ * The exceptions that do not need to be wrapped in
+ * UndeclaredThrowableException. exceptions[i] is the same as, or a
+ * subset of subclasses, of methods[i].getExceptionTypes(), depending on
+ * compatible throws clauses with multiple inheritance. It is unspecified
+ * if these lists include or exclude subclasses of Error and
+ * RuntimeException, but excluding them is harmless and generates a
+ * smaller class.
+ */
+ Class[][] exceptions;
+
+ /**
+ * For unique id's
+ */
+ private static int count;
+
+ /**
+ * The id of this proxy class
+ */
+ final int id = count++;
+
+ /**
+ * Construct a ProxyData with uninitialized data members.
+ */
+ ProxyData()
+ {
+ }
+
+ /**
+ * Return the name of a package (including the trailing dot)
+ * given the name of a class.
+ * Returns an empty string if no package. We use this in preference to
+ * using Class.getPackage() to avoid problems with ClassLoaders
+ * that don't set the package.
+ */
+ private static String getPackage(Class k)
+ {
+ String name = k.getName();
+ int idx = name.lastIndexOf('.');
+ return name.substring(0, idx + 1);
+ }
+
+ /**
+ * Verifies that the arguments are legal, and sets up remaining data
+ * This should only be called when a class must be generated, as
+ * it is expensive.
+ *
+ * @param pt the ProxyType to convert to ProxyData
+ * @return the flattened, verified ProxyData structure for use in
+ * class generation
+ * @throws IllegalArgumentException if `interfaces' contains
+ * non-interfaces or incompatible combinations, and verify is true
+ * @throws NullPointerException if interfaces is null or contains null
+ */
+ static ProxyData getProxyData(ProxyType pt)
+ {
+ Map method_set = (Map) ProxySignature.coreMethods.clone();
+ boolean in_package = false; // true if we encounter non-public interface
+
+ ProxyData data = new ProxyData();
+ data.interfaces = pt.interfaces;
+
+ // if interfaces is too large, we croak later on when the constant
+ // pool overflows
+ int i = data.interfaces.length;
+ while (--i >= 0)
+ {
+ Class inter = data.interfaces[i];
+ if (! inter.isInterface())
+ throw new IllegalArgumentException("not an interface: " + inter);
+ try
+ {
+ if (Class.forName(inter.getName(), false, pt.loader) != inter)
+ throw new IllegalArgumentException("not accessible in "
+ + "classloader: " + inter);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalArgumentException("not accessible in "
+ + "classloader: " + inter);
+ }
+ if (! Modifier.isPublic(inter.getModifiers()))
+ if (in_package)
+ {
+ String p = getPackage(inter);
+ if (! data.pack.equals(p))
+ throw new IllegalArgumentException("non-public interfaces "
+ + "from different "
+ + "packages");
+ }
+ else
+ {
+ in_package = true;
+ data.pack = getPackage(inter);
+ }
+ for (int j = i-1; j >= 0; j--)
+ if (data.interfaces[j] == inter)
+ throw new IllegalArgumentException("duplicate interface: "
+ + inter);
+ Method[] methods = inter.getMethods();
+ int j = methods.length;
+ while (--j >= 0)
+ {
+ ProxySignature sig = new ProxySignature(methods[j]);
+ ProxySignature old = (ProxySignature) method_set.put(sig, sig);
+ if (old != null)
+ sig.checkCompatibility(old);
+ }
+ }
+
+ i = method_set.size();
+ data.methods = new Method[i];
+ data.exceptions = new Class[i][];
+ Iterator itr = method_set.values().iterator();
+ while (--i >= 0)
+ {
+ ProxySignature sig = (ProxySignature) itr.next();
+ data.methods[i] = sig.method;
+ data.exceptions[i] = (Class[]) sig.exceptions
+ .toArray(new Class[sig.exceptions.size()]);
+ }
+ return data;
+ }
+ } // class ProxyData
+
+ /**
+ * Does all the work of building a class. By making this a nested class,
+ * this code is not loaded in memory if the VM has a native
+ * implementation instead.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ClassFactory
+ {
+ /** Constants for assisting the compilation */
+ private static final byte POOL = 0;
+ private static final byte FIELD = 1;
+ private static final byte METHOD = 2;
+ private static final byte INTERFACE = 3;
+ private static final String CTOR_SIG
+ = "(Ljava/lang/reflect/InvocationHandler;)V";
+ private static final String INVOKE_SIG = "(Ljava/lang/Object;"
+ + "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";
+
+ /** Bytecodes for insertion in the class definition byte[] */
+ private static final char ACONST_NULL = 1;
+ private static final char ICONST_0 = 3;
+ private static final char BIPUSH = 16;
+ private static final char SIPUSH = 17;
+ private static final char ILOAD = 21;
+ private static final char ILOAD_0 = 26;
+ private static final char ALOAD_0 = 42;
+ private static final char ALOAD_1 = 43;
+ private static final char AALOAD = 50;
+ private static final char AASTORE = 83;
+ private static final char DUP = 89;
+ private static final char DUP_X1 = 90;
+ private static final char SWAP = 95;
+ private static final char IRETURN = 172;
+ private static final char LRETURN = 173;
+ private static final char FRETURN = 174;
+ private static final char DRETURN = 175;
+ private static final char ARETURN = 176;
+ private static final char RETURN = 177;
+ private static final char GETSTATIC = 178;
+ private static final char GETFIELD = 180;
+ private static final char INVOKEVIRTUAL = 182;
+ private static final char INVOKESPECIAL = 183;
+ private static final char INVOKESTATIC = 184;
+ private static final char INVOKEINTERFACE = 185;
+ private static final char NEW = 187;
+ private static final char ANEWARRAY = 189;
+ private static final char ATHROW = 191;
+ private static final char CHECKCAST = 192;
+
+ // Implementation note: we use StringBuffers to hold the byte data, since
+ // they automatically grow. However, we only use the low 8 bits of
+ // every char in the array, so we are using twice the necessary memory
+ // for the ease StringBuffer provides.
+
+ /** The constant pool. */
+ private final StringBuffer pool = new StringBuffer();
+ /** The rest of the class data. */
+ private final StringBuffer stream = new StringBuffer();
+
+ /** Map of strings to byte sequences, to minimize size of pool. */
+ private final Map poolEntries = new HashMap();
+
+ /** The VM name of this proxy class. */
+ private final String qualName;
+
+ /**
+ * The Method objects the proxy class refers to when calling the
+ * invocation handler.
+ */
+ private final Method[] methods;
+
+ /**
+ * Initializes the buffers with the bytecode contents for a proxy class.
+ *
+ * @param data the remainder of the class data
+ * @throws IllegalArgumentException if anything else goes wrong this
+ * late in the game; as far as I can tell, this will only happen
+ * if the constant pool overflows, which is possible even when
+ * the user doesn't exceed the 65535 interface limit
+ */
+ ClassFactory(ProxyData data)
+ {
+ methods = data.methods;
+
+ // magic = 0xcafebabe
+ // minor_version = 0
+ // major_version = 46
+ // constant_pool_count: place-holder for now
+ pool.append("\u00ca\u00fe\u00ba\u00be\0\0\0\56\0\0");
+ // constant_pool[], filled in as we go
+
+ // access_flags
+ putU2(Modifier.SUPER | Modifier.FINAL | Modifier.PUBLIC);
+ // this_class
+ qualName = (data.pack + "$Proxy" + data.id);
+ putU2(classInfo(TypeSignature.getEncodingOfClass(qualName, false)));
+ // super_class
+ putU2(classInfo("java/lang/reflect/Proxy"));
+
+ // interfaces_count
+ putU2(data.interfaces.length);
+ // interfaces[]
+ for (int i = 0; i < data.interfaces.length; i++)
+ putU2(classInfo(data.interfaces[i]));
+
+ // Recall that Proxy classes serialize specially, so we do not need
+ // to worry about a <clinit> method for this field. Instead, we
+ // just assign it by reflection after the class is successfully loaded.
+ // fields_count - private static Method[] m;
+ putU2(1);
+ // fields[]
+ // m.access_flags
+ putU2(Modifier.PRIVATE | Modifier.STATIC);
+ // m.name_index
+ putU2(utf8Info("m"));
+ // m.descriptor_index
+ putU2(utf8Info("[Ljava/lang/reflect/Method;"));
+ // m.attributes_count
+ putU2(0);
+ // m.attributes[]
+
+ // methods_count - # handler methods, plus <init>
+ putU2(methods.length + 1);
+ // methods[]
+ // <init>.access_flags
+ putU2(Modifier.PUBLIC);
+ // <init>.name_index
+ putU2(utf8Info("<init>"));
+ // <init>.descriptor_index
+ putU2(utf8Info(CTOR_SIG));
+ // <init>.attributes_count - only Code is needed
+ putU2(1);
+ // <init>.Code.attribute_name_index
+ putU2(utf8Info("Code"));
+ // <init>.Code.attribute_length = 18
+ // <init>.Code.info:
+ // $Proxynn(InvocationHandler h) { super(h); }
+ // <init>.Code.max_stack = 2
+ // <init>.Code.max_locals = 2
+ // <init>.Code.code_length = 6
+ // <init>.Code.code[]
+ stream.append("\0\0\0\22\0\2\0\2\0\0\0\6" + ALOAD_0 + ALOAD_1
+ + INVOKESPECIAL);
+ putU2(refInfo(METHOD, "java/lang/reflect/Proxy", "<init>", CTOR_SIG));
+ // <init>.Code.exception_table_length = 0
+ // <init>.Code.exception_table[]
+ // <init>.Code.attributes_count = 0
+ // <init>.Code.attributes[]
+ stream.append(RETURN + "\0\0\0\0");
+
+ for (int i = methods.length - 1; i >= 0; i--)
+ emitMethod(i, data.exceptions[i]);
+
+ // attributes_count
+ putU2(0);
+ // attributes[] - empty; omit SourceFile attribute
+ // XXX should we mark this with a Synthetic attribute?
+ }
+
+ /**
+ * Produce the bytecode for a single method.
+ *
+ * @param i the index of the method we are building
+ * @param e the exceptions possible for the method
+ */
+ private void emitMethod(int i, Class[] e)
+ {
+ // First, we precalculate the method length and other information.
+
+ Method m = methods[i];
+ Class[] paramtypes = m.getParameterTypes();
+ int wrap_overhead = 0; // max words taken by wrapped primitive
+ int param_count = 1; // 1 for this
+ int code_length = 16; // aload_0, getfield, aload_0, getstatic, const,
+ // aaload, const/aconst_null, invokeinterface
+ if (i > 5)
+ {
+ if (i > Byte.MAX_VALUE)
+ code_length += 2; // sipush
+ else
+ code_length++; // bipush
+ }
+ if (paramtypes.length > 0)
+ {
+ code_length += 3; // anewarray
+ if (paramtypes.length > Byte.MAX_VALUE)
+ code_length += 2; // sipush
+ else if (paramtypes.length > 5)
+ code_length++; // bipush
+ for (int j = 0; j < paramtypes.length; j++)
+ {
+ code_length += 4; // dup, const, load, store
+ Class type = paramtypes[j];
+ if (j > 5)
+ {
+ if (j > Byte.MAX_VALUE)
+ code_length += 2; // sipush
+ else
+ code_length++; // bipush
+ }
+ if (param_count >= 4)
+ code_length++; // 2-byte load
+ param_count++;
+ if (type.isPrimitive())
+ {
+ code_length += 7; // new, dup, invokespecial
+ if (type == long.class || type == double.class)
+ {
+ wrap_overhead = 3;
+ param_count++;
+ }
+ else if (wrap_overhead < 2)
+ wrap_overhead = 2;
+ }
+ }
+ }
+ int end_pc = code_length;
+ Class ret_type = m.getReturnType();
+ if (ret_type == void.class)
+ code_length++; // return
+ else if (ret_type.isPrimitive())
+ code_length += 7; // cast, invokevirtual, return
+ else
+ code_length += 4; // cast, return
+ int exception_count = 0;
+ boolean throws_throwable = false;
+ for (int j = 0; j < e.length; j++)
+ if (e[j] == Throwable.class)
+ {
+ throws_throwable = true;
+ break;
+ }
+ if (! throws_throwable)
+ {
+ exception_count = e.length + 3; // Throwable, Error, RuntimeException
+ code_length += 9; // new, dup_x1, swap, invokespecial, athrow
+ }
+ int handler_pc = code_length - 1;
+ StringBuffer signature = new StringBuffer("(");
+ for (int j = 0; j < paramtypes.length; j++)
+ signature.append(TypeSignature.getEncodingOfClass(paramtypes[j]));
+ signature.append(")").append(TypeSignature.getEncodingOfClass(ret_type));
+
+ // Now we have enough information to emit the method.
+
+ // handler.access_flags
+ putU2(Modifier.PUBLIC | Modifier.FINAL);
+ // handler.name_index
+ putU2(utf8Info(m.getName()));
+ // handler.descriptor_index
+ putU2(utf8Info(signature.toString()));
+ // handler.attributes_count - Code is necessary, Exceptions possible
+ putU2(e.length > 0 ? 2 : 1);
+
+ // handler.Code.info:
+ // type name(args) {
+ // try {
+ // return (type) h.invoke(this, methods[i], new Object[] {args});
+ // } catch (<declared Exceptions> e) {
+ // throw e;
+ // } catch (Throwable t) {
+ // throw new UndeclaredThrowableException(t);
+ // }
+ // }
+ // Special cases:
+ // if arg_n is primitive, wrap it
+ // if method throws Throwable, try-catch is not needed
+ // if method returns void, return statement not needed
+ // if method returns primitive, unwrap it
+ // save space by sharing code for all the declared handlers
+
+ // handler.Code.attribute_name_index
+ putU2(utf8Info("Code"));
+ // handler.Code.attribute_length
+ putU4(12 + code_length + 8 * exception_count);
+ // handler.Code.max_stack
+ putU2(param_count == 1 ? 4 : 7 + wrap_overhead);
+ // handler.Code.max_locals
+ putU2(param_count);
+ // handler.Code.code_length
+ putU4(code_length);
+ // handler.Code.code[]
+ putU1(ALOAD_0);
+ putU1(GETFIELD);
+ putU2(refInfo(FIELD, "java/lang/reflect/Proxy", "h",
+ "Ljava/lang/reflect/InvocationHandler;"));
+ putU1(ALOAD_0);
+ putU1(GETSTATIC);
+ putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName, false),
+ "m", "[Ljava/lang/reflect/Method;"));
+ putConst(i);
+ putU1(AALOAD);
+ if (paramtypes.length > 0)
+ {
+ putConst(paramtypes.length);
+ putU1(ANEWARRAY);
+ putU2(classInfo("java/lang/Object"));
+ param_count = 1;
+ for (int j = 0; j < paramtypes.length; j++, param_count++)
+ {
+ putU1(DUP);
+ putConst(j);
+ if (paramtypes[j].isPrimitive())
+ {
+ putU1(NEW);
+ putU2(classInfo(wrapper(paramtypes[j])));
+ putU1(DUP);
+ }
+ putLoad(param_count, paramtypes[j]);
+ if (paramtypes[j].isPrimitive())
+ {
+ putU1(INVOKESPECIAL);
+ putU2(refInfo(METHOD, wrapper(paramtypes[j]), "<init>",
+ '(' + (TypeSignature
+ .getEncodingOfClass(paramtypes[j])
+ + ")V")));
+ if (paramtypes[j] == long.class
+ || paramtypes[j] == double.class)
+ param_count++;
+ }
+ putU1(AASTORE);
+ }
+ }
+ else
+ putU1(ACONST_NULL);
+ putU1(INVOKEINTERFACE);
+ putU2(refInfo(INTERFACE, "java/lang/reflect/InvocationHandler",
+ "invoke", INVOKE_SIG));
+ putU1(4); // InvocationHandler, this, Method, Object[]
+ putU1(0);
+ if (ret_type == void.class)
+ putU1(RETURN);
+ else if (ret_type.isPrimitive())
+ {
+ putU1(CHECKCAST);
+ putU2(classInfo(wrapper(ret_type)));
+ putU1(INVOKEVIRTUAL);
+ putU2(refInfo(METHOD, wrapper(ret_type),
+ ret_type.getName() + "Value",
+ "()" + TypeSignature.getEncodingOfClass(ret_type)));
+ if (ret_type == long.class)
+ putU1(LRETURN);
+ else if (ret_type == float.class)
+ putU1(FRETURN);
+ else if (ret_type == double.class)
+ putU1(DRETURN);
+ else
+ putU1(IRETURN);
+ }
+ else
+ {
+ putU1(CHECKCAST);
+ putU2(classInfo(ret_type));
+ putU1(ARETURN);
+ }
+ if (! throws_throwable)
+ {
+ putU1(NEW);
+ putU2(classInfo("java/lang/reflect/UndeclaredThrowableException"));
+ putU1(DUP_X1);
+ putU1(SWAP);
+ putU1(INVOKESPECIAL);
+ putU2(refInfo(METHOD,
+ "java/lang/reflect/UndeclaredThrowableException",
+ "<init>", "(Ljava/lang/Throwable;)V"));
+ putU1(ATHROW);
+ }
+
+ // handler.Code.exception_table_length
+ putU2(exception_count);
+ // handler.Code.exception_table[]
+ if (! throws_throwable)
+ {
+ // handler.Code.exception_table.start_pc
+ putU2(0);
+ // handler.Code.exception_table.end_pc
+ putU2(end_pc);
+ // handler.Code.exception_table.handler_pc
+ putU2(handler_pc);
+ // handler.Code.exception_table.catch_type
+ putU2(classInfo("java/lang/Error"));
+ // handler.Code.exception_table.start_pc
+ putU2(0);
+ // handler.Code.exception_table.end_pc
+ putU2(end_pc);
+ // handler.Code.exception_table.handler_pc
+ putU2(handler_pc);
+ // handler.Code.exception_table.catch_type
+ putU2(classInfo("java/lang/RuntimeException"));
+ for (int j = 0; j < e.length; j++)
+ {
+ // handler.Code.exception_table.start_pc
+ putU2(0);
+ // handler.Code.exception_table.end_pc
+ putU2(end_pc);
+ // handler.Code.exception_table.handler_pc
+ putU2(handler_pc);
+ // handler.Code.exception_table.catch_type
+ putU2(classInfo(e[j]));
+ }
+ // handler.Code.exception_table.start_pc
+ putU2(0);
+ // handler.Code.exception_table.end_pc
+ putU2(end_pc);
+ // handler.Code.exception_table.handler_pc -
+ // -8 for undeclared handler, which falls thru to normal one
+ putU2(handler_pc - 8);
+ // handler.Code.exception_table.catch_type
+ putU2(0);
+ }
+ // handler.Code.attributes_count
+ putU2(0);
+ // handler.Code.attributes[]
+
+ if (e.length > 0)
+ {
+ // handler.Exceptions.attribute_name_index
+ putU2(utf8Info("Exceptions"));
+ // handler.Exceptions.attribute_length
+ putU4(2 * e.length + 2);
+ // handler.Exceptions.number_of_exceptions
+ putU2(e.length);
+ // handler.Exceptions.exception_index_table[]
+ for (int j = 0; j < e.length; j++)
+ putU2(classInfo(e[j]));
+ }
+ }
+
+ /**
+ * Creates the Class object that corresponds to the bytecode buffers
+ * built when this object was constructed.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @return the proxy class Class object
+ */
+ Class generate(ClassLoader loader)
+ {
+ byte[] bytecode = new byte[pool.length() + stream.length()];
+ // More efficient to bypass calling charAt() repetitively.
+ char[] c = pool.toString().toCharArray();
+ int i = c.length;
+ while (--i >= 0)
+ bytecode[i] = (byte) c[i];
+ c = stream.toString().toCharArray();
+ i = c.length;
+ int j = bytecode.length;
+ while (i > 0)
+ bytecode[--j] = (byte) c[--i];
+
+ // Patch the constant pool size, which we left at 0 earlier.
+ int count = poolEntries.size() + 1;
+ bytecode[8] = (byte) (count >> 8);
+ bytecode[9] = (byte) count;
+
+ try
+ {
+ Class vmClassLoader = Class.forName("java.lang.VMClassLoader");
+ Class[] types = {ClassLoader.class, String.class,
+ byte[].class, int.class, int.class,
+ ProtectionDomain.class };
+ Method m = vmClassLoader.getDeclaredMethod("defineClass", types);
+ // We can bypass the security check of setAccessible(true), since
+ // we're in the same package.
+ m.flag = true;
+
+ Object[] args = {loader, qualName, bytecode, new Integer(0),
+ new Integer(bytecode.length),
+ Object.class.getProtectionDomain() };
+ Class clazz = (Class) m.invoke(null, args);
+
+ // Finally, initialize the m field of the proxy class, before
+ // returning it.
+ Field f = clazz.getDeclaredField("m");
+ f.flag = true;
+ // we can share the array, because it is not publicized
+ f.set(null, methods);
+
+ return clazz;
+ }
+ catch (Exception e)
+ {
+ // assert false;
+ throw (Error) new InternalError("Unexpected: " + e).initCause(e);
+ }
+ }
+
+ /**
+ * Put a single byte on the stream.
+ *
+ * @param i the information to add (only lowest 8 bits are used)
+ */
+ private void putU1(int i)
+ {
+ stream.append((char) i);
+ }
+
+ /**
+ * Put two bytes on the stream.
+ *
+ * @param i the information to add (only lowest 16 bits are used)
+ */
+ private void putU2(int i)
+ {
+ stream.append((char) (i >> 8)).append((char) i);
+ }
+
+ /**
+ * Put four bytes on the stream.
+ *
+ * @param i the information to add (treated as unsigned)
+ */
+ private void putU4(int i)
+ {
+ stream.append((char) (i >> 24)).append((char) (i >> 16));
+ stream.append((char) (i >> 8)).append((char) i);
+ }
+
+ /**
+ * Put bytecode to load a constant integer on the stream. This only
+ * needs to work for values less than Short.MAX_VALUE.
+ *
+ * @param i the int to add
+ */
+ private void putConst(int i)
+ {
+ if (i >= -1 && i <= 5)
+ putU1(ICONST_0 + i);
+ else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE)
+ {
+ putU1(BIPUSH);
+ putU1(i);
+ }
+ else
+ {
+ putU1(SIPUSH);
+ putU2(i);
+ }
+ }
+
+ /**
+ * Put bytecode to load a given local variable on the stream.
+ *
+ * @param i the slot to load
+ * @param type the base type of the load
+ */
+ private void putLoad(int i, Class type)
+ {
+ int offset = 0;
+ if (type == long.class)
+ offset = 1;
+ else if (type == float.class)
+ offset = 2;
+ else if (type == double.class)
+ offset = 3;
+ else if (! type.isPrimitive())
+ offset = 4;
+ if (i < 4)
+ putU1(ILOAD_0 + 4 * offset + i);
+ else
+ {
+ putU1(ILOAD + offset);
+ putU1(i);
+ }
+ }
+
+ /**
+ * Given a primitive type, return its wrapper class name.
+ *
+ * @param clazz the primitive type (but not void.class)
+ * @return the internal form of the wrapper class name
+ */
+ private String wrapper(Class clazz)
+ {
+ if (clazz == boolean.class)
+ return "java/lang/Boolean";
+ if (clazz == byte.class)
+ return "java/lang/Byte";
+ if (clazz == short.class)
+ return "java/lang/Short";
+ if (clazz == char.class)
+ return "java/lang/Character";
+ if (clazz == int.class)
+ return "java/lang/Integer";
+ if (clazz == long.class)
+ return "java/lang/Long";
+ if (clazz == float.class)
+ return "java/lang/Float";
+ if (clazz == double.class)
+ return "java/lang/Double";
+ // assert false;
+ return null;
+ }
+
+ /**
+ * Returns the entry of this String in the Constant pool, adding it
+ * if necessary.
+ *
+ * @param str the String to resolve
+ * @return the index of the String in the constant pool
+ */
+ private char utf8Info(String str)
+ {
+ String utf8 = toUtf8(str);
+ int len = utf8.length();
+ return poolIndex("\1" + (char) (len >> 8) + (char) (len & 0xff) + utf8);
+ }
+
+ /**
+ * Returns the entry of the appropriate class info structure in the
+ * Constant pool, adding it if necessary.
+ *
+ * @param name the class name, in internal form
+ * @return the index of the ClassInfo in the constant pool
+ */
+ private char classInfo(String name)
+ {
+ char index = utf8Info(name);
+ char[] c = {7, (char) (index >> 8), (char) (index & 0xff)};
+ return poolIndex(new String(c));
+ }
+
+ /**
+ * Returns the entry of the appropriate class info structure in the
+ * Constant pool, adding it if necessary.
+ *
+ * @param clazz the class type
+ * @return the index of the ClassInfo in the constant pool
+ */
+ private char classInfo(Class clazz)
+ {
+ return classInfo(TypeSignature.getEncodingOfClass(clazz.getName(),
+ false));
+ }
+
+ /**
+ * Returns the entry of the appropriate fieldref, methodref, or
+ * interfacemethodref info structure in the Constant pool, adding it
+ * if necessary.
+ *
+ * @param structure FIELD, METHOD, or INTERFACE
+ * @param clazz the class name, in internal form
+ * @param name the simple reference name
+ * @param type the type of the reference
+ * @return the index of the appropriate Info structure in the constant pool
+ */
+ private char refInfo(byte structure, String clazz, String name,
+ String type)
+ {
+ char cindex = classInfo(clazz);
+ char ntindex = nameAndTypeInfo(name, type);
+ // relies on FIELD == 1, METHOD == 2, INTERFACE == 3
+ char[] c = {(char) (structure + 8),
+ (char) (cindex >> 8), (char) (cindex & 0xff),
+ (char) (ntindex >> 8), (char) (ntindex & 0xff)};
+ return poolIndex(new String(c));
+ }
+
+ /**
+ * Returns the entry of the appropriate nameAndTyperef info structure
+ * in the Constant pool, adding it if necessary.
+ *
+ * @param name the simple name
+ * @param type the reference type
+ * @return the index of the NameAndTypeInfo structure in the constant pool
+ */
+ private char nameAndTypeInfo(String name, String type)
+ {
+ char nindex = utf8Info(name);
+ char tindex = utf8Info(type);
+ char[] c = {12, (char) (nindex >> 8), (char) (nindex & 0xff),
+ (char) (tindex >> 8), (char) (tindex & 0xff)};
+ return poolIndex(new String(c));
+ }
+
+ /**
+ * Converts a regular string to a UTF8 string, where the upper byte
+ * of every char is 0, and '\\u0000' is not in the string. This is
+ * basically to use a String as a fancy byte[], and while it is less
+ * efficient in memory use, it is easier for hashing.
+ *
+ * @param str the original, in straight unicode
+ * @return a modified string, in UTF8 format in the low bytes
+ */
+ private String toUtf8(String str)
+ {
+ final char[] ca = str.toCharArray();
+ final int len = ca.length;
+
+ // Avoid object creation, if str is already fits UTF8.
+ int i;
+ for (i = 0; i < len; i++)
+ if (ca[i] == 0 || ca[i] > '\u007f')
+ break;
+ if (i == len)
+ return str;
+
+ final StringBuffer sb = new StringBuffer(str);
+ sb.setLength(i);
+ for ( ; i < len; i++)
+ {
+ final char c = ca[i];
+ if (c > 0 && c <= '\u007f')
+ sb.append(c);
+ else if (c <= '\u07ff') // includes '\0'
+ {
+ sb.append((char) (0xc0 | (c >> 6)));
+ sb.append((char) (0x80 | (c & 0x6f)));
+ }
+ else
+ {
+ sb.append((char) (0xe0 | (c >> 12)));
+ sb.append((char) (0x80 | ((c >> 6) & 0x6f)));
+ sb.append((char) (0x80 | (c & 0x6f)));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Returns the location of a byte sequence (conveniently wrapped in
+ * a String with all characters between \u0001 and \u00ff inclusive)
+ * in the constant pool, adding it if necessary.
+ *
+ * @param sequence the byte sequence to look for
+ * @return the index of the sequence
+ * @throws IllegalArgumentException if this would make the constant
+ * pool overflow
+ */
+ private char poolIndex(String sequence)
+ {
+ Integer i = (Integer) poolEntries.get(sequence);
+ if (i == null)
+ {
+ // pool starts at index 1
+ int size = poolEntries.size() + 1;
+ if (size >= 65535)
+ throw new IllegalArgumentException("exceeds VM limitations");
+ i = new Integer(size);
+ poolEntries.put(sequence, i);
+ pool.append(sequence);
+ }
+ return (char) i.intValue();
+ }
+ } // class ClassFactory
+}
diff --git a/libjava/classpath/java/lang/reflect/README b/libjava/classpath/java/lang/reflect/README
new file mode 100644
index 00000000000..99ea224d7f6
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/README
@@ -0,0 +1,4 @@
+README for java.lang.reflect:
+
+java.lang.reflect is now mostly empty. We've carved out the classes that have
+to do with the VM and put them into the VM interface.
diff --git a/libjava/classpath/java/lang/reflect/ReflectPermission.java b/libjava/classpath/java/lang/reflect/ReflectPermission.java
new file mode 100644
index 00000000000..56eccf8130c
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/ReflectPermission.java
@@ -0,0 +1,102 @@
+/* ReflectPermission.java - named permission for reflaction
+ Copyright (C) 2000, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.reflect;
+
+import java.security.BasicPermission;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ */
+
+/**
+ * This class implements permissions for reflection. This is a named
+ * permission, and the only defined name is suppressAccessChecks, which
+ * allows suppression of normal Java objects when using reflection.
+ *
+ * <table>
+ * <tr>
+ * <th>Permission Target Name</th>
+ * <th>What Permission Allows</th>
+ * <th>Risk of Allowing Permission</th>
+ * </tr>
+ * <tr>
+ * <td><code>suppressAccessChecks</code></td>
+ * <td>Ability to access fields, invoke methods, and construct objects
+ * via reflection, including non-public members in contexts where
+ * such access is not legal at compile-time.</td>
+ * <td>This is dangerous. It exposes possibly confidential information,
+ * and malicious code could interfere with the internals of the Virtual
+ * Machine by corrupting private data.</td>
+ * </tr>
+ * </table>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class ReflectPermission
+ extends BasicPermission
+{
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = 7412737110241507485L;
+
+ /**
+ * Construct a ReflectPermission with the given name.
+ *
+ * @param name The permission name
+ */
+ public ReflectPermission(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Construct a ReflectPermission with the given name.
+ *
+ * @param name The permission name
+ * @param actions The actions; this is ignored and should be null
+ */
+ public ReflectPermission(String name, String actions)
+ {
+ super(name, actions);
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/TODO b/libjava/classpath/java/lang/reflect/TODO
new file mode 100755
index 00000000000..6514c760317
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/TODO
@@ -0,0 +1,4 @@
+TODO for java.lang.reflect Java side
+
+- more tests!
+- Java 2 support (waiting on java.lang Java 2 support)
diff --git a/libjava/classpath/java/lang/reflect/Type.java b/libjava/classpath/java/lang/reflect/Type.java
new file mode 100644
index 00000000000..c9ea5bfb9cb
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Type.java
@@ -0,0 +1,55 @@
+/* Type.java - Superinterface for all types.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * Represents any <code>Type</code> within the Java programming
+ * language. This may be a primitive type (e.g. <code>int</code>,
+ * an array type (e.g. <code>double[]>/code>), a raw type
+ * (e.g. <code>Calendar</code>), a parameterized type
+ * (e.g. <code>List&lt;Boolean&gt;</code>, or a type
+ * variable (e.g. <code>T extends String</code>).
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface Type
+{
+}
diff --git a/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java b/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java
new file mode 100644
index 00000000000..6d5a8008459
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java
@@ -0,0 +1,128 @@
+/* UndeclaredThrowableException.java -- wraps an undeclared checked exception
+ thrown by a Proxy invocation handler
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * This exception class is thrown by a {@link Proxy} instance if
+ * the {@link InvocationHandler#invoke(Object, Method, Object[]) invoke}
+ * method of that instance's InvocationHandler attempts to throw an
+ * exception that not declared by the throws clauses of all of the
+ * interface methods that the proxy instance is implementing.
+ *
+ * <p>When thrown by Proxy, this class will always wrap a checked
+ * exception, never {@link Error} or {@link RuntimeException},
+ * which are unchecked.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Proxy
+ * @see InvocationHandler
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public class UndeclaredThrowableException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = 330127114055056639L;
+
+ /**
+ * The immutable exception that this wraps. This field is redundant
+ * with {@link Throwable#cause}, but is necessary for serial compatibility.
+ *
+ * @serial the chained exception
+ */
+ private final Throwable undeclaredThrowable;
+
+ /**
+ * Wraps the given checked exception into a RuntimeException, with no
+ * detail message. {@link Throwable#initCause(Throwable)} will fail
+ * on this instance.
+ *
+ * @param cause the undeclared throwable that caused this exception,
+ * may be null
+ */
+ public UndeclaredThrowableException(Throwable cause)
+ {
+ this(cause, null);
+ }
+
+ /**
+ * Wraps the given checked exception into a RuntimeException, with the
+ * specified detail message. {@link Throwable#initCause(Throwable)} will
+ * fail on this instance.
+ *
+ * @param cause the undeclared throwable that caused this exception,
+ * may be null
+ * @param message the message, may be null
+ */
+ public UndeclaredThrowableException(Throwable cause, String message)
+ {
+ super(message, cause);
+ undeclaredThrowable = cause;
+ }
+
+ /**
+ * Returns the cause of this exception. If this exception was created
+ * by a {@link Proxy} instance, it will be a non-null checked
+ * exception. This method pre-dates exception chaining, and is now
+ * simply a longer way to call <code>getCause()</code>.
+ *
+ * @return the cause of this exception, may be null
+ * @see #getCause()
+ */
+ public Throwable getUndeclaredThrowable()
+ {
+ return undeclaredThrowable;
+ }
+
+ /**
+ * Returns the cause of this exception. If this exception was created
+ * by a {@link Proxy} instance, it will be a non-null checked
+ * exception.
+ *
+ * @return the cause of this exception, may be null
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return undeclaredThrowable;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/WildcardType.java b/libjava/classpath/java/lang/reflect/WildcardType.java
new file mode 100644
index 00000000000..4f789067cf0
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/WildcardType.java
@@ -0,0 +1,115 @@
+/* WildcardType.java -- A wildcard type expression e.g. ? extends String
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+/**
+ * Represents a wildcard type expression, where the type variable
+ * is unnamed. The simplest example of this is <code>?</code>,
+ * which represents any unbounded type. Another example is
+ * <code>? extends Number</code>, which specifies any type
+ * which is a subclass of <code>Number</code> (<code>Number</code>
+ * is the upper bound).
+ * </p>
+ * <p>
+ * <code>? super String</code> gives the type a less common lower bound,
+ * which means that the type must be either a <code>String</code> or one
+ * of its superclasses. This can be useful in working with collections.
+ * You may want a method to add instances of a class to a collection
+ * with a more generic type (e.g. adding <code>String</code>s to
+ * a list of <code>Object</code>s), but don't want to allow users
+ * to pass in a collection with a more specific type.
+ * </p>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface WildcardType extends Type
+{
+
+ /**
+ * <p>
+ * Returns an array of <code>Type</code>s, which specify the
+ * lower bounds of this type. The default lower bound is
+ * <code>null</code>, which causes this method to return an
+ * empty array.
+ * </p>
+ * <p>
+ * In generating the array of <code>Type</code>s, each
+ * <code>ParameterizedType</code> or <code>TypeVariable</code> is
+ * created, (see the documentation for these classes for details of this
+ * process), if necessary, while all other types are simply
+ * resolved.
+ * </p>
+ *
+ * @return an array of <code>Type</code> objects, representing
+ * the wildcard type's lower bounds.
+ * @throws TypeNotPresentException if any of the types referred to by
+ * the lower bounds of this type do not actually exist.
+ * @throws MalformedParameterizedTypeException if any of the types
+ * refer to a type which can not be instantiated.
+ */
+ Type[] getLowerBounds();
+
+ /**
+ * <p>
+ * Returns an array of <code>Type</code>s, which specify the
+ * upper bounds of this type. The default upper bound is
+ * <code>Object</code>, which causes this method to return an
+ * array, containing just the <code>Type</code> instance for
+ * <code>Object</code>.
+ * </p>
+ * <p>
+ * In generating the array of <code>Type</code>s, each
+ * <code>ParameterizedType</code> or <code>TypeVariable</code> is
+ * created, (see the documentation for these classes for details of this
+ * process), if necessary, while all other types are simply
+ * resolved.
+ * </p>
+ *
+ * @return an array of <code>Type</code> objects, representing
+ * the wildcard type's upper bounds.
+ * @throws TypeNotPresentException if any of the types referred to by
+ * the upper bounds of this type do not actually exist.
+ * @throws MalformedParameterizedTypeException if any of the types
+ * refer to a type which can not be instantiated.
+ */
+ Type[] getUpperBounds();
+
+}
diff --git a/libjava/classpath/java/lang/reflect/package.html b/libjava/classpath/java/lang/reflect/package.html
new file mode 100644
index 00000000000..9f7ed632836
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.lang.reflect package.
+ Copyright (C) 2002 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 - java.lang.reflect</title></head>
+
+<body>
+<p>Runtime inspection and manipulation of object classes, methods, arguments
+and fields.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/math/BigDecimal.java b/libjava/classpath/java/math/BigDecimal.java
new file mode 100644
index 00000000000..d99be0f56ba
--- /dev/null
+++ b/libjava/classpath/java/math/BigDecimal.java
@@ -0,0 +1,517 @@
+/* java.math.BigDecimal -- Arbitrary precision decimals.
+ Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.math;
+
+public class BigDecimal extends Number implements Comparable
+{
+ private BigInteger intVal;
+ private int scale;
+ private static final long serialVersionUID = 6108874887143696463L;
+
+ private static final BigDecimal ZERO =
+ new BigDecimal (BigInteger.valueOf (0), 0);
+
+ private static final BigDecimal ONE =
+ new BigDecimal (BigInteger.valueOf (1), 0);
+
+ public static final int ROUND_UP = 0;
+ public static final int ROUND_DOWN = 1;
+ public static final int ROUND_CEILING = 2;
+ public static final int ROUND_FLOOR = 3;
+ public static final int ROUND_HALF_UP = 4;
+ public static final int ROUND_HALF_DOWN = 5;
+ public static final int ROUND_HALF_EVEN = 6;
+ public static final int ROUND_UNNECESSARY = 7;
+
+ public BigDecimal (BigInteger num)
+ {
+ this (num, 0);
+ }
+
+ public BigDecimal (BigInteger num, int scale) throws NumberFormatException
+ {
+ if (scale < 0)
+ throw new NumberFormatException ("scale of " + scale + " is < 0");
+ this.intVal = num;
+ this.scale = scale;
+ }
+
+ public BigDecimal (double num) throws NumberFormatException
+ {
+ if (Double.isInfinite (num) || Double.isNaN (num))
+ throw new NumberFormatException ("invalid argument: " + num);
+ // Note we can't convert NUM to a String and then use the
+ // String-based constructor. The BigDecimal documentation makes
+ // it clear that the two constructors work differently.
+
+ final int mantissaBits = 52;
+ final int exponentBits = 11;
+ final long mantMask = (1L << mantissaBits) - 1;
+ final long expMask = (1L << exponentBits) - 1;
+
+ long bits = Double.doubleToLongBits (num);
+ 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;
+ // Ordinary numbers have an implied leading `1' bit.
+ if (! denormal)
+ mantissa |= (1L << mantissaBits);
+
+ // Shave off factors of 10.
+ while (exponent < 0 && (mantissa & 1) == 0)
+ {
+ ++exponent;
+ mantissa >>= 1;
+ }
+
+ intVal = BigInteger.valueOf (bits < 0 ? - mantissa : mantissa);
+ if (exponent < 0)
+ {
+ // We have MANTISSA * 2 ^ (EXPONENT).
+ // Since (1/2)^N == 5^N * 10^-N we can easily convert this
+ // into a power of 10.
+ scale = (int) (- exponent);
+ BigInteger mult = BigInteger.valueOf (5).pow (scale);
+ intVal = intVal.multiply (mult);
+ }
+ else
+ {
+ intVal = intVal.shiftLeft ((int) exponent);
+ scale = 0;
+ }
+ }
+
+ public BigDecimal (String num) throws NumberFormatException
+ {
+ int len = num.length();
+ int start = 0, point = 0;
+ int dot = -1;
+ boolean negative = false;
+ if (num.charAt(0) == '+')
+ {
+ ++start;
+ ++point;
+ }
+ else if (num.charAt(0) == '-')
+ {
+ ++start;
+ ++point;
+ negative = true;
+ }
+
+ while (point < len)
+ {
+ char c = num.charAt (point);
+ if (c == '.')
+ {
+ if (dot >= 0)
+ throw new NumberFormatException ("multiple `.'s in number");
+ dot = point;
+ }
+ else if (c == 'e' || c == 'E')
+ break;
+ else if (Character.digit (c, 10) < 0)
+ throw new NumberFormatException ("unrecognized character: " + c);
+ ++point;
+ }
+
+ String val;
+ if (dot >= 0)
+ {
+ val = num.substring (start, dot) + num.substring (dot + 1, point);
+ scale = point - 1 - dot;
+ }
+ else
+ {
+ val = num.substring (start, point);
+ scale = 0;
+ }
+ if (val.length () == 0)
+ throw new NumberFormatException ("no digits seen");
+
+ if (negative)
+ val = "-" + val;
+ intVal = new BigInteger (val);
+
+ // Now parse exponent.
+ if (point < len)
+ {
+ point++;
+ if (num.charAt(point) == '+')
+ point++;
+
+ if (point >= len )
+ throw new NumberFormatException ("no exponent following e or E");
+
+ try
+ {
+ int exp = Integer.parseInt (num.substring (point));
+ exp -= scale;
+ if (signum () == 0)
+ scale = 0;
+ else if (exp > 0)
+ {
+ intVal = intVal.multiply (BigInteger.valueOf (10).pow (exp));
+ scale = 0;
+ }
+ else
+ scale = - exp;
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new NumberFormatException ("malformed exponent");
+ }
+ }
+ }
+
+ public static BigDecimal valueOf (long val)
+ {
+ return valueOf (val, 0);
+ }
+
+ public static BigDecimal valueOf (long val, int scale)
+ throws NumberFormatException
+ {
+ if ((scale == 0) && ((int)val == val))
+ switch ((int) val)
+ {
+ case 0:
+ return ZERO;
+ case 1:
+ return ONE;
+ }
+
+ return new BigDecimal (BigInteger.valueOf (val), scale);
+ }
+
+ public BigDecimal add (BigDecimal val)
+ {
+ // For addition, need to line up decimals. Note that the movePointRight
+ // method cannot be used for this as it might return a BigDecimal with
+ // scale == 0 instead of the scale we need.
+ BigInteger op1 = intVal;
+ BigInteger op2 = val.intVal;
+ if (scale < val.scale)
+ op1 = op1.multiply (BigInteger.valueOf (10).pow (val.scale - scale));
+ else if (scale > val.scale)
+ op2 = op2.multiply (BigInteger.valueOf (10).pow (scale - val.scale));
+
+ return new BigDecimal (op1.add (op2), Math.max (scale, val.scale));
+ }
+
+ public BigDecimal subtract (BigDecimal val)
+ {
+ return this.add(val.negate());
+ }
+
+ public BigDecimal multiply (BigDecimal val)
+ {
+ return new BigDecimal (intVal.multiply (val.intVal), scale + val.scale);
+ }
+
+ public BigDecimal divide (BigDecimal val, int roundingMode)
+ throws ArithmeticException, IllegalArgumentException
+ {
+ return divide (val, scale, roundingMode);
+ }
+
+ public BigDecimal divide(BigDecimal val, int newScale, int roundingMode)
+ throws ArithmeticException, IllegalArgumentException
+ {
+ if (roundingMode < 0 || roundingMode > 7)
+ throw
+ new IllegalArgumentException("illegal rounding mode: " + roundingMode);
+
+ if (newScale < 0)
+ throw new ArithmeticException ("scale is negative: " + newScale);
+
+ if (intVal.signum () == 0) // handle special case of 0.0/0.0
+ return newScale == 0 ? ZERO : new BigDecimal (ZERO.intVal, newScale);
+
+ // Ensure that pow gets a non-negative value.
+ BigInteger valIntVal = val.intVal;
+ int power = newScale - (scale - val.scale);
+ if (power < 0)
+ {
+ // Effectively increase the scale of val to avoid an
+ // ArithmeticException for a negative power.
+ valIntVal = valIntVal.multiply (BigInteger.valueOf (10).pow (-power));
+ power = 0;
+ }
+
+ BigInteger dividend = intVal.multiply (BigInteger.valueOf (10).pow (power));
+
+ BigInteger parts[] = dividend.divideAndRemainder (valIntVal);
+
+ BigInteger unrounded = parts[0];
+ if (parts[1].signum () == 0) // no remainder, no rounding necessary
+ return new BigDecimal (unrounded, newScale);
+
+ if (roundingMode == ROUND_UNNECESSARY)
+ throw new ArithmeticException ("newScale is not large enough");
+
+ int sign = intVal.signum () * valIntVal.signum ();
+
+ if (roundingMode == ROUND_CEILING)
+ roundingMode = (sign > 0) ? ROUND_UP : ROUND_DOWN;
+ else if (roundingMode == ROUND_FLOOR)
+ roundingMode = (sign < 0) ? ROUND_UP : ROUND_DOWN;
+ else
+ {
+ // half is -1 if remainder*2 < positive intValue (*power), 0 if equal,
+ // 1 if >. This implies that the remainder to round is less than,
+ // equal to, or greater than half way to the next digit.
+ BigInteger posRemainder
+ = parts[1].signum () < 0 ? parts[1].negate() : parts[1];
+ valIntVal = valIntVal.signum () < 0 ? valIntVal.negate () : valIntVal;
+ int half = posRemainder.shiftLeft(1).compareTo(valIntVal);
+
+ switch(roundingMode)
+ {
+ case ROUND_HALF_UP:
+ roundingMode = (half < 0) ? ROUND_DOWN : ROUND_UP;
+ break;
+ case ROUND_HALF_DOWN:
+ roundingMode = (half > 0) ? ROUND_UP : ROUND_DOWN;
+ break;
+ case ROUND_HALF_EVEN:
+ if (half < 0)
+ roundingMode = ROUND_DOWN;
+ else if (half > 0)
+ roundingMode = ROUND_UP;
+ else if (unrounded.testBit(0)) // odd, then ROUND_HALF_UP
+ roundingMode = ROUND_UP;
+ else // even, ROUND_HALF_DOWN
+ roundingMode = ROUND_DOWN;
+ break;
+ }
+ }
+
+ if (roundingMode == ROUND_UP)
+ unrounded = unrounded.add (BigInteger.valueOf (sign > 0 ? 1 : -1));
+
+ // roundingMode == ROUND_DOWN
+ return new BigDecimal (unrounded, newScale);
+ }
+
+ public int compareTo (BigDecimal val)
+ {
+ if (scale == val.scale)
+ return intVal.compareTo (val.intVal);
+
+ BigInteger thisParts[] =
+ intVal.divideAndRemainder (BigInteger.valueOf (10).pow (scale));
+ BigInteger valParts[] =
+ val.intVal.divideAndRemainder (BigInteger.valueOf (10).pow (val.scale));
+
+ int compare;
+ if ((compare = thisParts[0].compareTo (valParts[0])) != 0)
+ return compare;
+
+ // quotients are the same, so compare remainders
+
+ // remove trailing zeros
+ if (thisParts[1].equals (BigInteger.valueOf (0)) == false)
+ while (thisParts[1].mod (BigInteger.valueOf (10)).equals
+ (BigInteger.valueOf (0)))
+ thisParts[1] = thisParts[1].divide (BigInteger.valueOf (10));
+ // again...
+ if (valParts[1].equals(BigInteger.valueOf (0)) == false)
+ while (valParts[1].mod (BigInteger.valueOf (10)).equals
+ (BigInteger.valueOf (0)))
+ valParts[1] = valParts[1].divide (BigInteger.valueOf (10));
+
+ // and compare them
+ return thisParts[1].compareTo (valParts[1]);
+ }
+
+ public int compareTo (Object val)
+ {
+ return(compareTo((BigDecimal)val));
+ }
+
+ public boolean equals (Object o)
+ {
+ return (o instanceof BigDecimal
+ && scale == ((BigDecimal) o).scale
+ && compareTo ((BigDecimal) o) == 0);
+ }
+
+ public int hashCode()
+ {
+ return intValue() ^ scale;
+ }
+
+ public BigDecimal max (BigDecimal val)
+ {
+ switch (compareTo (val))
+ {
+ case 1:
+ return this;
+ default:
+ return val;
+ }
+ }
+
+ public BigDecimal min (BigDecimal val)
+ {
+ switch (compareTo (val))
+ {
+ case -1:
+ return this;
+ default:
+ return val;
+ }
+ }
+
+ public BigDecimal movePointLeft (int n)
+ {
+ return (n < 0) ? movePointRight (-n) : new BigDecimal (intVal, scale + n);
+ }
+
+ public BigDecimal movePointRight (int n)
+ {
+ if (n < 0)
+ return movePointLeft (-n);
+
+ if (scale >= n)
+ return new BigDecimal (intVal, scale - n);
+
+ return new BigDecimal (intVal.multiply
+ (BigInteger.valueOf (10).pow (n - scale)), 0);
+ }
+
+ public int signum ()
+ {
+ return intVal.signum ();
+ }
+
+ public int scale ()
+ {
+ return scale;
+ }
+
+ public BigInteger unscaledValue()
+ {
+ return intVal;
+ }
+
+ public BigDecimal abs ()
+ {
+ return new BigDecimal (intVal.abs (), scale);
+ }
+
+ public BigDecimal negate ()
+ {
+ return new BigDecimal (intVal.negate (), scale);
+ }
+
+ public String toString ()
+ {
+ String bigStr = intVal.toString();
+ if (scale == 0)
+ return bigStr;
+
+ boolean negative = (bigStr.charAt(0) == '-');
+
+ int point = bigStr.length() - scale - (negative ? 1 : 0);
+
+ StringBuffer sb = new StringBuffer(bigStr.length() + 2 +
+ (point <= 0 ? (-point + 1) : 0));
+ if (point <= 0)
+ {
+ if (negative)
+ sb.append('-');
+ sb.append('0').append('.');
+ while (point < 0)
+ {
+ sb.append('0');
+ point++;
+ }
+ sb.append(bigStr.substring(negative ? 1 : 0));
+ }
+ else
+ {
+ sb.append(bigStr);
+ sb.insert(point + (negative ? 1 : 0), '.');
+ }
+ return sb.toString();
+ }
+
+ public BigInteger toBigInteger ()
+ {
+ return scale == 0 ? intVal :
+ intVal.divide (BigInteger.valueOf (10).pow (scale));
+ }
+
+ public int intValue ()
+ {
+ return toBigInteger ().intValue ();
+ }
+
+ public long longValue ()
+ {
+ return toBigInteger().longValue();
+ }
+
+ public float floatValue()
+ {
+ return Float.valueOf(toString()).floatValue();
+ }
+
+ public double doubleValue()
+ {
+ return Double.valueOf(toString()).doubleValue();
+ }
+
+ public BigDecimal setScale (int scale) throws ArithmeticException
+ {
+ return setScale (scale, ROUND_UNNECESSARY);
+ }
+
+ public BigDecimal setScale (int scale, int roundingMode)
+ throws ArithmeticException, IllegalArgumentException
+ {
+ return divide (ONE, scale, roundingMode);
+ }
+}
diff --git a/libjava/classpath/java/math/BigInteger.java b/libjava/classpath/java/math/BigInteger.java
new file mode 100644
index 00000000000..82f550d144c
--- /dev/null
+++ b/libjava/classpath/java/math/BigInteger.java
@@ -0,0 +1,2230 @@
+/* java.math.BigInteger -- Arbitary precision integers
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.math;
+
+import gnu.java.math.MPN;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Random;
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998) and
+ * "Applied Cryptography, Second Edition" by Bruce Schneier (Wiley, 1996).
+ *
+ * Based primarily on IntNum.java BitOps.java by Per Bothner (per@bothner.com)
+ * (found in Kawa 1.6.62).
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @date December 20, 1999.
+ * @status believed complete and correct.
+ */
+public class BigInteger extends Number implements Comparable
+{
+ /** All integers are stored in 2's-complement form.
+ * If words == null, the ival is the value of this BigInteger.
+ * Otherwise, the first ival elements of words make the value
+ * of this BigInteger, stored in little-endian order, 2's-complement form. */
+ private transient int ival;
+ private transient int[] words;
+
+ // Serialization fields.
+ private int bitCount = -1;
+ private int bitLength = -1;
+ private int firstNonzeroByteNum = -2;
+ private int lowestSetBit = -2;
+ private byte[] magnitude;
+ private int signum;
+ private static final long serialVersionUID = -8287574255936472291L;
+
+
+ /** We pre-allocate integers in the range minFixNum..maxFixNum. */
+ private static final int minFixNum = -100;
+ private static final int maxFixNum = 1024;
+ private static final int numFixNum = maxFixNum-minFixNum+1;
+ private static final BigInteger[] smallFixNums = new BigInteger[numFixNum];
+
+ static {
+ for (int i = numFixNum; --i >= 0; )
+ smallFixNums[i] = new BigInteger(i + minFixNum);
+ }
+
+ // JDK1.2
+ public static final BigInteger ZERO = smallFixNums[-minFixNum];
+
+ // JDK1.2
+ public static final BigInteger ONE = smallFixNums[1 - minFixNum];
+
+ /* Rounding modes: */
+ private static final int FLOOR = 1;
+ private static final int CEILING = 2;
+ private static final int TRUNCATE = 3;
+ private static final int ROUND = 4;
+
+ /** When checking the probability of primes, it is most efficient to
+ * first check the factoring of small primes, so we'll use this array.
+ */
+ private static final int[] primes =
+ { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
+ 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
+ 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181,
+ 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 };
+
+ /** HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Table 4.4. */
+ private static final int[] k =
+ {100,150,200,250,300,350,400,500,600,800,1250, Integer.MAX_VALUE};
+ private static final int[] t =
+ { 27, 18, 15, 12, 9, 8, 7, 6, 5, 4, 3, 2};
+
+ private BigInteger()
+ {
+ }
+
+ /* Create a new (non-shared) BigInteger, and initialize to an int. */
+ private BigInteger(int value)
+ {
+ ival = value;
+ }
+
+ public BigInteger(String val, int radix)
+ {
+ BigInteger result = valueOf(val, radix);
+ this.ival = result.ival;
+ this.words = result.words;
+ }
+
+ public BigInteger(String val)
+ {
+ this(val, 10);
+ }
+
+ /* Create a new (non-shared) BigInteger, and initialize from a byte array. */
+ public BigInteger(byte[] val)
+ {
+ if (val == null || val.length < 1)
+ throw new NumberFormatException();
+
+ words = byteArrayToIntArray(val, val[0] < 0 ? -1 : 0);
+ BigInteger result = make(words, words.length);
+ this.ival = result.ival;
+ this.words = result.words;
+ }
+
+ public BigInteger(int signum, byte[] magnitude)
+ {
+ if (magnitude == null || signum > 1 || signum < -1)
+ throw new NumberFormatException();
+
+ if (signum == 0)
+ {
+ int i;
+ for (i = magnitude.length - 1; i >= 0 && magnitude[i] == 0; --i)
+ ;
+ if (i >= 0)
+ throw new NumberFormatException();
+ return;
+ }
+
+ // Magnitude is always positive, so don't ever pass a sign of -1.
+ words = byteArrayToIntArray(magnitude, 0);
+ BigInteger result = make(words, words.length);
+ this.ival = result.ival;
+ this.words = result.words;
+
+ if (signum < 0)
+ setNegative();
+ }
+
+ public BigInteger(int numBits, Random rnd)
+ {
+ if (numBits < 0)
+ throw new IllegalArgumentException();
+
+ init(numBits, rnd);
+ }
+
+ private void init(int numBits, Random rnd)
+ {
+ int highbits = numBits & 31;
+ if (highbits > 0)
+ highbits = rnd.nextInt() >>> (32 - highbits);
+ int nwords = numBits / 32;
+
+ while (highbits == 0 && nwords > 0)
+ {
+ highbits = rnd.nextInt();
+ --nwords;
+ }
+ if (nwords == 0 && highbits >= 0)
+ {
+ ival = highbits;
+ }
+ else
+ {
+ ival = highbits < 0 ? nwords + 2 : nwords + 1;
+ words = new int[ival];
+ words[nwords] = highbits;
+ while (--nwords >= 0)
+ words[nwords] = rnd.nextInt();
+ }
+ }
+
+ public BigInteger(int bitLength, int certainty, Random rnd)
+ {
+ this(bitLength, rnd);
+
+ // Keep going until we find a probable prime.
+ while (true)
+ {
+ if (isProbablePrime(certainty))
+ return;
+
+ init(bitLength, rnd);
+ }
+ }
+
+ /**
+ * Return a BigInteger that is bitLength bits long with a
+ * probability < 2^-100 of being composite.
+ *
+ * @param bitLength length in bits of resulting number
+ * @param rnd random number generator to use
+ * @throws ArithmeticException if bitLength < 2
+ * @since 1.4
+ */
+ public static BigInteger probablePrime(int bitLength, Random rnd)
+ {
+ if (bitLength < 2)
+ throw new ArithmeticException();
+
+ return new BigInteger(bitLength, 100, rnd);
+ }
+
+ /** Return a (possibly-shared) BigInteger with a given long value. */
+ public static BigInteger valueOf(long val)
+ {
+ if (val >= minFixNum && val <= maxFixNum)
+ return smallFixNums[(int) val - minFixNum];
+ int i = (int) val;
+ if ((long) i == val)
+ return new BigInteger(i);
+ BigInteger result = alloc(2);
+ result.ival = 2;
+ result.words[0] = i;
+ result.words[1] = (int)(val >> 32);
+ return result;
+ }
+
+ /** Make a canonicalized BigInteger from an array of words.
+ * The array may be reused (without copying). */
+ private static BigInteger make(int[] words, int len)
+ {
+ if (words == null)
+ return valueOf(len);
+ len = BigInteger.wordsNeeded(words, len);
+ if (len <= 1)
+ return len == 0 ? ZERO : valueOf(words[0]);
+ BigInteger num = new BigInteger();
+ num.words = words;
+ num.ival = len;
+ return num;
+ }
+
+ /** Convert a big-endian byte array to a little-endian array of words. */
+ private static int[] byteArrayToIntArray(byte[] bytes, int sign)
+ {
+ // Determine number of words needed.
+ int[] words = new int[bytes.length/4 + 1];
+ int nwords = words.length;
+
+ // Create a int out of modulo 4 high order bytes.
+ int bptr = 0;
+ int word = sign;
+ for (int i = bytes.length % 4; i > 0; --i, bptr++)
+ word = (word << 8) | (bytes[bptr] & 0xff);
+ words[--nwords] = word;
+
+ // Elements remaining in byte[] are a multiple of 4.
+ while (nwords > 0)
+ words[--nwords] = bytes[bptr++] << 24 |
+ (bytes[bptr++] & 0xff) << 16 |
+ (bytes[bptr++] & 0xff) << 8 |
+ (bytes[bptr++] & 0xff);
+ return words;
+ }
+
+ /** Allocate a new non-shared BigInteger.
+ * @param nwords number of words to allocate
+ */
+ private static BigInteger alloc(int nwords)
+ {
+ BigInteger result = new BigInteger();
+ if (nwords > 1)
+ result.words = new int[nwords];
+ return result;
+ }
+
+ /** Change words.length to nwords.
+ * We allow words.length to be upto nwords+2 without reallocating.
+ */
+ private void realloc(int nwords)
+ {
+ if (nwords == 0)
+ {
+ if (words != null)
+ {
+ if (ival > 0)
+ ival = words[0];
+ words = null;
+ }
+ }
+ else if (words == null
+ || words.length < nwords
+ || words.length > nwords + 2)
+ {
+ int[] new_words = new int [nwords];
+ if (words == null)
+ {
+ new_words[0] = ival;
+ ival = 1;
+ }
+ else
+ {
+ if (nwords < ival)
+ ival = nwords;
+ System.arraycopy(words, 0, new_words, 0, ival);
+ }
+ words = new_words;
+ }
+ }
+
+ private boolean isNegative()
+ {
+ return (words == null ? ival : words[ival - 1]) < 0;
+ }
+
+ public int signum()
+ {
+ int top = words == null ? ival : words[ival-1];
+ if (top == 0 && words == null)
+ return 0;
+ return top < 0 ? -1 : 1;
+ }
+
+ private static int compareTo(BigInteger x, BigInteger y)
+ {
+ if (x.words == null && y.words == null)
+ return x.ival < y.ival ? -1 : x.ival > y.ival ? 1 : 0;
+ boolean x_negative = x.isNegative();
+ boolean y_negative = y.isNegative();
+ if (x_negative != y_negative)
+ return x_negative ? -1 : 1;
+ int x_len = x.words == null ? 1 : x.ival;
+ int y_len = y.words == null ? 1 : y.ival;
+ if (x_len != y_len)
+ return (x_len > y_len) != x_negative ? 1 : -1;
+ return MPN.cmp(x.words, y.words, x_len);
+ }
+
+ // JDK1.2
+ public int compareTo(Object obj)
+ {
+ if (obj instanceof BigInteger)
+ return compareTo(this, (BigInteger) obj);
+ throw new ClassCastException();
+ }
+
+ public int compareTo(BigInteger val)
+ {
+ return compareTo(this, val);
+ }
+
+ public BigInteger min(BigInteger val)
+ {
+ return compareTo(this, val) < 0 ? this : val;
+ }
+
+ public BigInteger max(BigInteger val)
+ {
+ return compareTo(this, val) > 0 ? this : val;
+ }
+
+ private boolean isZero()
+ {
+ return words == null && ival == 0;
+ }
+
+ private boolean isOne()
+ {
+ return words == null && ival == 1;
+ }
+
+ /** Calculate how many words are significant in words[0:len-1].
+ * Returns the least value x such that x>0 && words[0:x-1]==words[0:len-1],
+ * when words is viewed as a 2's complement integer.
+ */
+ private static int wordsNeeded(int[] words, int len)
+ {
+ int i = len;
+ if (i > 0)
+ {
+ int word = words[--i];
+ if (word == -1)
+ {
+ while (i > 0 && (word = words[i - 1]) < 0)
+ {
+ i--;
+ if (word != -1) break;
+ }
+ }
+ else
+ {
+ while (word == 0 && i > 0 && (word = words[i - 1]) >= 0) i--;
+ }
+ }
+ return i + 1;
+ }
+
+ private BigInteger canonicalize()
+ {
+ if (words != null
+ && (ival = BigInteger.wordsNeeded(words, ival)) <= 1)
+ {
+ if (ival == 1)
+ ival = words[0];
+ words = null;
+ }
+ if (words == null && ival >= minFixNum && ival <= maxFixNum)
+ return smallFixNums[ival - minFixNum];
+ return this;
+ }
+
+ /** Add two ints, yielding a BigInteger. */
+ private static BigInteger add(int x, int y)
+ {
+ return valueOf((long) x + (long) y);
+ }
+
+ /** Add a BigInteger and an int, yielding a new BigInteger. */
+ private static BigInteger add(BigInteger x, int y)
+ {
+ if (x.words == null)
+ return BigInteger.add(x.ival, y);
+ BigInteger result = new BigInteger(0);
+ result.setAdd(x, y);
+ return result.canonicalize();
+ }
+
+ /** Set this to the sum of x and y.
+ * OK if x==this. */
+ private void setAdd(BigInteger x, int y)
+ {
+ if (x.words == null)
+ {
+ set((long) x.ival + (long) y);
+ return;
+ }
+ int len = x.ival;
+ realloc(len + 1);
+ long carry = y;
+ for (int i = 0; i < len; i++)
+ {
+ carry += ((long) x.words[i] & 0xffffffffL);
+ words[i] = (int) carry;
+ carry >>= 32;
+ }
+ if (x.words[len - 1] < 0)
+ carry--;
+ words[len] = (int) carry;
+ ival = wordsNeeded(words, len + 1);
+ }
+
+ /** Destructively add an int to this. */
+ private void setAdd(int y)
+ {
+ setAdd(this, y);
+ }
+
+ /** Destructively set the value of this to a long. */
+ private void set(long y)
+ {
+ int i = (int) y;
+ if ((long) i == y)
+ {
+ ival = i;
+ words = null;
+ }
+ else
+ {
+ realloc(2);
+ words[0] = i;
+ words[1] = (int) (y >> 32);
+ ival = 2;
+ }
+ }
+
+ /** Destructively set the value of this to the given words.
+ * The words array is reused, not copied. */
+ private void set(int[] words, int length)
+ {
+ this.ival = length;
+ this.words = words;
+ }
+
+ /** Destructively set the value of this to that of y. */
+ private void set(BigInteger y)
+ {
+ if (y.words == null)
+ set(y.ival);
+ else if (this != y)
+ {
+ realloc(y.ival);
+ System.arraycopy(y.words, 0, words, 0, y.ival);
+ ival = y.ival;
+ }
+ }
+
+ /** Add two BigIntegers, yielding their sum as another BigInteger. */
+ private static BigInteger add(BigInteger x, BigInteger y, int k)
+ {
+ if (x.words == null && y.words == null)
+ return valueOf((long) k * (long) y.ival + (long) x.ival);
+ if (k != 1)
+ {
+ if (k == -1)
+ y = BigInteger.neg(y);
+ else
+ y = BigInteger.times(y, valueOf(k));
+ }
+ if (x.words == null)
+ return BigInteger.add(y, x.ival);
+ if (y.words == null)
+ return BigInteger.add(x, y.ival);
+ // Both are big
+ if (y.ival > x.ival)
+ { // Swap so x is longer then y.
+ BigInteger tmp = x; x = y; y = tmp;
+ }
+ BigInteger result = alloc(x.ival + 1);
+ int i = y.ival;
+ long carry = MPN.add_n(result.words, x.words, y.words, i);
+ long y_ext = y.words[i - 1] < 0 ? 0xffffffffL : 0;
+ for (; i < x.ival; i++)
+ {
+ carry += ((long) x.words[i] & 0xffffffffL) + y_ext;;
+ result.words[i] = (int) carry;
+ carry >>>= 32;
+ }
+ if (x.words[i - 1] < 0)
+ y_ext--;
+ result.words[i] = (int) (carry + y_ext);
+ result.ival = i+1;
+ return result.canonicalize();
+ }
+
+ public BigInteger add(BigInteger val)
+ {
+ return add(this, val, 1);
+ }
+
+ public BigInteger subtract(BigInteger val)
+ {
+ return add(this, val, -1);
+ }
+
+ private static BigInteger times(BigInteger x, int y)
+ {
+ if (y == 0)
+ return ZERO;
+ if (y == 1)
+ return x;
+ int[] xwords = x.words;
+ int xlen = x.ival;
+ if (xwords == null)
+ return valueOf((long) xlen * (long) y);
+ boolean negative;
+ BigInteger result = BigInteger.alloc(xlen + 1);
+ if (xwords[xlen - 1] < 0)
+ {
+ negative = true;
+ negate(result.words, xwords, xlen);
+ xwords = result.words;
+ }
+ else
+ negative = false;
+ if (y < 0)
+ {
+ negative = !negative;
+ y = -y;
+ }
+ result.words[xlen] = MPN.mul_1(result.words, xwords, xlen, y);
+ result.ival = xlen + 1;
+ if (negative)
+ result.setNegative();
+ return result.canonicalize();
+ }
+
+ private static BigInteger times(BigInteger x, BigInteger y)
+ {
+ if (y.words == null)
+ return times(x, y.ival);
+ if (x.words == null)
+ return times(y, x.ival);
+ boolean negative = false;
+ int[] xwords;
+ int[] ywords;
+ int xlen = x.ival;
+ int ylen = y.ival;
+ if (x.isNegative())
+ {
+ negative = true;
+ xwords = new int[xlen];
+ negate(xwords, x.words, xlen);
+ }
+ else
+ {
+ negative = false;
+ xwords = x.words;
+ }
+ if (y.isNegative())
+ {
+ negative = !negative;
+ ywords = new int[ylen];
+ negate(ywords, y.words, ylen);
+ }
+ else
+ ywords = y.words;
+ // Swap if x is shorter then y.
+ if (xlen < ylen)
+ {
+ int[] twords = xwords; xwords = ywords; ywords = twords;
+ int tlen = xlen; xlen = ylen; ylen = tlen;
+ }
+ BigInteger result = BigInteger.alloc(xlen+ylen);
+ MPN.mul(result.words, xwords, xlen, ywords, ylen);
+ result.ival = xlen+ylen;
+ if (negative)
+ result.setNegative();
+ return result.canonicalize();
+ }
+
+ public BigInteger multiply(BigInteger y)
+ {
+ return times(this, y);
+ }
+
+ private static void divide(long x, long y,
+ BigInteger quotient, BigInteger remainder,
+ int rounding_mode)
+ {
+ boolean xNegative, yNegative;
+ if (x < 0)
+ {
+ xNegative = true;
+ if (x == Long.MIN_VALUE)
+ {
+ divide(valueOf(x), valueOf(y),
+ quotient, remainder, rounding_mode);
+ return;
+ }
+ x = -x;
+ }
+ else
+ xNegative = false;
+
+ if (y < 0)
+ {
+ yNegative = true;
+ if (y == Long.MIN_VALUE)
+ {
+ if (rounding_mode == TRUNCATE)
+ { // x != Long.Min_VALUE implies abs(x) < abs(y)
+ if (quotient != null)
+ quotient.set(0);
+ if (remainder != null)
+ remainder.set(x);
+ }
+ else
+ divide(valueOf(x), valueOf(y),
+ quotient, remainder, rounding_mode);
+ return;
+ }
+ y = -y;
+ }
+ else
+ yNegative = false;
+
+ long q = x / y;
+ long r = x % y;
+ boolean qNegative = xNegative ^ yNegative;
+
+ boolean add_one = false;
+ if (r != 0)
+ {
+ switch (rounding_mode)
+ {
+ case TRUNCATE:
+ break;
+ case CEILING:
+ case FLOOR:
+ if (qNegative == (rounding_mode == FLOOR))
+ add_one = true;
+ break;
+ case ROUND:
+ add_one = r > ((y - (q & 1)) >> 1);
+ break;
+ }
+ }
+ if (quotient != null)
+ {
+ if (add_one)
+ q++;
+ if (qNegative)
+ q = -q;
+ quotient.set(q);
+ }
+ if (remainder != null)
+ {
+ // The remainder is by definition: X-Q*Y
+ if (add_one)
+ {
+ // Subtract the remainder from Y.
+ r = y - r;
+ // In this case, abs(Q*Y) > abs(X).
+ // So sign(remainder) = -sign(X).
+ xNegative = ! xNegative;
+ }
+ else
+ {
+ // If !add_one, then: abs(Q*Y) <= abs(X).
+ // So sign(remainder) = sign(X).
+ }
+ if (xNegative)
+ r = -r;
+ remainder.set(r);
+ }
+ }
+
+ /** Divide two integers, yielding quotient and remainder.
+ * @param x the numerator in the division
+ * @param y the denominator in the division
+ * @param quotient is set to the quotient of the result (iff quotient!=null)
+ * @param remainder is set to the remainder of the result
+ * (iff remainder!=null)
+ * @param rounding_mode one of FLOOR, CEILING, TRUNCATE, or ROUND.
+ */
+ private static void divide(BigInteger x, BigInteger y,
+ BigInteger quotient, BigInteger remainder,
+ int rounding_mode)
+ {
+ if ((x.words == null || x.ival <= 2)
+ && (y.words == null || y.ival <= 2))
+ {
+ long x_l = x.longValue();
+ long y_l = y.longValue();
+ if (x_l != Long.MIN_VALUE && y_l != Long.MIN_VALUE)
+ {
+ divide(x_l, y_l, quotient, remainder, rounding_mode);
+ return;
+ }
+ }
+
+ boolean xNegative = x.isNegative();
+ boolean yNegative = y.isNegative();
+ boolean qNegative = xNegative ^ yNegative;
+
+ int ylen = y.words == null ? 1 : y.ival;
+ int[] ywords = new int[ylen];
+ y.getAbsolute(ywords);
+ while (ylen > 1 && ywords[ylen - 1] == 0) ylen--;
+
+ int xlen = x.words == null ? 1 : x.ival;
+ int[] xwords = new int[xlen+2];
+ x.getAbsolute(xwords);
+ while (xlen > 1 && xwords[xlen-1] == 0) xlen--;
+
+ int qlen, rlen;
+
+ int cmpval = MPN.cmp(xwords, xlen, ywords, ylen);
+ if (cmpval < 0) // abs(x) < abs(y)
+ { // quotient = 0; remainder = num.
+ int[] rwords = xwords; xwords = ywords; ywords = rwords;
+ rlen = xlen; qlen = 1; xwords[0] = 0;
+ }
+ else if (cmpval == 0) // abs(x) == abs(y)
+ {
+ xwords[0] = 1; qlen = 1; // quotient = 1
+ ywords[0] = 0; rlen = 1; // remainder = 0;
+ }
+ else if (ylen == 1)
+ {
+ qlen = xlen;
+ // Need to leave room for a word of leading zeros if dividing by 1
+ // and the dividend has the high bit set. It might be safe to
+ // increment qlen in all cases, but it certainly is only necessary
+ // in the following case.
+ if (ywords[0] == 1 && xwords[xlen-1] < 0)
+ qlen++;
+ rlen = 1;
+ ywords[0] = MPN.divmod_1(xwords, xwords, xlen, ywords[0]);
+ }
+ else // abs(x) > abs(y)
+ {
+ // Normalize the denominator, i.e. make its most significant bit set by
+ // shifting it normalization_steps bits to the left. Also shift the
+ // numerator the same number of steps (to keep the quotient the same!).
+
+ int nshift = MPN.count_leading_zeros(ywords[ylen - 1]);
+ if (nshift != 0)
+ {
+ // Shift up the denominator setting the most significant bit of
+ // the most significant word.
+ MPN.lshift(ywords, 0, ywords, ylen, nshift);
+
+ // Shift up the numerator, possibly introducing a new most
+ // significant word.
+ int x_high = MPN.lshift(xwords, 0, xwords, xlen, nshift);
+ xwords[xlen++] = x_high;
+ }
+
+ if (xlen == ylen)
+ xwords[xlen++] = 0;
+ MPN.divide(xwords, xlen, ywords, ylen);
+ rlen = ylen;
+ MPN.rshift0 (ywords, xwords, 0, rlen, nshift);
+
+ qlen = xlen + 1 - ylen;
+ if (quotient != null)
+ {
+ for (int i = 0; i < qlen; i++)
+ xwords[i] = xwords[i+ylen];
+ }
+ }
+
+ if (ywords[rlen-1] < 0)
+ {
+ ywords[rlen] = 0;
+ rlen++;
+ }
+
+ // Now the quotient is in xwords, and the remainder is in ywords.
+
+ boolean add_one = false;
+ if (rlen > 1 || ywords[0] != 0)
+ { // Non-zero remainder i.e. in-exact quotient.
+ switch (rounding_mode)
+ {
+ case TRUNCATE:
+ break;
+ case CEILING:
+ case FLOOR:
+ if (qNegative == (rounding_mode == FLOOR))
+ add_one = true;
+ break;
+ case ROUND:
+ // int cmp = compareTo(remainder<<1, abs(y));
+ BigInteger tmp = remainder == null ? new BigInteger() : remainder;
+ tmp.set(ywords, rlen);
+ tmp = shift(tmp, 1);
+ if (yNegative)
+ tmp.setNegative();
+ int cmp = compareTo(tmp, y);
+ // Now cmp == compareTo(sign(y)*(remainder<<1), y)
+ if (yNegative)
+ cmp = -cmp;
+ add_one = (cmp == 1) || (cmp == 0 && (xwords[0]&1) != 0);
+ }
+ }
+ if (quotient != null)
+ {
+ quotient.set(xwords, qlen);
+ if (qNegative)
+ {
+ if (add_one) // -(quotient + 1) == ~(quotient)
+ quotient.setInvert();
+ else
+ quotient.setNegative();
+ }
+ else if (add_one)
+ quotient.setAdd(1);
+ }
+ if (remainder != null)
+ {
+ // The remainder is by definition: X-Q*Y
+ remainder.set(ywords, rlen);
+ if (add_one)
+ {
+ // Subtract the remainder from Y:
+ // abs(R) = abs(Y) - abs(orig_rem) = -(abs(orig_rem) - abs(Y)).
+ BigInteger tmp;
+ if (y.words == null)
+ {
+ tmp = remainder;
+ tmp.set(yNegative ? ywords[0] + y.ival : ywords[0] - y.ival);
+ }
+ else
+ tmp = BigInteger.add(remainder, y, yNegative ? 1 : -1);
+ // Now tmp <= 0.
+ // In this case, abs(Q) = 1 + floor(abs(X)/abs(Y)).
+ // Hence, abs(Q*Y) > abs(X).
+ // So sign(remainder) = -sign(X).
+ if (xNegative)
+ remainder.setNegative(tmp);
+ else
+ remainder.set(tmp);
+ }
+ else
+ {
+ // If !add_one, then: abs(Q*Y) <= abs(X).
+ // So sign(remainder) = sign(X).
+ if (xNegative)
+ remainder.setNegative();
+ }
+ }
+ }
+
+ public BigInteger divide(BigInteger val)
+ {
+ if (val.isZero())
+ throw new ArithmeticException("divisor is zero");
+
+ BigInteger quot = new BigInteger();
+ divide(this, val, quot, null, TRUNCATE);
+ return quot.canonicalize();
+ }
+
+ public BigInteger remainder(BigInteger val)
+ {
+ if (val.isZero())
+ throw new ArithmeticException("divisor is zero");
+
+ BigInteger rem = new BigInteger();
+ divide(this, val, null, rem, TRUNCATE);
+ return rem.canonicalize();
+ }
+
+ public BigInteger[] divideAndRemainder(BigInteger val)
+ {
+ if (val.isZero())
+ throw new ArithmeticException("divisor is zero");
+
+ BigInteger[] result = new BigInteger[2];
+ result[0] = new BigInteger();
+ result[1] = new BigInteger();
+ divide(this, val, result[0], result[1], TRUNCATE);
+ result[0].canonicalize();
+ result[1].canonicalize();
+ return result;
+ }
+
+ public BigInteger mod(BigInteger m)
+ {
+ if (m.isNegative() || m.isZero())
+ throw new ArithmeticException("non-positive modulus");
+
+ BigInteger rem = new BigInteger();
+ divide(this, m, null, rem, FLOOR);
+ return rem.canonicalize();
+ }
+
+ /** Calculate the integral power of a BigInteger.
+ * @param exponent the exponent (must be non-negative)
+ */
+ public BigInteger pow(int exponent)
+ {
+ if (exponent <= 0)
+ {
+ if (exponent == 0)
+ return ONE;
+ throw new ArithmeticException("negative exponent");
+ }
+ if (isZero())
+ return this;
+ int plen = words == null ? 1 : ival; // Length of pow2.
+ int blen = ((bitLength() * exponent) >> 5) + 2 * plen;
+ boolean negative = isNegative() && (exponent & 1) != 0;
+ int[] pow2 = new int [blen];
+ int[] rwords = new int [blen];
+ int[] work = new int [blen];
+ getAbsolute(pow2); // pow2 = abs(this);
+ int rlen = 1;
+ rwords[0] = 1; // rwords = 1;
+ for (;;) // for (i = 0; ; i++)
+ {
+ // pow2 == this**(2**i)
+ // prod = this**(sum(j=0..i-1, (exponent>>j)&1))
+ if ((exponent & 1) != 0)
+ { // r *= pow2
+ MPN.mul(work, pow2, plen, rwords, rlen);
+ int[] temp = work; work = rwords; rwords = temp;
+ rlen += plen;
+ while (rwords[rlen - 1] == 0) rlen--;
+ }
+ exponent >>= 1;
+ if (exponent == 0)
+ break;
+ // pow2 *= pow2;
+ MPN.mul(work, pow2, plen, pow2, plen);
+ int[] temp = work; work = pow2; pow2 = temp; // swap to avoid a copy
+ plen *= 2;
+ while (pow2[plen - 1] == 0) plen--;
+ }
+ if (rwords[rlen - 1] < 0)
+ rlen++;
+ if (negative)
+ negate(rwords, rwords, rlen);
+ return BigInteger.make(rwords, rlen);
+ }
+
+ private static int[] euclidInv(int a, int b, int prevDiv)
+ {
+ if (b == 0)
+ throw new ArithmeticException("not invertible");
+
+ if (b == 1)
+ // Success: values are indeed invertible!
+ // Bottom of the recursion reached; start unwinding.
+ return new int[] { -prevDiv, 1 };
+
+ int[] xy = euclidInv(b, a % b, a / b); // Recursion happens here.
+ a = xy[0]; // use our local copy of 'a' as a work var
+ xy[0] = a * -prevDiv + xy[1];
+ xy[1] = a;
+ return xy;
+ }
+
+ private static void euclidInv(BigInteger a, BigInteger b,
+ BigInteger prevDiv, BigInteger[] xy)
+ {
+ if (b.isZero())
+ throw new ArithmeticException("not invertible");
+
+ if (b.isOne())
+ {
+ // Success: values are indeed invertible!
+ // Bottom of the recursion reached; start unwinding.
+ xy[0] = neg(prevDiv);
+ xy[1] = ONE;
+ return;
+ }
+
+ // Recursion happens in the following conditional!
+
+ // If a just contains an int, then use integer math for the rest.
+ if (a.words == null)
+ {
+ int[] xyInt = euclidInv(b.ival, a.ival % b.ival, a.ival / b.ival);
+ xy[0] = new BigInteger(xyInt[0]);
+ xy[1] = new BigInteger(xyInt[1]);
+ }
+ else
+ {
+ BigInteger rem = new BigInteger();
+ BigInteger quot = new BigInteger();
+ divide(a, b, quot, rem, FLOOR);
+ // quot and rem may not be in canonical form. ensure
+ rem.canonicalize();
+ quot.canonicalize();
+ euclidInv(b, rem, quot, xy);
+ }
+
+ BigInteger t = xy[0];
+ xy[0] = add(xy[1], times(t, prevDiv), -1);
+ xy[1] = t;
+ }
+
+ public BigInteger modInverse(BigInteger y)
+ {
+ if (y.isNegative() || y.isZero())
+ throw new ArithmeticException("non-positive modulo");
+
+ // Degenerate cases.
+ if (y.isOne())
+ return ZERO;
+ if (isOne())
+ return ONE;
+
+ // Use Euclid's algorithm as in gcd() but do this recursively
+ // rather than in a loop so we can use the intermediate results as we
+ // unwind from the recursion.
+ // Used http://www.math.nmsu.edu/~crypto/EuclideanAlgo.html as reference.
+ BigInteger result = new BigInteger();
+ boolean swapped = false;
+
+ if (y.words == null)
+ {
+ // The result is guaranteed to be less than the modulus, y (which is
+ // an int), so simplify this by working with the int result of this
+ // modulo y. Also, if this is negative, make it positive via modulo
+ // math. Note that BigInteger.mod() must be used even if this is
+ // already an int as the % operator would provide a negative result if
+ // this is negative, BigInteger.mod() never returns negative values.
+ int xval = (words != null || isNegative()) ? mod(y).ival : ival;
+ int yval = y.ival;
+
+ // Swap values so x > y.
+ if (yval > xval)
+ {
+ int tmp = xval; xval = yval; yval = tmp;
+ swapped = true;
+ }
+ // Normally, the result is in the 2nd element of the array, but
+ // if originally x < y, then x and y were swapped and the result
+ // is in the 1st element of the array.
+ result.ival =
+ euclidInv(yval, xval % yval, xval / yval)[swapped ? 0 : 1];
+
+ // Result can't be negative, so make it positive by adding the
+ // original modulus, y.ival (not the possibly "swapped" yval).
+ if (result.ival < 0)
+ result.ival += y.ival;
+ }
+ else
+ {
+ // As above, force this to be a positive value via modulo math.
+ BigInteger x = isNegative() ? this.mod(y) : this;
+
+ // Swap values so x > y.
+ if (x.compareTo(y) < 0)
+ {
+ result = x; x = y; y = result; // use 'result' as a work var
+ swapped = true;
+ }
+ // As above (for ints), result will be in the 2nd element unless
+ // the original x and y were swapped.
+ BigInteger rem = new BigInteger();
+ BigInteger quot = new BigInteger();
+ divide(x, y, quot, rem, FLOOR);
+ // quot and rem may not be in canonical form. ensure
+ rem.canonicalize();
+ quot.canonicalize();
+ BigInteger[] xy = new BigInteger[2];
+ euclidInv(y, rem, quot, xy);
+ result = swapped ? xy[0] : xy[1];
+
+ // Result can't be negative, so make it positive by adding the
+ // original modulus, y (which is now x if they were swapped).
+ if (result.isNegative())
+ result = add(result, swapped ? x : y, 1);
+ }
+
+ return result;
+ }
+
+ public BigInteger modPow(BigInteger exponent, BigInteger m)
+ {
+ if (m.isNegative() || m.isZero())
+ throw new ArithmeticException("non-positive modulo");
+
+ if (exponent.isNegative())
+ return modInverse(m);
+ if (exponent.isOne())
+ return mod(m);
+
+ // To do this naively by first raising this to the power of exponent
+ // and then performing modulo m would be extremely expensive, especially
+ // for very large numbers. The solution is found in Number Theory
+ // where a combination of partial powers and moduli can be done easily.
+ //
+ // We'll use the algorithm for Additive Chaining which can be found on
+ // p. 244 of "Applied Cryptography, Second Edition" by Bruce Schneier.
+ BigInteger s = ONE;
+ BigInteger t = this;
+ BigInteger u = exponent;
+
+ while (!u.isZero())
+ {
+ if (u.and(ONE).isOne())
+ s = times(s, t).mod(m);
+ u = u.shiftRight(1);
+ t = times(t, t).mod(m);
+ }
+
+ return s;
+ }
+
+ /** Calculate Greatest Common Divisor for non-negative ints. */
+ private static int gcd(int a, int b)
+ {
+ // Euclid's algorithm, copied from libg++.
+ int tmp;
+ if (b > a)
+ {
+ tmp = a; a = b; b = tmp;
+ }
+ for(;;)
+ {
+ if (b == 0)
+ return a;
+ if (b == 1)
+ return b;
+ tmp = b;
+ b = a % b;
+ a = tmp;
+ }
+ }
+
+ public BigInteger gcd(BigInteger y)
+ {
+ int xval = ival;
+ int yval = y.ival;
+ if (words == null)
+ {
+ if (xval == 0)
+ return abs(y);
+ if (y.words == null
+ && xval != Integer.MIN_VALUE && yval != Integer.MIN_VALUE)
+ {
+ if (xval < 0)
+ xval = -xval;
+ if (yval < 0)
+ yval = -yval;
+ return valueOf(gcd(xval, yval));
+ }
+ xval = 1;
+ }
+ if (y.words == null)
+ {
+ if (yval == 0)
+ return abs(this);
+ yval = 1;
+ }
+ int len = (xval > yval ? xval : yval) + 1;
+ int[] xwords = new int[len];
+ int[] ywords = new int[len];
+ getAbsolute(xwords);
+ y.getAbsolute(ywords);
+ len = MPN.gcd(xwords, ywords, len);
+ BigInteger result = new BigInteger(0);
+ result.ival = len;
+ result.words = xwords;
+ return result.canonicalize();
+ }
+
+ /**
+ * <p>Returns <code>true</code> if this BigInteger is probably prime,
+ * <code>false</code> if it's definitely composite. If <code>certainty</code>
+ * is <code><= 0</code>, <code>true</code> is returned.</p>
+ *
+ * @param certainty a measure of the uncertainty that the caller is willing
+ * to tolerate: if the call returns <code>true</code> the probability that
+ * this BigInteger is prime exceeds <code>(1 - 1/2<sup>certainty</sup>)</code>.
+ * The execution time of this method is proportional to the value of this
+ * parameter.
+ * @return <code>true</code> if this BigInteger is probably prime,
+ * <code>false</code> if it's definitely composite.
+ */
+ public boolean isProbablePrime(int certainty)
+ {
+ if (certainty < 1)
+ return true;
+
+ /** We'll use the Rabin-Miller algorithm for doing a probabilistic
+ * primality test. It is fast, easy and has faster decreasing odds of a
+ * composite passing than with other tests. This means that this
+ * method will actually have a probability much greater than the
+ * 1 - .5^certainty specified in the JCL (p. 117), but I don't think
+ * anyone will complain about better performance with greater certainty.
+ *
+ * The Rabin-Miller algorithm can be found on pp. 259-261 of "Applied
+ * Cryptography, Second Edition" by Bruce Schneier.
+ */
+
+ // First rule out small prime factors
+ BigInteger rem = new BigInteger();
+ int i;
+ for (i = 0; i < primes.length; i++)
+ {
+ if (words == null && ival == primes[i])
+ return true;
+
+ divide(this, smallFixNums[primes[i] - minFixNum], null, rem, TRUNCATE);
+ if (rem.canonicalize().isZero())
+ return false;
+ }
+
+ // Now perform the Rabin-Miller test.
+
+ // Set b to the number of times 2 evenly divides (this - 1).
+ // I.e. 2^b is the largest power of 2 that divides (this - 1).
+ BigInteger pMinus1 = add(this, -1);
+ int b = pMinus1.getLowestSetBit();
+
+ // Set m such that this = 1 + 2^b * m.
+ BigInteger m = pMinus1.divide(valueOf(2L << b - 1));
+
+ // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Note
+ // 4.49 (controlling the error probability) gives the number of trials
+ // for an error probability of 1/2**80, given the number of bits in the
+ // number to test. we shall use these numbers as is if/when 'certainty'
+ // is less or equal to 80, and twice as much if it's greater.
+ int bits = this.bitLength();
+ for (i = 0; i < k.length; i++)
+ if (bits <= k[i])
+ break;
+ int trials = t[i];
+ if (certainty > 80)
+ trials *= 2;
+ BigInteger z;
+ for (int t = 0; t < trials; t++)
+ {
+ // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al.
+ // Remark 4.28 states: "...A strategy that is sometimes employed
+ // is to fix the bases a to be the first few primes instead of
+ // choosing them at random.
+ z = smallFixNums[primes[t] - minFixNum].modPow(m, this);
+ if (z.isOne() || z.equals(pMinus1))
+ continue; // Passes the test; may be prime.
+
+ for (i = 0; i < b; )
+ {
+ if (z.isOne())
+ return false;
+ i++;
+ if (z.equals(pMinus1))
+ break; // Passes the test; may be prime.
+
+ z = z.modPow(valueOf(2), this);
+ }
+
+ if (i == b && !z.equals(pMinus1))
+ return false;
+ }
+ return true;
+ }
+
+ private void setInvert()
+ {
+ if (words == null)
+ ival = ~ival;
+ else
+ {
+ for (int i = ival; --i >= 0; )
+ words[i] = ~words[i];
+ }
+ }
+
+ private void setShiftLeft(BigInteger x, int count)
+ {
+ int[] xwords;
+ int xlen;
+ if (x.words == null)
+ {
+ if (count < 32)
+ {
+ set((long) x.ival << count);
+ return;
+ }
+ xwords = new int[1];
+ xwords[0] = x.ival;
+ xlen = 1;
+ }
+ else
+ {
+ xwords = x.words;
+ xlen = x.ival;
+ }
+ int word_count = count >> 5;
+ count &= 31;
+ int new_len = xlen + word_count;
+ if (count == 0)
+ {
+ realloc(new_len);
+ for (int i = xlen; --i >= 0; )
+ words[i+word_count] = xwords[i];
+ }
+ else
+ {
+ new_len++;
+ realloc(new_len);
+ int shift_out = MPN.lshift(words, word_count, xwords, xlen, count);
+ count = 32 - count;
+ words[new_len-1] = (shift_out << count) >> count; // sign-extend.
+ }
+ ival = new_len;
+ for (int i = word_count; --i >= 0; )
+ words[i] = 0;
+ }
+
+ private void setShiftRight(BigInteger x, int count)
+ {
+ if (x.words == null)
+ set(count < 32 ? x.ival >> count : x.ival < 0 ? -1 : 0);
+ else if (count == 0)
+ set(x);
+ else
+ {
+ boolean neg = x.isNegative();
+ int word_count = count >> 5;
+ count &= 31;
+ int d_len = x.ival - word_count;
+ if (d_len <= 0)
+ set(neg ? -1 : 0);
+ else
+ {
+ if (words == null || words.length < d_len)
+ realloc(d_len);
+ MPN.rshift0 (words, x.words, word_count, d_len, count);
+ ival = d_len;
+ if (neg)
+ words[d_len-1] |= -2 << (31 - count);
+ }
+ }
+ }
+
+ private void setShift(BigInteger x, int count)
+ {
+ if (count > 0)
+ setShiftLeft(x, count);
+ else
+ setShiftRight(x, -count);
+ }
+
+ private static BigInteger shift(BigInteger x, int count)
+ {
+ if (x.words == null)
+ {
+ if (count <= 0)
+ return valueOf(count > -32 ? x.ival >> (-count) : x.ival < 0 ? -1 : 0);
+ if (count < 32)
+ return valueOf((long) x.ival << count);
+ }
+ if (count == 0)
+ return x;
+ BigInteger result = new BigInteger(0);
+ result.setShift(x, count);
+ return result.canonicalize();
+ }
+
+ public BigInteger shiftLeft(int n)
+ {
+ return shift(this, n);
+ }
+
+ public BigInteger shiftRight(int n)
+ {
+ return shift(this, -n);
+ }
+
+ private void format(int radix, StringBuffer buffer)
+ {
+ if (words == null)
+ buffer.append(Integer.toString(ival, radix));
+ else if (ival <= 2)
+ buffer.append(Long.toString(longValue(), radix));
+ else
+ {
+ boolean neg = isNegative();
+ int[] work;
+ if (neg || radix != 16)
+ {
+ work = new int[ival];
+ getAbsolute(work);
+ }
+ else
+ work = words;
+ int len = ival;
+
+ if (radix == 16)
+ {
+ if (neg)
+ buffer.append('-');
+ int buf_start = buffer.length();
+ for (int i = len; --i >= 0; )
+ {
+ int word = work[i];
+ for (int j = 8; --j >= 0; )
+ {
+ int hex_digit = (word >> (4 * j)) & 0xF;
+ // Suppress leading zeros:
+ if (hex_digit > 0 || buffer.length() > buf_start)
+ buffer.append(Character.forDigit(hex_digit, 16));
+ }
+ }
+ }
+ else
+ {
+ int i = buffer.length();
+ for (;;)
+ {
+ int digit = MPN.divmod_1(work, work, len, radix);
+ buffer.append(Character.forDigit(digit, radix));
+ while (len > 0 && work[len-1] == 0) len--;
+ if (len == 0)
+ break;
+ }
+ if (neg)
+ buffer.append('-');
+ /* Reverse buffer. */
+ int j = buffer.length() - 1;
+ while (i < j)
+ {
+ char tmp = buffer.charAt(i);
+ buffer.setCharAt(i, buffer.charAt(j));
+ buffer.setCharAt(j, tmp);
+ i++; j--;
+ }
+ }
+ }
+ }
+
+ public String toString()
+ {
+ return toString(10);
+ }
+
+ public String toString(int radix)
+ {
+ if (words == null)
+ return Integer.toString(ival, radix);
+ if (ival <= 2)
+ return Long.toString(longValue(), radix);
+ int buf_size = ival * (MPN.chars_per_word(radix) + 1);
+ StringBuffer buffer = new StringBuffer(buf_size);
+ format(radix, buffer);
+ return buffer.toString();
+ }
+
+ public int intValue()
+ {
+ if (words == null)
+ return ival;
+ return words[0];
+ }
+
+ public long longValue()
+ {
+ if (words == null)
+ return ival;
+ if (ival == 1)
+ return words[0];
+ return ((long)words[1] << 32) + ((long)words[0] & 0xffffffffL);
+ }
+
+ public int hashCode()
+ {
+ // FIXME: May not match hashcode of JDK.
+ return words == null ? ival : (words[0] + words[ival - 1]);
+ }
+
+ /* Assumes x and y are both canonicalized. */
+ private static boolean equals(BigInteger x, BigInteger y)
+ {
+ if (x.words == null && y.words == null)
+ return x.ival == y.ival;
+ if (x.words == null || y.words == null || x.ival != y.ival)
+ return false;
+ for (int i = x.ival; --i >= 0; )
+ {
+ if (x.words[i] != y.words[i])
+ return false;
+ }
+ return true;
+ }
+
+ /* Assumes this and obj are both canonicalized. */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof BigInteger))
+ return false;
+ return equals(this, (BigInteger) obj);
+ }
+
+ private static BigInteger valueOf(String s, int radix)
+ throws NumberFormatException
+ {
+ int len = s.length();
+ // Testing (len < MPN.chars_per_word(radix)) would be more accurate,
+ // but slightly more expensive, for little practical gain.
+ if (len <= 15 && radix <= 16)
+ return valueOf(Long.parseLong(s, radix));
+
+ int byte_len = 0;
+ byte[] bytes = new byte[len];
+ boolean negative = false;
+ for (int i = 0; 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;
+ }
+ }
+ return valueOf(bytes, byte_len, negative, radix);
+ }
+
+ private static BigInteger valueOf(byte[] digits, int byte_len,
+ boolean negative, int radix)
+ {
+ int chars_per_word = MPN.chars_per_word(radix);
+ int[] words = new int[byte_len / chars_per_word + 1];
+ int size = MPN.set_str(words, digits, byte_len, radix);
+ if (size == 0)
+ return ZERO;
+ if (words[size-1] < 0)
+ words[size++] = 0;
+ if (negative)
+ negate(words, words, size);
+ return make(words, size);
+ }
+
+ public double doubleValue()
+ {
+ if (words == null)
+ return (double) ival;
+ if (ival <= 2)
+ return (double) longValue();
+ if (isNegative())
+ return neg(this).roundToDouble(0, true, false);
+ return roundToDouble(0, false, false);
+ }
+
+ public float floatValue()
+ {
+ return (float) doubleValue();
+ }
+
+ /** Return true if any of the lowest n bits are one.
+ * (false if n is negative). */
+ private boolean checkBits(int n)
+ {
+ if (n <= 0)
+ return false;
+ if (words == null)
+ return n > 31 || ((ival & ((1 << n) - 1)) != 0);
+ int i;
+ for (i = 0; i < (n >> 5) ; i++)
+ if (words[i] != 0)
+ return true;
+ return (n & 31) != 0 && (words[i] & ((1 << (n & 31)) - 1)) != 0;
+ }
+
+ /** Convert a semi-processed BigInteger to double.
+ * Number must be non-negative. Multiplies by a power of two, applies sign,
+ * and converts to double, with the usual java rounding.
+ * @param exp power of two, positive or negative, by which to multiply
+ * @param neg true if negative
+ * @param remainder true if the BigInteger is the result of a truncating
+ * division that had non-zero remainder. To ensure proper rounding in
+ * this case, the BigInteger must have at least 54 bits. */
+ private double roundToDouble(int exp, boolean neg, boolean remainder)
+ {
+ // Compute length.
+ int il = bitLength();
+
+ // Exponent when normalized to have decimal point directly after
+ // leading one. This is stored excess 1023 in the exponent bit field.
+ exp += il - 1;
+
+ // Gross underflow. If exp == -1075, we let the rounding
+ // computation determine whether it is minval or 0 (which are just
+ // 0x0000 0000 0000 0001 and 0x0000 0000 0000 0000 as bit
+ // patterns).
+ if (exp < -1075)
+ return neg ? -0.0 : 0.0;
+
+ // gross overflow
+ if (exp > 1023)
+ return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+
+ // number of bits in mantissa, including the leading one.
+ // 53 unless it's denormalized
+ int ml = (exp >= -1022 ? 53 : 53 + exp + 1022);
+
+ // Get top ml + 1 bits. The extra one is for rounding.
+ long m;
+ int excess_bits = il - (ml + 1);
+ if (excess_bits > 0)
+ m = ((words == null) ? ival >> excess_bits
+ : MPN.rshift_long(words, ival, excess_bits));
+ else
+ m = longValue() << (- excess_bits);
+
+ // Special rounding for maxval. If the number exceeds maxval by
+ // any amount, even if it's less than half a step, it overflows.
+ if (exp == 1023 && ((m >> 1) == (1L << 53) - 1))
+ {
+ if (remainder || checkBits(il - ml))
+ return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ else
+ return neg ? - Double.MAX_VALUE : Double.MAX_VALUE;
+ }
+
+ // Normal round-to-even rule: round up if the bit dropped is a one, and
+ // the bit above it or any of the bits below it is a one.
+ if ((m & 1) == 1
+ && ((m & 2) == 2 || remainder || checkBits(excess_bits)))
+ {
+ m += 2;
+ // Check if we overflowed the mantissa
+ if ((m & (1L << 54)) != 0)
+ {
+ exp++;
+ // renormalize
+ m >>= 1;
+ }
+ // Check if a denormalized mantissa was just rounded up to a
+ // normalized one.
+ else if (ml == 52 && (m & (1L << 53)) != 0)
+ exp++;
+ }
+
+ // Discard the rounding bit
+ m >>= 1;
+
+ long bits_sign = neg ? (1L << 63) : 0;
+ exp += 1023;
+ long bits_exp = (exp <= 0) ? 0 : ((long)exp) << 52;
+ long bits_mant = m & ~(1L << 52);
+ return Double.longBitsToDouble(bits_sign | bits_exp | bits_mant);
+ }
+
+ /** Copy the abolute value of this into an array of words.
+ * Assumes words.length >= (this.words == null ? 1 : this.ival).
+ * Result is zero-extended, but need not be a valid 2's complement number.
+ */
+ private void getAbsolute(int[] words)
+ {
+ int len;
+ if (this.words == null)
+ {
+ len = 1;
+ words[0] = this.ival;
+ }
+ else
+ {
+ len = this.ival;
+ for (int i = len; --i >= 0; )
+ words[i] = this.words[i];
+ }
+ if (words[len - 1] < 0)
+ negate(words, words, len);
+ for (int i = words.length; --i > len; )
+ words[i] = 0;
+ }
+
+ /** Set dest[0:len-1] to the negation of src[0:len-1].
+ * Return true if overflow (i.e. if src is -2**(32*len-1)).
+ * Ok for src==dest. */
+ private static boolean negate(int[] dest, int[] src, int len)
+ {
+ long carry = 1;
+ boolean negative = src[len-1] < 0;
+ for (int i = 0; i < len; i++)
+ {
+ carry += ((long) (~src[i]) & 0xffffffffL);
+ dest[i] = (int) carry;
+ carry >>= 32;
+ }
+ return (negative && dest[len-1] < 0);
+ }
+
+ /** Destructively set this to the negative of x.
+ * It is OK if x==this.*/
+ private void setNegative(BigInteger x)
+ {
+ int len = x.ival;
+ if (x.words == null)
+ {
+ if (len == Integer.MIN_VALUE)
+ set(- (long) len);
+ else
+ set(-len);
+ return;
+ }
+ realloc(len + 1);
+ if (negate(words, x.words, len))
+ words[len++] = 0;
+ ival = len;
+ }
+
+ /** Destructively negate this. */
+ private void setNegative()
+ {
+ setNegative(this);
+ }
+
+ private static BigInteger abs(BigInteger x)
+ {
+ return x.isNegative() ? neg(x) : x;
+ }
+
+ public BigInteger abs()
+ {
+ return abs(this);
+ }
+
+ private static BigInteger neg(BigInteger x)
+ {
+ if (x.words == null && x.ival != Integer.MIN_VALUE)
+ return valueOf(- x.ival);
+ BigInteger result = new BigInteger(0);
+ result.setNegative(x);
+ return result.canonicalize();
+ }
+
+ public BigInteger negate()
+ {
+ return neg(this);
+ }
+
+ /** Calculates ceiling(log2(this < 0 ? -this : this+1))
+ * See Common Lisp: the Language, 2nd ed, p. 361.
+ */
+ public int bitLength()
+ {
+ if (words == null)
+ return MPN.intLength(ival);
+ return MPN.intLength(words, ival);
+ }
+
+ public byte[] toByteArray()
+ {
+ // Determine number of bytes needed. The method bitlength returns
+ // the size without the sign bit, so add one bit for that and then
+ // add 7 more to emulate the ceil function using integer math.
+ byte[] bytes = new byte[(bitLength() + 1 + 7) / 8];
+ int nbytes = bytes.length;
+
+ int wptr = 0;
+ int word;
+
+ // Deal with words array until one word or less is left to process.
+ // If BigInteger is an int, then it is in ival and nbytes will be <= 4.
+ while (nbytes > 4)
+ {
+ word = words[wptr++];
+ for (int i = 4; i > 0; --i, word >>= 8)
+ bytes[--nbytes] = (byte) word;
+ }
+
+ // Deal with the last few bytes. If BigInteger is an int, use ival.
+ word = (words == null) ? ival : words[wptr];
+ for ( ; nbytes > 0; word >>= 8)
+ bytes[--nbytes] = (byte) word;
+
+ return bytes;
+ }
+
+ /** Return the boolean opcode (for bitOp) for swapped operands.
+ * I.e. bitOp(swappedOp(op), x, y) == bitOp(op, y, x).
+ */
+ private static int swappedOp(int op)
+ {
+ return
+ "\000\001\004\005\002\003\006\007\010\011\014\015\012\013\016\017"
+ .charAt(op);
+ }
+
+ /** Do one the the 16 possible bit-wise operations of two BigIntegers. */
+ private static BigInteger bitOp(int op, BigInteger x, BigInteger y)
+ {
+ switch (op)
+ {
+ case 0: return ZERO;
+ case 1: return x.and(y);
+ case 3: return x;
+ case 5: return y;
+ case 15: return valueOf(-1);
+ }
+ BigInteger result = new BigInteger();
+ setBitOp(result, op, x, y);
+ return result.canonicalize();
+ }
+
+ /** Do one the the 16 possible bit-wise operations of two BigIntegers. */
+ private static void setBitOp(BigInteger result, int op,
+ BigInteger x, BigInteger y)
+ {
+ if (y.words == null) ;
+ else if (x.words == null || x.ival < y.ival)
+ {
+ BigInteger temp = x; x = y; y = temp;
+ op = swappedOp(op);
+ }
+ int xi;
+ int yi;
+ int xlen, ylen;
+ if (y.words == null)
+ {
+ yi = y.ival;
+ ylen = 1;
+ }
+ else
+ {
+ yi = y.words[0];
+ ylen = y.ival;
+ }
+ if (x.words == null)
+ {
+ xi = x.ival;
+ xlen = 1;
+ }
+ else
+ {
+ xi = x.words[0];
+ xlen = x.ival;
+ }
+ if (xlen > 1)
+ result.realloc(xlen);
+ int[] w = result.words;
+ int i = 0;
+ // Code for how to handle the remainder of x.
+ // 0: Truncate to length of y.
+ // 1: Copy rest of x.
+ // 2: Invert rest of x.
+ int finish = 0;
+ int ni;
+ switch (op)
+ {
+ case 0: // clr
+ ni = 0;
+ break;
+ case 1: // and
+ for (;;)
+ {
+ ni = xi & yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ if (yi < 0) finish = 1;
+ break;
+ case 2: // andc2
+ for (;;)
+ {
+ ni = xi & ~yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ if (yi >= 0) finish = 1;
+ break;
+ case 3: // copy x
+ ni = xi;
+ finish = 1; // Copy rest
+ break;
+ case 4: // andc1
+ for (;;)
+ {
+ ni = ~xi & yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ if (yi < 0) finish = 2;
+ break;
+ case 5: // copy y
+ for (;;)
+ {
+ ni = yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ break;
+ case 6: // xor
+ for (;;)
+ {
+ ni = xi ^ yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ finish = yi < 0 ? 2 : 1;
+ break;
+ case 7: // ior
+ for (;;)
+ {
+ ni = xi | yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ if (yi >= 0) finish = 1;
+ break;
+ case 8: // nor
+ for (;;)
+ {
+ ni = ~(xi | yi);
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ if (yi >= 0) finish = 2;
+ break;
+ case 9: // eqv [exclusive nor]
+ for (;;)
+ {
+ ni = ~(xi ^ yi);
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ finish = yi >= 0 ? 2 : 1;
+ break;
+ case 10: // c2
+ for (;;)
+ {
+ ni = ~yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ break;
+ case 11: // orc2
+ for (;;)
+ {
+ ni = xi | ~yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ if (yi < 0) finish = 1;
+ break;
+ case 12: // c1
+ ni = ~xi;
+ finish = 2;
+ break;
+ case 13: // orc1
+ for (;;)
+ {
+ ni = ~xi | yi;
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ if (yi >= 0) finish = 2;
+ break;
+ case 14: // nand
+ for (;;)
+ {
+ ni = ~(xi & yi);
+ if (i+1 >= ylen) break;
+ w[i++] = ni; xi = x.words[i]; yi = y.words[i];
+ }
+ if (yi < 0) finish = 2;
+ break;
+ default:
+ case 15: // set
+ ni = -1;
+ break;
+ }
+ // Here i==ylen-1; w[0]..w[i-1] have the correct result;
+ // and ni contains the correct result for w[i+1].
+ if (i+1 == xlen)
+ finish = 0;
+ switch (finish)
+ {
+ case 0:
+ if (i == 0 && w == null)
+ {
+ result.ival = ni;
+ return;
+ }
+ w[i++] = ni;
+ break;
+ case 1: w[i] = ni; while (++i < xlen) w[i] = x.words[i]; break;
+ case 2: w[i] = ni; while (++i < xlen) w[i] = ~x.words[i]; break;
+ }
+ result.ival = i;
+ }
+
+ /** Return the logical (bit-wise) "and" of a BigInteger and an int. */
+ private static BigInteger and(BigInteger x, int y)
+ {
+ if (x.words == null)
+ return valueOf(x.ival & y);
+ if (y >= 0)
+ return valueOf(x.words[0] & y);
+ int len = x.ival;
+ int[] words = new int[len];
+ words[0] = x.words[0] & y;
+ while (--len > 0)
+ words[len] = x.words[len];
+ return make(words, x.ival);
+ }
+
+ /** Return the logical (bit-wise) "and" of two BigIntegers. */
+ public BigInteger and(BigInteger y)
+ {
+ if (y.words == null)
+ return and(this, y.ival);
+ else if (words == null)
+ return and(y, ival);
+
+ BigInteger x = this;
+ if (ival < y.ival)
+ {
+ BigInteger temp = this; x = y; y = temp;
+ }
+ int i;
+ int len = y.isNegative() ? x.ival : y.ival;
+ int[] words = new int[len];
+ for (i = 0; i < y.ival; i++)
+ words[i] = x.words[i] & y.words[i];
+ for ( ; i < len; i++)
+ words[i] = x.words[i];
+ return make(words, len);
+ }
+
+ /** Return the logical (bit-wise) "(inclusive) or" of two BigIntegers. */
+ public BigInteger or(BigInteger y)
+ {
+ return bitOp(7, this, y);
+ }
+
+ /** Return the logical (bit-wise) "exclusive or" of two BigIntegers. */
+ public BigInteger xor(BigInteger y)
+ {
+ return bitOp(6, this, y);
+ }
+
+ /** Return the logical (bit-wise) negation of a BigInteger. */
+ public BigInteger not()
+ {
+ return bitOp(12, this, ZERO);
+ }
+
+ public BigInteger andNot(BigInteger val)
+ {
+ return and(val.not());
+ }
+
+ public BigInteger clearBit(int n)
+ {
+ if (n < 0)
+ throw new ArithmeticException();
+
+ return and(ONE.shiftLeft(n).not());
+ }
+
+ public BigInteger setBit(int n)
+ {
+ if (n < 0)
+ throw new ArithmeticException();
+
+ return or(ONE.shiftLeft(n));
+ }
+
+ public boolean testBit(int n)
+ {
+ if (n < 0)
+ throw new ArithmeticException();
+
+ return !and(ONE.shiftLeft(n)).isZero();
+ }
+
+ public BigInteger flipBit(int n)
+ {
+ if (n < 0)
+ throw new ArithmeticException();
+
+ return xor(ONE.shiftLeft(n));
+ }
+
+ public int getLowestSetBit()
+ {
+ if (isZero())
+ return -1;
+
+ if (words == null)
+ return MPN.findLowestBit(ival);
+ else
+ return MPN.findLowestBit(words);
+ }
+
+ // bit4count[I] is number of '1' bits in I.
+ private static final byte[] bit4_count = { 0, 1, 1, 2, 1, 2, 2, 3,
+ 1, 2, 2, 3, 2, 3, 3, 4};
+
+ private static int bitCount(int i)
+ {
+ int count = 0;
+ while (i != 0)
+ {
+ count += bit4_count[i & 15];
+ i >>>= 4;
+ }
+ return count;
+ }
+
+ private static int bitCount(int[] x, int len)
+ {
+ int count = 0;
+ while (--len >= 0)
+ count += bitCount(x[len]);
+ return count;
+ }
+
+ /** Count one bits in a BigInteger.
+ * If argument is negative, count zero bits instead. */
+ public int bitCount()
+ {
+ int i, x_len;
+ int[] x_words = words;
+ if (x_words == null)
+ {
+ x_len = 1;
+ i = bitCount(ival);
+ }
+ else
+ {
+ x_len = ival;
+ i = bitCount(x_words, x_len);
+ }
+ return isNegative() ? x_len * 32 - i : i;
+ }
+
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ words = byteArrayToIntArray(magnitude, signum < 0 ? -1 : 0);
+ BigInteger result = make(words, words.length);
+ this.ival = result.ival;
+ this.words = result.words;
+ }
+
+ private void writeObject(ObjectOutputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ signum = signum();
+ magnitude = toByteArray();
+ s.defaultWriteObject();
+ }
+}
diff --git a/libjava/classpath/java/math/class-dependencies.conf b/libjava/classpath/java/math/class-dependencies.conf
new file mode 100644
index 00000000000..4fbf75eb1ce
--- /dev/null
+++ b/libjava/classpath/java/math/class-dependencies.conf
@@ -0,0 +1,58 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+# end of file
diff --git a/libjava/classpath/java/math/package.html b/libjava/classpath/java/math/package.html
new file mode 100644
index 00000000000..62d12ea1683
--- /dev/null
+++ b/libjava/classpath/java/math/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.math package.
+ Copyright (C) 2002 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 - java.math</title></head>
+
+<body>
+<p>Arbitrary large decimals and integers.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/net/Authenticator.java b/libjava/classpath/java/net/Authenticator.java
new file mode 100644
index 00000000000..229e140cc76
--- /dev/null
+++ b/libjava/classpath/java/net/Authenticator.java
@@ -0,0 +1,313 @@
+/* Authenticator.java -- Abstract class for obtaining authentication info
+ Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This abstract class provides a model for obtaining authentication
+ * information (in the form of a username and password) required by
+ * some network operations (such as hitting a password protected
+ * web site).
+ * <p>
+ * To make use of this feature, a programmer must create a subclass
+ * that knows how to obtain the necessary info. An example
+ * would be a class that popped up a dialog box to prompt the user.
+ * After creating an instance of that subclass, the static
+ * <code>setDefault</code> method of this class is called to set up
+ * that instance as the object to use on subsequent calls to obtain
+ * authorization.
+ *
+ * @since 1.2
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status Believed to be JDK 1.4 complete
+ */
+public abstract class Authenticator
+{
+ /*
+ * Class Variables
+ */
+
+ /**
+ * This is the default Authenticator object to use for password requests
+ */
+ private static Authenticator defaultAuthenticator;
+
+ /*
+ * Instance Variables
+ */
+
+ /**
+ * The hostname of the site requesting authentication
+ */
+ private String host;
+
+ /**
+ * InternetAddress of the site requesting authentication
+ */
+ private InetAddress addr;
+
+ /**
+ * The port number of the site requesting authentication
+ */
+ private int port;
+
+ /**
+ * The protocol name of the site requesting authentication
+ */
+ private String protocol;
+
+ /**
+ * The prompt to display to the user when requesting authentication info
+ */
+ private String prompt;
+
+ /**
+ * The authentication scheme in use
+ */
+ private String scheme;
+
+ /*
+ * Class Methods
+ */
+
+ /**
+ * This method sets the default <code>Authenticator</code> object (an
+ * instance of a subclass of <code>Authenticator</code>) to use when
+ * prompting the user for
+ * information. Note that this method checks to see if the caller is
+ * allowed to set this value (the "setDefaultAuthenticator" permission)
+ * and throws a <code>SecurityException</code> if it is not.
+ *
+ * @param defAuth The new default <code>Authenticator</code> object to use
+ *
+ * @exception SecurityException If the caller does not have permission
+ * to perform this operation
+ */
+ public static void setDefault(Authenticator defAuth)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new NetPermission("setDefaultAuthenticator"));
+
+ defaultAuthenticator = defAuth;
+ }
+
+ /**
+ * This method is called whenever a username and password for a given
+ * network operation is required. First, a security check is made to see
+ * if the caller has the "requestPasswordAuthentication"
+ * permission. If not, the method thows an exception. If there is no
+ * default <code>Authenticator</code> object, the method then returns
+ * <code>null</code>. Otherwise, the default authenticators's instance
+ * variables are initialized and it's <code>getPasswordAuthentication</code>
+ * method is called to get the actual authentication information to return.
+ *
+ * @param addr The address requesting authentication
+ * @param port The port requesting authentication
+ * @param protocol The protocol requesting authentication
+ * @param prompt The prompt to display to the user when requesting
+ * authentication info
+ * @param scheme The authentication scheme in use
+ *
+ * @return A <code>PasswordAuthentication</code> object with the user's
+ * authentication info.
+ *
+ * @exception SecurityException If the caller does not have permission to
+ * perform this operation
+ */
+ public static PasswordAuthentication requestPasswordAuthentication(InetAddress addr,
+ int port,
+ String protocol,
+ String prompt,
+ String scheme)
+ throws SecurityException
+ {
+ return requestPasswordAuthentication(null, addr, port, protocol, prompt,
+ scheme);
+ }
+
+ /**
+ * This method is called whenever a username and password for a given
+ * network operation is required. First, a security check is made to see
+ * if the caller has the "requestPasswordAuthentication"
+ * permission. If not, the method thows an exception. If there is no
+ * default <code>Authenticator</code> object, the method then returns
+ * <code>null</code>. Otherwise, the default authenticators's instance
+ * variables are initialized and it's <code>getPasswordAuthentication</code>
+ * method is called to get the actual authentication information to return.
+ * This method is the preferred one as it can be used with hostname
+ * when addr is unknown.
+ *
+ * @param host The hostname requesting authentication
+ * @param addr The address requesting authentication
+ * @param port The port requesting authentication
+ * @param protocol The protocol requesting authentication
+ * @param prompt The prompt to display to the user when requesting
+ * authentication info
+ * @param scheme The authentication scheme in use
+ *
+ * @return A <code>PasswordAuthentication</code> object with the user's
+ * authentication info.
+ *
+ * @exception SecurityException If the caller does not have permission to
+ * perform this operation
+ *
+ * @since 1.4
+ */
+ public static PasswordAuthentication requestPasswordAuthentication(String host,
+ InetAddress addr,
+ int port,
+ String protocol,
+ String prompt,
+ String scheme)
+ throws SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new NetPermission("requestPasswordAuthentication"));
+
+ if (defaultAuthenticator == null)
+ return null;
+
+ defaultAuthenticator.host = host;
+ defaultAuthenticator.addr = addr;
+ defaultAuthenticator.port = port;
+ defaultAuthenticator.protocol = protocol;
+ defaultAuthenticator.prompt = prompt;
+ defaultAuthenticator.scheme = scheme;
+
+ return defaultAuthenticator.getPasswordAuthentication();
+ }
+
+ /*
+ * Constructors
+ */
+
+ /**
+ * Default, no-argument constructor for subclasses to call.
+ */
+ public Authenticator()
+ {
+ }
+
+ /*
+ * Instance Methods
+ */
+
+ /**
+ * This method returns the address of the site that is requesting
+ * authentication.
+ *
+ * @return The requesting site's address
+ */
+ protected final InetAddress getRequestingSite()
+ {
+ return addr;
+ }
+
+ /**
+ * Returns the hostname of the host or proxy requesting authorization,
+ * or <code>null</code> if not available.
+ *
+ * @return The name of the host requesting authentication, or
+ * <code>null</code> if it is not available.
+ *
+ * @since 1.4
+ */
+ protected final String getRequestingHost()
+ {
+ return host;
+ }
+
+ /**
+ * This method returns the port of the site that is requesting
+ * authentication.
+ *
+ * @return The requesting port
+ */
+ protected final int getRequestingPort()
+ {
+ return port;
+ }
+
+ /**
+ * This method returns the requesting protocol of the operation that is
+ * requesting authentication
+ *
+ * @return The requesting protocol
+ */
+ protected final String getRequestingProtocol()
+ {
+ return protocol;
+ }
+
+ /**
+ * Returns the prompt that should be used when requesting authentication
+ * information from the user
+ *
+ * @return The user prompt
+ */
+ protected final String getRequestingPrompt()
+ {
+ return prompt;
+ }
+
+ /**
+ * This method returns the authentication scheme in use
+ *
+ * @return The authentication scheme
+ */
+ protected final String getRequestingScheme()
+ {
+ return scheme;
+ }
+
+ /**
+ * This method is called whenever a request for authentication is made. It
+ * can call the other getXXX methods to determine the information relevant
+ * to this request. Subclasses should override this method, which returns
+ * <code>null</code> by default.
+ *
+ * @return The <code>PasswordAuthentication</code> information
+ */
+ protected PasswordAuthentication getPasswordAuthentication()
+ {
+ return null;
+ }
+} // class Authenticator
diff --git a/libjava/classpath/java/net/BindException.java b/libjava/classpath/java/net/BindException.java
new file mode 100644
index 00000000000..cfb509a708e
--- /dev/null
+++ b/libjava/classpath/java/net/BindException.java
@@ -0,0 +1,74 @@
+/* BindException.java -- An exception occurred while binding to a socket
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception indicates that an error occurred while attempting to bind
+ * socket to a particular port.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class BindException extends SocketException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5945005768251722951L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public BindException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message, such as the
+ * text from strerror(3).
+ *
+ * @param message a message describing the error that occurred
+ */
+ public BindException(String message)
+ {
+ super(message);
+ }
+} // class BindException
diff --git a/libjava/classpath/java/net/ConnectException.java b/libjava/classpath/java/net/ConnectException.java
new file mode 100644
index 00000000000..c115d2fe04e
--- /dev/null
+++ b/libjava/classpath/java/net/ConnectException.java
@@ -0,0 +1,75 @@
+/* ConnectException.java -- An exception occurred while connecting to a host
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception indicates that an error occurred while attempting to
+ * connect to a remote host. Often this indicates that the remote host
+ * refused the connection (ie, is not listening on the target socket).
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ConnectException extends SocketException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 3831404271622369215L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public ConnectException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message, such as the
+ * text from strerror(3).
+ *
+ * @param message a message describing the error that occurred
+ */
+ public ConnectException(String message)
+ {
+ super(message);
+ }
+} // class ConnectException
diff --git a/libjava/classpath/java/net/ContentHandler.java b/libjava/classpath/java/net/ContentHandler.java
new file mode 100644
index 00000000000..7f63e740229
--- /dev/null
+++ b/libjava/classpath/java/net/ContentHandler.java
@@ -0,0 +1,126 @@
+/* ContentHandler.java -- Abstract class for handling content from URL's
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This is an abstract class that is the superclass for classes that read
+ * objects from URL's. Calling the <code>getContent()</code> method in the
+ * <code>URL</code> class or the <code>URLConnection</code> class will cause
+ * an instance of a subclass of <code>ContentHandler</code> to be created for
+ * the MIME type of the object being downloaded from the URL. Thus, this
+ * class is seldom needed by applications/applets directly, but only
+ * indirectly through methods in other classes.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public abstract class ContentHandler
+{
+ /*
+ * Constructors
+ */
+
+ /**
+ * Default, no-argument constructor.
+ */
+ public ContentHandler()
+ {
+ }
+
+ /*
+ * Instance Methods
+ */
+
+ /**
+ * This method reads from the <code>InputStream</code> of the passed in URL
+ * connection and uses the data downloaded to create an <code>Object</code>
+ * represening the content. For example, if the URL is pointing to a GIF
+ * file, this method might return an <code>Image</code> object. This method
+ * must be implemented by subclasses.
+ *
+ * @param urlc A <code>URLConnection</code> object to read data from.
+ *
+ * @return An object representing the data read
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract Object getContent(URLConnection urlc)
+ throws IOException;
+
+ /**
+ * This method reads from the <code>InputStream</code> of the passed in URL
+ * connection and uses the data downloaded to create an <code>Object</code>
+ * represening the content. For example, if the URL is pointing to a GIF
+ * file, this method might return an <code>Image</code> object. This method
+ * must be implemented by subclasses. This method uses the list of
+ * supplied classes as candidate types. If the data read doesn't match
+ * any of the supplied type, <code>null</code> is returned.
+ *
+ * @param urlc A <code>URLConnection</code> object to read data from.
+ * @param classes An array of types of objects that are candidate types
+ * for the data to be read.
+ *
+ * @return An object representing the data read, or <code>null</code>
+ * if the data does not match any of the candidate types.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.3
+ */
+ public Object getContent(URLConnection urlc, Class[] classes)
+ throws IOException
+ {
+ Object obj = getContent(urlc);
+
+ for (int i = 0; i < classes.length; i++)
+ {
+ if (classes[i].isInstance(obj))
+ return obj;
+ }
+
+ return null;
+ }
+} // class ContentHandler
diff --git a/libjava/classpath/java/net/ContentHandlerFactory.java b/libjava/classpath/java/net/ContentHandlerFactory.java
new file mode 100644
index 00000000000..51a92cf1521
--- /dev/null
+++ b/libjava/classpath/java/net/ContentHandlerFactory.java
@@ -0,0 +1,65 @@
+/* ContentHandlerFactory.java -- Interface for creating content handlers
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface maps MIME types to <code>ContentHandler</code> objects.
+ * It consists of one method that, when passed a MIME type, returns a
+ * handler for that type.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public interface ContentHandlerFactory
+{
+ /**
+ * This method is passed a MIME type as a string and is responsible for
+ * returning the appropriate <code>ContentHandler</code> object.
+ *
+ * @param mimeType The MIME type to map to a <code>ContentHandler</code>
+ *
+ * @return The <code>ContentHandler</code> for the passed in MIME type
+ */
+ ContentHandler createContentHandler(String mimeType);
+} // interface ContentHandlerFactory
diff --git a/libjava/classpath/java/net/DatagramPacket.java b/libjava/classpath/java/net/DatagramPacket.java
new file mode 100644
index 00000000000..e642f889c32
--- /dev/null
+++ b/libjava/classpath/java/net/DatagramPacket.java
@@ -0,0 +1,391 @@
+/* DatagramPacket.java -- Class to model a packet to be sent via UDP
+ Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This class models a packet of data that is to be sent across the network
+ * using a connectionless protocol such as UDP. It contains the data
+ * to be send, as well as the destination address and port. Note that
+ * datagram packets can arrive in any order and are not guaranteed to be
+ * delivered at all.
+ * <p>
+ * This class can also be used for receiving data from the network.
+ * <p>
+ * Note that for all method below where the buffer length passed by the
+ * caller cannot exceed the actually length of the byte array passed as
+ * the buffer, if this condition is not true, then the method silently
+ * reduces the length value to maximum allowable value.
+ *
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aarom M. Renn (arenn@urbanophile.com) (Documentation comments)
+ * @date April 28, 1999.
+ */
+public final class DatagramPacket
+{
+ /**
+ * The data buffer to send
+ */
+ private byte[] buffer;
+
+ /**
+ * This is the offset into the buffer to start sending from or receiving to.
+ */
+ private int offset;
+
+ /**
+ * The length of the data buffer to send.
+ */
+ int length;
+
+ /**
+ * The maximal length of the buffer.
+ */
+ int maxlen;
+
+ /**
+ * The address to which the packet should be sent or from which it
+ * was received.
+ */
+ private InetAddress address;
+
+ /**
+ * The port to which the packet should be sent or from which it was
+ * was received.
+ */
+ private int port;
+
+ /**
+ * This method initializes a new instance of <code>DatagramPacket</code>
+ * which has the specified buffer, offset, and length.
+ *
+ * @param buf The buffer for holding the incoming datagram.
+ * @param offset The offset into the buffer to start writing.
+ * @param length The maximum number of bytes to read.
+ *
+ * @since 1.2
+ */
+ public DatagramPacket(byte[] buf, int offset, int length)
+ {
+ setData(buf, offset, length);
+ address = null;
+ port = -1;
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * receiving packets from the network.
+ *
+ * @param buf A buffer for storing the returned packet data
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ */
+ public DatagramPacket(byte[] buf, int length)
+ {
+ this(buf, 0, length);
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * transmitting packets across the network.
+ *
+ * @param buf A buffer containing the data to send
+ * @param offset The offset into the buffer to start writing from.
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ * @param address The address to send to
+ * @param port The port to send to
+ *
+ * @since 1.2
+ */
+ public DatagramPacket(byte[] buf, int offset, int length,
+ InetAddress address, int port)
+ {
+ setData(buf, offset, length);
+ setAddress(address);
+ setPort(port);
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * transmitting packets across the network.
+ *
+ * @param buf A buffer containing the data to send
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ * @param address The address to send to
+ * @param port The port to send to
+ */
+ public DatagramPacket(byte[] buf, int length, InetAddress address, int port)
+ {
+ this(buf, 0, length, address, port);
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * transmitting packets across the network.
+ *
+ * @param buf A buffer containing the data to send
+ * @param offset The offset into the buffer to start writing from.
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ * @param address The socket address to send to
+ *
+ * @exception SocketException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ *
+ * @since 1.4
+ */
+ public DatagramPacket(byte[] buf, int offset, int length,
+ SocketAddress address) throws SocketException
+ {
+ if (! (address instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+
+ InetSocketAddress tmp = (InetSocketAddress) address;
+ setData(buf, offset, length);
+ setAddress(tmp.getAddress());
+ setPort(tmp.getPort());
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramPacket</code> for
+ * transmitting packets across the network.
+ *
+ * @param buf A buffer containing the data to send
+ * @param length The length of the buffer (must be &lt;= buf.length)
+ * @param address The socket address to send to
+ *
+ * @exception SocketException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ *
+ * @since 1.4
+ */
+ public DatagramPacket(byte[] buf, int length, SocketAddress address)
+ throws SocketException
+ {
+ this(buf, 0, length, address);
+ }
+
+ /**
+ * Returns the address that this packet is being sent to or, if it was used
+ * to receive a packet, the address that is was received from. If the
+ * constructor that doesn not take an address was used to create this object
+ * and no packet was actually read into this object, then this method
+ * returns <code>null</code>.
+ *
+ * @return The address for this packet.
+ */
+ public synchronized InetAddress getAddress()
+ {
+ return address;
+ }
+
+ /**
+ * Returns the port number this packet is being sent to or, if it was used
+ * to receive a packet, the port that it was received from. If the
+ * constructor that doesn not take an address was used to create this object
+ * and no packet was actually read into this object, then this method
+ * will return 0.
+ *
+ * @return The port number for this packet
+ */
+ public synchronized int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns the data buffer for this packet
+ *
+ * @return This packet's data buffer
+ */
+ public synchronized byte[] getData()
+ {
+ return buffer;
+ }
+
+ /**
+ * This method returns the current offset value into the data buffer
+ * where data will be sent from.
+ *
+ * @return The buffer offset.
+ *
+ * @since 1.2
+ */
+ public synchronized int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the length of the data in the buffer
+ *
+ * @return The length of the data
+ */
+ public synchronized int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * This sets the address to which the data packet will be transmitted.
+ *
+ * @param address The destination address
+ *
+ * @since 1.1
+ */
+ public synchronized void setAddress(InetAddress address)
+ {
+ this.address = address;
+ }
+
+ /**
+ * This sets the port to which the data packet will be transmitted.
+ *
+ * @param port The destination port
+ *
+ * @since 1.1
+ */
+ public synchronized void setPort(int port)
+ {
+ if (port < 0 || port > 65535)
+ throw new IllegalArgumentException("Invalid port: " + port);
+
+ this.port = port;
+ }
+
+ /**
+ * Sets the address of the remote host this package will be sent
+ *
+ * @param address The socket address of the remove host
+ *
+ * @exception IllegalArgumentException If address type is not supported
+ *
+ * @since 1.4
+ */
+ public void setSocketAddress(SocketAddress address)
+ throws IllegalArgumentException
+ {
+ if (address == null)
+ throw new IllegalArgumentException("address may not be null");
+
+ InetSocketAddress tmp = (InetSocketAddress) address;
+ this.address = tmp.getAddress();
+ this.port = tmp.getPort();
+ }
+
+ /**
+ * Gets the socket address of the host this packet
+ * will be sent to/is coming from
+ *
+ * @return The socket address of the remote host
+ *
+ * @since 1.4
+ */
+ public SocketAddress getSocketAddress()
+ {
+ return new InetSocketAddress(address, port);
+ }
+
+ /**
+ * Sets the data buffer for this packet.
+ *
+ * @param buf The new buffer for this packet
+ *
+ * @exception NullPointerException If the argument is null
+ *
+ * @since 1.1
+ */
+ public void setData(byte[] buf)
+ {
+ setData(buf, 0, buf.length);
+ }
+
+ /**
+ * This method sets the data buffer for the packet.
+ *
+ * @param buf The byte array containing the data for this packet.
+ * @param offset The offset into the buffer to start reading data from.
+ * @param length The number of bytes of data in the buffer.
+ *
+ * @exception NullPointerException If the argument is null
+ *
+ * @since 1.2
+ */
+ public synchronized void setData(byte[] buf, int offset, int length)
+ {
+ // This form of setData must be used if offset is to be changed.
+ if (buf == null)
+ throw new NullPointerException("Null buffer");
+ if (offset < 0)
+ throw new IllegalArgumentException("Invalid offset: " + offset);
+
+ buffer = buf;
+ this.offset = offset;
+ setLength(length);
+ }
+
+ /**
+ * Sets the length of the data in the buffer.
+ *
+ * @param length The new length. (Where len &lt;= buf.length)
+ *
+ * @exception IllegalArgumentException If the length is negative or
+ * if the length is greater than the packet's data buffer length
+ *
+ * @since 1.1
+ */
+ public synchronized void setLength(int length)
+ {
+ if (length < 0)
+ throw new IllegalArgumentException("Invalid length: " + length);
+ if (offset + length > buffer.length)
+ throw new IllegalArgumentException("Potential buffer overflow - offset: "
+ + offset + " length: " + length);
+
+ this.length = length;
+ this.maxlen = length;
+ }
+}
diff --git a/libjava/classpath/java/net/DatagramSocket.java b/libjava/classpath/java/net/DatagramSocket.java
new file mode 100644
index 00000000000..8596b7f807f
--- /dev/null
+++ b/libjava/classpath/java/net/DatagramSocket.java
@@ -0,0 +1,933 @@
+/* DatagramSocket.java -- A class to model UDP sockets
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.net.PlainDatagramSocketImpl;
+import gnu.java.nio.DatagramChannelImpl;
+
+import java.io.IOException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.IllegalBlockingModeException;
+
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+/**
+ * This class models a connectionless datagram socket that sends
+ * individual packets of data across the network. In the TCP/IP world,
+ * this means UDP. Datagram packets do not have guaranteed delivery,
+ * or any guarantee about the order the data will be received on the
+ * remote host.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @date May 3, 1999.
+ */
+public class DatagramSocket
+{
+ /**
+ * This is the user DatagramSocketImplFactory for this class. If this
+ * variable is null, a default factory is used.
+ */
+ private static DatagramSocketImplFactory factory;
+
+ /**
+ * This is the implementation object used by this socket.
+ */
+ private DatagramSocketImpl impl;
+
+ /**
+ * True if socket implementation was created.
+ */
+ private boolean implCreated;
+
+ /**
+ * This is the address we are "connected" to
+ */
+ private InetAddress remoteAddress;
+
+ /**
+ * This is the port we are "connected" to
+ */
+ private int remotePort = -1;
+
+ /**
+ * True if socket is bound.
+ */
+ private boolean bound;
+
+ /**
+ * Creates a <code>DatagramSocket</code> from a specified
+ * <code>DatagramSocketImpl</code> instance
+ *
+ * @param impl The <code>DatagramSocketImpl</code> the socket will be
+ * created from
+ *
+ * @since 1.4
+ */
+ protected DatagramSocket(DatagramSocketImpl impl)
+ {
+ if (impl == null)
+ throw new NullPointerException("impl may not be null");
+
+ this.impl = impl;
+ this.remoteAddress = null;
+ this.remotePort = -1;
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramSocket</code> that binds to
+ * a random port and every address on the local machine.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception SecurityException If a security manager exists and
+ * its <code>checkListen</code> method doesn't allow the operation.
+ */
+ public DatagramSocket() throws SocketException
+ {
+ this(new InetSocketAddress(0));
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramSocket</code> that binds to
+ * the specified port and every address on the local machine.
+ *
+ * @param port The local port number to bind to.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * <code>checkListen</code> method doesn't allow the operation.
+ * @exception SocketException If an error occurs.
+ */
+ public DatagramSocket(int port) throws SocketException
+ {
+ this(new InetSocketAddress(port));
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramSocket</code> that binds to
+ * the specified local port and address.
+ *
+ * @param port The local port number to bind to.
+ * @param addr The local address to bind to.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation.
+ * @exception SocketException If an error occurs.
+ */
+ public DatagramSocket(int port, InetAddress addr) throws SocketException
+ {
+ this(new InetSocketAddress(addr, port));
+ }
+
+ /**
+ * Initializes a new instance of <code>DatagramSocket</code> that binds to
+ * the specified local port and address.
+ *
+ * @param address The local address and port number to bind to.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * <code>checkListen</code> method doesn't allow the operation.
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.4
+ */
+ public DatagramSocket(SocketAddress address) throws SocketException
+ {
+ String propVal = System.getProperty("impl.prefix");
+ if (propVal == null || propVal.equals(""))
+ impl = new PlainDatagramSocketImpl();
+ else
+ try
+ {
+ impl =
+ (DatagramSocketImpl) Class.forName("java.net." + propVal
+ + "DatagramSocketImpl")
+ .newInstance();
+ }
+ catch (Exception e)
+ {
+ System.err.println("Could not instantiate class: java.net."
+ + propVal + "DatagramSocketImpl");
+ impl = new PlainDatagramSocketImpl();
+ }
+
+ if (address != null)
+ bind(address);
+ }
+
+ // This needs to be accessible from java.net.MulticastSocket
+ DatagramSocketImpl getImpl() throws SocketException
+ {
+ try
+ {
+ if (! implCreated)
+ {
+ impl.create();
+ implCreated = true;
+ }
+
+ return impl;
+ }
+ catch (IOException e)
+ {
+ SocketException se = new SocketException();
+ se.initCause(e);
+ throw se;
+ }
+ }
+
+ /**
+ * Closes this datagram socket.
+ */
+ public void close()
+ {
+ if (isClosed())
+ return;
+
+ try
+ {
+ getImpl().close();
+ }
+ catch (SocketException e)
+ {
+ // Ignore this case, just close the socket in finally clause.
+ }
+ finally
+ {
+ remoteAddress = null;
+ remotePort = -1;
+ impl = null;
+ }
+
+ try
+ {
+ if (getChannel() != null)
+ getChannel().close();
+ }
+ catch (IOException e)
+ {
+ // Do nothing.
+ }
+ }
+
+ /**
+ * This method returns the remote address to which this socket is
+ * connected. If this socket is not connected, then this method will
+ * return <code>null</code>.
+ *
+ * @return The remote address.
+ *
+ * @since 1.2
+ */
+ public InetAddress getInetAddress()
+ {
+ return remoteAddress;
+ }
+
+ /**
+ * This method returns the remote port to which this socket is
+ * connected. If this socket is not connected, then this method will
+ * return -1.
+ *
+ * @return The remote port.
+ *
+ * @since 1.2
+ */
+ public int getPort()
+ {
+ return remotePort;
+ }
+
+ /**
+ * Returns the local address this datagram socket is bound to.
+ *
+ * @return The local address is the socket is bound or null
+ *
+ * @since 1.1
+ */
+ public InetAddress getLocalAddress()
+ {
+ if (! isBound())
+ return null;
+
+ InetAddress localAddr;
+
+ try
+ {
+ localAddr =
+ (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(localAddr.getHostName(), -1);
+ }
+ catch (SecurityException e)
+ {
+ localAddr = InetAddress.ANY_IF;
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are bound.
+ return null;
+ }
+
+ return localAddr;
+ }
+
+ /**
+ * Returns the local port this socket is bound to.
+ *
+ * @return The local port number.
+ */
+ public int getLocalPort()
+ {
+ if (isClosed())
+ return -1;
+
+ try
+ {
+ return getImpl().getLocalPort();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are bound.
+ return 0;
+ }
+ }
+
+ /**
+ * Returns the value of the socket's SO_TIMEOUT setting. If this method
+ * returns 0 then SO_TIMEOUT is disabled.
+ *
+ * @return The current timeout in milliseconds.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.1
+ */
+ public synchronized int getSoTimeout() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT);
+
+ if (buf instanceof Integer)
+ return ((Integer) buf).intValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will
+ * disable SO_TIMEOUT. Any other value is the number of milliseconds
+ * a socket read/write will block before timing out.
+ *
+ * @param timeout The new SO_TIMEOUT value in milliseconds.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.1
+ */
+ public synchronized void setSoTimeout(int timeout) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (timeout < 0)
+ throw new IllegalArgumentException("Invalid timeout: " + timeout);
+
+ getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_SNDBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The send buffer size.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.2
+ */
+ public int getSendBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
+
+ if (buf instanceof Integer)
+ return ((Integer) buf).intValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_SNDBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new send buffer size.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception IllegalArgumentException If size is 0 or negative.
+ *
+ * @since 1.2
+ */
+ public void setSendBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (size < 0)
+ throw new IllegalArgumentException("Buffer size is less than 0");
+
+ getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_RCVBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The receive buffer size.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.2
+ */
+ public int getReceiveBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
+
+ if (buf instanceof Integer)
+ return ((Integer) buf).intValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_RCVBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new receive buffer size.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception IllegalArgumentException If size is 0 or negative.
+ *
+ * @since 1.2
+ */
+ public void setReceiveBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (size < 0)
+ throw new IllegalArgumentException("Buffer size is less than 0");
+
+ getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
+ }
+
+ /**
+ * This method connects this socket to the specified address and port.
+ * When a datagram socket is connected, it will only send or receive
+ * packets to and from the host to which it is connected. A multicast
+ * socket that is connected may only send and not receive packets.
+ *
+ * @param address The address to connect this socket to.
+ * @param port The port to connect this socket to.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception IllegalArgumentException If address or port are invalid.
+ * @exception SecurityException If the caller is not allowed to send
+ * datagrams to or receive from this address and port.
+ *
+ * @since 1.2
+ */
+ public void connect(InetAddress address, int port)
+ {
+ if (address == null)
+ throw new IllegalArgumentException("Connect address may not be null");
+
+ if ((port < 1) || (port > 65535))
+ throw new IllegalArgumentException("Port number is illegal: " + port);
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkConnect(address.getHostName(), port);
+
+ try
+ {
+ getImpl().connect(address, port);
+ remoteAddress = address;
+ remotePort = port;
+ }
+ catch (SocketException e)
+ {
+ // This means simply not connected or connect not implemented.
+ }
+ }
+
+ /**
+ * This method disconnects this socket from the address/port it was
+ * connected to. If the socket was not connected in the first place,
+ * this method does nothing.
+ *
+ * @since 1.2
+ */
+ public void disconnect()
+ {
+ if (! isConnected())
+ return;
+
+ try
+ {
+ getImpl().disconnect();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ }
+ finally
+ {
+ remoteAddress = null;
+ remotePort = -1;
+ }
+ }
+
+ /**
+ * Reads a datagram packet from the socket. Note that this method
+ * will block until a packet is received from the network. On return,
+ * the passed in <code>DatagramPacket</code> is populated with the data
+ * received and all the other information about the packet.
+ *
+ * @param p A <code>DatagramPacket</code> for storing the data
+ *
+ * @exception IOException If an error occurs.
+ * @exception SocketTimeoutException If setSoTimeout was previously called
+ * and the timeout has expired.
+ * @exception PortUnreachableException If the socket is connected to a
+ * currently unreachable destination. Note, there is no guarantee that the
+ * exception will be thrown.
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode.
+ * @exception SecurityException If a security manager exists and its
+ * checkAccept method doesn't allow the receive.
+ */
+ public synchronized void receive(DatagramPacket p) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (remoteAddress != null && remoteAddress.isMulticastAddress())
+ throw new IOException
+ ("Socket connected to a multicast address my not receive");
+
+ if (getChannel() != null && ! getChannel().isBlocking()
+ && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
+ throw new IllegalBlockingModeException();
+
+ getImpl().receive(p);
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null && isConnected())
+ s.checkAccept(p.getAddress().getHostName(), p.getPort());
+ }
+
+ /**
+ * Sends the specified packet. The host and port to which the packet
+ * are to be sent should be set inside the packet.
+ *
+ * @param p The datagram packet to send.
+ *
+ * @exception IOException If an error occurs.
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast or checkConnect method doesn't allow the send.
+ * @exception PortUnreachableException If the socket is connected to a
+ * currently unreachable destination. Note, there is no guarantee that the
+ * exception will be thrown.
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode.
+ */
+ public void send(DatagramPacket p) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null && ! isConnected())
+ {
+ InetAddress addr = p.getAddress();
+ if (addr.isMulticastAddress())
+ s.checkMulticast(addr);
+ else
+ s.checkConnect(addr.getHostAddress(), p.getPort());
+ }
+
+ if (isConnected())
+ {
+ if (p.getAddress() != null
+ && (remoteAddress != p.getAddress() || remotePort != p.getPort()))
+ throw new IllegalArgumentException
+ ("DatagramPacket address does not match remote address");
+ }
+
+ // FIXME: if this is a subclass of MulticastSocket,
+ // use getTimeToLive for TTL val.
+ if (getChannel() != null && ! getChannel().isBlocking()
+ && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
+ throw new IllegalBlockingModeException();
+
+ getImpl().send(p);
+ }
+
+ /**
+ * Binds the socket to the given socket address.
+ *
+ * @param address The socket address to bind to.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception SecurityException If a security manager exists and
+ * its checkListen method doesn't allow the operation.
+ * @exception IllegalArgumentException If address type is not supported.
+ *
+ * @since 1.4
+ */
+ public void bind(SocketAddress address) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! (address instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+
+ InetAddress addr = ((InetSocketAddress) address).getAddress();
+ int port = ((InetSocketAddress) address).getPort();
+
+ if (port < 0 || port > 65535)
+ throw new IllegalArgumentException("Invalid port: " + port);
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkListen(port);
+
+ if (addr == null)
+ addr = InetAddress.ANY_IF;
+
+ try
+ {
+ getImpl().bind(port, addr);
+ bound = true;
+ }
+ catch (SocketException exception)
+ {
+ getImpl().close();
+ throw exception;
+ }
+ catch (RuntimeException exception)
+ {
+ getImpl().close();
+ throw exception;
+ }
+ catch (Error error)
+ {
+ getImpl().close();
+ throw error;
+ }
+ }
+
+ /**
+ * Checks if the datagram socket is closed.
+ *
+ * @return True if socket is closed, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isClosed()
+ {
+ return impl == null;
+ }
+
+ /**
+ * Returns the datagram channel assoziated with this datagram socket.
+ *
+ * @return The associated <code>DatagramChannel</code> object or null
+ *
+ * @since 1.4
+ */
+ public DatagramChannel getChannel()
+ {
+ return null;
+ }
+
+ /**
+ * Connects the datagram socket to a specified socket address.
+ *
+ * @param address The socket address to connect to.
+ *
+ * @exception SocketException If an error occurs.
+ * @exception IllegalArgumentException If address type is not supported.
+ *
+ * @since 1.4
+ */
+ public void connect(SocketAddress address) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! (address instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+
+ InetSocketAddress tmp = (InetSocketAddress) address;
+ connect(tmp.getAddress(), tmp.getPort());
+ }
+
+ /**
+ * Returns the binding state of the socket.
+ *
+ * @return True if socket bound, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isBound()
+ {
+ return bound;
+ }
+
+ /**
+ * Returns the connection state of the socket.
+ *
+ * @return True if socket is connected, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isConnected()
+ {
+ return remoteAddress != null;
+ }
+
+ /**
+ * Returns the SocketAddress of the host this socket is conneted to
+ * or null if this socket is not connected.
+ *
+ * @return The socket address of the remote host if connected or null
+ *
+ * @since 1.4
+ */
+ public SocketAddress getRemoteSocketAddress()
+ {
+ if (! isConnected())
+ return null;
+
+ return new InetSocketAddress(remoteAddress, remotePort);
+ }
+
+ /**
+ * Returns the local SocketAddress this socket is bound to.
+ *
+ * @return The local SocketAddress or null if the socket is not bound.
+ *
+ * @since 1.4
+ */
+ public SocketAddress getLocalSocketAddress()
+ {
+ if (! isBound())
+ return null;
+
+ return new InetSocketAddress(getLocalAddress(), getLocalPort());
+ }
+
+ /**
+ * Enables/Disables SO_REUSEADDR.
+ *
+ * @param on Whether or not to have SO_REUSEADDR turned on.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.4
+ */
+ public void setReuseAddress(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
+ }
+
+ /**
+ * Checks if SO_REUSEADDR is enabled.
+ *
+ * @return True if SO_REUSEADDR is set on the socket, false otherwise.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.4
+ */
+ public boolean getReuseAddress() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR);
+
+ if (buf instanceof Boolean)
+ return ((Boolean) buf).booleanValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Enables/Disables SO_BROADCAST
+ *
+ * @param enable True if SO_BROADCAST should be enabled, false otherwise.
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setBroadcast(boolean enable) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable));
+ }
+
+ /**
+ * Checks if SO_BROADCAST is enabled
+ *
+ * @return Whether SO_BROADCAST is set
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getBroadcast() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST);
+
+ if (buf instanceof Boolean)
+ return ((Boolean) buf).booleanValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Sets the traffic class value
+ *
+ * @param tc The traffic class
+ *
+ * @exception SocketException If an error occurs
+ * @exception IllegalArgumentException If tc value is illegal
+ *
+ * @see DatagramSocket#getTrafficClass()
+ *
+ * @since 1.4
+ */
+ public void setTrafficClass(int tc) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (tc < 0 || tc > 255)
+ throw new IllegalArgumentException();
+
+ getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
+ }
+
+ /**
+ * Returns the current traffic class
+ *
+ * @return The current traffic class.
+ *
+ * @see DatagramSocket#setTrafficClass(int tc)
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public int getTrafficClass() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.IP_TOS);
+
+ if (buf instanceof Integer)
+ return ((Integer) buf).intValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Sets the datagram socket implementation factory for the application
+ *
+ * @param fac The factory to set
+ *
+ * @exception IOException If an error occurs
+ * @exception SocketException If the factory is already defined
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ */
+ public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
+ throws IOException
+ {
+ if (factory != null)
+ throw new SocketException("DatagramSocketImplFactory already defined");
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSetFactory();
+
+ factory = fac;
+ }
+}
diff --git a/libjava/classpath/java/net/DatagramSocketImpl.java b/libjava/classpath/java/net/DatagramSocketImpl.java
new file mode 100644
index 00000000000..cfcde92e5fc
--- /dev/null
+++ b/libjava/classpath/java/net/DatagramSocketImpl.java
@@ -0,0 +1,296 @@
+/* DatagramSocketImpl.java -- Abstract class for UDP socket implementations
+ Copyright (C) 1998, 1999 2000, 2001,
+ 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+
+/**
+ * This abstract class models a datagram socket implementation. An
+ * actual implementation class would implement these methods, probably
+ * via redirecting them to native code.
+ * <p>
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * <p>
+ * Status: Believed complete and correct.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ */
+public abstract class DatagramSocketImpl implements SocketOptions
+{
+ /**
+ * The local port to which this socket is bound
+ */
+ protected int localPort;
+
+ /**
+ * The FileDescriptor object for this object.
+ */
+ protected FileDescriptor fd;
+
+ /**
+ * Default, no-argument constructor for subclasses to call.
+ */
+ public DatagramSocketImpl()
+ {
+ }
+
+ /**
+ * This method binds the socket to the specified local port and address.
+ *
+ * @param lport The port number to bind to
+ * @param laddr The address to bind to
+ *
+ * @exception SocketException If an error occurs
+ */
+ protected abstract void bind(int lport, InetAddress laddr)
+ throws SocketException;
+
+ /**
+ * This methods closes the socket
+ */
+ protected abstract void close();
+
+ /**
+ * Creates a new datagram socket.
+ *
+ * @exception SocketException If an error occurs
+ */
+ protected abstract void create() throws SocketException;
+
+ /**
+ * Takes a peek at the next packet received in order to retrieve the
+ * address of the sender
+ *
+ * @param i The <code>InetAddress</code> to fill in with the information
+ * about the sender if the next packet
+ *
+ * @return The port number of the sender of the packet
+ *
+ * @exception IOException If an error occurs
+ * @exception PortUnreachableException May be thrown if the socket is
+ * connected to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ */
+ protected abstract int peek(InetAddress i) throws IOException;
+
+ /**
+ * Takes a peek at the next packet received. This packet is not consumed.
+ * With the next peekData/receive operation this packet will be read again.
+ *
+ * @param p The <code>DatagramPacket</code> to fill in with the data sent.
+ *
+ * @return The port number of the sender of the packet.
+ *
+ * @exception IOException If an error occurs
+ * @exception PortUnreachableException May be thrown if the socket is
+ * connected to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ *
+ * @since 1.4
+ */
+ protected abstract int peekData(DatagramPacket p) throws IOException;
+
+ /**
+ * Transmits the specified packet of data to the network. The destination
+ * host and port should be encoded in the packet.
+ *
+ * @param p The packet to send
+ *
+ * @exception IOException If an error occurs
+ * @exception PortUnreachableException May be thrown if the socket is
+ * connected to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ */
+ protected abstract void send(DatagramPacket p) throws IOException;
+
+ /**
+ * Receives a packet of data from the network Will block until a packet
+ * arrives. The packet info in populated into the passed in
+ * <code>DatagramPacket</code> object.
+ *
+ * @param p A place to store the incoming packet.
+ *
+ * @exception IOException If an error occurs
+ * @exception PortUnreachableException May be thrown if the socket is
+ * connected to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ */
+ protected abstract void receive(DatagramPacket p) throws IOException;
+
+ /**
+ * Connects the socket to a host specified by address and port.
+ *
+ * @param address The <code>InetAddress</code> of the host to connect to
+ * @param port The port number of the host to connect to
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected void connect(InetAddress address, int port)
+ throws SocketException
+ {
+ // This method has to be overwritten by real implementations
+ }
+
+ /**
+ * Disconnects the socket.
+ *
+ * @since 1.4
+ */
+ protected void disconnect()
+ {
+ // This method has to be overwritten by real implementations
+ }
+
+ /**
+ * Sets the Time to Live (TTL) setting on this socket to the specified
+ * value. <b>Use <code>setTimeToLive(int)</code></b> instead.
+ *
+ * @param ttl The new Time to Live value
+ *
+ * @exception IOException If an error occurs
+ * @deprecated
+ */
+ protected abstract void setTTL(byte ttl) throws IOException;
+
+ /**
+ * This method returns the current Time to Live (TTL) setting on this
+ * socket. <b>Use <code>getTimeToLive()</code></b> instead.
+ *
+ * @return the current time-to-live
+ *
+ * @exception IOException If an error occurs
+ *
+ * @deprecated // FIXME: when ?
+ */
+ protected abstract byte getTTL() throws IOException;
+
+ /**
+ * Sets the Time to Live (TTL) setting on this socket to the specified
+ * value.
+ *
+ * @param ttl The new Time to Live value
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void setTimeToLive(int ttl) throws IOException;
+
+ /**
+ * This method returns the current Time to Live (TTL) setting on this
+ * socket.
+ *
+ * @return the current time-to-live
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract int getTimeToLive() throws IOException;
+
+ /**
+ * Causes this socket to join the specified multicast group
+ *
+ * @param inetaddr The multicast address to join with
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void join(InetAddress inetaddr) throws IOException;
+
+ /**
+ * Causes the socket to leave the specified multicast group.
+ *
+ * @param inetaddr The multicast address to leave
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void leave(InetAddress inetaddr) throws IOException;
+
+ /**
+ * Causes this socket to join the specified multicast group on a specified
+ * device
+ *
+ * @param mcastaddr The address to leave
+ * @param netIf The specified network interface to join the group at
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected abstract void joinGroup(SocketAddress mcastaddr,
+ NetworkInterface netIf)
+ throws IOException;
+
+ /**
+ * Leaves a multicast group
+ *
+ * @param mcastaddr The address to join
+ * @param netIf The specified network interface to leave the group at
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected abstract void leaveGroup(SocketAddress mcastaddr,
+ NetworkInterface netIf)
+ throws IOException;
+
+ /**
+ * Returns the FileDescriptor for this socket
+ *
+ * @return the file descriptor associated with this socket
+ */
+ protected FileDescriptor getFileDescriptor()
+ {
+ return fd;
+ }
+
+ /**
+ * Returns the local port this socket is bound to
+ *
+ * @return the local port
+ */
+ protected int getLocalPort()
+ {
+ return localPort;
+ }
+}
diff --git a/libjava/classpath/java/net/DatagramSocketImplFactory.java b/libjava/classpath/java/net/DatagramSocketImplFactory.java
new file mode 100644
index 00000000000..014651aa899
--- /dev/null
+++ b/libjava/classpath/java/net/DatagramSocketImplFactory.java
@@ -0,0 +1,60 @@
+/* DatagramSocketImplFactory.java --
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/** Written using on-line Java Platform 1.4 API Specification.
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface defines one method which returns a
+ * <code>DatagramSocketImpl</code> object.
+ * This should not be needed by ordinary applications.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.3
+ */
+public interface DatagramSocketImplFactory
+{
+ /**
+ * This method returns an instance of the DatagramSocketImpl object
+ *
+ * @return A DatagramSocketImpl object
+ */
+ DatagramSocketImpl createDatagramSocketImpl();
+} // interface DatagramSocketImplFactory
diff --git a/libjava/classpath/java/net/FileNameMap.java b/libjava/classpath/java/net/FileNameMap.java
new file mode 100644
index 00000000000..6f1d25a6a52
--- /dev/null
+++ b/libjava/classpath/java/net/FileNameMap.java
@@ -0,0 +1,65 @@
+/* FileNameMap.java -- Maps filenames to MIME types
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface has one method which, when passed a filename, returns
+ * the MIME type associated with that filename.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ */
+public interface FileNameMap
+{
+ /**
+ * This method is passed a filename and is responsible for determining
+ * the appropriate MIME type for that file.
+ *
+ * @param filename The name of the file to generate a MIME type for.
+ *
+ * @return The MIME type for the filename passed in.
+ */
+ String getContentTypeFor(String filename);
+} // interface FileNameMap
diff --git a/libjava/classpath/java/net/HttpURLConnection.java b/libjava/classpath/java/net/HttpURLConnection.java
new file mode 100644
index 00000000000..07eae48e77a
--- /dev/null
+++ b/libjava/classpath/java/net/HttpURLConnection.java
@@ -0,0 +1,589 @@
+/* HttpURLConnection.java -- Subclass of communications links using
+ Hypertext Transfer Protocol.
+ Copyright (C) 1998, 1999, 2000, 2002, 2003 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.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.security.Permission;
+
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This class provides a common abstract implementation for those
+ * URL connection classes that will connect using the HTTP protocol.
+ * In addition to the functionality provided by the URLConnection
+ * class, it defines constants for HTTP return code values and
+ * methods for setting the HTTP request method and determining whether
+ * or not to follow redirects.
+ *
+ * @since 1.1
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class HttpURLConnection extends URLConnection
+{
+ /* HTTP Success Response Codes */
+
+ /**
+ * Indicates that the client may continue with its request. This value
+ * is specified as part of RFC 2068 but was not included in Sun's JDK, so
+ * beware of using this value
+ */
+ static final int HTTP_CONTINUE = 100;
+
+ /**
+ * Indicates the request succeeded.
+ */
+ public static final int HTTP_OK = 200;
+
+ /**
+ * The requested resource has been created.
+ */
+ public static final int HTTP_CREATED = 201;
+
+ /**
+ * The request has been accepted for processing but has not completed.
+ * There is no guarantee that the requested action will actually ever
+ * be completed succesfully, but everything is ok so far.
+ */
+ public static final int HTTP_ACCEPTED = 202;
+
+ /**
+ * The meta-information returned in the header is not the actual data
+ * from the original server, but may be from a local or other copy.
+ * Normally this still indicates a successful completion.
+ */
+ public static final int HTTP_NOT_AUTHORITATIVE = 203;
+
+ /**
+ * The server performed the request, but there is no data to send
+ * back. This indicates that the user's display should not be changed.
+ */
+ public static final int HTTP_NO_CONTENT = 204;
+
+ /**
+ * The server performed the request, but there is no data to sent back,
+ * however, the user's display should be "reset" to clear out any form
+ * fields entered.
+ */
+ public static final int HTTP_RESET = 205;
+
+ /**
+ * The server completed the partial GET request for the resource.
+ */
+ public static final int HTTP_PARTIAL = 206;
+
+ /* HTTP Redirection Response Codes */
+
+ /**
+ * There is a list of choices available for the requested resource.
+ */
+ public static final int HTTP_MULT_CHOICE = 300;
+
+ /**
+ * The resource has been permanently moved to a new location.
+ */
+ public static final int HTTP_MOVED_PERM = 301;
+
+ /**
+ * The resource requested has been temporarily moved to a new location.
+ */
+ public static final int HTTP_MOVED_TEMP = 302;
+
+ /**
+ * The response to the request issued is available at another location.
+ */
+ public static final int HTTP_SEE_OTHER = 303;
+
+ /**
+ * The document has not been modified since the criteria specified in
+ * a conditional GET.
+ */
+ public static final int HTTP_NOT_MODIFIED = 304;
+
+ /**
+ * The requested resource needs to be accessed through a proxy.
+ */
+ public static final int HTTP_USE_PROXY = 305;
+
+ /* HTTP Client Error Response Codes */
+
+ /**
+ * The request was misformed or could not be understood.
+ */
+ public static final int HTTP_BAD_REQUEST = 400;
+
+ /**
+ * The request made requires user authorization. Try again with
+ * a correct authentication header.
+ */
+ public static final int HTTP_UNAUTHORIZED = 401;
+
+ /**
+ * Code reserved for future use - I hope way in the future.
+ */
+ public static final int HTTP_PAYMENT_REQUIRED = 402;
+
+ /**
+ * There is no permission to access the requested resource.
+ */
+ public static final int HTTP_FORBIDDEN = 403;
+
+ /**
+ * The requested resource was not found.
+ */
+ public static final int HTTP_NOT_FOUND = 404;
+
+ /**
+ * The specified request method is not allowed for this resource.
+ */
+ public static final int HTTP_BAD_METHOD = 405;
+
+ /**
+ * Based on the input headers sent, the resource returned in response
+ * to the request would not be acceptable to the client.
+ */
+ public static final int HTTP_NOT_ACCEPTABLE = 406;
+
+ /**
+ * The client must authenticate with a proxy prior to attempting this
+ * request.
+ */
+ public static final int HTTP_PROXY_AUTH = 407;
+
+ /**
+ * The request timed out.
+ */
+ public static final int HTTP_CLIENT_TIMEOUT = 408;
+
+ /**
+ * There is a conflict between the current state of the resource and the
+ * requested action.
+ */
+ public static final int HTTP_CONFLICT = 409;
+
+ /**
+ * The requested resource is no longer available. This ususally indicates
+ * a permanent condition.
+ */
+ public static final int HTTP_GONE = 410;
+
+ /**
+ * A Content-Length header is required for this request, but was not
+ * supplied.
+ */
+ public static final int HTTP_LENGTH_REQUIRED = 411;
+
+ /**
+ * A client specified pre-condition was not met on the server.
+ */
+ public static final int HTTP_PRECON_FAILED = 412;
+
+ /**
+ * The request sent was too large for the server to handle.
+ */
+ public static final int HTTP_ENTITY_TOO_LARGE = 413;
+
+ /**
+ * The name of the resource specified was too long.
+ */
+ public static final int HTTP_REQ_TOO_LONG = 414;
+
+ /**
+ * The request is in a format not supported by the requested resource.
+ */
+ public static final int HTTP_UNSUPPORTED_TYPE = 415;
+
+ /* HTTP Server Error Response Codes */
+
+ /**
+ * This error code indicates that some sort of server error occurred.
+ *
+ * @deprecated
+ */
+ public static final int HTTP_SERVER_ERROR = 500;
+
+ /**
+ * The server encountered an unexpected error (such as a CGI script crash)
+ * that prevents the request from being fulfilled.
+ */
+ public static final int HTTP_INTERNAL_ERROR = 500;
+
+ /**
+ * The server does not support the requested functionality.
+ * @since 1.3
+ */
+ public static final int HTTP_NOT_IMPLEMENTED = 501;
+
+ /**
+ * The proxy encountered a bad response from the server it was proxy-ing for
+ */
+ public static final int HTTP_BAD_GATEWAY = 502;
+
+ /**
+ * The HTTP service is not availalble, such as because it is overloaded
+ * and does not want additional requests.
+ */
+ public static final int HTTP_UNAVAILABLE = 503;
+
+ /**
+ * The proxy timed out getting a reply from the remote server it was
+ * proxy-ing for.
+ */
+ public static final int HTTP_GATEWAY_TIMEOUT = 504;
+
+ /**
+ * This server does not support the protocol version requested.
+ */
+ public static final int HTTP_VERSION = 505;
+
+ // Non-HTTP response static variables
+
+ /**
+ * Flag to indicate whether or not redirects should be automatically
+ * followed by default.
+ */
+ private static boolean followRedirects = true;
+
+ /**
+ * This is a list of valid request methods, separated by "|" characters.
+ */
+ private static final String valid_methods =
+ "|GET|POST|HEAD|OPTIONS|PUT|DELETE|TRACE|";
+
+ // Instance Variables
+
+ /**
+ * The requested method in use for this connection. Default is GET.
+ */
+ protected String method = "GET";
+
+ /**
+ * The response code received from the server
+ */
+ protected int responseCode = -1;
+
+ /**
+ * The response message string received from the server.
+ */
+ protected String responseMessage;
+
+ /**
+ * If this instance should follow redirect requests.
+ */
+ protected boolean instanceFollowRedirects = followRedirects;
+
+ /**
+ * Whether we already got a valid response code for this connection.
+ * Used by <code>getResponseCode()</code> and
+ * <code>getResponseMessage()</code>.
+ */
+ private boolean gotResponseVals;
+
+ /**
+ * Create an HttpURLConnection for the specified URL
+ *
+ * @param url The URL to create this connection for.
+ */
+ protected HttpURLConnection(URL url)
+ {
+ super(url);
+ }
+
+ /**
+ * Closes the connection to the server.
+ */
+ public abstract void disconnect();
+
+ /**
+ * Returns a boolean indicating whether or not this connection is going
+ * through a proxy
+ *
+ * @return true if through a proxy, false otherwise
+ */
+ public abstract boolean usingProxy();
+
+ /**
+ * Sets whether HTTP redirects (requests with response code 3xx) should be
+ * automatically followed by this class. True by default
+ *
+ * @param set true if redirects should be followed, false otherwis.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ */
+ public static void setFollowRedirects(boolean set)
+ {
+ // Throw an exception if an extant security mgr precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+
+ followRedirects = set;
+ }
+
+ /**
+ * Returns a boolean indicating whether or not HTTP redirects will
+ * automatically be followed or not.
+ *
+ * @return true if redirects will be followed, false otherwise
+ */
+ public static boolean getFollowRedirects()
+ {
+ return followRedirects;
+ }
+
+ /**
+ * Returns the value of this HttpURLConnection's instanceFollowRedirects
+ * field
+ *
+ * @return true if following redirects is enabled, false otherwise
+ */
+ public boolean getInstanceFollowRedirects()
+ {
+ return instanceFollowRedirects;
+ }
+
+ /**
+ * Sets the value of this HttpURLConnection's instanceFollowRedirects field
+ *
+ * @param follow true to enable following redirects, false otherwise
+ */
+ public void setInstanceFollowRedirects(boolean follow)
+ {
+ instanceFollowRedirects = follow;
+ }
+
+ /**
+ * Set the method for the URL request, one of:
+ * GET POST HEAD OPTIONS PUT DELETE TRACE are legal
+ *
+ * @param method the method to use
+ *
+ * @exception ProtocolException If the method cannot be reset or if the
+ * requested method isn't valid for HTTP
+ */
+ public void setRequestMethod(String method) throws ProtocolException
+ {
+ if (connected)
+ throw new ProtocolException("Already connected");
+
+ method = method.toUpperCase();
+ if (valid_methods.indexOf("|" + method + "|") != -1)
+ this.method = method;
+ else
+ throw new ProtocolException("Invalid HTTP request method: " + method);
+ }
+
+ /**
+ * The request method currently in use for this connection.
+ *
+ * @return The request method
+ */
+ public String getRequestMethod()
+ {
+ return method;
+ }
+
+ /**
+ * Gets the status code from an HTTP response message, or -1 if
+ * the response code could not be determined.
+ * Note that all valid response codes have class variables
+ * defined for them in this class.
+ *
+ * @return The response code
+ *
+ * @exception IOException If an error occurs
+ */
+ public int getResponseCode() throws IOException
+ {
+ if (! gotResponseVals)
+ getResponseVals();
+ return responseCode;
+ }
+
+ /**
+ * Gets the HTTP response message, if any, returned along with the
+ * response code from a server. Null if no response message was set
+ * or an error occured while connecting.
+ *
+ * @return The response message
+ *
+ * @exception IOException If an error occurs
+ */
+ public String getResponseMessage() throws IOException
+ {
+ if (! gotResponseVals)
+ getResponseVals();
+ return responseMessage;
+ }
+
+ private void getResponseVals() throws IOException
+ {
+ // getHeaderField() will connect for us, but do it here first in
+ // order to pick up IOExceptions.
+ if (! connected)
+ connect();
+
+ gotResponseVals = true;
+
+ // If responseCode not yet explicitly set by subclass
+ if (responseCode == -1)
+ {
+ // Response is the first header received from the connection.
+ String respField = getHeaderField(0);
+
+ if (respField == null || ! respField.startsWith("HTTP/"))
+ {
+ // Set to default values on failure.
+ responseCode = -1;
+ responseMessage = null;
+ return;
+ }
+
+ int firstSpc;
+ int nextSpc;
+ firstSpc = respField.indexOf(' ');
+ nextSpc = respField.indexOf(' ', firstSpc + 1);
+ responseMessage = respField.substring(nextSpc + 1);
+ String codeStr = respField.substring(firstSpc + 1, nextSpc);
+ try
+ {
+ responseCode = Integer.parseInt(codeStr);
+ }
+ catch (NumberFormatException e)
+ {
+ // Set to default values on failure.
+ responseCode = -1;
+ responseMessage = null;
+ }
+ }
+ }
+
+ /**
+ * Returns a permission object representing the permission necessary to make
+ * the connection represented by this object
+ *
+ * @return the permission necessary for this connection
+ *
+ * @exception IOException If an error occurs
+ */
+ public Permission getPermission() throws IOException
+ {
+ URL url = getURL();
+ String host = url.getHost();
+ int port = url.getPort();
+ if (port == -1)
+ port = 80;
+
+ host = host + ":" + port;
+
+ return new SocketPermission(host, "connect");
+ }
+
+ /**
+ * This method allows the caller to retrieve any data that might have
+ * been sent despite the fact that an error occurred. For example, the
+ * HTML page sent along with a 404 File Not Found error. If the socket
+ * is not connected, or if no error occurred or no data was returned,
+ * this method returns <code>null</code>.
+ *
+ * @return An <code>InputStream</code> for reading error data.
+ */
+ public InputStream getErrorStream()
+ {
+ if (! connected)
+ return null;
+
+ int code;
+ try
+ {
+ code = getResponseCode();
+ }
+ catch (IOException e)
+ {
+ code = -1;
+ }
+
+ if (code == -1)
+ return null;
+
+ if (((code / 100) != 4) || ((code / 100) != 5))
+ return null;
+
+ try
+ {
+ PushbackInputStream pbis = new PushbackInputStream(getInputStream());
+
+ int i = pbis.read();
+ if (i == -1)
+ return null;
+
+ pbis.unread(i);
+ return pbis;
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value of the named field parsed as date
+ *
+ * @param key the key of the header field
+ * @param value the default value if the header field is not present
+ *
+ * @return the value of the header field
+ */
+ public long getHeaderFieldDate(String key, long value)
+ {
+ // FIXME: implement this correctly
+ // http://www.w3.org/Protocols/HTTP-NG/ng-notes.txt
+ return super.getHeaderFieldDate(key, value);
+ }
+}
diff --git a/libjava/classpath/java/net/Inet4Address.java b/libjava/classpath/java/net/Inet4Address.java
new file mode 100644
index 00000000000..00c6501de0c
--- /dev/null
+++ b/libjava/classpath/java/net/Inet4Address.java
@@ -0,0 +1,233 @@
+/* Inet4Address.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.io.ObjectStreamException;
+
+/*
+ * Written using on-line Java Platform 1.4 API Specification and
+ * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt),
+ * RFC 1918 (http://www.ietf.org/rfc/rfc1918.txt),
+ * RFC 2365 (http://www.ietf.org/rfc/rfc2365.txt)
+ *
+ * @author Michael Koch
+ * @status Believed complete and correct.
+ */
+public final class Inet4Address extends InetAddress
+{
+ /**
+ * For compatability with Sun's JDK 1.4.2 rev. 5
+ */
+ static final long serialVersionUID = 3286316764910316507L;
+
+ /**
+ * needed for serialization
+ */
+ private Object writeReplace() throws ObjectStreamException
+ {
+ return new InetAddress(addr, hostName);
+ }
+
+ /**
+ * Initializes this object's addr instance variable from the passed in
+ * byte array. Note that this constructor is protected and is called
+ * only by static methods in this class.
+ *
+ * @param addr The IP number of this address as an array of bytes
+ * @param hostname The hostname of this IP address.
+ */
+ Inet4Address(byte[] addr, String host)
+ {
+ super(addr, host);
+ }
+
+ /**
+ * Checks if the address is a multicast address
+ *
+ * @since 1.1
+ */
+ public boolean isMulticastAddress()
+ {
+ return super.isMulticastAddress();
+ }
+
+ /**
+ * Checks if this address is a loopback address
+ */
+ public boolean isLoopbackAddress()
+ {
+ return super.isLoopbackAddress();
+ }
+
+ /**
+ * Checks if this address is a wildcard address
+ *
+ * @since 1.4
+ */
+ public boolean isAnyLocalAddress()
+ {
+ return super.isAnyLocalAddress();
+ }
+
+ /**
+ * Checks if this address is a link local address
+ *
+ * @since 1.4
+ */
+ public boolean isLinkLocalAddress()
+ {
+ return super.isLinkLocalAddress();
+ }
+
+ /**
+ * Checks if this address is a site local address
+ *
+ * @since 1.4
+ */
+ public boolean isSiteLocalAddress()
+ {
+ return super.isSiteLocalAddress();
+ }
+
+ /**
+ * Checks if this multicast address has global scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCGlobal()
+ {
+ return super.isMCGlobal();
+ }
+
+ /**
+ * Checks if this multicast address has node scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCNodeLocal()
+ {
+ return isMCNodeLocal();
+ }
+
+ /**
+ * Checks if this multicast address has link scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCLinkLocal()
+ {
+ return super.isMCLinkLocal();
+ }
+
+ /**
+ * Checks if this multicast address has site scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCSiteLocal()
+ {
+ return super.isMCSiteLocal();
+ }
+
+ /**
+ * Checks if this multicast address has organization scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCOrgLocal()
+ {
+ return isMCOrgLocal();
+ }
+
+ /**
+ * Returns the address of the current instance
+ */
+ public byte[] getAddress()
+ {
+ return (byte[]) addr.clone();
+ }
+
+ /**
+ * Returns the address as string
+ *
+ * @since 1.0.2
+ */
+ public String getHostAddress()
+ {
+ return super.getHostAddress();
+ }
+
+ /**
+ * Computes the hashcode of the instance
+ */
+ public int hashCode()
+ {
+ int hash = 0;
+ int len = addr.length;
+ int i = len > 4 ? len - 4 : 0;
+
+ for (; i < len; i++)
+ hash = (hash << 8) | (addr[i] & 0xFF);
+
+ return hash;
+ }
+
+ /**
+ * Compare the current Inet4Address instance with obj
+ *
+ * @param obj Object to compare with
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof InetAddress))
+ return false;
+
+ byte[] addr1 = addr;
+ byte[] addr2 = ((InetAddress) obj).addr;
+
+ if (addr1.length != addr2.length)
+ return false;
+
+ for (int i = addr1.length; --i >= 0;)
+ if (addr1[i] != addr2[i])
+ return false;
+
+ return true;
+ }
+}
diff --git a/libjava/classpath/java/net/Inet6Address.java b/libjava/classpath/java/net/Inet6Address.java
new file mode 100644
index 00000000000..0d62fe919a0
--- /dev/null
+++ b/libjava/classpath/java/net/Inet6Address.java
@@ -0,0 +1,261 @@
+/* Inet6Address.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.util.Arrays;
+
+/*
+ * 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.
+ */
+public final class Inet6Address extends InetAddress
+{
+ static final long serialVersionUID = 6880410070516793377L;
+
+ /**
+ * Needed for serialization
+ */
+ byte[] ipaddress;
+
+ /**
+ * Create an Inet6Address object
+ *
+ * @param addr The IP address
+ * @param host The hostname
+ */
+ Inet6Address(byte[] addr, String host)
+ {
+ super(addr, host);
+ // Super constructor clones the addr. Get a reference to the clone.
+ this.ipaddress = this.addr;
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is an IP multicast address
+ *
+ * @since 1.1
+ */
+ public boolean isMulticastAddress()
+ {
+ return ipaddress[0] == 0xFF;
+ }
+
+ /**
+ * Utility routine to check if the InetAddress in a wildcard address
+ *
+ * @since 1.4
+ */
+ public boolean isAnyLocalAddress()
+ {
+ byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ return Arrays.equals(ipaddress, anylocal);
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is a loopback address
+ *
+ * @since 1.4
+ */
+ public boolean isLoopbackAddress()
+ {
+ byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+ return Arrays.equals(ipaddress, loopback);
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is an link local address
+ *
+ * @since 1.4
+ */
+ public boolean isLinkLocalAddress()
+ {
+ return ipaddress[0] == 0xFA;
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is a site local address
+ *
+ * @since 1.4
+ */
+ public boolean isSiteLocalAddress()
+ {
+ return ipaddress[0] == 0xFB;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has global scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCGlobal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0xE;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has node scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCNodeLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0x1;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has link scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCLinkLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0x2;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has site scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCSiteLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0x5;
+ }
+
+ /**
+ * Utility routine to check if the multicast address has organization scope
+ *
+ * @since 1.4
+ */
+ public boolean isMCOrgLocal()
+ {
+ if (! isMulticastAddress())
+ return false;
+
+ return (ipaddress[1] & 0x0F) == 0x8;
+ }
+
+ /**
+ * Returns the raw IP address of this InetAddress object. The result is in
+ * network byte order: the highest order byte of the address is i
+ * n getAddress()[0]
+ */
+ public byte[] getAddress()
+ {
+ return (byte[]) ipaddress.clone();
+ }
+
+ /**
+ * Returns the IP address string in textual presentation
+ */
+ public String getHostAddress()
+ {
+ StringBuffer sbuf = new StringBuffer(40);
+
+ for (int i = 0; i < 16; i += 2)
+ {
+ int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF);
+
+ if (i > 0)
+ sbuf.append(':');
+
+ sbuf.append(Integer.toHexString(x));
+ }
+
+ return sbuf.toString();
+ }
+
+ /**
+ * Returns a hashcode for this IP address
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ * Compares this object against the specified object
+ */
+ public boolean equals(Object obj)
+ {
+ 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);
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is an
+ * IPv4 compatible IPv6 address
+ *
+ * @since 1.4
+ */
+ public boolean isIPv4CompatibleAddress()
+ {
+ if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00
+ || ipaddress[3] != 0x00 || ipaddress[4] != 0x00
+ || ipaddress[5] != 0x00 || ipaddress[6] != 0x00
+ || ipaddress[7] != 0x00 || ipaddress[8] != 0x00
+ || ipaddress[9] != 0x00 || ipaddress[10] != 0x00
+ || ipaddress[11] != 0x00)
+ return false;
+
+ return true;
+ }
+}
diff --git a/libjava/classpath/java/net/InetAddress.java b/libjava/classpath/java/net/InetAddress.java
new file mode 100644
index 00000000000..94dc6cb6d84
--- /dev/null
+++ b/libjava/classpath/java/net/InetAddress.java
@@ -0,0 +1,813 @@
+/* InetAddress.java -- Class to model an Internet address
+ Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+/**
+ * This class models an Internet address. It does not have a public
+ * constructor. Instead, new instances of this objects are created
+ * using the static methods getLocalHost(), getByName(), and
+ * getAllByName().
+ *
+ * <p>This class fulfills the function of the C style functions gethostname(),
+ * gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names
+ * into their corresponding numeric addresses and vice versa.</p>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner
+ *
+ * @specnote This class is not final since JK 1.4
+ */
+public class InetAddress implements Serializable
+{
+ private static final long serialVersionUID = 3286316764910316507L;
+
+ /**
+ * The default DNS hash table size,
+ * Use a prime number happy with hash table.
+ */
+ private static final int DEFAULT_CACHE_SIZE = 89;
+
+ /**
+ * The default caching period in minutes.
+ */
+ private static final int DEFAULT_CACHE_PERIOD = 4 * 60;
+
+ /**
+ * Percentage of cache entries to purge when the table gets full.
+ */
+ private static final int DEFAULT_CACHE_PURGE_PCT = 30;
+
+ /**
+ * The special IP address INADDR_ANY.
+ */
+ private static InetAddress inaddr_any;
+
+ /**
+ * Dummy InetAddress, used to bind socket to any (all) network interfaces.
+ */
+ static InetAddress ANY_IF;
+
+ /**
+ * Stores static localhost address object.
+ */
+ static InetAddress LOCALHOST;
+
+ /**
+ * The size of the cache.
+ */
+ private static int cache_size = 0;
+
+ /**
+ * The length of time we will continue to read the address from cache
+ * before forcing another lookup.
+ */
+ private static int cache_period = 0;
+
+ /**
+ * What percentage of the cache we will purge if it gets full.
+ */
+ private static int cache_purge_pct = 0;
+
+ /**
+ * HashMap to use as DNS lookup cache.
+ * Use HashMap because all accesses to cache are already synchronized.
+ */
+ private static HashMap cache;
+
+ static
+ {
+ // Look for properties that override default caching behavior
+ cache_size =
+ Integer.getInteger("gnu.java.net.dns_cache_size", DEFAULT_CACHE_SIZE)
+ .intValue();
+ cache_period =
+ Integer.getInteger("gnu.java.net.dns_cache_period",
+ DEFAULT_CACHE_PERIOD * 60 * 1000).intValue();
+
+ cache_purge_pct =
+ Integer.getInteger("gnu.java.net.dns_cache_purge_pct",
+ DEFAULT_CACHE_PURGE_PCT).intValue();
+
+ // Fallback to defaults if necessary
+ if ((cache_purge_pct < 1) || (cache_purge_pct > 100))
+ cache_purge_pct = DEFAULT_CACHE_PURGE_PCT;
+
+ // Create the cache
+ if (cache_size != 0)
+ cache = new HashMap(cache_size);
+
+ // precompute the ANY_IF address
+ try
+ {
+ ANY_IF = getInaddrAny();
+
+ byte[] ip_localhost = { 127, 0, 0, 1 };
+ LOCALHOST = new Inet4Address(ip_localhost, "localhost");
+ }
+ catch (UnknownHostException uhe)
+ {
+ // Hmmm, make one up and hope that it works.
+ byte[] zeros = { 0, 0, 0, 0 };
+ ANY_IF = new Inet4Address(zeros, "0.0.0.0");
+ }
+ }
+
+ /**
+ * The Serialized Form specifies that an int 'address' is saved/restored.
+ * This class uses a byte array internally so we'll just do the conversion
+ * at serialization time and leave the rest of the algorithm as is.
+ */
+ private int address;
+
+ /**
+ * An array of octets representing an IP address.
+ */
+ transient byte[] addr;
+
+ /**
+ * The name of the host for this address.
+ */
+ String hostName;
+
+ /**
+ * The time this address was looked up.
+ */
+ transient long lookup_time;
+
+ /**
+ * The field 'family' seems to be the AF_ value.
+ * FIXME: Much of the code in the other java.net classes does not make
+ * use of this family field. A better implementation would be to make
+ * use of getaddrinfo() and have other methods just check the family
+ * field rather than examining the length of the address each time.
+ */
+ int family;
+
+ /**
+ * Initializes this object's addr instance variable from the passed in
+ * byte array. Note that this constructor is protected and is called
+ * only by static methods in this class.
+ *
+ * @param ipaddr The IP number of this address as an array of bytes
+ * @param hostname The hostname of this IP address.
+ */
+ InetAddress(byte[] ipaddr, String hostname)
+ {
+ addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
+ hostName = hostname;
+
+ lookup_time = System.currentTimeMillis();
+
+ family = 2; /* AF_INET */
+ }
+
+ /**
+ * Returns true if this address is a multicast address, false otherwise.
+ * An address is multicast if the high four bits are "1110". These are
+ * also known as "Class D" addresses.
+ *
+ * @return true if mulitcast, false if not
+ *
+ * @since 1.1
+ */
+ public boolean isMulticastAddress()
+ {
+ // Mask against high order bits of 1110
+ if (addr.length == 4)
+ return (addr[0] & 0xf0) == 0xe0;
+
+ return false;
+ }
+
+ /**
+ * Utility routine to check if the InetAddress in a wildcard address
+ *
+ * @since 1.4
+ */
+ public boolean isAnyLocalAddress()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+ return equals(ANY_IF);
+ }
+
+ /**
+ * Utility routine to check if the InetAddress is a loopback address
+ *
+ * @since 1.4
+ */
+ public boolean isLoopbackAddress()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+ return (addr[0] & 0xff) == 0x7f;
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a link local address
+ *
+ * @since 1.4
+ */
+ public boolean isLinkLocalAddress()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+ // XXX: This seems to not exist with IPv4 addresses
+ return false;
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a site local address
+ *
+ * @since 1.4
+ */
+ public boolean isSiteLocalAddress()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+
+ // 10.0.0.0/8
+ if ((addr[0] & 0xff) == 0x0a)
+ return true;
+
+ // 172.16.0.0/12
+ if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10)
+ return true;
+
+ // 192.168.0.0/16
+ if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8)
+ return true;
+
+ // XXX: Do we need to check more addresses here ?
+ return false;
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a global multicast address
+ *
+ * @since 1.4
+ */
+ public boolean isMCGlobal()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+ // XXX: This seems to not exist with IPv4 addresses
+ return false;
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a node local multicast address.
+ *
+ * @since 1.4
+ */
+ public boolean isMCNodeLocal()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+ // XXX: This seems to not exist with IPv4 addresses
+ return false;
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a link local multicast address.
+ *
+ * @since 1.4
+ */
+ public boolean isMCLinkLocal()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+ if (! isMulticastAddress())
+ return false;
+
+ return ((addr[0] & 0xff) == 0xe0
+ && (addr[1] & 0xff) == 0x00
+ && (addr[2] & 0xff) == 0x00);
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a site local multicast address.
+ *
+ * @since 1.4
+ */
+ public boolean isMCSiteLocal()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+ // XXX: This seems to not exist with IPv4 addresses
+ return false;
+ }
+
+ /**
+ * Utility routine to check if InetAddress is a organization local
+ * multicast address.
+ *
+ * @since 1.4
+ */
+ public boolean isMCOrgLocal()
+ {
+ // This is the IPv4 implementation.
+ // Any class derived from InetAddress should override this.
+ // XXX: This seems to not exist with IPv4 addresses
+ return false;
+ }
+
+ /**
+ * Returns the hostname for this address. This will return the IP address
+ * as a String if there is no hostname available for this address
+ *
+ * @return The hostname for this address
+ */
+ public String getHostName()
+ {
+ if (hostName != null)
+ return hostName;
+
+ try
+ {
+ hostName = VMInetAddress.getHostByAddr(addr);
+ return hostName;
+ }
+ catch (UnknownHostException e)
+ {
+ return getHostAddress();
+ }
+ }
+
+ /**
+ * Returns the canonical hostname represented by this InetAddress
+ *
+ * @since 1.4
+ */
+ public String getCanonicalHostName()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ try
+ {
+ sm.checkConnect(hostName, -1);
+ }
+ catch (SecurityException e)
+ {
+ return getHostAddress();
+ }
+ }
+
+ // Try to find the FDQN now
+ InetAddress address;
+ byte[] ipaddr = getAddress();
+
+ if (ipaddr.length == 16)
+ address = new Inet6Address(getAddress(), null);
+ else
+ address = new Inet4Address(getAddress(), null);
+
+ return address.getHostName();
+ }
+
+ /**
+ * Returns the IP address of this object as a byte array.
+ *
+ * @return IP address
+ */
+ public byte[] getAddress()
+ {
+ // An experiment shows that JDK1.2 returns a different byte array each
+ // time. This makes sense, in terms of security.
+ return (byte[]) addr.clone();
+ }
+
+ /**
+ * Returns the IP address of this object as a String. The address is in
+ * the dotted octet notation, for example, "127.0.0.1".
+ *
+ * @return The IP address of this object in String form
+ *
+ * @since 1.0.2
+ */
+ public String getHostAddress()
+ {
+ StringBuffer sb = new StringBuffer(40);
+
+ int len = addr.length;
+ int i = 0;
+
+ for ( ; ; )
+ {
+ sb.append(addr[i] & 0xff);
+ i++;
+
+ if (i == len)
+ break;
+
+ sb.append('.');
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Returns a hash value for this address. Useful for creating hash
+ * tables. Overrides Object.hashCode()
+ *
+ * @return A hash value for this address.
+ */
+ public int hashCode()
+ {
+ // There hashing algorithm is not specified, but a simple experiment
+ // shows that it is equal to the address, as a 32-bit big-endian integer.
+ int hash = 0;
+ int len = addr.length;
+ int i = len > 4 ? len - 4 : 0;
+
+ for (; i < len; i++)
+ hash = (hash << 8) | (addr[i] & 0xff);
+
+ return hash;
+ }
+
+ /**
+ * Tests this address for equality against another InetAddress. The two
+ * addresses are considered equal if they contain the exact same octets.
+ * This implementation overrides Object.equals()
+ *
+ * @param obj The address to test for equality
+ *
+ * @return true if the passed in object's address is equal to this one's,
+ * false otherwise
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof InetAddress))
+ return false;
+
+ // "The Java Class Libraries" 2nd edition says "If a machine has
+ // multiple names instances of InetAddress for different name of
+ // that same machine are not equal. This is because they have
+ // different host names." This violates the description in the
+ // JDK 1.2 API documentation. A little experimentation
+ // shows that the latter is correct.
+ byte[] addr2 = ((InetAddress) obj).addr;
+
+ if (addr.length != addr2.length)
+ return false;
+
+ for (int i = 0; i < addr.length; i++)
+ if (addr[i] != addr2[i])
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Converts this address to a String. This string contains the IP in
+ * dotted decimal form. For example: "127.0.0.1" This method is equivalent
+ * to getHostAddress() and overrides Object.toString()
+ *
+ * @return This address in String form
+ */
+ public String toString()
+ {
+ String addr = getHostAddress();
+ String host = (hostName != null) ? hostName : "";
+ return host + "/" + addr;
+ }
+
+ /**
+ * Returns an InetAddress object given the raw IP address.
+ *
+ * The argument is in network byte order: the highest order byte of the
+ * address is in getAddress()[0].
+ *
+ * @param addr The IP address to create the InetAddress object from
+ *
+ * @exception UnknownHostException If IP address has illegal length
+ *
+ * @since 1.4
+ */
+ public static InetAddress getByAddress(byte[] addr)
+ throws UnknownHostException
+ {
+ return getByAddress(null, addr);
+ }
+
+ /**
+ * Creates an InetAddress based on the provided host name and IP address.
+ * No name service is checked for the validity of the address.
+ *
+ * @param host The hostname of the InetAddress object to create
+ * @param addr The IP address to create the InetAddress object from
+ *
+ * @exception UnknownHostException If IP address is of illegal length
+ *
+ * @since 1.4
+ */
+ public static InetAddress getByAddress(String host, byte[] addr)
+ throws UnknownHostException
+ {
+ if (addr.length == 4)
+ return new Inet4Address(addr, host);
+
+ if (addr.length == 16)
+ return new Inet6Address(addr, host);
+
+ throw new UnknownHostException("IP address has illegal length");
+ }
+
+ /**
+ * If hostname is a valid numeric IP address, return the numeric address.
+ * Otherwise, return null.
+ *
+ * @param hostname the name of the host
+ */
+ private static byte[] aton(String hostname)
+ {
+ StringTokenizer st = new StringTokenizer(hostname, ".");
+
+ if (st.countTokens() == 4)
+ {
+ int index;
+ byte[] address = new byte[4];
+
+ for (index = 0; index < 4; index++)
+ {
+ try
+ {
+ short n = Short.parseShort(st.nextToken());
+
+ if ((n < 0) || (n > 255))
+ break;
+
+ address[index] = (byte) n;
+ }
+ catch (NumberFormatException e)
+ {
+ break;
+ }
+ }
+
+ if (index == 4)
+ return address;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns an InetAddress object representing the IP address of the given
+ * hostname. This name can be either a hostname such as "www.urbanophile.com"
+ * or an IP address in dotted decimal format such as "127.0.0.1". If the
+ * hostname is null or "", the hostname of the local machine is supplied by
+ * default. This method is equivalent to returning the first element in
+ * the InetAddress array returned from GetAllByName.
+ *
+ * @param hostname The name of the desired host, or null for the local
+ * loopback address.
+ *
+ * @return The address of the host as an InetAddress object.
+ *
+ * @exception UnknownHostException If no IP address for the host could
+ * be found
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ public static InetAddress getByName(String hostname)
+ throws UnknownHostException
+ {
+ InetAddress[] addresses = getAllByName(hostname);
+ return addresses[0];
+ }
+
+ /**
+ * Returns an array of InetAddress objects representing all the host/ip
+ * addresses of a given host, given the host's name. This name can be
+ * either a hostname such as "www.urbanophile.com" or an IP address in
+ * dotted decimal format such as "127.0.0.1". If the value is null, the
+ * hostname of the local machine is supplied by default.
+ *
+ * @param hostname The name of the desired host, or null for the
+ * local loopback address.
+ *
+ * @return All addresses of the host as an array of InetAddress objects.
+ *
+ * @exception UnknownHostException If no IP address for the host could
+ * be found
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ public static InetAddress[] getAllByName(String hostname)
+ throws UnknownHostException
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkConnect(hostname, -1);
+
+ InetAddress[] addresses;
+
+ // Default to current host if necessary
+ if (hostname == null)
+ {
+ addresses = new InetAddress[1];
+ addresses[0] = LOCALHOST;
+ return addresses;
+ }
+
+ // Check the cache for this host before doing a lookup
+ addresses = checkCacheFor(hostname);
+
+ if (addresses != null)
+ return addresses;
+
+ // Not in cache, try the lookup
+ byte[][] iplist = VMInetAddress.getHostByName(hostname);
+
+ if (iplist.length == 0)
+ throw new UnknownHostException(hostname);
+
+ addresses = new InetAddress[iplist.length];
+
+ for (int i = 0; i < iplist.length; i++)
+ {
+ if (iplist[i].length != 4)
+ throw new UnknownHostException(hostname);
+
+ addresses[i] = new Inet4Address(iplist[i], hostname);
+ }
+
+ addToCache(hostname, addresses);
+ return addresses;
+ }
+
+ /**
+ * This method checks the DNS cache to see if we have looked this hostname
+ * up before. If so, we return the cached addresses unless it has been in the
+ * cache too long.
+ *
+ * @param hostname The hostname to check for
+ *
+ * @return The InetAddress for this hostname or null if not available
+ */
+ private static synchronized InetAddress[] checkCacheFor(String hostname)
+ {
+ InetAddress[] addresses = null;
+
+ if (cache_size == 0)
+ return null;
+
+ Object obj = cache.get(hostname);
+ if (obj == null)
+ return null;
+
+ if (obj instanceof InetAddress[])
+ addresses = (InetAddress[]) obj;
+
+ if (addresses == null)
+ return null;
+
+ if (cache_period != -1)
+ if ((System.currentTimeMillis() - addresses[0].lookup_time) > cache_period)
+ {
+ cache.remove(hostname);
+ return null;
+ }
+
+ return addresses;
+ }
+
+ /**
+ * This method adds an InetAddress object to our DNS cache. Note that
+ * if the cache is full, then we run a purge to get rid of old entries.
+ * This will cause a performance hit, thus applications using lots of
+ * lookups should set the cache size to be very large.
+ *
+ * @param hostname The hostname to cache this address under
+ * @param obj The InetAddress or InetAddress array to store
+ */
+ private static synchronized void addToCache(String hostname, Object obj)
+ {
+ if (cache_size == 0)
+ return;
+
+ // Check to see if hash table is full
+ if (cache_size != -1)
+ if (cache.size() == cache_size)
+ {
+ // FIXME Add code to purge later.
+ }
+
+ cache.put(hostname, obj);
+ }
+
+ /**
+ * Returns the special address INADDR_ANY used for binding to a local
+ * port on all IP addresses hosted by a the local host.
+ *
+ * @return An InetAddress object representing INDADDR_ANY
+ *
+ * @exception UnknownHostException If an error occurs
+ */
+ static InetAddress getInaddrAny() throws UnknownHostException
+ {
+ if (inaddr_any == null)
+ {
+ byte[] tmp = VMInetAddress.lookupInaddrAny();
+ inaddr_any = new Inet4Address(tmp, null);
+ }
+
+ return inaddr_any;
+ }
+
+ /**
+ * Returns an InetAddress object representing the address of the current
+ * host.
+ *
+ * @return The local host's address
+ *
+ * @exception UnknownHostException If no IP address for the host could
+ * be found
+ */
+ public static InetAddress getLocalHost() throws UnknownHostException
+ {
+ String hostname = VMInetAddress.getLocalHostname();
+ return getByName(hostname);
+ }
+
+ /*
+ * Needed for serialization
+ */
+ private void readResolve() throws ObjectStreamException
+ {
+ // FIXME: implement this
+ }
+
+ private void readObject(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException
+ {
+ ois.defaultReadObject();
+ addr = new byte[4];
+ addr[3] = (byte) address;
+
+ for (int i = 2; i >= 0; --i)
+ addr[i] = (byte) (address >>= 8);
+
+ family = 2; /* AF_INET */
+ }
+
+ private void writeObject(ObjectOutputStream oos) throws IOException
+ {
+ // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
+ // or a 16 byte IPv6 address.
+ int len = addr.length;
+ int i = len - 4;
+
+ for (; i < len; i++)
+ address = address << 8 | (addr[i] & 0xff);
+
+ oos.defaultWriteObject();
+ }
+}
diff --git a/libjava/classpath/java/net/InetSocketAddress.java b/libjava/classpath/java/net/InetSocketAddress.java
new file mode 100644
index 00000000000..30d34e7e808
--- /dev/null
+++ b/libjava/classpath/java/net/InetSocketAddress.java
@@ -0,0 +1,221 @@
+/* InetSocketAddress.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * InetSocketAddress instances represent socket addresses
+ * in the java.nio package. They encapsulate a InetAddress and
+ * a port number.
+ *
+ * @since 1.4
+ */
+public class InetSocketAddress extends SocketAddress
+{
+ /**
+ * Compatible with JDK 1.4+
+ */
+ private static final long serialVersionUID = 5076001401234631237L;
+
+ /**
+ * Name of host.
+ */
+ private String hostname;
+
+ /**
+ * Address of host.
+ */
+ private InetAddress addr;
+
+ /**
+ * Port of host.
+ */
+ private int port;
+
+ /**
+ * Constructs an InetSocketAddress instance.
+ *
+ * @param addr Address of the socket
+ * @param port Port if the socket
+ *
+ * @exception IllegalArgumentException If the port number is illegel
+ */
+ public InetSocketAddress(InetAddress addr, int port)
+ throws IllegalArgumentException
+ {
+ if (port < 0 || port > 65535)
+ throw new IllegalArgumentException("Bad port number: " + port);
+
+ if (addr == null)
+ addr = InetAddress.ANY_IF;
+
+ this.addr = addr;
+ this.port = port;
+ this.hostname = addr.getHostName();
+ }
+
+ /**
+ * Constructs an InetSocketAddress instance.
+ *
+ * @param port Port if the socket
+ *
+ * @exception IllegalArgumentException If the port number is illegal
+ */
+ public InetSocketAddress(int port) throws IllegalArgumentException
+ {
+ this((InetAddress) null, port);
+ }
+
+ /**
+ * Constructs an InetSocketAddress instance.
+ *
+ * @param hostname The hostname for the socket address
+ * @param port The port for the socket address
+ *
+ * @exception IllegalArgumentException If the port number is illegal
+ */
+ public InetSocketAddress(String hostname, int port)
+ throws IllegalArgumentException
+ {
+ if (hostname == null)
+ throw new IllegalArgumentException("Null host name value");
+
+ if (port < 0 || port > 65535)
+ throw new IllegalArgumentException("Bad port number: " + port);
+
+ this.port = port;
+ this.hostname = hostname;
+
+ try
+ {
+ this.addr = InetAddress.getByName(hostname);
+ }
+ catch (Exception e) // UnknownHostException, SecurityException
+ {
+ this.addr = null;
+ }
+ }
+
+ /**
+ * Test if obj is a <code>InetSocketAddress</code> and
+ * has the same address and port
+ *
+ * @param obj The obj to compare this address with.
+ *
+ * @return True if obj is equal.
+ */
+ public final boolean equals(Object obj)
+ {
+ // InetSocketAddress objects are equal when addr and port are equal.
+ // The hostname may differ.
+ if (obj instanceof InetSocketAddress)
+ {
+ InetSocketAddress sa = (InetSocketAddress) obj;
+
+ if (addr == null && sa.addr != null)
+ return false;
+ else if (addr == null && sa.addr == null)
+ return hostname.equals(sa.hostname) && sa.port == port;
+ else
+ return addr.equals(sa.addr) && sa.port == port;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the <code>InetAddress</code> or
+ * <code>null</code> if its unresolved
+ *
+ * @return The IP address of this address.
+ */
+ public final InetAddress getAddress()
+ {
+ return addr;
+ }
+
+ /**
+ * Returns <code>hostname</code>
+ *
+ * @return The hostname of this address.
+ */
+ public final String getHostName()
+ {
+ return hostname;
+ }
+
+ /**
+ * Returns the <code>port</code>
+ *
+ * @return The port of this address.
+ */
+ public final int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns the hashcode of the <code>InetSocketAddress</code>
+ *
+ * @return The hashcode for this address.
+ */
+ public final int hashCode()
+ {
+ return port + addr.hashCode();
+ }
+
+ /**
+ * Checks wether the address has been resolved or not
+ *
+ * @return True if address is unresolved.
+ */
+ public final boolean isUnresolved()
+ {
+ return addr == null;
+ }
+
+ /**
+ * Returns the <code>InetSocketAddress</code> as string
+ *
+ * @return A string represenation of this address.
+ */
+ public String toString()
+ {
+ return (addr == null ? hostname : addr.getHostName()) + ":" + port;
+ }
+}
diff --git a/libjava/classpath/java/net/JarURLConnection.java b/libjava/classpath/java/net/JarURLConnection.java
new file mode 100644
index 00000000000..3067ecb81e6
--- /dev/null
+++ b/libjava/classpath/java/net/JarURLConnection.java
@@ -0,0 +1,228 @@
+/* JarURLConnection.java -- Class for manipulating remote jar files
+ Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+
+/**
+ * This abstract class represents a common superclass for implementations
+ * of jar URL's. A jar URL is a special type of URL that allows JAR
+ * files on remote systems to be accessed. It has the form:
+ * <p>
+ * jar:&lt;standard URL pointing to jar filei&gt;!/file/within/jarfile
+ * <p> for example:
+ * <p>
+ * jar:http://www.urbanophile.com/java/foo.jar!/com/urbanophile/bar.class
+ * <p>
+ * That example URL points to the file /com/urbanophile/bar.class in the
+ * remote JAR file http://www.urbanophile.com/java/foo.jar. The HTTP
+ * protocol is used only as an example. Any supported remote protocol
+ * can be used.
+ * <p>
+ * This class currently works by retrieving the entire jar file into a
+ * local cache file, then performing standard jar operations on it.
+ * (At least this is true for the default protocol implementation).
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Kresten Krab Thorup (krab@gnu.org)
+ * @date Aug 10, 1999.
+ *
+ * @since 1.2
+ */
+public abstract class JarURLConnection extends URLConnection
+{
+ /**
+ * This is the actual URL that points the remote jar file. This is parsed
+ * out of the jar URL by the constructor.
+ */
+ private final URL jarFileURL;
+
+ /**
+ * The connection to the jar file itself. A JarURLConnection
+ * can represent an entry in a jar file or an entire jar file. In
+ * either case this describes just the jar file itself.
+ */
+ protected URLConnection jarFileURLConnection;
+
+ /**
+ * This is the jar file "entry name" or portion after the "!/" in the
+ * URL which represents the pathname inside the actual jar file.
+ */
+ private final String entryName;
+
+ /**
+ * Creates a JarURLConnection from an URL object
+ *
+ * @param url The URL object for this connection.
+ *
+ * @exception MalformedURLException If url is invalid
+ *
+ * @specnote This constructor is protected since JDK 1.4
+ */
+ protected JarURLConnection(URL url) throws MalformedURLException
+ {
+ super(url);
+
+ if (! url.getProtocol().equals("jar"))
+ throw new MalformedURLException(url + ": Not jar protocol.");
+
+ String spec = url.getFile();
+ int bang = spec.indexOf("!/");
+ if (bang == -1)
+ throw new MalformedURLException(url + ": No `!/' in spec.");
+
+ // Extract the url for the jar itself.
+ jarFileURL = new URL(spec.substring(0, bang));
+
+ // Get the name of the entry, if any.
+ entryName = spec.length() == (bang + 2) ? null : spec.substring(bang + 2);
+ }
+
+ /**
+ * This method returns the "real" URL where the JarFile is located.
+ * //****Is this right?*****
+ *
+ * @return The remote URL
+ */
+ public URL getJarFileURL()
+ {
+ return jarFileURL;
+ }
+
+ /**
+ * Returns the "entry name" portion of the jar URL. This is the portion
+ * after the "!/" in the jar URL that represents the pathname inside the
+ * actual jar file.
+ *
+ * @return The entry name.
+ */
+ public String getEntryName()
+ {
+ return entryName;
+ }
+
+ /**
+ * Returns the entry in this jar file specified by the URL.
+ *
+ * @return The jar entry
+ *
+ * @exception IOException If an error occurs
+ */
+ public JarEntry getJarEntry() throws IOException
+ {
+ JarFile jarFile = getJarFile();
+
+ return jarFile != null ? jarFile.getJarEntry(entryName) : null;
+ }
+
+ /**
+ * Returns a read-only JarFile object for the remote jar file
+ *
+ * @return The JarFile object
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract JarFile getJarFile() throws IOException;
+
+ /**
+ * Returns an array of Certificate objects for the jar file entry specified
+ * by this URL or null if there are none
+ *
+ * @return A Certificate array
+ *
+ * @exception IOException If an error occurs
+ */
+ public Certificate[] getCertificates() throws IOException
+ {
+ JarEntry entry = getJarEntry();
+
+ return entry != null ? entry.getCertificates() : null;
+ }
+
+ /**
+ * Returns the main Attributes for the jar file specified in the URL or
+ * null if there are none
+ *
+ * @return The main Attributes for the JAR file for this connection
+ *
+ * @exception IOException If an error occurs
+ */
+ public Attributes getMainAttributes() throws IOException
+ {
+ Manifest manifest = getManifest();
+
+ return manifest != null ? manifest.getMainAttributes() : null;
+ }
+
+ /**
+ * Returns the Attributes for the Jar entry specified by the URL or null
+ * if none
+ *
+ * @return The Attributes object for this connection if the URL for it points
+ * to a JAR file entry, null otherwise
+ *
+ * @exception IOException If an error occurs
+ */
+ public Attributes getAttributes() throws IOException
+ {
+ JarEntry entry = getJarEntry();
+
+ return entry != null ? entry.getAttributes() : null;
+ }
+
+ /**
+ * Returns a Manifest object for this jar file, or null if there is no
+ * manifest.
+ *
+ * @return The Manifest for this connection, or null if none
+ *
+ * @exception IOException If an error occurs
+ */
+ public Manifest getManifest() throws IOException
+ {
+ JarFile file = getJarFile();
+
+ return file != null ? file.getManifest() : null;
+ }
+}
diff --git a/libjava/classpath/java/net/MalformedURLException.java b/libjava/classpath/java/net/MalformedURLException.java
new file mode 100644
index 00000000000..27e201886a0
--- /dev/null
+++ b/libjava/classpath/java/net/MalformedURLException.java
@@ -0,0 +1,74 @@
+/* MalformedURLException.java -- A URL was not in a valid format
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * This exception indicates that a URL passed to an object was not in a
+ * valid format.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class MalformedURLException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -182787522200415866L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public MalformedURLException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public MalformedURLException(String message)
+ {
+ super(message);
+ }
+} // class MalformedURLException
diff --git a/libjava/classpath/java/net/MimeTypeMapper.java b/libjava/classpath/java/net/MimeTypeMapper.java
new file mode 100644
index 00000000000..1747f4d5685
--- /dev/null
+++ b/libjava/classpath/java/net/MimeTypeMapper.java
@@ -0,0 +1,213 @@
+/* MimeTypeMapper.java -- A class for mapping file names to MIME types
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.util.Hashtable;
+
+
+/**
+ * This non-public class is used to implement the FileNameMap interface
+ * which defines a mechanism for mapping filenames to MIME types.
+ *
+ * @version 0.5
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+class MimeTypeMapper implements FileNameMap
+{
+ /**
+ * This array of strings is used to identify a MIME type based on a file
+ * extension. This is list is based on the Apache mime.types file.
+ */
+ protected static final String[][] mime_strings =
+ {
+ { "application/mac-binhex40", "hqx" },
+ { "application/mac-compactpro", "cpt" },
+ { "application/msword", "doc" },
+ { "application/octet-stream", "bin" },
+ { "application/octet-stream", "dms" },
+ { "application/octet-stream", "lha" },
+ { "application/octet-stream", "lzh" },
+ { "application/octet-stream", "exe" },
+ { "application/octet-stream", "class" },
+ { "application/oda", "oda" },
+ { "application/pdf", "pdf" },
+ { "application/postscript", "ai" },
+ { "application/postscript", "eps" },
+ { "application/postscript", "ps" },
+ { "application/powerpoint", "ppt" },
+ { "application/rtf", "rtf" },
+ { "application/x-bcpio", "bcpio" },
+ { "application/x-cdlink", "vcd" },
+ { "application/x-compress", "Z" },
+ { "application/x-cpio", "cpio" },
+ { "application/x-csh", "csh" },
+ { "application/x-director", "dcr" },
+ { "application/x-director", "dir" },
+ { "application/x-director", "dxr" },
+ { "application/x-dvi", "dvi" },
+ { "application/x-gtar", "gtar" },
+ { "application/x-gzip", "gz" },
+ { "application/x-hdf", "hdf" },
+ { "application/x-httpd-cgi", "cgi" },
+ { "application/x-koan", "skp" },
+ { "application/x-koan", "skd" },
+ { "application/x-koan", "skt" },
+ { "application/x-koan", "skm" },
+ { "application/x-latex", "latex" },
+ { "application/x-mif", "mif" },
+ { "application/x-netcdf", "nc" },
+ { "application/x-netcdf", "cdf" },
+ { "application/x-sh", "sh" },
+ { "application/x-shar", "shar" },
+ { "application/x-stuffit", "sit" },
+ { "application/x-sv4cpio", "sv4cpio" },
+ { "application/x-sv4crc", "sv4crc" },
+ { "application/x-tar", "tar" },
+ { "application/x-tcl", "tcl" },
+ { "application/x-tex", "tex" },
+ { "application/x-texinfo", "texinfo" },
+ { "application/x-texinfo", "texi" },
+ { "application/x-troff", "t" },
+ { "application/x-troff", "tr" },
+ { "application/x-troff", "roff" },
+ { "application/x-troff-man", "man" },
+ { "application/x-troff-me", "me" },
+ { "application/x-troff-ms", "ms" },
+ { "application/x-ustar", "ustar" },
+ { "application/x-wais-source", "src" },
+ { "application/zip", "zip" },
+ { "audio/basic", "au" },
+ { "audio/basic", "snd" },
+ { "audio/mpeg", "mpga" },
+ { "audio/mpeg", "mp2" },
+ { "audio/mpeg", "mp3" },
+ { "audio/x-aiff", "aif" },
+ { "audio/x-aiff", "aiff" },
+ { "audio/x-aiff", "aifc" },
+ { "audio/x-pn-realaudio", "ram" },
+ { "audio/x-pn-realaudio-plugin", "rpm" },
+ { "audio/x-realaudio", "ra" },
+ { "audio/x-wav", "wav" },
+ { "chemical/x-pdb", "pdb" },
+ { "chemical/x-pdb", "xyz" },
+ { "image/gif", "gif" },
+ { "image/ief", "ief" },
+ { "image/jpeg", "jpeg" },
+ { "image/jpeg", "jpg" },
+ { "image/jpeg", "jpe" },
+ { "image/png", "png" },
+ { "image/tiff", "tiff" },
+ { "image/tiff", "tif" },
+ { "image/x-cmu-raster", "ras" },
+ { "image/x-portable-anymap", "pnm" },
+ { "image/x-portable-bitmap", "pbm" },
+ { "image/x-portable-graymap", "pgm" },
+ { "image/x-portable-pixmap", "ppm" },
+ { "image/x-rgb", "rgb" },
+ { "image/x-xbitmap", "xbm" },
+ { "image/x-xpixmap", "xpm" },
+ { "image/x-xwindowdump", "xwd" },
+ { "text/html", "html" },
+ { "text/html", "htm" },
+ { "text/plain", "txt" },
+ { "text/richtext", "rtx" },
+ { "text/tab-separated-values", "tsv" },
+ { "text/x-setext", "etx" },
+ { "text/x-sgml", "sgml" },
+ { "text/x-sgml", "sgm" },
+ { "video/mpeg", "mpeg" },
+ { "video/mpeg", "mpg" },
+ { "video/mpeg", "mpe" },
+ { "video/quicktime", "qt" },
+ { "video/quicktime", "mov" },
+ { "video/x-msvideo", "avi" },
+ { "video/x-sgi-movie", "movie" },
+ { "x-conference/x-cooltalk", "ice" },
+ { "x-world/x-vrml", "wrl" },
+ { "x-world/x-vrml", "vrml" }
+ };
+
+ /**
+ * The MIME types above are put into this Hashtable for faster lookup.
+ */
+ private static Hashtable mime_types = new Hashtable(150);
+
+ // Static initializer to load MIME types into Hashtable
+ static
+ {
+ for (int i = 0; i < mime_strings.length; i++)
+ mime_types.put(mime_strings[i][1], mime_strings[i][0]);
+ }
+
+ /**
+ * Create a new <code>MimeTypeMapper</code> object.
+ */
+ public MimeTypeMapper()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * The method returns the MIME type of the filename passed as an argument.
+ * The value returned is based on the extension of the filename. The
+ * default content type returned if this method cannot determine the
+ * actual content type is "application/octet-stream"
+ *
+ * @param filename The name of the file to return the MIME type for
+ *
+ * @return The MIME type
+ */
+ public String getContentTypeFor(String filename)
+ {
+ int index = filename.lastIndexOf(".");
+ if (index != -1)
+ {
+ if (index == filename.length())
+ return "application/octet-stream";
+ else
+ filename = filename.substring(index + 1);
+ }
+
+ String type = (String) mime_types.get(filename);
+ if (type == null)
+ return "application/octet-stream";
+ else
+ return type;
+ }
+}
diff --git a/libjava/classpath/java/net/MulticastSocket.java b/libjava/classpath/java/net/MulticastSocket.java
new file mode 100644
index 00000000000..03bdf1e77d9
--- /dev/null
+++ b/libjava/classpath/java/net/MulticastSocket.java
@@ -0,0 +1,486 @@
+/* MulticastSocket.java -- Class for using multicast sockets
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+/**
+ * This class models a multicast UDP socket. A multicast address is a
+ * class D internet address (one whose most significant bits are 1110).
+ * A multicast group consists of a multicast address and a well known
+ * port number. All members of the group listening on that address and
+ * port will receive all the broadcasts to the group.
+ * <p>
+ * Please note that applets are not allowed to use multicast sockets
+ *
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com) (Documentation comments)
+ * @since 1.1
+ * @date May 18, 1999.
+ */
+public class MulticastSocket extends DatagramSocket
+{
+ /**
+ * Create a MulticastSocket that this not bound to any address
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ */
+ public MulticastSocket() throws IOException
+ {
+ this(new InetSocketAddress(0));
+ }
+
+ /**
+ * Create a multicast socket bound to the specified port
+ *
+ * @param port The port to bind to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ */
+ public MulticastSocket(int port) throws IOException
+ {
+ this(new InetSocketAddress(port));
+ }
+
+ /**
+ * Create a multicast socket bound to the specified SocketAddress.
+ *
+ * @param address The SocketAddress the multicast socket will be bound to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ *
+ * @since 1.4
+ */
+ public MulticastSocket(SocketAddress address) throws IOException
+ {
+ super((SocketAddress) null);
+ setReuseAddress(true);
+ if (address != null)
+ bind(address);
+ }
+
+ /**
+ * Returns the interface being used for multicast packets
+ *
+ * @return The multicast interface
+ *
+ * @exception SocketException If an error occurs
+ */
+ public InetAddress getInterface() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ return (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
+ }
+
+ /**
+ * Returns the current value of the "Time to Live" option. This is the
+ * number of hops a packet can make before it "expires". This method id
+ * deprecated. Use <code>getTimeToLive</code> instead.
+ *
+ * @return The TTL value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @deprecated 1.2 Replaced by getTimeToLive()
+ *
+ * @see MulticastSocket#getTimeToLive()
+ */
+ public byte getTTL() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ // Use getTTL here rather than getTimeToLive in case we're using an impl
+ // other than the default PlainDatagramSocketImpl and it doesn't have
+ // getTimeToLive yet.
+ return getImpl().getTTL();
+ }
+
+ /**
+ * Returns the current value of the "Time to Live" option. This is the
+ * number of hops a packet can make before it "expires".
+ *
+ * @return The TTL value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.2
+ */
+ public int getTimeToLive() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ return getImpl().getTimeToLive();
+ }
+
+ /**
+ * Sets the interface to use for sending multicast packets.
+ *
+ * @param addr The new interface to use.
+ *
+ * @exception SocketException If an error occurs.
+ *
+ * @since 1.4
+ */
+ public void setInterface(InetAddress addr) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.IP_MULTICAST_IF, addr);
+ }
+
+ /**
+ * Sets the local network interface used to send multicast messages
+ *
+ * @param netIf The local network interface used to send multicast messages
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @see MulticastSocket#getNetworkInterface()
+ *
+ * @since 1.4
+ */
+ public void setNetworkInterface(NetworkInterface netIf)
+ throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Enumeration e = netIf.getInetAddresses();
+
+ if (! e.hasMoreElements())
+ throw new SocketException("no network devices found");
+
+ InetAddress address = (InetAddress) e.nextElement();
+ getImpl().setOption(SocketOptions.IP_MULTICAST_IF, address);
+ }
+
+ /**
+ * Gets the local network interface which is used to send multicast messages
+ *
+ * @return The local network interface to send multicast messages
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
+ *
+ * @since 1.4
+ */
+ public NetworkInterface getNetworkInterface() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ InetAddress address =
+ (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
+ NetworkInterface netIf = NetworkInterface.getByInetAddress(address);
+
+ return netIf;
+ }
+
+ /**
+ * Disable/Enable local loopback of multicast packets. The option is used by
+ * the platform's networking code as a hint for setting whether multicast
+ * data will be looped back to the local socket.
+ *
+ * Because this option is a hint, applications that want to verify what
+ * loopback mode is set to should call #getLoopbackMode
+ *
+ * @param disable True to disable loopback mode
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setLoopbackMode(boolean disable) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP,
+ Boolean.valueOf(disable));
+ }
+
+ /**
+ * Checks if local loopback mode is enabled
+ *
+ * @return true if loopback mode is enabled, false otherwise
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getLoopbackMode() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP);
+
+ if (buf instanceof Boolean)
+ return ((Boolean) buf).booleanValue();
+
+ throw new SocketException("unexpected type");
+ }
+
+ /**
+ * Sets the "Time to Live" value for a socket. The value must be between
+ * 1 and 255.
+ *
+ * @param ttl The new TTL value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @deprecated 1.2 Replaced by <code>setTimeToLive</code>
+ *
+ * @see MulticastSocket#setTimeToLive(int ttl)
+ */
+ public void setTTL(byte ttl) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ // Use setTTL here rather than setTimeToLive in case we're using an impl
+ // other than the default PlainDatagramSocketImpl and it doesn't have
+ // setTimeToLive yet.
+ getImpl().setTTL(ttl);
+ }
+
+ /**
+ * Sets the "Time to Live" value for a socket. The value must be between
+ * 1 and 255.
+ *
+ * @param ttl The new TTL value
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.2
+ */
+ public void setTimeToLive(int ttl) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (ttl <= 0 || ttl > 255)
+ throw new IllegalArgumentException("Invalid ttl: " + ttl);
+
+ getImpl().setTimeToLive(ttl);
+ }
+
+ /**
+ * Joins the specified multicast group.
+ *
+ * @param mcastaddr The address of the group to join
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast method doesn't allow the operation
+ */
+ public void joinGroup(InetAddress mcastaddr) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! mcastaddr.isMulticastAddress())
+ throw new IOException("Not a Multicast address");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMulticast(mcastaddr);
+
+ getImpl().join(mcastaddr);
+ }
+
+ /**
+ * Leaves the specified multicast group
+ *
+ * @param mcastaddr The address of the group to leave
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast method doesn't allow the operation
+ */
+ public void leaveGroup(InetAddress mcastaddr) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! mcastaddr.isMulticastAddress())
+ throw new IOException("Not a Multicast address");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMulticast(mcastaddr);
+
+ getImpl().leave(mcastaddr);
+ }
+
+ /**
+ * Joins the specified mulitcast group on a specified interface.
+ *
+ * @param mcastaddr The multicast address to join
+ * @param netIf The local network interface to receive the multicast
+ * messages on or null to defer the interface set by #setInterface or
+ * #setNetworkInterface
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast method doesn't allow the operation
+ *
+ * @see MulticastSocket#setInterface(InetAddress addr)
+ * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
+ *
+ * @since 1.4
+ */
+ public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! (mcastaddr instanceof InetSocketAddress))
+ throw new IllegalArgumentException("SocketAddress type not supported");
+
+ InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
+
+ if (! tmp.getAddress().isMulticastAddress())
+ throw new IOException("Not a Multicast address");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMulticast(tmp.getAddress());
+
+ getImpl().joinGroup(mcastaddr, netIf);
+ }
+
+ /**
+ * Leaves the specified mulitcast group on a specified interface.
+ *
+ * @param mcastaddr The multicast address to leave
+ * @param netIf The local networki interface or null to defer to the
+ * interface set by setInterface or setNetworkInterface
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ * @exception SecurityException If a security manager exists and its
+ * checkMulticast method doesn't allow the operation
+ *
+ * @see MulticastSocket#setInterface(InetAddress addr)
+ * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
+ *
+ * @since 1.4
+ */
+ public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
+
+ if (! tmp.getAddress().isMulticastAddress())
+ throw new IOException("Not a Multicast address");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkMulticast(tmp.getAddress());
+
+ getImpl().leaveGroup(mcastaddr, netIf);
+ }
+
+ /**
+ * Sends a packet of data to a multicast address with a TTL that is
+ * different from the default TTL on this socket. The default TTL for
+ * the socket is not changed.
+ *
+ * @param packet The packet of data to send
+ * @param ttl The TTL for this packet
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect or checkMulticast method doesn't allow the operation
+ *
+ * @deprecated
+ */
+ public synchronized void send(DatagramPacket packet, byte ttl)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ {
+ InetAddress addr = packet.getAddress();
+ if (addr.isMulticastAddress())
+ s.checkPermission(new SocketPermission(addr.getHostName()
+ + packet.getPort(),
+ "accept,connect"));
+ else
+ s.checkConnect(addr.getHostAddress(), packet.getPort());
+ }
+
+ int oldttl = getImpl().getTimeToLive();
+ getImpl().setTimeToLive(((int) ttl) & 0xFF);
+ getImpl().send(packet);
+ getImpl().setTimeToLive(oldttl);
+ }
+}
diff --git a/libjava/classpath/java/net/NetPermission.java b/libjava/classpath/java/net/NetPermission.java
new file mode 100644
index 00000000000..cabe54e065c
--- /dev/null
+++ b/libjava/classpath/java/net/NetPermission.java
@@ -0,0 +1,90 @@
+/* NetPermission.java -- A class for basic miscellaneous network permission
+ Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.security.BasicPermission;
+
+
+/**
+ * This class is used to model miscellaneous network permissions. It is
+ * a subclass of <code>BasicPermission</code>. This means that it models a
+ * "boolean" permission. One that you either have or do not have. Thus
+ * there is no permitted action list associated with this object.
+ *
+ * The following permission names are defined for this class:
+ *
+ * <ul>
+ * <li>setDefaultAuthenticator - Grants the ability to install a facility
+ * to collect username and password information when requested by a
+ * web site or proxy server.</li>
+ * <li>requestPasswordAuthentication - Grants the ability to ask the
+ * authentication facility for the user's password.</li>
+ * <li>specifyStreamHandler - Grants the permission to specify the
+ * stream handler class used when loading from a URL.</li>
+ * </ul>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public final class NetPermission extends BasicPermission
+{
+ static final long serialVersionUID = -8343910153355041693L;
+
+ /**
+ * Initializes a new instance of <code>NetPermission</code> with the
+ * specified name.
+ *
+ * @param name The name of this permission.
+ */
+ public NetPermission(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Initializes a new instance of <code>NetPermission</code> with the
+ * specified name and perms. Note that the perms field is irrelevant and is
+ * ignored. This constructor should never need to be used.
+ *
+ * @param name The name of this permission
+ * @param perms The permitted actions of this permission (ignored)
+ */
+ public NetPermission(String name, String perms)
+ {
+ super(name);
+ }
+}
diff --git a/libjava/classpath/java/net/NetworkInterface.java b/libjava/classpath/java/net/NetworkInterface.java
new file mode 100644
index 00000000000..eccd2dac9fb
--- /dev/null
+++ b/libjava/classpath/java/net/NetworkInterface.java
@@ -0,0 +1,259 @@
+/* NetworkInterface.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * This class models a network interface on the host computer. A network
+ * interface contains a name (typically associated with a specific
+ * hardware adapter) and a list of addresses that are bound to it.
+ * For example, an ethernet interface may be named "eth0" and have the
+ * address 192.168.1.101 assigned to it.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.4
+ */
+public final class NetworkInterface
+{
+ private String name;
+ private Vector inetAddresses;
+
+ NetworkInterface(String name, InetAddress address)
+ {
+ this.name = name;
+ this.inetAddresses = new Vector(1, 1);
+ this.inetAddresses.add(address);
+ }
+
+ NetworkInterface(String name, InetAddress[] addresses)
+ {
+ this.name = name;
+ this.inetAddresses = new Vector(addresses.length, 1);
+
+ for (int i = 0; i < addresses.length; i++)
+ this.inetAddresses.add(addresses[i]);
+ }
+
+ /**
+ * Returns the name of the network interface
+ *
+ * @return The name of the interface.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns all available addresses of the network interface
+ *
+ * If a @see SecurityManager is available all addresses are checked
+ * with @see SecurityManager::checkConnect() if they are available.
+ * Only <code>InetAddresses</code> are returned where the security manager
+ * doesn't throw an exception.
+ *
+ * @return An enumeration of all addresses.
+ */
+ public Enumeration getInetAddresses()
+ {
+ SecurityManager s = System.getSecurityManager();
+
+ if (s == null)
+ return inetAddresses.elements();
+
+ Vector tmpInetAddresses = new Vector(1, 1);
+
+ for (Enumeration addresses = inetAddresses.elements();
+ addresses.hasMoreElements();)
+ {
+ InetAddress addr = (InetAddress) addresses.nextElement();
+ try
+ {
+ s.checkConnect(addr.getHostAddress(), 58000);
+ tmpInetAddresses.add(addr);
+ }
+ catch (SecurityException e)
+ {
+ // Ignore.
+ }
+ }
+
+ return tmpInetAddresses.elements();
+ }
+
+ /**
+ * Returns the display name of the interface
+ *
+ * @return The display name of the interface
+ */
+ public String getDisplayName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns an network interface by name
+ *
+ * @param name The name of the interface to return
+ *
+ * @return a <code>NetworkInterface</code> object representing the interface,
+ * or null if there is no interface with that name.
+ *
+ * @exception SocketException If an error occurs
+ * @exception NullPointerException If the specified name is null
+ */
+ public static NetworkInterface getByName(String name)
+ throws SocketException
+ {
+ Vector networkInterfaces = VMNetworkInterface.getInterfaces();
+
+ for (Enumeration e = networkInterfaces.elements(); e.hasMoreElements();)
+ {
+ NetworkInterface tmp = (NetworkInterface) e.nextElement();
+
+ if (name.equals(tmp.getName()))
+ return tmp;
+ }
+
+ // No interface with the given name found.
+ return null;
+ }
+
+ /**
+ * Return a network interface by its address
+ *
+ * @param addr The address of the interface to return
+ *
+ * @return the interface, or <code>null</code> if none found
+ *
+ * @exception SocketException If an error occurs
+ * @exception NullPointerException If the specified addess is null
+ */
+ public static NetworkInterface getByInetAddress(InetAddress addr)
+ throws SocketException
+ {
+ Vector networkInterfaces = VMNetworkInterface.getInterfaces();
+
+ for (Enumeration interfaces = networkInterfaces.elements();
+ interfaces.hasMoreElements();)
+ {
+ NetworkInterface tmp = (NetworkInterface) interfaces.nextElement();
+
+ for (Enumeration addresses = tmp.inetAddresses.elements();
+ addresses.hasMoreElements();)
+ {
+ if (addr.equals((InetAddress) addresses.nextElement()))
+ return tmp;
+ }
+ }
+
+ throw new SocketException("no network interface is bound to such an IP address");
+ }
+
+ /**
+ * Return an <code>Enumeration</code> of all available network interfaces
+ *
+ * @return all interfaces
+ *
+ * @exception SocketException If an error occurs
+ */
+ public static Enumeration getNetworkInterfaces() throws SocketException
+ {
+ Vector networkInterfaces = VMNetworkInterface.getInterfaces();
+
+ if (networkInterfaces.isEmpty())
+ return null;
+
+ return networkInterfaces.elements();
+ }
+
+ /**
+ * Checks if the current instance is equal to obj
+ *
+ * @param obj The object to compare with
+ *
+ * @return <code>true</code> if equal, <code>false</code> otherwise
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof NetworkInterface))
+ return false;
+
+ NetworkInterface tmp = (NetworkInterface) obj;
+
+ return (name.equals(tmp.name) && inetAddresses.equals(tmp.inetAddresses));
+ }
+
+ /**
+ * Returns the hashcode of the current instance
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // FIXME: hash correctly
+ return name.hashCode() + inetAddresses.hashCode();
+ }
+
+ /**
+ * Returns a string representation of the interface
+ *
+ * @return the string
+ */
+ public String toString()
+ {
+ // FIXME: check if this is correct
+ String result;
+ String separator = System.getProperty("line.separator");
+
+ result =
+ "name: " + getDisplayName() + " (" + getName() + ") addresses:"
+ + separator;
+
+ for (Enumeration e = inetAddresses.elements(); e.hasMoreElements();)
+ {
+ InetAddress address = (InetAddress) e.nextElement();
+ result += address.toString() + ";" + separator;
+ }
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/java/net/NoRouteToHostException.java b/libjava/classpath/java/net/NoRouteToHostException.java
new file mode 100644
index 00000000000..48c3a8e604e
--- /dev/null
+++ b/libjava/classpath/java/net/NoRouteToHostException.java
@@ -0,0 +1,74 @@
+/* NoRouteToHostException.java -- Cannot connect to a host
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception indicates that there is no TCP/IP route to the requested
+ * host. This is often due to a misconfigured routing table.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class NoRouteToHostException extends SocketException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -1897550894873493790L;
+
+ /**
+ * Create an instance without a descriptive error message.
+ */
+ public NoRouteToHostException()
+ {
+ }
+
+ /**
+ * Create an instance with a descriptive error message, such as the text
+ * from strerror(3).
+ *
+ * @param message a message describing the error that occurred
+ */
+ public NoRouteToHostException(String message)
+ {
+ super(message);
+ }
+} // class NoRouteToHostException
diff --git a/libjava/classpath/java/net/PasswordAuthentication.java b/libjava/classpath/java/net/PasswordAuthentication.java
new file mode 100644
index 00000000000..1d4ec89611d
--- /dev/null
+++ b/libjava/classpath/java/net/PasswordAuthentication.java
@@ -0,0 +1,92 @@
+/* PasswordAuthentication.java -- Container class for username/password pairs
+ Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This class serves a container for username/password pairs.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ *
+ * @since 1.2
+ */
+public final class PasswordAuthentication
+{
+ /**
+ * The username
+ */
+ private String username;
+
+ /**
+ * The password
+ */
+ private char[] password;
+
+ /**
+ * Creates a new <code>PasswordAuthentication</code> object from the
+ * specified username and password.
+ *
+ * @param username The username for this object
+ * @param password The password for this object
+ */
+ public PasswordAuthentication(String username, char[] password)
+ {
+ this.username = username;
+ this.password = password;
+ }
+
+ /**
+ * Returns the username associated with this object
+ *
+ * @return The username
+ */
+ public String getUserName()
+ {
+ return username;
+ }
+
+ /**
+ * Returns the password associated with this object
+ *
+ * @return The password
+ */
+ public char[] getPassword()
+ {
+ return password;
+ }
+}
diff --git a/libjava/classpath/java/net/PortUnreachableException.java b/libjava/classpath/java/net/PortUnreachableException.java
new file mode 100644
index 00000000000..49a8c9ea103
--- /dev/null
+++ b/libjava/classpath/java/net/PortUnreachableException.java
@@ -0,0 +1,72 @@
+/* PortUnreachableException.java -- received an ICMP port unreachable datagram
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception signals that an ICMP port unreachable datagram has been
+ * received.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class PortUnreachableException extends SocketException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 8462541992376507323L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public PortUnreachableException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public PortUnreachableException(String message)
+ {
+ super(message);
+ }
+} // class PortUnreachableException
diff --git a/libjava/classpath/java/net/ProtocolException.java b/libjava/classpath/java/net/ProtocolException.java
new file mode 100644
index 00000000000..27718a9793d
--- /dev/null
+++ b/libjava/classpath/java/net/ProtocolException.java
@@ -0,0 +1,75 @@
+/* ProtocolException.java -- a low level protocol error occurred
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * This exception indicates that some sort of low level protocol
+ * exception occurred. Look in the descriptive message (if any) for
+ * details on what went wrong.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class ProtocolException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -6098449442062388080L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public ProtocolException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public ProtocolException(String message)
+ {
+ super(message);
+ }
+} // class ProtocolException
diff --git a/libjava/classpath/java/net/STATUS b/libjava/classpath/java/net/STATUS
new file mode 100644
index 00000000000..25dff963e06
--- /dev/null
+++ b/libjava/classpath/java/net/STATUS
@@ -0,0 +1,48 @@
+X ContentHandlerFactory
+X FileNameMap
+X SocketImplFactory
+X URLStreamHandlerFactory
+* Authenticator
+* ContentHandler
++ DatagramPacket
++ DatagramSocket
++ DatagramSocketImpl
++ HttpURLConnection
++ InetAddress
+* JarURLConnection
++ MulticastSocket
+* NetPermission
+* PasswordAuthentication
++ PlainDatagramSocketImpl
++ PlainSocketImpl (internal)
++ ServerSocket
++ Socket
++ SocketImpl
++ SocketInputStream (internal)
++ SocketOptions (internal)
++ SocketOutputStream (internal)
+* SocketPermission
++ URL
+ URLClassLoader
++ URLConnection
+* URLEncoder
++ URLStreamHandler
+X BindException
+X ConnectException
+X MalformedURLException
+X NoRouteToHostException
+X ProtocolException
+X SocketException
+X UnknownHostException
+X UnknownServiceException
+
+---------------
++ Native InetAddress
++ Native SocketImpl
++ Native DatagramSocketImpl
++ Protocol Handler for HTTP
+ Protocol Handler for FTP
++ ContentHandler for text
+ ContentHandler for gif
+ ContentHandler for jpeg
+
diff --git a/libjava/classpath/java/net/ServerSocket.java b/libjava/classpath/java/net/ServerSocket.java
new file mode 100644
index 00000000000..f73c7482aa5
--- /dev/null
+++ b/libjava/classpath/java/net/ServerSocket.java
@@ -0,0 +1,599 @@
+/* ServerSocket.java -- Class for implementing server side sockets
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.net.PlainSocketImpl;
+
+import java.io.IOException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.ServerSocketChannel;
+
+
+/* Written using on-line Java Platform 1.2 API Specification.
+ * Status: I believe all methods are implemented.
+ */
+
+/**
+ * This class models server side sockets. The basic model is that the
+ * server socket is created and bound to some well known port. It then
+ * listens for and accepts connections. At that point the client and
+ * server sockets are ready to communicate with one another utilizing
+ * whatever application layer protocol they desire.
+ *
+ * As with the <code>Socket</code> class, most instance methods of this class
+ * simply redirect their calls to an implementation class.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public class ServerSocket
+{
+ /**
+ * This is the user defined SocketImplFactory, if one is supplied
+ */
+ private static SocketImplFactory factory;
+
+ /**
+ * This is the SocketImp object to which most instance methods in this
+ * class are redirected
+ */
+ private SocketImpl impl;
+
+ /**
+ * We need to retain the local address even after the socket is closed.
+ */
+ private InetSocketAddress local;
+
+ /*
+ * This constructor is only used by java.nio.
+ */
+
+ // FIXME: Workaround a bug in gcj.
+ //ServerSocket (PlainSocketImpl impl) throws IOException
+ ServerSocket(SocketImpl impl) throws IOException
+ {
+ if (impl == null)
+ throw new NullPointerException("impl may not be null");
+
+ this.impl = impl;
+ this.impl.create(true);
+ }
+
+ /*
+ * This method is only used by java.nio.
+ */
+
+ // FIXME: Workaround a bug in gcj.
+ //PlainSocketImpl getImpl()
+ SocketImpl getImpl()
+ {
+ return impl;
+ }
+
+ /**
+ * Constructor that simply sets the implementation.
+ *
+ * @exception IOException If an error occurs
+ *
+ * @specnote This constructor is public since JDK 1.4
+ */
+ public ServerSocket() throws IOException
+ {
+ if (factory != null)
+ impl = factory.createSocketImpl();
+ else
+ impl = new PlainSocketImpl();
+
+ impl.create(true);
+ }
+
+ /**
+ * Creates a server socket and binds it to the specified port. If the
+ * port number is 0, a random free port will be chosen. The pending
+ * connection queue on this socket will be set to 50.
+ *
+ * @param port The port number to bind to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ */
+ public ServerSocket(int port) throws IOException
+ {
+ this(port, 50);
+ }
+
+ /**
+ * Creates a server socket and binds it to the specified port. If the
+ * port number is 0, a random free port will be chosen. The pending
+ * connection queue on this socket will be set to the value passed as
+ * arg2.
+ *
+ * @param port The port number to bind to
+ * @param backlog The length of the pending connection queue
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ */
+ public ServerSocket(int port, int backlog) throws IOException
+ {
+ this(port, backlog, null);
+ }
+
+ /**
+ * Creates a server socket and binds it to the specified port. If the
+ * port number is 0, a random free port will be chosen. The pending
+ * connection queue on this socket will be set to the value passed as
+ * backlog. The third argument specifies a particular local address to
+ * bind t or null to bind to all local address.
+ *
+ * @param port The port number to bind to
+ * @param backlog The length of the pending connection queue
+ * @param bindAddr The address to bind to, or null to bind to all addresses
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ *
+ * @since 1.1
+ */
+ public ServerSocket(int port, int backlog, InetAddress bindAddr)
+ throws IOException
+ {
+ this();
+
+ // bind/listen socket
+ bind(new InetSocketAddress(bindAddr, port), backlog);
+ }
+
+ /**
+ * Binds the server socket to a specified socket address
+ *
+ * @param endpoint The socket address to bind to
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ *
+ * @since 1.4
+ */
+ public void bind(SocketAddress endpoint) throws IOException
+ {
+ bind(endpoint, 50);
+ }
+
+ /**
+ * Binds the server socket to a specified socket address
+ *
+ * @param endpoint The socket address to bind to
+ * @param backlog The length of the pending connection queue
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If address type is not supported
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ *
+ * @since 1.4
+ */
+ public void bind(SocketAddress endpoint, int backlog)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ if (! (endpoint instanceof InetSocketAddress))
+ throw new IllegalArgumentException("Address type not supported");
+
+ InetSocketAddress tmp = (InetSocketAddress) endpoint;
+
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkListen(tmp.getPort());
+
+ InetAddress addr = tmp.getAddress();
+
+ // Initialize addr with 0.0.0.0.
+ if (addr == null)
+ addr = InetAddress.ANY_IF;
+
+ try
+ {
+ impl.bind(addr, tmp.getPort());
+ impl.listen(backlog);
+ local = new InetSocketAddress(
+ (InetAddress) impl.getOption(SocketOptions.SO_BINDADDR),
+ impl.getLocalPort());
+ }
+ catch (IOException exception)
+ {
+ close();
+ throw exception;
+ }
+ catch (RuntimeException exception)
+ {
+ close();
+ throw exception;
+ }
+ catch (Error error)
+ {
+ close();
+ throw error;
+ }
+ }
+
+ /**
+ * This method returns the local address to which this socket is bound
+ *
+ * @return The socket's local address
+ */
+ public InetAddress getInetAddress()
+ {
+ if (local == null)
+ return null;
+
+ return local.getAddress();
+ }
+
+ /**
+ * This method returns the local port number to which this socket is bound
+ *
+ * @return The socket's port number
+ */
+ public int getLocalPort()
+ {
+ if (local == null)
+ return -1;
+
+ return local.getPort();
+ }
+
+ /**
+ * Returns the local socket address
+ *
+ * @return the local socket address, null if not bound
+ *
+ * @since 1.4
+ */
+ public SocketAddress getLocalSocketAddress()
+ {
+ return local;
+ }
+
+ /**
+ * Accepts a new connection and returns a connected <code>Socket</code>
+ * instance representing that connection. This method will block until a
+ * connection is available.
+ *
+ * @return socket object for the just accepted connection
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkListen method doesn't allow the operation
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode
+ * @exception SocketTimeoutException If a timeout was previously set with
+ * setSoTimeout and the timeout has been reached
+ */
+ public Socket accept() throws IOException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkListen(impl.getLocalPort());
+
+ Socket socket = new Socket();
+
+ try
+ {
+ implAccept(socket);
+ }
+ catch (IOException e)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException e2)
+ {
+ // Ignore.
+ }
+
+ throw e;
+ }
+
+ return socket;
+ }
+
+ /**
+ * This protected method is used to help subclasses override
+ * <code>ServerSocket.accept()</code>. The passed in socket will be
+ * connected when this method returns.
+ *
+ * @param socket The socket that is used for the accepted connection
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode
+ *
+ * @since 1.1
+ */
+ protected final void implAccept(Socket socket) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ // The Sun spec says that if we have an associated channel and
+ // it is in non-blocking mode, we throw an IllegalBlockingModeException.
+ // However, in our implementation if the channel itself initiated this
+ // operation, then we must honor it regardless of its blocking mode.
+ if (getChannel() != null && ! getChannel().isBlocking()
+ && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
+ throw new IllegalBlockingModeException();
+
+ impl.accept(socket.impl);
+ socket.implCreated = true;
+ }
+
+ /**
+ * Closes this socket and stops listening for connections
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ if (isClosed())
+ return;
+
+ impl.close();
+ impl = null;
+
+ if (getChannel() != null)
+ getChannel().close();
+ }
+
+ /**
+ * Returns the unique <code>ServerSocketChannel</code> object
+ * associated with this socket, if any.
+ *
+ * <p>The socket only has a <code>ServerSocketChannel</code> if its created
+ * by <code>ServerSocketChannel.open()</code>.</p>
+ *
+ * @return the associated socket channel, null if none exists
+ *
+ * @since 1.4
+ */
+ public ServerSocketChannel getChannel()
+ {
+ return null;
+ }
+
+ /**
+ * Returns true when the socket is bound, otherwise false
+ *
+ * @return true if socket is bound, false otherwise
+ *
+ * @since 1.4
+ */
+ public boolean isBound()
+ {
+ return local != null;
+ }
+
+ /**
+ * Returns true if the socket is closed, otherwise false
+ *
+ * @return true if socket is closed, false otherwise
+ *
+ * @since 1.4
+ */
+ public boolean isClosed()
+ {
+ return impl == null;
+ }
+
+ /**
+ * Sets the value of SO_TIMEOUT. A value of 0 implies that SO_TIMEOUT is
+ * disabled (ie, operations never time out). This is the number of
+ * milliseconds a socket operation can block before an
+ * InterruptedIOException is thrown.
+ *
+ * @param timeout The new SO_TIMEOUT value
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.1
+ */
+ public void setSoTimeout(int timeout) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ if (timeout < 0)
+ throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
+
+ impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
+ }
+
+ /**
+ * Retrieves the current value of the SO_TIMEOUT setting. A value of 0
+ * implies that SO_TIMEOUT is disabled (ie, operations never time out).
+ * This is the number of milliseconds a socket operation can block before
+ * an InterruptedIOException is thrown.
+ *
+ * @return The value of SO_TIMEOUT
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.1
+ */
+ public int getSoTimeout() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
+
+ if (! (timeout instanceof Integer))
+ throw new IOException("Internal Error");
+
+ return ((Integer) timeout).intValue();
+ }
+
+ /**
+ * Enables/Disables the SO_REUSEADDR option
+ *
+ * @param on true if SO_REUSEADDR should be enabled, false otherwise
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setReuseAddress(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
+ }
+
+ /**
+ * Checks if the SO_REUSEADDR option is enabled
+ *
+ * @return true if SO_REUSEADDR is set, false otherwise
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getReuseAddress() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ Object reuseaddr = impl.getOption(SocketOptions.SO_REUSEADDR);
+
+ if (! (reuseaddr instanceof Boolean))
+ throw new SocketException("Internal Error");
+
+ return ((Boolean) reuseaddr).booleanValue();
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_RCVBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new receive buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ * @exception IllegalArgumentException If size is 0 or negative
+ *
+ * @since 1.4
+ */
+ public void setReceiveBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ if (size <= 0)
+ throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
+
+ impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_RCVBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The receive buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.4
+ */
+ public int getReceiveBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("ServerSocket is closed");
+
+ Object buf = impl.getOption(SocketOptions.SO_RCVBUF);
+
+ if (! (buf instanceof Integer))
+ throw new SocketException("Internal Error: Unexpected type");
+
+ return ((Integer) buf).intValue();
+ }
+
+ /**
+ * Returns the value of this socket as a <code>String</code>.
+ *
+ * @return This socket represented as a <code>String</code>.
+ */
+ public String toString()
+ {
+ if (! isBound())
+ return "ServerSocket[unbound]";
+
+ return ("ServerSocket[addr=" + getInetAddress() + ",port="
+ + impl.getPort() + ",localport=" + impl.getLocalPort() + "]");
+ }
+
+ /**
+ * Sets the <code>SocketImplFactory</code> for all
+ * <code>ServerSocket</code>'s. This may only be done
+ * once per virtual machine. Subsequent attempts will generate an
+ * exception. Note that a <code>SecurityManager</code> check is made prior
+ * to setting the factory. If insufficient privileges exist to set the
+ * factory, an exception will be thrown
+ *
+ * @param fac the factory to set
+ *
+ * @exception SecurityException If this operation is not allowed by the
+ * <code>SecurityManager</code>.
+ * @exception SocketException If the factory object is already defined
+ * @exception IOException If any other error occurs
+ */
+ public static synchronized void setSocketFactory(SocketImplFactory fac)
+ throws IOException
+ {
+ factory = fac;
+ }
+}
diff --git a/libjava/classpath/java/net/Socket.java b/libjava/classpath/java/net/Socket.java
new file mode 100644
index 00000000000..9432a6be1d8
--- /dev/null
+++ b/libjava/classpath/java/net/Socket.java
@@ -0,0 +1,1284 @@
+/* Socket.java -- Client socket implementation
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.net.PlainSocketImpl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SocketChannel;
+
+
+/* Written using on-line Java Platform 1.2 API Specification.
+ * Status: I believe all methods are implemented.
+ */
+
+/**
+ * This class models a client site socket. A socket is a TCP/IP endpoint
+ * for network communications conceptually similar to a file handle.
+ * <p>
+ * This class does not actually do any work. Instead, it redirects all of
+ * its calls to a socket implementation object which implements the
+ * <code>SocketImpl</code> interface. The implementation class is
+ * instantiated by factory class that implements the
+ * <code>SocketImplFactory interface</code>. A default
+ * factory is provided, however the factory may be set by a call to
+ * the <code>setSocketImplFactory</code> method. Note that this may only be
+ * done once per virtual machine. If a subsequent attempt is made to set the
+ * factory, a <code>SocketException</code> will be thrown.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public class Socket
+{
+ /**
+ * This is the user SocketImplFactory for this class. If this variable is
+ * null, a default factory is used.
+ */
+ static SocketImplFactory factory;
+
+ /**
+ * The implementation object to which calls are redirected
+ */
+ // package-private because ServerSocket.implAccept() needs to access it.
+ SocketImpl impl;
+
+ /**
+ * True if socket implementation was created by calling their
+ * create() method.
+ */
+ // package-private because ServerSocket.implAccept() needs to access it.
+ boolean implCreated;
+
+ /**
+ * True if the socket is bound.
+ */
+ private boolean bound;
+
+ /**
+ * True if input is shutdown.
+ */
+ private boolean inputShutdown;
+
+ /**
+ * True if output is shutdown.
+ */
+ private boolean outputShutdown;
+
+ /**
+ * Initializes a new instance of <code>Socket</code> object without
+ * connecting to a remote host. This useful for subclasses of socket that
+ * might want this behavior.
+ *
+ * @specnote This constructor is public since JDK 1.4
+ * @since 1.1
+ */
+ public Socket()
+ {
+ if (factory != null)
+ impl = factory.createSocketImpl();
+ else
+ impl = new PlainSocketImpl();
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> object without
+ * connecting to a remote host. This is useful for subclasses of socket
+ * that might want this behavior.
+ * <p>
+ * Additionally, this socket will be created using the supplied
+ * implementation class instead the default class or one returned by a
+ * factory. If this value is <code>null</code>, the default Socket
+ * implementation is used.
+ *
+ * @param impl The <code>SocketImpl</code> to use for this
+ * <code>Socket</code>
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.1
+ */
+ protected Socket(SocketImpl impl) throws SocketException
+ {
+ if (impl == null)
+ this.impl = new PlainSocketImpl();
+ else
+ this.impl = impl;
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * hostname and port specified as arguments.
+ *
+ * @param host The name of the host to connect to
+ * @param port The port number to connect to
+ *
+ * @exception UnknownHostException If the hostname cannot be resolved to a
+ * network address.
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ public Socket(String host, int port)
+ throws UnknownHostException, IOException
+ {
+ this(InetAddress.getByName(host), port, null, 0, true);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * address and port number specified as arguments.
+ *
+ * @param address The address to connect to
+ * @param port The port number to connect to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ public Socket(InetAddress address, int port) throws IOException
+ {
+ this(address, port, null, 0, true);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> that connects to the
+ * named host on the specified port and binds to the specified local address
+ * and port.
+ *
+ * @param host The name of the remote host to connect to.
+ * @param port The remote port to connect to.
+ * @param localAddr The local address to bind to.
+ * @param localPort The local port to bind to.
+ *
+ * @exception SecurityException If the <code>SecurityManager</code>
+ * exists and does not allow a connection to the specified host/port or
+ * binding to the specified local host/port.
+ * @exception IOException If a connection error occurs.
+ *
+ * @since 1.1
+ */
+ public Socket(String host, int port, InetAddress localAddr, int localPort)
+ throws IOException
+ {
+ this(InetAddress.getByName(host), port, localAddr, localPort, true);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * address and port number specified as arguments, plus binds to the
+ * specified local address and port.
+ *
+ * @param address The remote address to connect to
+ * @param port The remote port to connect to
+ * @param localAddr The local address to connect to
+ * @param localPort The local port to connect to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ *
+ * @since 1.1
+ */
+ public Socket(InetAddress address, int port, InetAddress localAddr,
+ int localPort) throws IOException
+ {
+ this(address, port, localAddr, localPort, true);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * hostname and port specified as arguments. If the stream argument is set
+ * to <code>true</code>, then a stream socket is created. If it is
+ * <code>false</code>, a datagram socket is created.
+ *
+ * @param host The name of the host to connect to
+ * @param port The port to connect to
+ * @param stream <code>true</code> for a stream socket, <code>false</code>
+ * for a datagram socket
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ *
+ * @deprecated Use the <code>DatagramSocket</code> class to create
+ * datagram oriented sockets.
+ */
+ public Socket(String host, int port, boolean stream)
+ throws IOException
+ {
+ this(InetAddress.getByName(host), port, null, 0, stream);
+ }
+
+ /**
+ * Initializes a new instance of <code>Socket</code> and connects to the
+ * address and port number specified as arguments. If the stream param is
+ * <code>true</code>, a stream socket will be created, otherwise a datagram
+ * socket is created.
+ *
+ * @param host The address to connect to
+ * @param port The port number to connect to
+ * @param stream <code>true</code> to create a stream socket,
+ * <code>false</code> to create a datagram socket.
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ *
+ * @deprecated Use the <code>DatagramSocket</code> class to create
+ * datagram oriented sockets.
+ */
+ public Socket(InetAddress host, int port, boolean stream)
+ throws IOException
+ {
+ this(host, port, null, 0, stream);
+ }
+
+ /**
+ * This constructor is where the real work takes place. Connect to the
+ * specified address and port. Use default local values if not specified,
+ * otherwise use the local host and port passed in. Create as stream or
+ * datagram based on "stream" argument.
+ * <p>
+ *
+ * @param raddr The remote address to connect to
+ * @param rport The remote port to connect to
+ * @param laddr The local address to connect to
+ * @param lport The local port to connect to
+ * @param stream true for a stream socket, false for a datagram socket
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ */
+ private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport,
+ boolean stream) throws IOException
+ {
+ this();
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkConnect(raddr.getHostName(), rport);
+
+ // bind socket
+ SocketAddress bindaddr =
+ laddr == null ? null : new InetSocketAddress(laddr, lport);
+ bind(bindaddr);
+
+ // connect socket
+ connect(new InetSocketAddress(raddr, rport));
+
+ // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
+ // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
+ // that default. JDK 1.2 doc infers not to do a bind.
+ }
+
+ private SocketImpl getImpl() throws SocketException
+ {
+ try
+ {
+ if (! implCreated)
+ {
+ impl.create(true);
+ implCreated = true;
+ }
+ }
+ catch (IOException e)
+ {
+ throw new SocketException(e.getMessage());
+ }
+
+ return impl;
+ }
+
+ /**
+ * Binds the socket to the givent local address/port
+ *
+ * @param bindpoint The address/port to bind to
+ *
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager exists and its
+ * checkConnect method doesn't allow the operation
+ * @exception IllegalArgumentException If the address type is not supported
+ *
+ * @since 1.4
+ */
+ public void bind(SocketAddress bindpoint) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ // XXX: JDK 1.4.1 API documentation says that if bindpoint is null the
+ // socket will be bound to an ephemeral port and a valid local address.
+ if (bindpoint == null)
+ bindpoint = new InetSocketAddress(InetAddress.ANY_IF, 0);
+
+ if (! (bindpoint instanceof InetSocketAddress))
+ throw new IllegalArgumentException();
+
+ InetSocketAddress tmp = (InetSocketAddress) bindpoint;
+
+ // bind to address/port
+ try
+ {
+ getImpl().bind(tmp.getAddress(), tmp.getPort());
+ bound = true;
+ }
+ catch (IOException exception)
+ {
+ close();
+ throw exception;
+ }
+ catch (RuntimeException exception)
+ {
+ close();
+ throw exception;
+ }
+ catch (Error error)
+ {
+ close();
+ throw error;
+ }
+ }
+
+ /**
+ * Connects the socket with a remote address.
+ *
+ * @param endpoint The address to connect to
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If the addess type is not supported
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode
+ *
+ * @since 1.4
+ */
+ public void connect(SocketAddress endpoint) throws IOException
+ {
+ connect(endpoint, 0);
+ }
+
+ /**
+ * Connects the socket with a remote address. A timeout of zero is
+ * interpreted as an infinite timeout. The connection will then block
+ * until established or an error occurs.
+ *
+ * @param endpoint The address to connect to
+ * @param timeout The length of the timeout in milliseconds, or
+ * 0 to indicate no timeout.
+ *
+ * @exception IOException If an error occurs
+ * @exception IllegalArgumentException If the address type is not supported
+ * @exception IllegalBlockingModeException If this socket has an associated
+ * channel, and the channel is in non-blocking mode
+ * @exception SocketTimeoutException If the timeout is reached
+ *
+ * @since 1.4
+ */
+ public void connect(SocketAddress endpoint, int timeout)
+ throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! (endpoint instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+
+ // The Sun spec says that if we have an associated channel and
+ // it is in non-blocking mode, we throw an IllegalBlockingModeException.
+ // However, in our implementation if the channel itself initiated this
+ // operation, then we must honor it regardless of its blocking mode.
+ if (getChannel() != null && ! getChannel().isBlocking()
+ && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
+ throw new IllegalBlockingModeException();
+
+ if (! isBound())
+ bind(null);
+
+ try
+ {
+ getImpl().connect(endpoint, timeout);
+ }
+ catch (IOException exception)
+ {
+ close();
+ throw exception;
+ }
+ catch (RuntimeException exception)
+ {
+ close();
+ throw exception;
+ }
+ catch (Error error)
+ {
+ close();
+ throw error;
+ }
+ }
+
+ /**
+ * Returns the address of the remote end of the socket. If this socket
+ * is not connected, then <code>null</code> is returned.
+ *
+ * @return The remote address this socket is connected to
+ */
+ public InetAddress getInetAddress()
+ {
+ if (! isConnected())
+ return null;
+
+ try
+ {
+ return getImpl().getInetAddress();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the local address to which this socket is bound. If this socket
+ * is not connected, then a wildcard address, for which
+ * @see isAnyLocalAddress() is <code>true</code>, is returned.
+ *
+ * @return The local address
+ *
+ * @since 1.1
+ */
+ public InetAddress getLocalAddress()
+ {
+ if (! isBound())
+ return InetAddress.ANY_IF;
+
+ InetAddress addr = null;
+
+ try
+ {
+ addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
+ }
+ catch (SocketException e)
+ {
+ // (hopefully) shouldn't happen
+ // throw new java.lang.InternalError
+ // ("Error in PlainSocketImpl.getOption");
+ return null;
+ }
+
+ // FIXME: According to libgcj, checkConnect() is supposed to be called
+ // before performing this operation. Problems: 1) We don't have the
+ // addr until after we do it, so we do a post check. 2). The docs I
+ // see don't require this in the Socket case, only DatagramSocket, but
+ // we'll assume they mean both.
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkConnect(addr.getHostName(), getLocalPort());
+
+ return addr;
+ }
+
+ /**
+ * Returns the port number of the remote end of the socket connection. If
+ * this socket is not connected, then 0 is returned.
+ *
+ * @return The remote port this socket is connected to
+ */
+ public int getPort()
+ {
+ if (! isConnected())
+ return 0;
+
+ try
+ {
+ return getImpl().getPort();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns the local port number to which this socket is bound. If this
+ * socket is not connected, then -1 is returned.
+ *
+ * @return The local port
+ */
+ public int getLocalPort()
+ {
+ if (! isBound())
+ return -1;
+
+ try
+ {
+ if (getImpl() != null)
+ return getImpl().getLocalPort();
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are bound.
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns local socket address.
+ *
+ * @return the local socket address, null if not bound
+ *
+ * @since 1.4
+ */
+ public SocketAddress getLocalSocketAddress()
+ {
+ if (! isBound())
+ return null;
+
+ InetAddress addr = getLocalAddress();
+
+ try
+ {
+ return new InetSocketAddress(addr, getImpl().getLocalPort());
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are bound.
+ return null;
+ }
+ }
+
+ /**
+ * Returns the remote socket address.
+ *
+ * @return the remote socket address, null of not connected
+ *
+ * @since 1.4
+ */
+ public SocketAddress getRemoteSocketAddress()
+ {
+ if (! isConnected())
+ return null;
+
+ try
+ {
+ return new InetSocketAddress(getImpl().getInetAddress(),
+ getImpl().getPort());
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ return null;
+ }
+ }
+
+ /**
+ * Returns an InputStream for reading from this socket.
+ *
+ * @return The InputStream object
+ *
+ * @exception IOException If an error occurs or Socket is not connected
+ */
+ public InputStream getInputStream() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! isConnected())
+ throw new IOException("not connected");
+
+ return getImpl().getInputStream();
+ }
+
+ /**
+ * Returns an OutputStream for writing to this socket.
+ *
+ * @return The OutputStream object
+ *
+ * @exception IOException If an error occurs or Socket is not connected
+ */
+ public OutputStream getOutputStream() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (! isConnected())
+ throw new IOException("not connected");
+
+ return getImpl().getOutputStream();
+ }
+
+ /**
+ * Sets the TCP_NODELAY option on the socket.
+ *
+ * @param on true to enable, false to disable
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.1
+ */
+ public void setTcpNoDelay(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
+ }
+
+ /**
+ * Tests whether or not the TCP_NODELAY option is set on the socket.
+ * Returns true if enabled, false if disabled. When on it disables the
+ * Nagle algorithm which means that packets are always send immediatly and
+ * never merged together to reduce network trafic.
+ *
+ * @return Whether or not TCP_NODELAY is set
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ *
+ * @since 1.1
+ */
+ public boolean getTcpNoDelay() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object on = getImpl().getOption(SocketOptions.TCP_NODELAY);
+
+ if (on instanceof Boolean)
+ return (((Boolean) on).booleanValue());
+ else
+ throw new SocketException("Internal Error");
+ }
+
+ /**
+ * Sets the value of the SO_LINGER option on the socket. If the
+ * SO_LINGER option is set on a socket and there is still data waiting to
+ * be sent when the socket is closed, then the close operation will block
+ * until either that data is delivered or until the timeout period
+ * expires. The linger interval is specified in hundreths of a second
+ * (platform specific?)
+ *
+ * @param on true to enable SO_LINGER, false to disable
+ * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
+ * SO_LINGER not set.
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ * @exception IllegalArgumentException If linger is negative
+ *
+ * @since 1.1
+ */
+ public void setSoLinger(boolean on, int linger) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (on)
+ {
+ if (linger < 0)
+ throw new IllegalArgumentException("SO_LINGER must be >= 0");
+
+ if (linger > 65535)
+ linger = 65535;
+
+ getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger));
+ }
+ else
+ getImpl().setOption(SocketOptions.SO_LINGER, Boolean.valueOf(false));
+ }
+
+ /**
+ * Returns the value of the SO_LINGER option on the socket. If the
+ * SO_LINGER option is set on a socket and there is still data waiting to
+ * be sent when the socket is closed, then the close operation will block
+ * until either that data is delivered or until the timeout period
+ * expires. This method either returns the timeouts (in hundredths of
+ * of a second (platform specific?)) if SO_LINGER is set, or -1 if
+ * SO_LINGER is not set.
+ *
+ * @return The SO_LINGER timeout in hundreths of a second or -1
+ * if SO_LINGER not set
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.1
+ */
+ public int getSoLinger() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object linger = getImpl().getOption(SocketOptions.SO_LINGER);
+
+ if (linger instanceof Integer)
+ return (((Integer) linger).intValue());
+ else
+ return -1;
+ }
+
+ /**
+ * Sends urgent data through the socket
+ *
+ * @param data The data to send.
+ * Only the lowest eight bits of data are sent
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void sendUrgentData(int data) throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().sendUrgentData(data);
+ }
+
+ /**
+ * Enables/disables the SO_OOBINLINE option
+ *
+ * @param on True if SO_OOBLINE should be enabled
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setOOBInline(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
+ }
+
+ /**
+ * Returns the current setting of the SO_OOBINLINE option for this socket
+ *
+ * @return True if SO_OOBINLINE is set, false otherwise.
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getOOBInline() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE);
+
+ if (buf instanceof Boolean)
+ return (((Boolean) buf).booleanValue());
+ else
+ throw new SocketException("Internal Error: Unexpected type");
+ }
+
+ /**
+ * Sets the value of the SO_TIMEOUT option on the socket. If this value
+ * is set, and an read/write is performed that does not complete within
+ * the timeout period, a short count is returned (or an EWOULDBLOCK signal
+ * would be sent in Unix if no data had been read). A value of 0 for
+ * this option implies that there is no timeout (ie, operations will
+ * block forever). On systems that have separate read and write timeout
+ * values, this method returns the read timeout. This
+ * value is in milliseconds.
+ *
+ * @param timeout The length of the timeout in milliseconds, or
+ * 0 to indicate no timeout.
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ *
+ * @since 1.1
+ */
+ public synchronized void setSoTimeout(int timeout) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (timeout < 0)
+ throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
+
+ getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
+ }
+
+ /**
+ * Returns the value of the SO_TIMEOUT option on the socket. If this value
+ * is set, and an read/write is performed that does not complete within
+ * the timeout period, a short count is returned (or an EWOULDBLOCK signal
+ * would be sent in Unix if no data had been read). A value of 0 for
+ * this option implies that there is no timeout (ie, operations will
+ * block forever). On systems that have separate read and write timeout
+ * values, this method returns the read timeout. This
+ * value is in thousandths of a second (implementation specific?).
+ *
+ * @return The length of the timeout in thousandth's of a second or 0
+ * if not set
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ *
+ * @since 1.1
+ */
+ public synchronized int getSoTimeout() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT);
+ if (timeout instanceof Integer)
+ return (((Integer) timeout).intValue());
+ else
+ return 0;
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_SNDBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new send buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket not connected
+ * @exception IllegalArgumentException If size is 0 or negative
+ *
+ * @since 1.2
+ */
+ public void setSendBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (size <= 0)
+ throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
+
+ getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_SNDBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The send buffer size.
+ *
+ * @exception SocketException If an error occurs or socket not connected
+ *
+ * @since 1.2
+ */
+ public int getSendBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
+
+ if (buf instanceof Integer)
+ return (((Integer) buf).intValue());
+ else
+ throw new SocketException("Internal Error: Unexpected type");
+ }
+
+ /**
+ * This method sets the value for the system level socket option
+ * SO_RCVBUF to the specified value. Note that valid values for this
+ * option are specific to a given operating system.
+ *
+ * @param size The new receive buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ * @exception IllegalArgumentException If size is 0 or negative
+ *
+ * @since 1.2
+ */
+ public void setReceiveBufferSize(int size) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (size <= 0)
+ throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
+
+ getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
+ }
+
+ /**
+ * This method returns the value of the system level socket option
+ * SO_RCVBUF, which is used by the operating system to tune buffer
+ * sizes for data transfers.
+ *
+ * @return The receive buffer size.
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.2
+ */
+ public int getReceiveBufferSize() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
+
+ if (buf instanceof Integer)
+ return (((Integer) buf).intValue());
+ else
+ throw new SocketException("Internal Error: Unexpected type");
+ }
+
+ /**
+ * This method sets the value for the socket level socket option
+ * SO_KEEPALIVE.
+ *
+ * @param on True if SO_KEEPALIVE should be enabled
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.3
+ */
+ public void setKeepAlive(boolean on) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
+ }
+
+ /**
+ * This method returns the value of the socket level socket option
+ * SO_KEEPALIVE.
+ *
+ * @return The setting
+ *
+ * @exception SocketException If an error occurs or Socket is not connected
+ *
+ * @since 1.3
+ */
+ public boolean getKeepAlive() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE);
+
+ if (buf instanceof Boolean)
+ return (((Boolean) buf).booleanValue());
+ else
+ throw new SocketException("Internal Error: Unexpected type");
+ }
+
+ /**
+ * Closes the socket.
+ *
+ * @exception IOException If an error occurs
+ */
+ public synchronized void close() throws IOException
+ {
+ if (isClosed())
+ return;
+
+ getImpl().close();
+ impl = null;
+ bound = false;
+
+ if (getChannel() != null)
+ getChannel().close();
+ }
+
+ /**
+ * Converts this <code>Socket</code> to a <code>String</code>.
+ *
+ * @return The <code>String</code> representation of this <code>Socket</code>
+ */
+ public String toString()
+ {
+ try
+ {
+ if (isConnected())
+ return ("Socket[addr=" + getImpl().getInetAddress() + ",port="
+ + getImpl().getPort() + ",localport="
+ + getImpl().getLocalPort() + "]");
+ }
+ catch (SocketException e)
+ {
+ // This cannot happen as we are connected.
+ }
+
+ return "Socket[unconnected]";
+ }
+
+ /**
+ * Sets the <code>SocketImplFactory</code>. This may be done only once per
+ * virtual machine. Subsequent attempts will generate a
+ * <code>SocketException</code>. Note that a <code>SecurityManager</code>
+ * check is made prior to setting the factory. If
+ * insufficient privileges exist to set the factory, then an
+ * <code>IOException</code> will be thrown.
+ *
+ * @param fac the factory to set
+ *
+ * @exception SecurityException If the <code>SecurityManager</code> does
+ * not allow this operation.
+ * @exception SocketException If the SocketImplFactory is already defined
+ * @exception IOException If any other error occurs
+ */
+ public static synchronized void setSocketImplFactory(SocketImplFactory fac)
+ throws IOException
+ {
+ // See if already set
+ if (factory != null)
+ throw new SocketException("SocketImplFactory already defined");
+
+ // Check permissions
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSetFactory();
+
+ if (fac == null)
+ throw new SocketException("SocketImplFactory cannot be null");
+
+ factory = fac;
+ }
+
+ /**
+ * Closes the input side of the socket stream.
+ *
+ * @exception IOException If an error occurs.
+ *
+ * @since 1.3
+ */
+ public void shutdownInput() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().shutdownInput();
+ inputShutdown = true;
+ }
+
+ /**
+ * Closes the output side of the socket stream.
+ *
+ * @exception IOException If an error occurs.
+ *
+ * @since 1.3
+ */
+ public void shutdownOutput() throws IOException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().shutdownOutput();
+ outputShutdown = true;
+ }
+
+ /**
+ * Returns the socket channel associated with this socket.
+ *
+ * @return the associated socket channel,
+ * null if no associated channel exists
+ *
+ * @since 1.4
+ */
+ public SocketChannel getChannel()
+ {
+ return null;
+ }
+
+ /**
+ * Checks if the SO_REUSEADDR option is enabled
+ *
+ * @return True if SO_REUSEADDR is set, false otherwise.
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public boolean getReuseAddress() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR);
+
+ if (! (reuseaddr instanceof Boolean))
+ throw new SocketException("Internal Error");
+
+ return ((Boolean) reuseaddr).booleanValue();
+ }
+
+ /**
+ * Enables/Disables the SO_REUSEADDR option
+ *
+ * @param reuseAddress true if SO_REUSEADDR should be enabled,
+ * false otherwise
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @since 1.4
+ */
+ public void setReuseAddress(boolean reuseAddress) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ getImpl().setOption(SocketOptions.SO_REUSEADDR,
+ Boolean.valueOf(reuseAddress));
+ }
+
+ /**
+ * Returns the current traffic class
+ *
+ * @return The current traffic class.
+ *
+ * @exception SocketException If an error occurs
+ *
+ * @see Socket#setTrafficClass(int tc)
+ *
+ * @since 1.4
+ */
+ public int getTrafficClass() throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ Object obj = getImpl().getOption(SocketOptions.IP_TOS);
+
+ if (obj instanceof Integer)
+ return ((Integer) obj).intValue();
+ else
+ throw new SocketException("Unexpected type");
+ }
+
+ /**
+ * Sets the traffic class value
+ *
+ * @param tc The traffic class
+ *
+ * @exception SocketException If an error occurs
+ * @exception IllegalArgumentException If tc value is illegal
+ *
+ * @see Socket#getTrafficClass()
+ *
+ * @since 1.4
+ */
+ public void setTrafficClass(int tc) throws SocketException
+ {
+ if (isClosed())
+ throw new SocketException("socket is closed");
+
+ if (tc < 0 || tc > 255)
+ throw new IllegalArgumentException();
+
+ getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
+ }
+
+ /**
+ * Checks if the socket is connected
+ *
+ * @return True if socket is connected, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isConnected()
+ {
+ try
+ {
+ if (getImpl() == null)
+ return false;
+
+ return getImpl().getInetAddress() != null;
+ }
+ catch (SocketException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Checks if the socket is already bound.
+ *
+ * @return True if socket is bound, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isBound()
+ {
+ return bound;
+ }
+
+ /**
+ * Checks if the socket is closed.
+ *
+ * @return True if socket is closed, false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isClosed()
+ {
+ return impl == null;
+ }
+
+ /**
+ * Checks if the socket's input stream is shutdown
+ *
+ * @return True if input is shut down.
+ *
+ * @since 1.4
+ */
+ public boolean isInputShutdown()
+ {
+ return inputShutdown;
+ }
+
+ /**
+ * Checks if the socket's output stream is shutdown
+ *
+ * @return True if output is shut down.
+ *
+ * @since 1.4
+ */
+ public boolean isOutputShutdown()
+ {
+ return outputShutdown;
+ }
+}
diff --git a/libjava/classpath/java/net/SocketAddress.java b/libjava/classpath/java/net/SocketAddress.java
new file mode 100644
index 00000000000..48ab010097f
--- /dev/null
+++ b/libjava/classpath/java/net/SocketAddress.java
@@ -0,0 +1,63 @@
+/* SocketAddress.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.Serializable;
+
+
+/**
+ * Abstract base class for InetSocketAddress.
+ * InetSocketAddress is to my knowledge the only derived
+ * class. [Ronald]
+ *
+ * @since 1.4
+ */
+public abstract class SocketAddress implements Serializable
+{
+ /**
+ * Compatible with JDK 1.4+
+ */
+ static final long serialVersionUID = 5215720748342549866L;
+
+ /**
+ * Initializes the socket address.
+ */
+ public SocketAddress()
+ {
+ }
+}
diff --git a/libjava/classpath/java/net/SocketException.java b/libjava/classpath/java/net/SocketException.java
new file mode 100644
index 00000000000..37b2f6fba43
--- /dev/null
+++ b/libjava/classpath/java/net/SocketException.java
@@ -0,0 +1,75 @@
+/* SocketException.java -- An exception occurred while performing a socket op
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * This exception indicates that a generic error occurred related to an
+ * operation on a socket. Check the descriptive message (if any) for
+ * details on the nature of this error
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner
+ * @status updated to 1.4
+ */
+public class SocketException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -5935874303556886934L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public SocketException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public SocketException(String message)
+ {
+ super(message);
+ }
+} // class SocketException
diff --git a/libjava/classpath/java/net/SocketImpl.java b/libjava/classpath/java/net/SocketImpl.java
new file mode 100644
index 00000000000..77f470be332
--- /dev/null
+++ b/libjava/classpath/java/net/SocketImpl.java
@@ -0,0 +1,321 @@
+/* SocketImpl.java -- Abstract socket implementation class
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+/* Written using on-line Java Platform 1.2 API Specification.
+ * Believed complete and correct.
+ */
+
+/**
+ * This abstract class serves as the parent class for socket implementations.
+ * The implementation class serves an intermediary to native routines that
+ * perform system specific socket operations.
+ * <p>
+ * A default implementation is provided by the system, but this can be
+ * changed via installing a <code>SocketImplFactory</code> (through a call
+ * to the static method <code>Socket.setSocketImplFactory</code>). A
+ * subclass of <code>Socket</code> can also pass in a <code>SocketImpl</code>
+ * to the <code>Socket(SocketImpl)</code> constructor to use an
+ * implementation different from the system default without installing
+ * a factory.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public abstract class SocketImpl implements SocketOptions
+{
+ /**
+ * The address of the remote end of the socket connection
+ */
+ protected InetAddress address;
+
+ /**
+ * A FileDescriptor object representing this socket connection.
+ */
+ protected FileDescriptor fd;
+
+ /**
+ * The port number the socket is bound to locally
+ */
+ protected int localport = -1;
+
+ /**
+ * The port number of the remote end of the socket connection
+ */
+ protected int port;
+
+ /**
+ * Default, no-argument constructor for use by subclasses.
+ */
+ public SocketImpl()
+ {
+ }
+
+ /**
+ * Creates a new socket that is not bound to any local address/port and
+ * is not connected to any remote address/port. This will be created as
+ * a stream socket if the stream parameter is true, or a datagram socket
+ * if the stream parameter is false.
+ *
+ * @param stream true for a stream socket, false for a datagram socket
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void create(boolean stream) throws IOException;
+
+ /**
+ * Connects to the remote hostname and port specified as arguments.
+ *
+ * @param host The remote hostname to connect to
+ * @param port The remote port to connect to
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void connect(String host, int port)
+ throws IOException;
+
+ /**
+ * Connects to the remote address and port specified as arguments.
+ *
+ * @param host The remote address to connect to
+ * @param port The remote port to connect to
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void connect(InetAddress host, int port)
+ throws IOException;
+
+ /**
+ * Connects to the socket to the host specified in address. This
+ * method blocks until successful connected or the timeout occurs.
+ * A timeout of zero means no timout.
+ *
+ * @param address Data of remote host
+ * @param timeout time to wait to stop connecting
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected abstract void connect(SocketAddress address, int timeout)
+ throws IOException;
+
+ /**
+ * Binds to the specified port on the specified addr. Note that this addr
+ * must represent a local IP address.
+ * <p>
+ * Note that it is unspecified how to bind to all interfaces on the localhost
+ * (INADDR_ANY).
+ *
+ * @param host The address to bind to
+ * @param port The port number to bind to
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void bind(InetAddress host, int port)
+ throws IOException;
+
+ /**
+ * Starts listening for connections on a socket. The backlog parameter
+ * is how many pending connections will queue up waiting to be serviced
+ * before being accept'ed. If the queue of pending requests exceeds this
+ * number, additional connections will be refused.
+ *
+ * @param backlog The length of the pending connection queue
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void listen(int backlog) throws IOException;
+
+ /**
+ * Accepts a connection on this socket.
+ *
+ * @param s The implementation object for the accepted connection.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void accept(SocketImpl s) throws IOException;
+
+ /**
+ * Returns an <code>InputStream</code> object for reading from this socket.
+ *
+ * @return An <code>InputStream</code> for reading from this socket.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract InputStream getInputStream() throws IOException;
+
+ /**
+ * Returns an <code>OutputStream</code> object for writing to this socket
+ *
+ * @return An <code>OutputStream</code> for writing to this socket.
+ *
+ * @exception IOException If an error occurs.
+ */
+ protected abstract OutputStream getOutputStream() throws IOException;
+
+ /**
+ * Returns the number of bytes that the caller can read from this socket
+ * without blocking.
+ *
+ * @return The number of readable bytes before blocking
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract int available() throws IOException;
+
+ /**
+ * Closes the socket. This will normally cause any resources, such as the
+ * InputStream, OutputStream and associated file descriptors to be freed.
+ * <p>
+ * Note that if the SO_LINGER option is set on this socket, then the
+ * operation could block.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void close() throws IOException;
+
+ /**
+ * Returns the FileDescriptor objects for this socket.
+ *
+ * @return A FileDescriptor for this socket.
+ */
+ protected FileDescriptor getFileDescriptor()
+ {
+ return fd;
+ }
+
+ /**
+ * Returns the remote address this socket is connected to
+ *
+ * @return The remote address
+ */
+ protected InetAddress getInetAddress()
+ {
+ return address;
+ }
+
+ /**
+ * Returns the remote port this socket is connected to
+ *
+ * @return The remote port
+ */
+ protected int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns true or false when this socket supports sending urgent data
+ * or not.
+ *
+ * @return true if the socket implementation supports sending urgent data,
+ * false otherwise
+ *
+ * @since 1.4
+ */
+ protected boolean supportsUrgentData()
+ {
+ // This method has to be overwritten by socket classes that support
+ // sending urgend data.
+ return false;
+ }
+
+ /**
+ * Sends one byte of urgent data to the socket.
+ *
+ * @param data The byte to send, the low eight bits of it
+ *
+ * @exception IOException If an error occurs
+ *
+ * @since 1.4
+ */
+ protected abstract void sendUrgentData(int data) throws IOException;
+
+ /**
+ * Returns the local port this socket is bound to
+ *
+ * @return The local port
+ */
+ protected int getLocalPort()
+ {
+ return localport;
+ }
+
+ /**
+ * Returns a <code>String</code> representing the remote host and port of
+ * this socket.
+ *
+ * @return A <code>String</code> for this socket.
+ */
+ public String toString()
+ {
+ return "[addr="
+ + ((address == null) ? "0.0.0.0/0.0.0.0" : address.toString())
+ + ",port=" + port + ",localport=" + localport + "]";
+ }
+
+ /**
+ * Shut down the input side of this socket. Subsequent reads will
+ * return end-of-file.
+ *
+ * @exception IOException if an error occurs
+ */
+ protected void shutdownInput() throws IOException
+ {
+ throw new IOException("Not implemented in this socket class");
+ }
+
+ /**
+ * Shut down the output side of this socket. Subsequent writes will
+ * fail with an IOException.
+ *
+ * @exception IOException if an error occurs
+ */
+ protected void shutdownOutput() throws IOException
+ {
+ throw new IOException("Not implemented in this socket class");
+ }
+}
diff --git a/libjava/classpath/java/net/SocketImplFactory.java b/libjava/classpath/java/net/SocketImplFactory.java
new file mode 100644
index 00000000000..b7cb10ca65f
--- /dev/null
+++ b/libjava/classpath/java/net/SocketImplFactory.java
@@ -0,0 +1,59 @@
+/* SocketImplFactory.java -- Interface to create a SocketImpl object
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/** Written using on-line Java Platform 1.2 API Specification.
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface defines one method which returns a <code>SocketImpl</code>
+ * object. This should not be needed by ordinary applications.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public interface SocketImplFactory
+{
+ /**
+ * This method returns an instance of the <code>SocketImpl</code> object
+ *
+ * @return A <code>SocketImpl</code> object
+ */
+ SocketImpl createSocketImpl();
+} // interface SocketImplFactory
diff --git a/libjava/classpath/java/net/SocketOptions.java b/libjava/classpath/java/net/SocketOptions.java
new file mode 100644
index 00000000000..659bf750c3b
--- /dev/null
+++ b/libjava/classpath/java/net/SocketOptions.java
@@ -0,0 +1,166 @@
+/* SocketOptions.java -- Implements options for sockets (duh!)
+ Copyright (C) 1998, 1999, 2000, 2001,
+ 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification.
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface is used by <code>SocketImpl</code> and
+ * <code>DatagramSocketImpl</code> to implement options
+ * on sockets.
+ *
+ * @since 1.2
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status should be completely JDK 1.4 compatible
+ */
+public interface SocketOptions
+{
+ /**
+ * Option id for the SO_KEEPALIVE value
+ * @since 1.3
+ */
+ int SO_KEEPALIVE = 0x8;
+
+ /**
+ * Option id for the SO_LINGER value
+ */
+ int SO_LINGER = 0x80; // 128
+
+ /**
+ * Option id for the SO_TIMEOUT value
+ */
+ int SO_TIMEOUT = 0x1006; // 4102
+
+ /**
+ * Retrieve the local address to which the socket is bound.
+ */
+ int SO_BINDADDR = 0x0F; // 15
+
+ /**
+ * Option id for the send buffer size
+ * @since 1.2
+ */
+ int SO_SNDBUF = 0x1001; // 4097
+
+ /**
+ * Option id for the receive buffer size
+ * @since 1.2
+ */
+ int SO_RCVBUF = 0x1002; // 4098
+
+ /**
+ * Sets the SO_REUSEADDR parameter on a socket
+ */
+ int SO_REUSEADDR = 0x04; // 4
+
+ /**
+ * Sets SO_BROADCAST for a socket
+ * @since 1.4
+ */
+ int SO_BROADCAST = 0x20; // 32
+
+ /**
+ * Sets SO_OOBINLINE for a socket
+ * @since 1.4
+ */
+ int SO_OOBINLINE = 0x1003; // 4099
+
+ /**
+ * Option id for the TCP_NODELAY value
+ */
+ int TCP_NODELAY = 0x01; // 1
+
+ /**
+ * Options id for the IP_MULTICAST_IF value
+ */
+ int IP_MULTICAST_IF = 0x10; // 16
+
+ /**
+ * same as above
+ * @since 1.4
+ */
+ int IP_MULTICAST_IF2 = 0x1F; // 31
+
+ /**
+ * This option enables or disables local loopback of multicast datagrams.
+ * @since 1.4
+ */
+ int IP_MULTICAST_LOOP = 0x12; // 18
+
+ /**
+ * This option sets the type-of-service or traffic class field in the
+ * IP header for a TCP or UDP socket.
+ * @since 1.4
+ */
+ int IP_TOS = 0x03; // 3
+
+ /**
+ * Sets the specified option on a socket to the passed in object. For
+ * options that take an integer argument, the passed in object is an
+ * <code>Integer</code>. For options that are set to on or off, the
+ * value passed will be a <code>Boolean</code>. The <code>optionId</code>
+ * parameter is one of the defined constants in this interface.
+ *
+ * @param optionId The identifier of the option
+ * @param val The value to set the option to
+ *
+ * @exception SocketException If an error occurs
+ */
+ void setOption(int optionId, Object val) throws SocketException;
+
+ /**
+ * Returns the current setting of the specified option. The
+ * <code>Object</code> returned will be an <code>Integer</code> for options
+ * that have integer values. For options that are set to on or off, a
+ * <code>Boolean</code> will be returned. The <code>optionId</code>
+ * parameter is one of the defined constants in this interface.
+ *
+ * @param optionId The option identifier
+ *
+ * @return The current value of the option
+ *
+ * @exception SocketException If an error occurs
+ */
+ Object getOption(int optionId) throws SocketException;
+} // interface SocketOptions
diff --git a/libjava/classpath/java/net/SocketPermission.java b/libjava/classpath/java/net/SocketPermission.java
new file mode 100644
index 00000000000..8ccd01baec5
--- /dev/null
+++ b/libjava/classpath/java/net/SocketPermission.java
@@ -0,0 +1,408 @@
+/* SocketPermission.java -- Class modeling permissions for socket operations
+ Copyright (C) 1998, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.Serializable;
+import java.security.Permission;
+import java.security.PermissionCollection;
+
+
+/**
+ * This class models a specific set of permssions for connecting to a
+ * host. There are two elements to this, the host/port combination and
+ * the permission list.
+ * <p>
+ * The host/port combination is specified as followed
+ * <p>
+ * <pre>
+ * hostname[:[-]port[-[port]]]
+ * </pre>
+ * <p>
+ * The hostname portion can be either a hostname or IP address. If it is
+ * a hostname, a wildcard is allowed in hostnames. This wildcard is a "*"
+ * and matches one or more characters. Only one "*" may appear in the
+ * host and it must be the leftmost character. For example,
+ * "*.urbanophile.com" matches all hosts in the "urbanophile.com" domain.
+ * <p>
+ * The port portion can be either a single value, or a range of values
+ * treated as inclusive. The first or the last port value in the range
+ * can be omitted in which case either the minimum or maximum legal
+ * value for a port (respectively) is used by default. Here are some
+ * examples:
+ * <p><ul>
+ * <li>8080 - Represents port 8080 only</li>
+ * <li>2000-3000 - Represents ports 2000 through 3000 inclusive</li>
+ * <li>-4000 - Represents ports 0 through 4000 inclusive</li>
+ * <li>1024- - Represents ports 1024 through 65535 inclusive</li>
+ * </ul><p>
+ * The permission list is a comma separated list of individual permissions.
+ * These individual permissions are:
+ * <p>
+ * <pre>
+ * accept
+ * connect
+ * listen
+ * resolve
+ * </pre>
+ * <p>
+ * The "listen" permission is only relevant if the host is localhost. If
+ * any permission at all is specified, then resolve permission is implied to
+ * exist.
+ * <p>
+ * Here are a variety of examples of how to create SocketPermission's
+ * <p><pre>
+ * SocketPermission("www.urbanophile.com", "connect");
+ * Can connect to any port on www.urbanophile.com
+ * SocketPermission("www.urbanophile.com:80", "connect,accept");
+ * Can connect to or accept connections from www.urbanophile.com on port 80
+ * SocketPermission("localhost:1024-", "listen,accept,connect");
+ * Can connect to, accept from, an listen on any local port number 1024
+ * and up.
+ * SocketPermission("*.edu", "connect");
+ * Can connect to any host in the edu domain
+ * SocketPermission("197.197.20.1", "accept");
+ * Can accept connections from 197.197.20.1
+ * </pre><p>
+ *
+ * This class also supports IPv6 addresses. These should be specified
+ * in either RFC 2732 format or in full uncompressed form.
+ *
+ * @since 1.2
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public final class SocketPermission extends Permission implements Serializable
+{
+ static final long serialVersionUID = -7204263841984476862L;
+
+// FIXME: Needs serialization work, including readObject/writeObject methods.
+
+ /**
+ * A hostname/port combination as described above
+ */
+ private transient String hostport;
+
+ /**
+ * A comma separated list of actions for which we have permission
+ */
+ private String actions;
+
+ /**
+ * Initializes a new instance of <code>SocketPermission</code> with the
+ * specified host/port combination and actions string.
+ *
+ * @param hostport The hostname/port number combination
+ * @param actions The actions string
+ */
+ public SocketPermission(String hostport, String actions)
+ {
+ super(hostport);
+
+ this.hostport = hostport;
+ this.actions = actions;
+ }
+
+ /**
+ * Tests this object for equality against another. This will be true if
+ * and only if the passed object is an instance of
+ * <code>SocketPermission</code> and both its hostname/port combination
+ * and permissions string are identical.
+ *
+ * @param obj The object to test against for equality
+ *
+ * @return <code>true</code> if object is equal to this object,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof SocketPermission))
+ return false;
+
+ if (((SocketPermission) obj).hostport.equals(hostport))
+ if (((SocketPermission) obj).actions.equals(actions))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this object. Overrides the
+ * <code>Permission.hashCode()</code>.
+ *
+ * @return A hash code
+ */
+ public int hashCode()
+ {
+ int hash = 100;
+ if (hostport != null)
+ hash += hostport.hashCode();
+ if (actions != null)
+ hash += actions.hashCode();
+ return hash;
+ }
+
+ /**
+ * Returns the list of permission actions in this object in canonical
+ * order. The canonical order is "connect,listen,accept,resolve"
+ *
+ * @return The permitted action string.
+ */
+ public String getActions()
+ {
+ boolean found = false;
+ StringBuffer sb = new StringBuffer("");
+
+ if (actions.indexOf("connect") != -1)
+ {
+ sb.append("connect");
+ found = true;
+ }
+
+ if (actions.indexOf("listen") != -1)
+ if (found)
+ sb.append(",listen");
+ else
+ {
+ sb.append("listen");
+ found = true;
+ }
+
+ if (actions.indexOf("accept") != -1)
+ if (found)
+ sb.append(",accept");
+ else
+ {
+ sb.append("accept");
+ found = true;
+ }
+
+ if (found)
+ sb.append(",resolve");
+ else if (actions.indexOf("resolve") != -1)
+ sb.append("resolve");
+
+ return sb.toString();
+ }
+
+ /**
+ * Returns a new <code>PermissionCollection</code> object that can hold
+ * <code>SocketPermission</code>'s.
+ *
+ * @return A new <code>PermissionCollection</code>.
+ */
+ public PermissionCollection newPermissionCollection()
+ {
+ // FIXME: Implement
+
+ return null;
+ }
+
+ /**
+ * Returns true if the permission object passed it is implied by the
+ * this permission. This will be true if:
+ *
+ * <ul>
+ * <li>The argument is of type <code>SocketPermission</code></li>
+ * <li>The actions list of the argument are in this object's actions</li>
+ * <li>The port range of the argument is within this objects port range</li>
+ * <li>The hostname is equal to or a subset of this objects hostname</li>
+ * </ul>
+ *
+ * <p>The argument's hostname will be a subset of this object's hostname if:</p>
+ *
+ * <ul>
+ * <li>The argument's hostname or IP address is equal to this object's.</li>
+ * <li>The argument's canonical hostname is equal to this object's.</li>
+ * <li>The argument's canonical name matches this domains hostname with
+ * wildcards</li>
+ * </ul>
+ *
+ * @param perm The <code>Permission</code> to check against
+ *
+ * @return <code>true</code> if the <code>Permission</code> is implied by
+ * this object, <code>false</code> otherwise.
+ */
+ public boolean implies(Permission perm)
+ {
+ SocketPermission p;
+
+ // First make sure we are the right object type
+ if (perm instanceof SocketPermission)
+ p = (SocketPermission) perm;
+ else
+ return false;
+
+ // Next check the actions
+ String ourlist = getActions();
+ String theirlist = p.getActions();
+
+ if (! ourlist.startsWith(theirlist))
+ return false;
+
+ // Now check ports
+ int ourfirstport = 0;
+
+ // Now check ports
+ int ourlastport = 0;
+
+ // Now check ports
+ int theirfirstport = 0;
+
+ // Now check ports
+ int theirlastport = 0;
+
+ // Get ours
+ if (hostport.indexOf(":") == -1)
+ {
+ ourfirstport = 0;
+ ourlastport = 65535;
+ }
+ else
+ {
+ // FIXME: Needs bulletproofing.
+ // This will dump if hostport if all sorts of bad data was passed to
+ // the constructor
+ String range = hostport.substring(hostport.indexOf(":") + 1);
+ if (range.startsWith("-"))
+ ourfirstport = 0;
+ else if (range.indexOf("-") == -1)
+ ourfirstport = Integer.parseInt(range);
+ else
+ ourfirstport =
+ Integer.parseInt(range.substring(0, range.indexOf("-")));
+
+ if (range.endsWith("-"))
+ ourlastport = 65535;
+ else if (range.indexOf("-") == -1)
+ ourlastport = Integer.parseInt(range);
+ else
+ ourlastport =
+ Integer.parseInt(range.substring(range.indexOf("-") + 1,
+ range.length()));
+ }
+
+ // Get theirs
+ if (p.hostport.indexOf(":") == -1)
+ {
+ theirfirstport = 0;
+ ourlastport = 65535;
+ }
+ else
+ {
+ // This will dump if hostport if all sorts of bad data was passed to
+ // the constructor
+ String range = p.hostport.substring(hostport.indexOf(":") + 1);
+ if (range.startsWith("-"))
+ theirfirstport = 0;
+ else if (range.indexOf("-") == -1)
+ theirfirstport = Integer.parseInt(range);
+ else
+ theirfirstport =
+ Integer.parseInt(range.substring(0, range.indexOf("-")));
+
+ if (range.endsWith("-"))
+ theirlastport = 65535;
+ else if (range.indexOf("-") == -1)
+ theirlastport = Integer.parseInt(range);
+ else
+ theirlastport =
+ Integer.parseInt(range.substring(range.indexOf("-") + 1,
+ range.length()));
+ }
+
+ // Now check them
+ if ((theirfirstport < ourfirstport) || (theirlastport > ourlastport))
+ return false;
+
+ // Finally we can check the hosts
+ String ourhost;
+
+ // Finally we can check the hosts
+ String theirhost;
+
+ // Get ours
+ if (hostport.indexOf(":") == -1)
+ ourhost = hostport;
+ else
+ ourhost = hostport.substring(0, hostport.indexOf(":"));
+
+ // Get theirs
+ if (p.hostport.indexOf(":") == -1)
+ theirhost = p.hostport;
+ else
+ theirhost = p.hostport.substring(0, p.hostport.indexOf(":"));
+
+ // Are they equal?
+ if (ourhost.equals(theirhost))
+ return true;
+
+ // Try the canonical names
+ String ourcanonical = null;
+
+ // Try the canonical names
+ String theircanonical = null;
+ try
+ {
+ ourcanonical = InetAddress.getByName(ourhost).getHostName();
+ theircanonical = InetAddress.getByName(theirhost).getHostName();
+ }
+ catch (UnknownHostException e)
+ {
+ // Who didn't resolve? Just assume current address is canonical enough
+ // Is this ok to do?
+ if (ourcanonical == null)
+ ourcanonical = ourhost;
+ if (theircanonical == null)
+ theircanonical = theirhost;
+ }
+
+ if (ourcanonical.equals(theircanonical))
+ return true;
+
+ // Well, last chance. Try for a wildcard
+ if (ourhost.indexOf("*.") != -1)
+ {
+ String wild_domain = ourhost.substring(ourhost.indexOf("*" + 1));
+ if (theircanonical.endsWith(wild_domain))
+ return true;
+ }
+
+ // Didn't make it
+ return false;
+ }
+}
diff --git a/libjava/classpath/java/net/SocketTimeoutException.java b/libjava/classpath/java/net/SocketTimeoutException.java
new file mode 100644
index 00000000000..21b0dcd86c2
--- /dev/null
+++ b/libjava/classpath/java/net/SocketTimeoutException.java
@@ -0,0 +1,73 @@
+/* SocketTimeoutException.java -- the socket timed out
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.InterruptedIOException;
+
+
+/**
+ * This exception signals that a socket read or accept timed out.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class SocketTimeoutException extends InterruptedIOException
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -8846654841826352300L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public SocketTimeoutException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public SocketTimeoutException(String message)
+ {
+ super(message);
+ }
+} // class SocketTimeoutException
diff --git a/libjava/classpath/java/net/TODO b/libjava/classpath/java/net/TODO
new file mode 100644
index 00000000000..e48969d3ae6
--- /dev/null
+++ b/libjava/classpath/java/net/TODO
@@ -0,0 +1,24 @@
+-- DNS cache purging.
+
+-- Implement ContentHandler chaining (non-JDK feature)
+
+-- Implement MIME type by file determination chaining using external
+ disk files. (non-JDK feature)
+
+-- Implement determining MIME type from an InputStream
+
+-- Datagram peek()'s
+
+-- Finalize methods for sockets
+
+-- HTTP - caching (supported by JDK?)
+
+-- HTTP - all protocol support beyond basic GET functionality
+
+-- Fix call to Date(String) in URLConnection.getHeaderFieldDate() when
+ I figure out why DateFormat isn't working.
+
+-- Finish off all JDK 1.2 permissions stuff
+
+-- Write URLClassLoader
+
diff --git a/libjava/classpath/java/net/URI.java b/libjava/classpath/java/net/URI.java
new file mode 100644
index 00000000000..aeceeeec555
--- /dev/null
+++ b/libjava/classpath/java/net/URI.java
@@ -0,0 +1,1438 @@
+/* URI.java -- An URI class
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * <p>
+ * A URI instance represents that defined by
+ * <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC3986</a>,
+ * with some deviations.
+ * </p>
+ * <p>
+ * At its highest level, a URI consists of:
+ * </p>
+ * <code>[<em>scheme</em><strong>:</strong>]<em>scheme-specific-part</em>
+ * [<strong>#</strong><em>fragment</em>]</code>
+ * </p>
+ * <p>
+ * where <strong>#</strong> and <strong>:</strong> are literal characters,
+ * and those parts enclosed in square brackets are optional.
+ * </p>
+ * <p>
+ * There are two main types of URI. An <em>opaque</em> URI is one
+ * which just consists of the above three parts, and is not further
+ * defined. An example of such a URI would be <em>mailto:</em> URI.
+ * In contrast, <em>hierarchical</em> URIs give further definition
+ * to the scheme-specific part, so as represent some part of a hierarchical
+ * structure.
+ * </p>
+ * <p>
+ * <code>[<strong>//</strong><em>authority</em>][<em>path</em>]
+ * [<strong>?</strong><em>query</em>]</code>
+ * </p>
+ * <p>
+ * with <strong>/</strong> and <strong>?</strong> being literal characters.
+ * When server-based, the authority section is further subdivided into:
+ * </p>
+ * <p>
+ * <code>[<em>user-info</em><strong>@</strong>]<em>host</em>
+ * [<strong>:</strong><em>port</em>]</code>
+ * </p>
+ * <p>
+ * with <strong>@</strong> and <strong>:</strong> as literal characters.
+ * Authority sections that are not server-based are said to be registry-based.
+ * </p>
+ * <p>
+ * Hierarchical URIs can be either relative or absolute. Absolute URIs
+ * always start with a `<strong>/</strong>', while relative URIs don't
+ * specify a scheme. Opaque URIs are always absolute.
+ * </p>
+ * <p>
+ * Each part of the URI may have one of three states: undefined, empty
+ * or containing some content. The former two of these are represented
+ * by <code>null</code> and the empty string in Java, respectively.
+ * The scheme-specific part may never be undefined. It also follows from
+ * this that the path sub-part may also not be undefined, so as to ensure
+ * the former.
+ * </p>
+ * <h2>Character Escaping and Quoting</h2>
+ * <p>
+ * The characters that can be used within a valid URI are restricted.
+ * There are two main classes of characters which can't be used as is
+ * within the URI:
+ * </p>
+ * <ol>
+ * <li><strong>Characters outside the US-ASCII character set</strong>.
+ * These have to be <strong>escaped</strong> in order to create
+ * an RFC-compliant URI; this means replacing the character with the
+ * appropriate hexadecimal value, preceded by a `%'.</li>
+ * <li><strong>Illegal characters</strong> (e.g. space characters,
+ * control characters) are quoted, which results in them being encoded
+ * in the same way as non-US-ASCII characters.</li>
+ * </ol>
+ * <p>
+ * The set of valid characters differs depending on the section of the URI:
+ * </p>
+ * <ul>
+ * <li><strong>Scheme</strong>: Must be an alphanumeric, `-', `.' or '+'.</li>
+ * <li><strong>Authority</strong>:Composed of the username, host, port, `@'
+ * and `:'.</li>
+ * <li><strong>Username</strong>: Allows unreserved or percent-encoded
+ * characters, sub-delimiters and `:'.</li>
+ * <li><strong>Host</strong>: Allows unreserved or percent-encoded
+ * characters, sub-delimiters and square brackets (`[' and `]') for IPv6
+ * addresses.</li>
+ * <li><strong>Port</strong>: Digits only.</li>
+ * <li><strong>Path</strong>: Allows the path characters and `/'.
+ * <li><strong>Query</strong>: Allows the path characters, `?' and '/'.
+ * <li><strong>Fragment</strong>: Allows the path characters, `?' and '/'.
+ * </ul>
+ * <p>
+ * These definitions reference the following sets of characters:
+ * </p>
+ * <ul>
+ * <li><strong>Unreserved characters</strong>: The alphanumerics plus
+ * `-', `.', `_', and `~'.</li>
+ * <li><strong>Sub-delimiters</strong>: `!', `$', `&', `(', `)', `*',
+ * `+', `,', `;', `=' and the single-quote itself.</li>
+ * <li><strong>Path characters</strong>: Unreserved and percent-encoded
+ * characters and the sub-delimiters along with `@' and `:'.</li>
+ * </ul>
+ * <p>
+ * The constructors and accessor methods allow the use and retrieval of
+ * URI components which contain non-US-ASCII characters directly.
+ * They are only escaped when the <code>toASCIIString()</code> method
+ * is used. In contrast, illegal characters are always quoted, with the
+ * exception of the return values of the non-raw accessors.
+ * </p>
+ *
+ * @author Ito Kazumitsu (ito.kazumitsu@hitachi-cable.co.jp)
+ * @author Dalibor Topic (robilad@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.4
+ */
+public final class URI
+ implements Comparable, Serializable
+{
+ /**
+ * For serialization compatability.
+ */
+ static final long serialVersionUID = -6052424284110960213L;
+
+ /**
+ * Regular expression for parsing URIs.
+ *
+ * Taken from RFC 2396, Appendix B.
+ * This expression doesn't parse IPv6 addresses.
+ */
+ private static final String URI_REGEXP =
+ "^(([^:/?#]+):)?((//([^/?#]*))?([^?#]*)(\\?([^#]*))?)?(#(.*))?";
+
+ /**
+ * Regular expression for parsing the authority segment.
+ */
+ private static final String AUTHORITY_REGEXP =
+ "(([^?#]*)@)?([^?#:]*)(:([0-9]*))?";
+
+ /**
+ * Valid characters (taken from rfc2396/3986)
+ */
+ private static final String RFC2396_DIGIT = "0123456789";
+ private static final String RFC2396_LOWALPHA = "abcdefghijklmnopqrstuvwxyz";
+ private static final String RFC2396_UPALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ private static final String RFC2396_ALPHA =
+ RFC2396_LOWALPHA + RFC2396_UPALPHA;
+ private static final String RFC2396_ALPHANUM = RFC2396_DIGIT + RFC2396_ALPHA;
+ private static final String RFC3986_UNRESERVED = RFC2396_ALPHANUM + "-._~";
+ private static final String RFC3986_SUBDELIMS = "!$&'()*+,;=";
+ private static final String RFC3986_REG_NAME =
+ RFC3986_UNRESERVED + RFC3986_SUBDELIMS + "%";
+ private static final String RFC3986_PCHAR = RFC3986_UNRESERVED +
+ RFC3986_SUBDELIMS + ":@%";
+ private static final String RFC3986_SEGMENT = RFC3986_PCHAR;
+ private static final String RFC3986_PATH_SEGMENTS = RFC3986_SEGMENT + "/";
+ private static final String RFC3986_SSP = RFC3986_PCHAR + "?/";
+ private static final String RFC3986_HOST = RFC3986_REG_NAME + "[]";
+ private static final String RFC3986_USERINFO = RFC3986_REG_NAME + ":";
+
+ /**
+ * Index of scheme component in parsed URI.
+ */
+ private static final int SCHEME_GROUP = 2;
+
+ /**
+ * Index of scheme-specific-part in parsed URI.
+ */
+ private static final int SCHEME_SPEC_PART_GROUP = 3;
+
+ /**
+ * Index of authority component in parsed URI.
+ */
+ private static final int AUTHORITY_GROUP = 5;
+
+ /**
+ * Index of path component in parsed URI.
+ */
+ private static final int PATH_GROUP = 6;
+
+ /**
+ * Index of query component in parsed URI.
+ */
+ private static final int QUERY_GROUP = 8;
+
+ /**
+ * Index of fragment component in parsed URI.
+ */
+ private static final int FRAGMENT_GROUP = 10;
+
+ /**
+ * Index of userinfo component in parsed authority section.
+ */
+ private static final int AUTHORITY_USERINFO_GROUP = 2;
+
+ /**
+ * Index of host component in parsed authority section.
+ */
+ private static final int AUTHORITY_HOST_GROUP = 3;
+
+ /**
+ * Index of port component in parsed authority section.
+ */
+ private static final int AUTHORITY_PORT_GROUP = 5;
+
+ /**
+ * The compiled version of the URI regular expression.
+ */
+ private static final Pattern URI_PATTERN;
+
+ /**
+ * The compiled version of the authority regular expression.
+ */
+ private static final Pattern AUTHORITY_PATTERN;
+
+ /**
+ * The set of valid hexadecimal characters.
+ */
+ private static final String HEX = "0123456789ABCDEF";
+
+ private transient String scheme;
+ private transient String rawSchemeSpecificPart;
+ private transient String schemeSpecificPart;
+ private transient String rawAuthority;
+ private transient String authority;
+ private transient String rawUserInfo;
+ private transient String userInfo;
+ private transient String rawHost;
+ private transient String host;
+ private transient int port = -1;
+ private transient String rawPath;
+ private transient String path;
+ private transient String rawQuery;
+ private transient String query;
+ private transient String rawFragment;
+ private transient String fragment;
+ private String string;
+
+ /**
+ * Static initializer to pre-compile the regular expressions.
+ */
+ static
+ {
+ URI_PATTERN = Pattern.compile(URI_REGEXP);
+ AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEXP);
+ }
+
+ private void readObject(ObjectInputStream is)
+ throws ClassNotFoundException, IOException
+ {
+ this.string = (String) is.readObject();
+ try
+ {
+ parseURI(this.string);
+ }
+ catch (URISyntaxException x)
+ {
+ // Should not happen.
+ throw new RuntimeException(x);
+ }
+ }
+
+ private void writeObject(ObjectOutputStream os) throws IOException
+ {
+ if (string == null)
+ string = toString();
+ os.writeObject(string);
+ }
+
+ /**
+ * <p>
+ * Returns the string content of the specified group of the supplied
+ * matcher. The returned value is modified according to the following:
+ * </p>
+ * <ul>
+ * <li>If the resulting string has a length greater than 0, then
+ * that string is returned.</li>
+ * <li>If a string of zero length, is matched, then the content
+ * of the preceding group is considered. If this is also an empty
+ * string, then <code>null</code> is returned to indicate an undefined
+ * value. Otherwise, the value is truly the empty string and this is
+ * the returned value.</li>
+ * </ul>
+ * <p>
+ * This method is used for matching against all parts of the URI
+ * that may be either undefined or empty (i.e. all those but the
+ * scheme-specific part and the path). In each case, the preceding
+ * group is the content of the original group, along with some
+ * additional distinguishing feature. For example, the preceding
+ * group for the query includes the preceding question mark,
+ * while that of the fragment includes the hash symbol. The presence
+ * of these features enables disambiguation between the two cases
+ * of a completely unspecified value and a simple non-existant value.
+ * The scheme differs in that it will never return an empty string;
+ * the delimiter follows the scheme rather than preceding it, so
+ * it becomes part of the following section. The same is true
+ * of the user information.
+ * </p>
+ *
+ * @param match the matcher, which contains the results of the URI
+ * matched against the URI regular expression.
+ * @return either the matched content, <code>null</code> for undefined
+ * values, or an empty string for a URI part with empty content.
+ */
+ private static String getURIGroup(Matcher match, int group)
+ {
+ String matched = match.group(group);
+ return matched.length() == 0
+ ? ((match.group(group - 1).length() == 0) ? null : "") : matched;
+ }
+
+ /**
+ * Sets fields of this URI by parsing the given string.
+ *
+ * @param str The string to parse
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ private void parseURI(String str) throws URISyntaxException
+ {
+ Matcher matcher = URI_PATTERN.matcher(str);
+
+ if (matcher.matches())
+ {
+ scheme = getURIGroup(matcher, SCHEME_GROUP);
+ rawSchemeSpecificPart = matcher.group(SCHEME_SPEC_PART_GROUP);
+ schemeSpecificPart = unquote(rawSchemeSpecificPart);
+ if (!isOpaque())
+ {
+ rawAuthority = getURIGroup(matcher, AUTHORITY_GROUP);
+ rawPath = matcher.group(PATH_GROUP);
+ rawQuery = getURIGroup(matcher, QUERY_GROUP);
+ }
+ rawFragment = getURIGroup(matcher, FRAGMENT_GROUP);
+ }
+ else
+ throw new URISyntaxException(str,
+ "doesn't match URI regular expression");
+ parseServerAuthority();
+
+ // We must eagerly unquote the parts, because this is the only time
+ // we may throw an exception.
+ authority = unquote(rawAuthority);
+ userInfo = unquote(rawUserInfo);
+ host = unquote(rawHost);
+ path = unquote(rawPath);
+ query = unquote(rawQuery);
+ fragment = unquote(rawFragment);
+ }
+
+ /**
+ * Unquote "%" + hex quotes characters
+ *
+ * @param str The string to unquote or null.
+ *
+ * @return The unquoted string or null if str was null.
+ *
+ * @exception URISyntaxException If the given string contains invalid
+ * escape sequences.
+ */
+ private static String unquote(String str) throws URISyntaxException
+ {
+ if (str == null)
+ return null;
+ byte[] buf = new byte[str.length()];
+ int pos = 0;
+ for (int i = 0; i < str.length(); i++)
+ {
+ char c = str.charAt(i);
+ if (c == '%')
+ {
+ if (i + 2 >= str.length())
+ throw new URISyntaxException(str, "Invalid quoted character");
+ int hi = Character.digit(str.charAt(++i), 16);
+ int lo = Character.digit(str.charAt(++i), 16);
+ if (lo < 0 || hi < 0)
+ throw new URISyntaxException(str, "Invalid quoted character");
+ buf[pos++] = (byte) (hi * 16 + lo);
+ }
+ else
+ buf[pos++] = (byte) c;
+ }
+ try
+ {
+ return new String(buf, 0, pos, "utf-8");
+ }
+ catch (java.io.UnsupportedEncodingException x2)
+ {
+ throw (Error) new InternalError().initCause(x2);
+ }
+ }
+
+ /**
+ * Quote characters illegal in URIs in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quote(String str)
+ {
+ return quote(str, RFC3986_SSP);
+ }
+
+ /**
+ * Quote characters illegal in URI authorities in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quoteAuthority(String str)
+ {
+ // Technically, we should be using RFC2396_AUTHORITY, but
+ // it contains no additional characters.
+ return quote(str, RFC3986_REG_NAME);
+ }
+
+ /**
+ * Quotes the characters in the supplied string that are not part of
+ * the specified set of legal characters.
+ *
+ * @param str the string to quote
+ * @param legalCharacters the set of legal characters
+ *
+ * @return the quoted string.
+ */
+ private static String quote(String str, String legalCharacters)
+ {
+ StringBuffer sb = new StringBuffer(str.length());
+ for (int i = 0; i < str.length(); i++)
+ {
+ char c = str.charAt(i);
+ if (legalCharacters.indexOf(c) == -1)
+ {
+ if (c <= 127)
+ {
+ sb.append('%');
+ sb.append(HEX.charAt(c / 16));
+ sb.append(HEX.charAt(c % 16));
+ }
+ }
+ else
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Quote characters illegal in URI hosts in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quoteHost(String str)
+ {
+ return quote(str, RFC3986_HOST);
+ }
+
+ /**
+ * Quote characters illegal in URI paths in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quotePath(String str)
+ {
+ // Technically, we should be using RFC2396_PATH, but
+ // it contains no additional characters.
+ return quote(str, RFC3986_PATH_SEGMENTS);
+ }
+
+ /**
+ * Quote characters illegal in URI user infos in given string.
+ *
+ * Replace illegal characters by encoding their UTF-8
+ * representation as "%" + hex code for each resulting
+ * UTF-8 character.
+ *
+ * @param str The string to quote
+ *
+ * @return The quoted string.
+ */
+ private static String quoteUserInfo(String str)
+ {
+ return quote(str, RFC3986_USERINFO);
+ }
+
+ /**
+ * Creates an URI from the given string
+ *
+ * @param str The string to create the URI from
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ * @exception NullPointerException If str is null
+ */
+ public URI(String str) throws URISyntaxException
+ {
+ this.string = str;
+ parseURI(str);
+ }
+
+ /**
+ * Create an URI from the given components
+ *
+ * @param scheme The scheme name
+ * @param userInfo The username and authorization info
+ * @param host The hostname
+ * @param port The port number
+ * @param path The path
+ * @param query The query
+ * @param fragment The fragment
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ public URI(String scheme, String userInfo, String host, int port,
+ String path, String query, String fragment)
+ throws URISyntaxException
+ {
+ this((scheme == null ? "" : scheme + ":")
+ + (userInfo == null && host == null && port == -1 ? "" : "//")
+ + (userInfo == null ? "" : quoteUserInfo(userInfo) + "@")
+ + (host == null ? "" : quoteHost(host))
+ + (port == -1 ? "" : ":" + String.valueOf(port))
+ + (path == null ? "" : quotePath(path))
+ + (query == null ? "" : "?" + quote(query))
+ + (fragment == null ? "" : "#" + quote(fragment)));
+ }
+
+ /**
+ * Create an URI from the given components
+ *
+ * @param scheme The scheme name
+ * @param authority The authority
+ * @param path The apth
+ * @param query The query
+ * @param fragment The fragment
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ public URI(String scheme, String authority, String path, String query,
+ String fragment) throws URISyntaxException
+ {
+ this((scheme == null ? "" : scheme + ":")
+ + (authority == null ? "" : "//" + quoteAuthority(authority))
+ + (path == null ? "" : quotePath(path))
+ + (query == null ? "" : "?" + quote(query))
+ + (fragment == null ? "" : "#" + quote(fragment)));
+ }
+
+ /**
+ * Create an URI from the given components
+ *
+ * @param scheme The scheme name
+ * @param host The hostname
+ * @param path The path
+ * @param fragment The fragment
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ public URI(String scheme, String host, String path, String fragment)
+ throws URISyntaxException
+ {
+ this(scheme, null, host, -1, path, null, fragment);
+ }
+
+ /**
+ * Create an URI from the given components
+ *
+ * @param scheme The scheme name
+ * @param ssp The scheme specific part
+ * @param fragment The fragment
+ *
+ * @exception URISyntaxException If the given string violates RFC 2396
+ */
+ public URI(String scheme, String ssp, String fragment)
+ throws URISyntaxException
+ {
+ this((scheme == null ? "" : scheme + ":")
+ + (ssp == null ? "" : quote(ssp))
+ + (fragment == null ? "" : "#" + quote(fragment)));
+ }
+
+ /**
+ * Create an URI from the given string
+ *
+ * @param str The string to create the URI from
+ *
+ * @exception IllegalArgumentException If the given string violates RFC 2396
+ * @exception NullPointerException If str is null
+ */
+ public static URI create(String str)
+ {
+ try
+ {
+ return new URI(str);
+ }
+ catch (URISyntaxException e)
+ {
+ throw (IllegalArgumentException) new IllegalArgumentException()
+ .initCause(e);
+ }
+ }
+
+ /**
+ * Attempts to parse this URI's authority component, if defined,
+ * into user-information, host, and port components. The purpose
+ * of this method was to disambiguate between some authority sections,
+ * which form invalid server-based authories, but valid registry
+ * based authorities. In the updated RFC 3986, the authority section
+ * is defined differently, with registry-based authorities part of
+ * the host section. Thus, this method is now simply an explicit
+ * way of parsing any authority section.
+ *
+ * @return the URI, with the authority section parsed into user
+ * information, host and port components.
+ * @throws URISyntaxException if the given string violates RFC 2396
+ */
+ public URI parseServerAuthority() throws URISyntaxException
+ {
+ if (rawAuthority != null)
+ {
+ Matcher matcher = AUTHORITY_PATTERN.matcher(rawAuthority);
+
+ if (matcher.matches())
+ {
+ rawUserInfo = getURIGroup(matcher, AUTHORITY_USERINFO_GROUP);
+ rawHost = getURIGroup(matcher, AUTHORITY_HOST_GROUP);
+
+ String portStr = getURIGroup(matcher, AUTHORITY_PORT_GROUP);
+
+ if (portStr != null)
+ try
+ {
+ port = Integer.parseInt(portStr);
+ }
+ catch (NumberFormatException e)
+ {
+ URISyntaxException use =
+ new URISyntaxException
+ (string, "doesn't match URI regular expression");
+ use.initCause(e);
+ throw use;
+ }
+ }
+ else
+ throw new URISyntaxException(string,
+ "doesn't match URI regular expression");
+ }
+ return this;
+ }
+
+ /**
+ * <p>
+ * Returns a normalized version of the URI. If the URI is opaque,
+ * or its path is already in normal form, then this URI is simply
+ * returned. Otherwise, the following transformation of the path
+ * element takes place:
+ * </p>
+ * <ol>
+ * <li>All `.' segments are removed.</li>
+ * <li>Each `..' segment which can be paired with a prior non-`..' segment
+ * is removed along with the preceding segment.</li>
+ * <li>A `.' segment is added to the front if the first segment contains
+ * a colon (`:'). This is a deviation from the RFC, which prevents
+ * confusion between the path and the scheme.</li>
+ * </ol>
+ * <p>
+ * The resulting URI will be free of `.' and `..' segments, barring those
+ * that were prepended or which couldn't be paired, respectively.
+ * </p>
+ *
+ * @return the normalized URI.
+ */
+ public URI normalize()
+ {
+ if (isOpaque() || path.indexOf("/./") == -1 && path.indexOf("/../") == -1)
+ return this;
+ try
+ {
+ return new URI(scheme, authority, normalizePath(path), query,
+ fragment);
+ }
+ catch (URISyntaxException e)
+ {
+ throw (Error) new InternalError("Normalized URI variant could not "+
+ "be constructed").initCause(e);
+ }
+ }
+
+ /**
+ * <p>
+ * Normalize the given path. The following transformation takes place:
+ * </p>
+ * <ol>
+ * <li>All `.' segments are removed.</li>
+ * <li>Each `..' segment which can be paired with a prior non-`..' segment
+ * is removed along with the preceding segment.</li>
+ * <li>A `.' segment is added to the front if the first segment contains
+ * a colon (`:'). This is a deviation from the RFC, which prevents
+ * confusion between the path and the scheme.</li>
+ * </ol>
+ * <p>
+ * The resulting URI will be free of `.' and `..' segments, barring those
+ * that were prepended or which couldn't be paired, respectively.
+ * </p>
+ *
+ * @param relativePath the relative path to be normalized.
+ * @return the normalized path.
+ */
+ private String normalizePath(String relativePath)
+ {
+ /*
+ This follows the algorithm in section 5.2.4. of RFC3986,
+ but doesn't modify the input buffer.
+ */
+ StringBuffer input = new StringBuffer(relativePath);
+ StringBuffer output = new StringBuffer();
+ int start = 0;
+ while (start < input.length())
+ {
+ /* A */
+ if (input.indexOf("../",start) == start)
+ {
+ start += 3;
+ continue;
+ }
+ if (input.indexOf("./",start) == start)
+ {
+ start += 2;
+ continue;
+ }
+ /* B */
+ if (input.indexOf("/./",start) == start)
+ {
+ start += 2;
+ continue;
+ }
+ if (input.indexOf("/.",start) == start
+ && input.charAt(start + 2) != '.')
+ {
+ start += 1;
+ input.setCharAt(start,'/');
+ continue;
+ }
+ /* C */
+ if (input.indexOf("/../",start) == start)
+ {
+ start += 3;
+ removeLastSegment(output);
+ continue;
+ }
+ if (input.indexOf("/..",start) == start)
+ {
+ start += 2;
+ input.setCharAt(start,'/');
+ removeLastSegment(output);
+ continue;
+ }
+ /* D */
+ if (start == input.length() - 1 && input.indexOf(".",start) == start)
+ {
+ input.delete(0,1);
+ continue;
+ }
+ if (start == input.length() - 2 && input.indexOf("..",start) == start)
+ {
+ input.delete(0,2);
+ continue;
+ }
+ /* E */
+ int indexOfSlash = input.indexOf("/",start);
+ while (indexOfSlash == start)
+ {
+ output.append("/");
+ ++start;
+ indexOfSlash = input.indexOf("/",start);
+ }
+ if (indexOfSlash == -1)
+ indexOfSlash = input.length();
+ output.append(input.substring(start, indexOfSlash));
+ start = indexOfSlash;
+ }
+ return output.toString();
+ }
+
+ /**
+ * Removes the last segment of the path from the specified buffer.
+ *
+ * @param buffer the buffer containing the path.
+ */
+ private void removeLastSegment(StringBuffer buffer)
+ {
+ int lastSlash = buffer.lastIndexOf("/");
+ if (lastSlash == -1)
+ buffer.setLength(0);
+ else
+ buffer.setLength(lastSlash);
+ }
+
+ /**
+ * Resolves the given URI against this URI
+ *
+ * @param uri The URI to resolve against this URI
+ *
+ * @return The resulting URI, or null when it couldn't be resolved
+ * for some reason.
+ *
+ * @throws NullPointerException if uri is null
+ */
+ public URI resolve(URI uri)
+ {
+ if (uri.isAbsolute())
+ return uri;
+ if (uri.isOpaque())
+ return uri;
+
+ String scheme = uri.getScheme();
+ String schemeSpecificPart = uri.getSchemeSpecificPart();
+ String authority = uri.getAuthority();
+ String path = uri.getPath();
+ String query = uri.getQuery();
+ String fragment = uri.getFragment();
+
+ try
+ {
+ if (fragment != null && path != null && path.equals("")
+ && scheme == null && authority == null && query == null)
+ return new URI(this.scheme, this.schemeSpecificPart, fragment);
+
+ if (authority == null)
+ {
+ authority = this.authority;
+ if (path == null)
+ path = "";
+ if (! (path.startsWith("/")))
+ {
+ StringBuffer basepath = new StringBuffer(this.path);
+ int i = this.path.lastIndexOf('/');
+
+ if (i >= 0)
+ basepath.delete(i + 1, basepath.length());
+
+ basepath.append(path);
+ path = normalizePath(basepath.toString());
+ }
+ }
+ return new URI(this.scheme, authority, path, query, fragment);
+ }
+ catch (URISyntaxException e)
+ {
+ throw (Error) new InternalError("Resolved URI variant could not "+
+ "be constructed").initCause(e);
+ }
+ }
+
+ /**
+ * Resolves the given URI string against this URI
+ *
+ * @param str The URI as string to resolve against this URI
+ *
+ * @return The resulting URI
+ *
+ * @throws IllegalArgumentException If the given URI string
+ * violates RFC 2396
+ * @throws NullPointerException If uri is null
+ */
+ public URI resolve(String str) throws IllegalArgumentException
+ {
+ return resolve(create(str));
+ }
+
+ /**
+ * <p>
+ * Relativizes the given URI against this URI. The following
+ * algorithm is used:
+ * </p>
+ * <ul>
+ * <li>If either URI is opaque, the given URI is returned.</li>
+ * <li>If the schemes of the URIs differ, the given URI is returned.</li>
+ * <li>If the authority components of the URIs differ, then the given
+ * URI is returned.</li>
+ * <li>If the path of this URI is not a prefix of the supplied URI,
+ * then the given URI is returned.</li>
+ * <li>If all the above conditions hold, a new URI is created using the
+ * query and fragment components of the given URI, along with a path
+ * computed by removing the path of this URI from the start of the path
+ * of the supplied URI.</li>
+ * </ul>
+ *
+ * @param uri the URI to relativize agsint this URI
+ * @return the resulting URI
+ * @throws NullPointerException if the uri is null
+ */
+ public URI relativize(URI uri)
+ {
+ if (isOpaque() || uri.isOpaque())
+ return uri;
+ if (scheme == null && uri.getScheme() != null)
+ return uri;
+ if (scheme != null && !(scheme.equals(uri.getScheme())))
+ return uri;
+ if (rawAuthority == null && uri.getRawAuthority() != null)
+ return uri;
+ if (rawAuthority != null && !(rawAuthority.equals(uri.getRawAuthority())))
+ return uri;
+ if (!(uri.getRawPath().startsWith(rawPath)))
+ return uri;
+ try
+ {
+ return new URI(null, null,
+ uri.getRawPath().substring(rawPath.length()),
+ uri.getRawQuery(), uri.getRawFragment());
+ }
+ catch (URISyntaxException e)
+ {
+ throw (Error) new InternalError("Relativized URI variant could not "+
+ "be constructed").initCause(e);
+ }
+ }
+
+ /**
+ * Creates an URL from an URI
+ *
+ * @throws MalformedURLException If a protocol handler for the URL could
+ * not be found, or if some other error occurred while constructing the URL
+ * @throws IllegalArgumentException If the URI is not absolute
+ */
+ public URL toURL() throws IllegalArgumentException, MalformedURLException
+ {
+ if (isAbsolute())
+ return new URL(this.toString());
+
+ throw new IllegalArgumentException("not absolute");
+ }
+
+ /**
+ * Returns the scheme of the URI
+ */
+ public String getScheme()
+ {
+ return scheme;
+ }
+
+ /**
+ * Tells whether this URI is absolute or not
+ */
+ public boolean isAbsolute()
+ {
+ return scheme != null;
+ }
+
+ /**
+ * Tell whether this URI is opaque or not
+ */
+ public boolean isOpaque()
+ {
+ return ((scheme != null) && ! (schemeSpecificPart.startsWith("/")));
+ }
+
+ /**
+ * Returns the raw scheme specific part of this URI.
+ * The scheme-specific part is never undefined, though it may be empty
+ */
+ public String getRawSchemeSpecificPart()
+ {
+ return rawSchemeSpecificPart;
+ }
+
+ /**
+ * Returns the decoded scheme specific part of this URI.
+ */
+ public String getSchemeSpecificPart()
+ {
+ return schemeSpecificPart;
+ }
+
+ /**
+ * Returns the raw authority part of this URI
+ */
+ public String getRawAuthority()
+ {
+ return rawAuthority;
+ }
+
+ /**
+ * Returns the decoded authority part of this URI
+ */
+ public String getAuthority()
+ {
+ return authority;
+ }
+
+ /**
+ * Returns the raw user info part of this URI
+ */
+ public String getRawUserInfo()
+ {
+ return rawUserInfo;
+ }
+
+ /**
+ * Returns the decoded user info part of this URI
+ */
+ public String getUserInfo()
+ {
+ return userInfo;
+ }
+
+ /**
+ * Returns the hostname of the URI
+ */
+ public String getHost()
+ {
+ return host;
+ }
+
+ /**
+ * Returns the port number of the URI
+ */
+ public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns the raw path part of this URI
+ */
+ public String getRawPath()
+ {
+ return rawPath;
+ }
+
+ /**
+ * Returns the path of the URI
+ */
+ public String getPath()
+ {
+ return path;
+ }
+
+ /**
+ * Returns the raw query part of this URI
+ */
+ public String getRawQuery()
+ {
+ return rawQuery;
+ }
+
+ /**
+ * Returns the query of the URI
+ */
+ public String getQuery()
+ {
+ return query;
+ }
+
+ /**
+ * Return the raw fragment part of this URI
+ */
+ public String getRawFragment()
+ {
+ return rawFragment;
+ }
+
+ /**
+ * Returns the fragment of the URI
+ */
+ public String getFragment()
+ {
+ return fragment;
+ }
+
+ /**
+ * <p>
+ * Compares the URI with the given object for equality. If the
+ * object is not a <code>URI</code>, then the method returns false.
+ * Otherwise, the following criteria are observed:
+ * </p>
+ * <ul>
+ * <li>The scheme of the URIs must either be null (undefined) in both cases,
+ * or equal, ignorant of case.</li>
+ * <li>The raw fragment of the URIs must either be null (undefined) in both
+ * cases, or equal, ignorant of case.</li>
+ * <li>Both URIs must be of the same type (opaque or hierarchial)</li>
+ * <li><strong>For opaque URIs:</strong></li>
+ * <ul>
+ * <li>The raw scheme-specific parts must be equal.</li>
+ * </ul>
+ * <li>For hierarchical URIs:</li>
+ * <ul>
+ * <li>The raw paths must be equal, ignorant of case.</li>
+ * <li>The raw queries are either both undefined or both equal, ignorant
+ * of case.</li>
+ * <li>The raw authority sections are either both undefined or:</li>
+ * <li><strong>For registry-based authorities:</strong></li>
+ * <ul><li>they are equal.</li></ul>
+ * <li><strong>For server-based authorities:</strong></li>
+ * <ul>
+ * <li>the hosts are equal, ignoring case</li>
+ * <li>the ports are equal</li>
+ * <li>the user information components are equal</li>
+ * </ul>
+ * </ul>
+ * </ul>
+ *
+ * @param obj the obj to compare the URI with.
+ * @return <code>true</code> if the objects are equal, according to
+ * the specification above.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof URI))
+ return false;
+ URI uriObj = (URI) obj;
+ if (scheme == null)
+ {
+ if (uriObj.getScheme() != null)
+ return false;
+ }
+ else
+ if (!(scheme.equalsIgnoreCase(uriObj.getScheme())))
+ return false;
+ if (rawFragment == null)
+ {
+ if (uriObj.getRawFragment() != null)
+ return false;
+ }
+ else
+ if (!(rawFragment.equalsIgnoreCase(uriObj.getRawFragment())))
+ return false;
+ boolean opaqueThis = isOpaque();
+ boolean opaqueObj = uriObj.isOpaque();
+ if (opaqueThis && opaqueObj)
+ return rawSchemeSpecificPart.equals(uriObj.getRawSchemeSpecificPart());
+ else if (!opaqueThis && !opaqueObj)
+ {
+ boolean common = rawPath.equalsIgnoreCase(uriObj.getRawPath())
+ && ((rawQuery == null && uriObj.getRawQuery() == null)
+ || rawQuery.equalsIgnoreCase(uriObj.getRawQuery()));
+ if (rawAuthority == null && uriObj.getRawAuthority() == null)
+ return common;
+ if (host == null)
+ return common
+ && rawAuthority.equalsIgnoreCase(uriObj.getRawAuthority());
+ return common
+ && host.equalsIgnoreCase(uriObj.getHost())
+ && port == uriObj.getPort()
+ && (rawUserInfo == null ?
+ uriObj.getRawUserInfo() == null :
+ rawUserInfo.equalsIgnoreCase(uriObj.getRawUserInfo()));
+ }
+ else
+ return false;
+ }
+
+ /**
+ * Computes the hashcode of the URI
+ */
+ public int hashCode()
+ {
+ return (getScheme() == null ? 0 : 13 * getScheme().hashCode())
+ + 17 * getRawSchemeSpecificPart().hashCode()
+ + (getRawFragment() == null ? 0 : 21 + getRawFragment().hashCode());
+ }
+
+ /**
+ * Compare the URI with another object that must also be a URI.
+ * Undefined components are taken to be less than any other component.
+ * The following criteria are observed:
+ * </p>
+ * <ul>
+ * <li>Two URIs with different schemes are compared according to their
+ * scheme, regardless of case.</li>
+ * <li>A hierarchical URI is less than an opaque URI with the same
+ * scheme.</li>
+ * <li><strong>For opaque URIs:</strong></li>
+ * <ul>
+ * <li>URIs with differing scheme-specific parts are ordered according
+ * to the ordering of the scheme-specific part.</li>
+ * <li>URIs with the same scheme-specific part are ordered by the
+ * raw fragment.</li>
+ * </ul>
+ * <li>For hierarchical URIs:</li>
+ * <ul>
+ * <li>URIs are ordered according to their raw authority sections,
+ * if they are unequal.</li>
+ * <li><strong>For registry-based authorities:</strong></li>
+ * <ul><li>they are ordered according to the ordering of the authority
+ * component.</li></ul>
+ * <li><strong>For server-based authorities:</strong></li>
+ * <ul>
+ * <li>URIs are ordered according to the raw user information.</li>
+ * <li>URIs with the same user information are ordered by the host,
+ * ignoring case.</li>
+ * <lI>URIs with the same host are ordered by the port.</li>
+ * </ul>
+ * <li>URIs with the same authority section are ordered by the raw path.</li>
+ * <li>URIs with the same path are ordered by their raw query.</li>
+ * <li>URIs with the same query are ordered by their raw fragments.</li>
+ * </ul>
+ * </ul>
+ *
+ * @param obj This object to compare this URI with
+ * @return a negative integer, zero or a positive integer depending
+ * on whether this URI is less than, equal to or greater
+ * than that supplied, respectively.
+ * @throws ClassCastException if the given object is not a URI
+ */
+ public int compareTo(Object obj)
+ throws ClassCastException
+ {
+ URI uri = (URI) obj;
+ if (scheme == null && uri.getScheme() != null)
+ return -1;
+ if (scheme != null)
+ {
+ int sCompare = scheme.compareToIgnoreCase(uri.getScheme());
+ if (sCompare != 0)
+ return sCompare;
+ }
+ boolean opaqueThis = isOpaque();
+ boolean opaqueObj = uri.isOpaque();
+ if (opaqueThis && !opaqueObj)
+ return 1;
+ if (!opaqueThis && opaqueObj)
+ return -1;
+ if (opaqueThis)
+ {
+ int ssCompare =
+ rawSchemeSpecificPart.compareTo(uri.getRawSchemeSpecificPart());
+ if (ssCompare == 0)
+ return compareFragments(uri);
+ else
+ return ssCompare;
+ }
+ if (rawAuthority == null && uri.getRawAuthority() != null)
+ return -1;
+ if (rawAuthority != null)
+ {
+ int aCompare = rawAuthority.compareTo(uri.getRawAuthority());
+ if (aCompare != 0)
+ {
+ if (host == null)
+ return aCompare;
+ if (rawUserInfo == null && uri.getRawUserInfo() != null)
+ return -1;
+ int uCompare = rawUserInfo.compareTo(uri.getRawUserInfo());
+ if (uCompare != 0)
+ return uCompare;
+ if (host == null && uri.getHost() != null)
+ return -1;
+ int hCompare = host.compareTo(uri.getHost());
+ if (hCompare != 0)
+ return hCompare;
+ return new Integer(port).compareTo(new Integer(uri.getPort()));
+ }
+ }
+ if (rawPath == null && uri.getRawPath() != null)
+ return -1;
+ if (rawPath != null)
+ {
+ int pCompare = rawPath.compareTo(uri.getRawPath());
+ if (pCompare != 0)
+ return pCompare;
+ }
+ if (rawQuery == null && uri.getRawQuery() != null)
+ return -1;
+ if (rawQuery != null)
+ {
+ int qCompare = rawQuery.compareTo(uri.getRawQuery());
+ if (qCompare != 0)
+ return qCompare;
+ }
+ return compareFragments(uri);
+ }
+
+ /**
+ * Compares the fragment of this URI with that of the supplied URI.
+ *
+ * @param uri the URI to compare with this one.
+ * @return a negative integer, zero or a positive integer depending
+ * on whether this uri's fragment is less than, equal to
+ * or greater than the fragment of the uri supplied, respectively.
+ */
+ private int compareFragments(URI uri)
+ {
+ if (rawFragment == null && uri.getRawFragment() != null)
+ return -1;
+ else if (rawFragment == null)
+ return 0;
+ else
+ return rawFragment.compareTo(uri.getRawFragment());
+ }
+
+ /**
+ * Returns the URI as a String. If the URI was created using a constructor,
+ * then this will be the same as the original input string.
+ *
+ * @return a string representation of the URI.
+ */
+ public String toString()
+ {
+ return (scheme == null ? "" : scheme + ":")
+ + rawSchemeSpecificPart
+ + (rawFragment == null ? "" : "#" + rawFragment);
+ }
+
+ /**
+ * Returns the URI as US-ASCII string. This is the same as the result
+ * from <code>toString()</code> for URIs that don't contain any non-US-ASCII
+ * characters. Otherwise, the non-US-ASCII characters are replaced
+ * by their percent-encoded representations.
+ *
+ * @return a string representation of the URI, containing only US-ASCII
+ * characters.
+ */
+ public String toASCIIString()
+ {
+ String strRep = toString();
+ boolean inNonAsciiBlock = false;
+ StringBuffer buffer = new StringBuffer();
+ StringBuffer encBuffer = null;
+ for (int i = 0; i < strRep.length(); i++)
+ {
+ char c = strRep.charAt(i);
+ if (c <= 127)
+ {
+ if (inNonAsciiBlock)
+ {
+ buffer.append(escapeCharacters(encBuffer.toString()));
+ inNonAsciiBlock = false;
+ }
+ buffer.append(c);
+ }
+ else
+ {
+ if (!inNonAsciiBlock)
+ {
+ encBuffer = new StringBuffer();
+ inNonAsciiBlock = true;
+ }
+ encBuffer.append(c);
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Converts the non-ASCII characters in the supplied string
+ * to their equivalent percent-encoded representations.
+ * That is, they are replaced by "%" followed by their hexadecimal value.
+ *
+ * @param str a string including non-ASCII characters.
+ * @return the string with the non-ASCII characters converted to their
+ * percent-encoded representations.
+ */
+ private static String escapeCharacters(String str)
+ {
+ try
+ {
+ StringBuffer sb = new StringBuffer();
+ // this is far from optimal, but it works
+ byte[] utf8 = str.getBytes("utf-8");
+ for (int j = 0; j < utf8.length; j++)
+ {
+ sb.append('%');
+ sb.append(HEX.charAt((utf8[j] & 0xff) / 16));
+ sb.append(HEX.charAt((utf8[j] & 0xff) % 16));
+ }
+ return sb.toString();
+ }
+ catch (java.io.UnsupportedEncodingException x)
+ {
+ throw (Error) new InternalError("Escaping error").initCause(x);
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/net/URISyntaxException.java b/libjava/classpath/java/net/URISyntaxException.java
new file mode 100644
index 00000000000..27a70bdb717
--- /dev/null
+++ b/libjava/classpath/java/net/URISyntaxException.java
@@ -0,0 +1,144 @@
+/* URISyntaxException.java -- a string could not be parsed as a URI
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * This exception is thrown when a String cannot be parsed as a URI.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see URI
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class URISyntaxException extends Exception
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 2137979680897488891L;
+
+ /**
+ * The failed input.
+ *
+ * @serial the bad URI
+ */
+ private final String input;
+
+ /**
+ * The index of failure.
+ *
+ * @serial the location of the problem
+ */
+ private final int index;
+
+ /**
+ * Create an exception from the invalid string, with the index set to -1.
+ *
+ * @param input the bad URI
+ * @param msg the descriptive error message
+ * @throws NullPointerException if input or msg are null
+ */
+ public URISyntaxException(String input, String msg)
+ {
+ this(input, msg, -1);
+ }
+
+ /**
+ * Create an exception from the invalid string, with the index of the
+ * point of failure.
+ *
+ * @param input the bad URI
+ * @param msg the descriptive error message
+ * @param index the index of the parse error, or -1
+ * @throws NullPointerException if input or msg are null
+ * @throws IllegalArgumentException if index &lt; -1
+ */
+ public URISyntaxException(String input, String msg, int index)
+ {
+ // The toString() hack checks for null.
+ super(msg.toString());
+ this.input = input.toString();
+ this.index = index;
+ if (index < -1)
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Returns the bad input string.
+ *
+ * @return the bad URI, guaranteed non-null
+ */
+ public String getInput()
+ {
+ return input;
+ }
+
+ /**
+ * Returns the reason for the failure.
+ *
+ * @return the message, guaranteed non-null
+ */
+ public String getReason()
+ {
+ return super.getMessage();
+ }
+
+ /**
+ * Returns the index of the failure, or -1.
+ *
+ * @return the index of failure
+ */
+ public int getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * Returns a message describing the parse error, as if by
+ * <code>getReason() + (getIndex() &gt;= 0 ? " at index " + getIndex() : "")
+ * + ": " + getInput()</code>.
+ *
+ * @return the message string
+ */
+ public String getMessage()
+ {
+ return (super.getMessage() + (index >= 0 ? " at index " + index : "")
+ + ": " + input);
+ }
+}
diff --git a/libjava/classpath/java/net/URL.java b/libjava/classpath/java/net/URL.java
new file mode 100644
index 00000000000..627dbc391e9
--- /dev/null
+++ b/libjava/classpath/java/net/URL.java
@@ -0,0 +1,956 @@
+/* URL.java -- Uniform Resource Locator Class
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.net.URLParseError;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This final class represents an Internet Uniform Resource Locator (URL).
+ * For details on the syntax of URL's and what they can be used for,
+ * refer to RFC 1738, available from <a
+ * href="http://ds.internic.net/rfcs/rfc1738.txt">
+ * http://ds.internic.net/rfcs/rfc1738.txt</a>
+ * <p>
+ * There are a great many protocols supported by URL's such as "http",
+ * "ftp", and "file". This object can handle any arbitrary URL for which
+ * a URLStreamHandler object can be written. Default protocol handlers
+ * are provided for the "http" and "ftp" protocols. Additional protocols
+ * handler implementations may be provided in the future. In any case,
+ * an application or applet can install its own protocol handlers that
+ * can be "chained" with other protocol hanlders in the system to extend
+ * the base functionality provided with this class. (Note, however, that
+ * unsigned applets cannot access properties by default or install their
+ * own protocol handlers).
+ * <p>
+ * This chaining is done via the system property java.protocol.handler.pkgs
+ * If this property is set, it is assumed to be a "|" separated list of
+ * package names in which to attempt locating protocol handlers. The
+ * protocol handler is searched for by appending the string
+ * ".&lt;protocol&gt;.Handler" to each packed in the list until a hander is
+ * found. If a protocol handler is not found in this list of packages, or if
+ * the property does not exist, then the default protocol handler of
+ * "gnu.java.net.&lt;protocol&gt;.Handler" is tried. If this is
+ * unsuccessful, a MalformedURLException is thrown.
+ * <p>
+ * All of the constructor methods of URL attempt to load a protocol
+ * handler and so any needed protocol handlers must be installed when
+ * the URL is constructed.
+ * <p>
+ * Here is an example of how URL searches for protocol handlers. Assume
+ * the value of java.protocol.handler.pkgs is "com.foo|com.bar" and the
+ * URL is "news://comp.lang.java.programmer". URL would looking the
+ * following places for protocol handlers:
+ * <p><pre>
+ * com.foo.news.Handler
+ * com.bar.news.Handler
+ * gnu.java.net.news.Handler
+ * </pre><p>
+ * If the protocol handler is not found in any of those locations, a
+ * MalformedURLException would be thrown.
+ * <p>
+ * Please note that a protocol handler must be a subclass of
+ * URLStreamHandler.
+ * <p>
+ * Normally, this class caches protocol handlers. Once it finds a handler
+ * for a particular protocol, it never tries to look up a new handler
+ * again. However, if the system property
+ * gnu.java.net.nocache_protocol_handlers is set, then this
+ * caching behavior is disabled. This property is specific to this
+ * implementation. Sun's JDK may or may not do protocol caching, but it
+ * almost certainly does not examine this property.
+ * <p>
+ * Please also note that an application can install its own factory for
+ * loading protocol handlers (see setURLStreamHandlerFactory). If this is
+ * done, then the above information is superseded and the behavior of this
+ * class in loading protocol handlers is dependent on that factory.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ *
+ * @see URLStreamHandler
+ */
+public final class URL implements Serializable
+{
+ private static final String DEFAULT_SEARCH_PATH =
+ "gnu.java.net.protocol|gnu.inet";
+
+ // Cached System ClassLoader
+ private static ClassLoader systemClassLoader;
+
+ /**
+ * The name of the protocol for this URL.
+ * The protocol is always stored in lower case.
+ */
+ private String protocol;
+
+ /**
+ * The "authority" portion of the URL.
+ */
+ private String authority;
+
+ /**
+ * The hostname or IP address of this protocol.
+ * This includes a possible user. For example <code>joe@some.host.net</code>.
+ */
+ private String host;
+
+ /**
+ * The user information necessary to establish the connection.
+ */
+ private String userInfo;
+
+ /**
+ * The port number of this protocol or -1 if the port number used is
+ * the default for this protocol.
+ */
+ private int port = -1; // Initialize for constructor using context.
+
+ /**
+ * The "file" portion of the URL. It is defined as <code>path[?query]</code>.
+ */
+ private String file;
+
+ /**
+ * The anchor portion of the URL.
+ */
+ private String ref;
+
+ /**
+ * This is the hashCode for this URL
+ */
+ private int hashCode;
+
+ /**
+ * The protocol handler in use for this URL
+ */
+ transient URLStreamHandler ph;
+
+ /**
+ * If an application installs its own protocol handler factory, this is
+ * where we keep track of it.
+ */
+ private static URLStreamHandlerFactory factory;
+ private static final long serialVersionUID = -7627629688361524110L;
+
+ /**
+ * This a table where we cache protocol handlers to avoid the overhead
+ * of looking them up each time.
+ */
+ private static HashMap ph_cache = new HashMap();
+
+ /**
+ * Whether or not to cache protocol handlers.
+ */
+ private static boolean cache_handlers;
+
+ static
+ {
+ String s = System.getProperty("gnu.java.net.nocache_protocol_handlers");
+
+ if (s == null)
+ cache_handlers = true;
+ else
+ cache_handlers = false;
+ }
+
+ /**
+ * Constructs a URL and loads a protocol handler for the values passed as
+ * arguments.
+ *
+ * @param protocol The protocol for this URL ("http", "ftp", etc)
+ * @param host The hostname or IP address to connect to
+ * @param port The port number to use, or -1 to use the protocol's
+ * default port
+ * @param file The "file" portion of the URL.
+ *
+ * @exception MalformedURLException If a protocol handler cannot be loaded or
+ * a parse error occurs.
+ */
+ public URL(String protocol, String host, int port, String file)
+ throws MalformedURLException
+ {
+ this(protocol, host, port, file, null);
+ }
+
+ /**
+ * Constructs a URL and loads a protocol handler for the values passed in
+ * as arugments. Uses the default port for the protocol.
+ *
+ * @param protocol The protocol for this URL ("http", "ftp", etc)
+ * @param host The hostname or IP address for this URL
+ * @param file The "file" portion of this URL.
+ *
+ * @exception MalformedURLException If a protocol handler cannot be loaded or
+ * a parse error occurs.
+ */
+ public URL(String protocol, String host, String file)
+ throws MalformedURLException
+ {
+ this(protocol, host, -1, file, null);
+ }
+
+ /**
+ * This method initializes a new instance of <code>URL</code> with the
+ * specified protocol, host, port, and file. Additionally, this method
+ * allows the caller to specify a protocol handler to use instead of
+ * the default. If this handler is specified, the caller must have
+ * the "specifyStreamHandler" permission (see <code>NetPermission</code>)
+ * or a <code>SecurityException</code> will be thrown.
+ *
+ * @param protocol The protocol for this URL ("http", "ftp", etc)
+ * @param host The hostname or IP address to connect to
+ * @param port The port number to use, or -1 to use the protocol's default
+ * port
+ * @param file The "file" portion of the URL.
+ * @param ph The protocol handler to use with this URL.
+ *
+ * @exception MalformedURLException If no protocol handler can be loaded
+ * for the specified protocol.
+ * @exception SecurityException If the <code>SecurityManager</code> exists
+ * and does not allow the caller to specify its own protocol handler.
+ *
+ * @since 1.2
+ */
+ public URL(String protocol, String host, int port, String file,
+ URLStreamHandler ph) throws MalformedURLException
+ {
+ if (protocol == null)
+ throw new MalformedURLException("null protocol");
+ protocol = protocol.toLowerCase();
+ this.protocol = protocol;
+
+ if (ph != null)
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkPermission(new NetPermission("specifyStreamHandler"));
+
+ this.ph = ph;
+ }
+ else
+ this.ph = getURLStreamHandler(protocol);
+
+ if (this.ph == null)
+ throw new MalformedURLException("Protocol handler not found: "
+ + protocol);
+
+ this.host = host;
+ this.port = port;
+ this.authority = (host != null) ? host : "";
+ if (port >= 0 && host != null)
+ this.authority += ":" + port;
+
+ int hashAt = file.indexOf('#');
+ if (hashAt < 0)
+ {
+ this.file = file;
+ this.ref = null;
+ }
+ else
+ {
+ this.file = file.substring(0, hashAt);
+ this.ref = file.substring(hashAt + 1);
+ }
+ hashCode = hashCode(); // Used for serialization.
+ }
+
+ /**
+ * Initializes a URL from a complete string specification such as
+ * "http://www.urbanophile.com/arenn/". First the protocol name is parsed
+ * out of the string. Then a handler is located for that protocol and
+ * the parseURL() method of that protocol handler is used to parse the
+ * remaining fields.
+ *
+ * @param spec The complete String representation of a URL
+ *
+ * @exception MalformedURLException If a protocol handler cannot be found
+ * or the URL cannot be parsed
+ */
+ public URL(String spec) throws MalformedURLException
+ {
+ this((URL) null, spec != null ? spec : "", (URLStreamHandler) null);
+ }
+
+ /**
+ * This method parses a String representation of a URL within the
+ * context of an existing URL. Principally this means that any
+ * fields not present the URL are inheritied from the context URL.
+ * This allows relative URL's to be easily constructed. If the
+ * context argument is null, then a complete URL must be specified
+ * in the URL string. If the protocol parsed out of the URL is
+ * different from the context URL's protocol, then then URL String
+ * is also expected to be a complete URL.
+ *
+ * @param context The context on which to parse the specification
+ * @param spec The string to parse an URL
+ *
+ * @exception MalformedURLException If a protocol handler cannot be found
+ * for the URL cannot be parsed
+ */
+ public URL(URL context, String spec) throws MalformedURLException
+ {
+ this(context, spec, (URLStreamHandler) null);
+ }
+
+ /**
+ * Creates an URL from given arguments
+ * This method parses a String representation of a URL within the
+ * context of an existing URL. Principally this means that any fields
+ * not present the URL are inheritied from the context URL. This allows
+ * relative URL's to be easily constructed. If the context argument is
+ * null, then a complete URL must be specified in the URL string.
+ * If the protocol parsed out of the URL is different
+ * from the context URL's protocol, then then URL String is also
+ * expected to be a complete URL.
+ * <p>
+ * Additionally, this method allows the caller to specify a protocol handler
+ * to use instead of the default. If this handler is specified, the caller
+ * must have the "specifyStreamHandler" permission
+ * (see <code>NetPermission</code>) or a <code>SecurityException</code>
+ * will be thrown.
+ *
+ * @param context The context in which to parse the specification
+ * @param spec The string to parse as an URL
+ * @param ph The stream handler for the URL
+ *
+ * @exception MalformedURLException If a protocol handler cannot be found
+ * or the URL cannot be parsed
+ * @exception SecurityException If the <code>SecurityManager</code> exists
+ * and does not allow the caller to specify its own protocol handler.
+ *
+ * @since 1.2
+ */
+ public URL(URL context, String spec, URLStreamHandler ph)
+ throws MalformedURLException
+ {
+ /* A protocol is defined by the doc as the substring before a ':'
+ * as long as the ':' occurs before any '/'.
+ *
+ * If context is null, then spec must be an absolute URL.
+ *
+ * The relative URL need not specify all the components of a URL.
+ * If the protocol, host name, or port number is missing, the value
+ * is inherited from the context. A bare file component is appended
+ * to the context's file. The optional anchor is not inherited.
+ */
+
+ // If this is an absolute URL, then ignore context completely.
+ // An absolute URL must have chars prior to "://" but cannot have a colon
+ // right after the "://". The second colon is for an optional port value
+ // and implies that the host from the context is used if available.
+ int colon;
+ int slash = spec.indexOf('/');
+ if ((colon = spec.indexOf("://", 1)) > 0
+ && ((colon < slash || slash < 0))
+ && ! spec.regionMatches(colon, "://:", 0, 4))
+ context = null;
+
+ if ((colon = spec.indexOf(':')) > 0
+ && (colon < slash || slash < 0))
+ {
+ // Protocol specified in spec string.
+ protocol = spec.substring(0, colon).toLowerCase();
+ if (context != null && context.protocol.equals(protocol))
+ {
+ // The 1.2 doc specifically says these are copied to the new URL.
+ host = context.host;
+ port = context.port;
+ file = context.file;
+ userInfo = context.userInfo;
+ if (file == null || file.length() == 0)
+ file = "/";
+ authority = context.authority;
+ }
+ }
+ else if (context != null)
+ {
+ // Protocol NOT specified in spec string.
+ // Use context fields (except ref) as a foundation for relative URLs.
+ colon = -1;
+ protocol = context.protocol;
+ host = context.host;
+ port = context.port;
+ file = context.file;
+ userInfo = context.userInfo;
+ if (file == null || file.length() == 0)
+ file = "/";
+ authority = context.authority;
+ }
+ else // Protocol NOT specified in spec. and no context available.
+ throw new MalformedURLException("Absolute URL required with null"
+ + " context: " + spec);
+
+ protocol = protocol.trim();
+
+ if (ph != null)
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkPermission(new NetPermission("specifyStreamHandler"));
+
+ this.ph = ph;
+ }
+ else
+ this.ph = getURLStreamHandler(protocol);
+
+ if (this.ph == null)
+ throw new MalformedURLException("Protocol handler not found: "
+ + protocol);
+
+ // JDK 1.2 doc for parseURL specifically states that any '#' ref
+ // is to be excluded by passing the 'limit' as the indexOf the '#'
+ // if one exists, otherwise pass the end of the string.
+ int hashAt = spec.indexOf('#', colon + 1);
+
+ try
+ {
+ this.ph.parseURL(this, spec, colon + 1,
+ hashAt < 0 ? spec.length() : hashAt);
+ }
+ catch (URLParseError e)
+ {
+ throw new MalformedURLException(e.getMessage());
+ }
+
+ if (hashAt >= 0)
+ ref = spec.substring(hashAt + 1);
+
+ hashCode = hashCode(); // Used for serialization.
+ }
+
+ /**
+ * Test another URL for equality with this one. This will be true only if
+ * the argument is non-null and all of the fields in the URL's match
+ * exactly (ie, protocol, host, port, file, and ref). Overrides
+ * Object.equals(), implemented by calling the equals method of the handler.
+ *
+ * @param obj The URL to compare with
+ *
+ * @return true if the URL is equal, false otherwise
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof URL))
+ return false;
+
+ return ph.equals(this, (URL) obj);
+ }
+
+ /**
+ * Returns the contents of this URL as an object by first opening a
+ * connection, then calling the getContent() method against the connection
+ *
+ * @return A content object for this URL
+ * @exception IOException If opening the connection or getting the
+ * content fails.
+ *
+ * @since 1.3
+ */
+ public Object getContent() throws IOException
+ {
+ return openConnection().getContent();
+ }
+
+ /**
+ * Gets the contents of this URL
+ *
+ * @param classes The allow classes for the content object.
+ *
+ * @return a context object for this URL.
+ *
+ * @exception IOException If an error occurs
+ */
+ public Object getContent(Class[] classes) throws IOException
+ {
+ // FIXME: implement this
+ return getContent();
+ }
+
+ /**
+ * Returns the file portion of the URL.
+ * Defined as <code>path[?query]</code>.
+ * Returns the empty string if there is no file portion.
+ *
+ * @return The filename specified in this URL, or an empty string if empty.
+ */
+ public String getFile()
+ {
+ return file == null ? "" : file;
+ }
+
+ /**
+ * Returns the path of the URL. This is the part of the file before any '?'
+ * character.
+ *
+ * @return The path specified in this URL, or null if empty.
+ *
+ * @since 1.3
+ */
+ public String getPath()
+ {
+ // The spec says we need to return an empty string, but some
+ // applications depends on receiving null when the path is empty.
+ if (file == null)
+ return null;
+ int quest = file.indexOf('?');
+ return quest < 0 ? getFile() : file.substring(0, quest);
+ }
+
+ /**
+ * Returns the authority of the URL
+ *
+ * @return The authority specified in this URL.
+ *
+ * @since 1.3
+ */
+ public String getAuthority()
+ {
+ return authority;
+ }
+
+ /**
+ * Returns the host of the URL
+ *
+ * @return The host specified in this URL.
+ */
+ public String getHost()
+ {
+ int at = (host == null) ? -1 : host.indexOf('@');
+ return at < 0 ? host : host.substring(at + 1, host.length());
+ }
+
+ /**
+ * Returns the port number of this URL or -1 if the default port number is
+ * being used.
+ *
+ * @return The port number
+ *
+ * @see #getDefaultPort()
+ */
+ public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Returns the default port of the URL. If the StreamHandler for the URL
+ * protocol does not define a default port it returns -1.
+ *
+ * @return The default port of the current protocol.
+ */
+ public int getDefaultPort()
+ {
+ return ph.getDefaultPort();
+ }
+
+ /**
+ * Returns the protocol of the URL
+ *
+ * @return The specified protocol.
+ */
+ public String getProtocol()
+ {
+ return protocol;
+ }
+
+ /**
+ * Returns the ref (sometimes called the "# reference" or "anchor") portion
+ * of the URL.
+ *
+ * @return The ref
+ */
+ public String getRef()
+ {
+ return ref;
+ }
+
+ /**
+ * Returns the user information of the URL. This is the part of the host
+ * name before the '@'.
+ *
+ * @return the user at a particular host or null when no user defined.
+ */
+ public String getUserInfo()
+ {
+ if (userInfo != null)
+ return userInfo;
+ int at = (host == null) ? -1 : host.indexOf('@');
+ return at < 0 ? null : host.substring(0, at);
+ }
+
+ /**
+ * Returns the query of the URL. This is the part of the file before the
+ * '?'.
+ *
+ * @return the query part of the file, or null when there is no query part.
+ */
+ public String getQuery()
+ {
+ int quest = (file == null) ? -1 : file.indexOf('?');
+ return quest < 0 ? null : file.substring(quest + 1, file.length());
+ }
+
+ /**
+ * Returns a hashcode computed by the URLStreamHandler of this URL
+ *
+ * @return The hashcode for this URL.
+ */
+ public int hashCode()
+ {
+ if (hashCode != 0)
+ return hashCode; // Use cached value if available.
+ else
+ return ph.hashCode(this);
+ }
+
+ /**
+ * Returns a URLConnection object that represents a connection to the remote
+ * object referred to by the URL. The URLConnection is created by calling the
+ * openConnection() method of the protocol handler
+ *
+ * @return A URLConnection for this URL
+ *
+ * @exception IOException If an error occurs
+ */
+ public URLConnection openConnection() throws IOException
+ {
+ return ph.openConnection(this);
+ }
+
+ /**
+ * Opens a connection to this URL and returns an InputStream for reading
+ * from that connection
+ *
+ * @return An <code>InputStream</code> for this URL.
+ *
+ * @exception IOException If an error occurs
+ */
+ public InputStream openStream() throws IOException
+ {
+ return openConnection().getInputStream();
+ }
+
+ /**
+ * Tests whether or not another URL refers to the same "file" as this one.
+ * This will be true if and only if the passed object is not null, is a
+ * URL, and matches all fields but the ref (ie, protocol, host, port,
+ * and file);
+ *
+ * @param url The URL object to test with
+ *
+ * @return true if URL matches this URL's file, false otherwise
+ */
+ public boolean sameFile(URL url)
+ {
+ return ph.sameFile(this, url);
+ }
+
+ /**
+ * Sets the specified fields of the URL. This is not a public method so
+ * that only URLStreamHandlers can modify URL fields. This might be called
+ * by the <code>parseURL()</code> method in that class. URLs are otherwise
+ * constant. If the given protocol does not exist, it will keep the previously
+ * set protocol.
+ *
+ * @param protocol The protocol name for this URL
+ * @param host The hostname or IP address for this URL
+ * @param port The port number of this URL
+ * @param file The "file" portion of this URL.
+ * @param ref The anchor portion of this URL.
+ */
+ protected void set(String protocol, String host, int port, String file,
+ String ref)
+ {
+ URLStreamHandler protocolHandler = null;
+ protocol = protocol.toLowerCase();
+ if (! this.protocol.equals(protocol))
+ protocolHandler = getURLStreamHandler(protocol);
+
+ // It is an hidden feature of the JDK. If the protocol does not exist,
+ // we keep the previously initialized protocol.
+ if (protocolHandler != null)
+ {
+ this.ph = protocolHandler;
+ this.protocol = protocol;
+ }
+ this.authority = "";
+ this.port = port;
+ this.host = host;
+ this.file = file;
+ this.ref = ref;
+
+ if (host != null)
+ this.authority += host;
+ if (port >= 0)
+ this.authority += ":" + port;
+
+ hashCode = hashCode(); // Used for serialization.
+ }
+
+ /**
+ * Sets the specified fields of the URL. This is not a public method so
+ * that only URLStreamHandlers can modify URL fields. URLs are otherwise
+ * constant. If the given protocol does not exist, it will keep the previously
+ * set protocol.
+ *
+ * @param protocol The protocol name for this URL.
+ * @param host The hostname or IP address for this URL.
+ * @param port The port number of this URL.
+ * @param authority The authority of this URL.
+ * @param userInfo The user and password (if needed) of this URL.
+ * @param path The "path" portion of this URL.
+ * @param query The query of this URL.
+ * @param ref The anchor portion of this URL.
+ *
+ * @since 1.3
+ */
+ protected void set(String protocol, String host, int port, String authority,
+ String userInfo, String path, String query, String ref)
+ {
+ URLStreamHandler protocolHandler = null;
+ protocol = protocol.toLowerCase();
+ if (! this.protocol.equals(protocol))
+ protocolHandler = getURLStreamHandler(protocol);
+
+ // It is an hidden feature of the JDK. If the protocol does not exist,
+ // we keep the previously initialized protocol.
+ if (protocolHandler != null)
+ {
+ this.ph = protocolHandler;
+ this.protocol = protocol;
+ }
+ this.host = host;
+ this.userInfo = userInfo;
+ this.port = port;
+ this.authority = authority;
+ if (query == null)
+ this.file = path;
+ else
+ this.file = path + "?" + query;
+ this.ref = ref;
+ hashCode = hashCode(); // Used for serialization.
+ }
+
+ /**
+ * Sets the URLStreamHandlerFactory for this class. This factory is
+ * responsible for returning the appropriate protocol handler for
+ * a given URL.
+ *
+ * @param fac The URLStreamHandlerFactory class to use
+ *
+ * @exception Error If the factory is alread set.
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ */
+ public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory fac)
+ {
+ if (factory != null)
+ throw new Error("URLStreamHandlerFactory already set");
+
+ // Throw an exception if an extant security mgr precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+ factory = fac;
+ }
+
+ /**
+ * Returns a String representing this URL. The String returned is
+ * created by calling the protocol handler's toExternalForm() method.
+ *
+ * @return A string for this URL
+ */
+ public String toExternalForm()
+ {
+ // Identical to toString().
+ return ph.toExternalForm(this);
+ }
+
+ /**
+ * Returns a String representing this URL. Identical to toExternalForm().
+ * The value returned is created by the protocol handler's
+ * toExternalForm method. Overrides Object.toString()
+ *
+ * @return A string for this URL
+ */
+ public String toString()
+ {
+ // Identical to toExternalForm().
+ return ph.toExternalForm(this);
+ }
+
+ /**
+ * This internal method is used in two different constructors to load
+ * a protocol handler for this URL.
+ *
+ * @param protocol The protocol to load a handler for
+ *
+ * @return A URLStreamHandler for this protocol, or null when not found.
+ */
+ private static synchronized URLStreamHandler getURLStreamHandler(String protocol)
+ {
+ URLStreamHandler ph = null;
+
+ // First, see if a protocol handler is in our cache.
+ if (cache_handlers)
+ {
+ if ((ph = (URLStreamHandler) ph_cache.get(protocol)) != null)
+ return ph;
+ }
+
+ // If a non-default factory has been set, use it to find the protocol.
+ if (factory != null)
+ {
+ ph = factory.createURLStreamHandler(protocol);
+ }
+
+ // Non-default factory may have returned null or a factory wasn't set.
+ // Use the default search algorithm to find a handler for this protocol.
+ if (ph == null)
+ {
+ // Get the list of packages to check and append our default handler
+ // to it, along with the JDK specified default as a last resort.
+ // Except in very unusual environments the JDK specified one shouldn't
+ // ever be needed (or available).
+ String ph_search_path =
+ System.getProperty("java.protocol.handler.pkgs");
+
+ // Tack our default package on at the ends.
+ if (ph_search_path != null)
+ ph_search_path += "|" + DEFAULT_SEARCH_PATH;
+ else
+ ph_search_path = DEFAULT_SEARCH_PATH;
+
+ // Finally loop through our search path looking for a match.
+ StringTokenizer pkgPrefix = new StringTokenizer(ph_search_path, "|");
+
+ // Cache the systemClassLoader
+ if (systemClassLoader == null)
+ {
+ systemClassLoader = (ClassLoader) AccessController.doPrivileged
+ (new PrivilegedAction() {
+ public Object run()
+ {
+ return ClassLoader.getSystemClassLoader();
+ }
+ });
+ }
+
+ do
+ {
+ try
+ {
+ // Try to get a class from the system/application
+ // classloader, initialize it, make an instance
+ // and try to cast it to a URLStreamHandler.
+ String clsName =
+ (pkgPrefix.nextToken() + "." + protocol + ".Handler");
+ Class c = Class.forName(clsName, true, systemClassLoader);
+ ph = (URLStreamHandler) c.newInstance();
+ }
+ catch (ThreadDeath death)
+ {
+ throw death;
+ }
+ catch (Throwable t)
+ {
+ // Ignored.
+ }
+ }
+ while (ph == null && pkgPrefix.hasMoreTokens());
+ }
+
+ // Update the hashtable with the new protocol handler.
+ if (ph != null && cache_handlers)
+ ph_cache.put(protocol, ph);
+ else
+ ph = null;
+
+ return ph;
+ }
+
+ private void readObject(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException
+ {
+ ois.defaultReadObject();
+ this.ph = getURLStreamHandler(protocol);
+ if (this.ph == null)
+ throw new IOException("Handler for protocol " + protocol + " not found");
+ }
+
+ private void writeObject(ObjectOutputStream oos) throws IOException
+ {
+ oos.defaultWriteObject();
+ }
+
+ /**
+ * Returns the equivalent <code>URI</code> object for this <code>URL</code>.
+ * This is the same as calling <code>new URI(this.toString())</code>.
+ * RFC2396-compliant URLs are guaranteed a successful conversion to
+ * a <code>URI</code> instance. However, there are some values which
+ * form valid URLs, but which do not also form RFC2396-compliant URIs.
+ *
+ * @throws URISyntaxException if this URL is not RFC2396-compliant,
+ * and thus can not be successfully converted to a URI.
+ */
+ public URI toURI()
+ throws URISyntaxException
+ {
+ return new URI(toString());
+ }
+
+}
diff --git a/libjava/classpath/java/net/URLClassLoader.java b/libjava/classpath/java/net/URLClassLoader.java
new file mode 100644
index 00000000000..8ebc3e05dd7
--- /dev/null
+++ b/libjava/classpath/java/net/URLClassLoader.java
@@ -0,0 +1,1171 @@
+/* URLClassLoader.java -- ClassLoader that loads classes from one or more URLs
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.SecureClassLoader;
+import java.security.cert.Certificate;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+
+/**
+ * A secure class loader that can load classes and resources from
+ * multiple locations. Given an array of <code>URL</code>s this class
+ * loader will retrieve classes and resources by fetching them from
+ * possible remote locations. Each <code>URL</code> is searched in
+ * order in which it was added. If the file portion of the
+ * <code>URL</code> ends with a '/' character then it is interpreted
+ * as a base directory, otherwise it is interpreted as a jar file from
+ * which the classes/resources are resolved.
+ *
+ * <p>New instances can be created by two static
+ * <code>newInstance()</code> methods or by three public
+ * contructors. Both ways give the option to supply an initial array
+ * of <code>URL</code>s and (optionally) a parent classloader (that is
+ * different from the standard system class loader).</p>
+ *
+ * <p>Normally creating a <code>URLClassLoader</code> throws a
+ * <code>SecurityException</code> if a <code>SecurityManager</code> is
+ * installed and the <code>checkCreateClassLoader()</code> method does
+ * not return true. But the <code>newInstance()</code> methods may be
+ * used by any code as long as it has permission to acces the given
+ * <code>URL</code>s. <code>URLClassLoaders</code> created by the
+ * <code>newInstance()</code> methods also explicitly call the
+ * <code>checkPackageAccess()</code> method of
+ * <code>SecurityManager</code> if one is installed before trying to
+ * load a class. Note that only subclasses of
+ * <code>URLClassLoader</code> can add new URLs after the
+ * URLClassLoader had been created. But it is always possible to get
+ * an array of all URLs that the class loader uses to resolve classes
+ * and resources by way of the <code>getURLs()</code> method.</p>
+ *
+ * <p>Open issues:
+ * <ul>
+ *
+ * <li>Should the URLClassLoader actually add the locations found in
+ * the manifest or is this the responsibility of some other
+ * loader/(sub)class? (see <a
+ * href="http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html">
+ * Extension Mechanism Architecture - Bundles Extensions</a>)</li>
+ *
+ * <li>How does <code>definePackage()</code> and sealing work
+ * precisely?</li>
+ *
+ * <li>We save and use the security context (when a created by
+ * <code>newInstance()</code> but do we have to use it in more
+ * places?</li>
+ *
+ * <li>The use of <code>URLStreamHandler</code>s has not been tested.</li>
+ *
+ * </ul>
+ * </p>
+ *
+ * @since 1.2
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @author Wu Gansha (gansha.wu@intel.com)
+ */
+public class URLClassLoader extends SecureClassLoader
+{
+ // Class Variables
+
+ /**
+ * A global cache to store mappings between URLLoader and URL,
+ * so we can avoid do all the homework each time the same URL
+ * comes.
+ * XXX - Keeps these loaders forever which prevents garbage collection.
+ */
+ private static HashMap urlloaders = new HashMap();
+
+ /**
+ * A cache to store mappings between handler factory and its
+ * private protocol handler cache (also a HashMap), so we can avoid
+ * create handlers each time the same protocol comes.
+ */
+ private static HashMap factoryCache = new HashMap(5);
+
+ // Instance variables
+
+ /** Locations to load classes from */
+ private final Vector urls = new Vector();
+
+ /**
+ * Store pre-parsed information for each url into this vector: each
+ * element is a URL loader. A jar file has its own class-path
+ * attribute which adds to the URLs that will be searched, but this
+ * does not add to the list of urls.
+ */
+ private final Vector urlinfos = new Vector();
+
+ /** Factory used to get the protocol handlers of the URLs */
+ private final URLStreamHandlerFactory factory;
+
+ /**
+ * The security context when created from <code>newInstance()</code>
+ * or null when created through a normal constructor or when no
+ * <code>SecurityManager</code> was installed.
+ */
+ private final AccessControlContext securityContext;
+
+ // Helper classes
+
+ /**
+ * A <code>URLLoader</code> contains all logic to load resources from a
+ * given base <code>URL</code>.
+ */
+ abstract static class URLLoader
+ {
+ /**
+ * Our classloader to get info from if needed.
+ */
+ final URLClassLoader classloader;
+
+ /**
+ * The base URL from which all resources are loaded.
+ */
+ final URL baseURL;
+
+ /**
+ * A <code>CodeSource</code> without any associated certificates.
+ * It is common for classes to not have certificates associated
+ * with them. If they come from the same <code>URLLoader</code>
+ * then it is safe to share the associated <code>CodeSource</code>
+ * between them since <code>CodeSource</code> is immutable.
+ */
+ final CodeSource noCertCodeSource;
+
+ URLLoader(URLClassLoader classloader, URL baseURL)
+ {
+ this(classloader, baseURL, baseURL);
+ }
+
+ URLLoader(URLClassLoader classloader, URL baseURL, URL overrideURL)
+ {
+ this.classloader = classloader;
+ this.baseURL = baseURL;
+ this.noCertCodeSource = new CodeSource(overrideURL, null);
+ }
+
+ /**
+ * Returns a <code>Resource</code> loaded by this
+ * <code>URLLoader</code>, or <code>null</code> when no
+ * <code>Resource</code> with the given name exists.
+ */
+ abstract Resource getResource(String s);
+
+ /**
+ * Returns the <code>Manifest</code> associated with the
+ * <code>Resource</code>s loaded by this <code>URLLoader</code> or
+ * <code>null</code> there is no such <code>Manifest</code>.
+ */
+ Manifest getManifest()
+ {
+ return null;
+ }
+
+ Vector getClassPath()
+ {
+ return null;
+ }
+ }
+
+ /**
+ * A <code>Resource</code> represents a resource in some
+ * <code>URLLoader</code>. It also contains all information (e.g.,
+ * <code>URL</code>, <code>CodeSource</code>, <code>Manifest</code> and
+ * <code>InputStream</code>) that is necessary for loading resources
+ * and creating classes from a <code>URL</code>.
+ */
+ abstract static class Resource
+ {
+ final URLLoader loader;
+ final String name;
+
+ Resource(URLLoader loader, String name)
+ {
+ this.loader = loader;
+ this.name = name;
+ }
+
+ /**
+ * Returns the non-null <code>CodeSource</code> associated with
+ * this resource.
+ */
+ CodeSource getCodeSource()
+ {
+ Certificate[] certs = getCertificates();
+ if (certs == null)
+ return loader.noCertCodeSource;
+ else
+ return new CodeSource(loader.baseURL, certs);
+ }
+
+ /**
+ * Returns <code>Certificates</code> associated with this
+ * resource, or null when there are none.
+ */
+ Certificate[] getCertificates()
+ {
+ return null;
+ }
+
+ /**
+ * Return a <code>URL</code> that can be used to access this resource.
+ */
+ abstract URL getURL();
+
+ /**
+ * Returns the size of this <code>Resource</code> in bytes or
+ * <code>-1</code> when unknown.
+ */
+ abstract int getLength();
+
+ /**
+ * Returns the non-null <code>InputStream</code> through which
+ * this resource can be loaded.
+ */
+ abstract InputStream getInputStream() throws IOException;
+ }
+
+ /**
+ * A <code>JarURLLoader</code> is a type of <code>URLLoader</code>
+ * only loading from jar url.
+ */
+ static final class JarURLLoader extends URLLoader
+ {
+ final JarFile jarfile; // The jar file for this url
+ final URL baseJarURL; // Base jar: url for all resources loaded from jar
+
+ Vector classPath; // The "Class-Path" attribute of this Jar's manifest
+
+ public JarURLLoader(URLClassLoader classloader, URL baseURL)
+ {
+ super(classloader, baseURL);
+
+ // Cache url prefix for all resources in this jar url.
+ String external = baseURL.toExternalForm();
+ StringBuffer sb = new StringBuffer(external.length() + 6);
+ sb.append("jar:");
+ sb.append(external);
+ sb.append("!/");
+ String jarURL = sb.toString();
+
+ this.classPath = null;
+ URL baseJarURL = null;
+ JarFile jarfile = null;
+ try
+ {
+ baseJarURL =
+ new URL(null, jarURL, classloader.getURLStreamHandler("jar"));
+
+ jarfile =
+ ((JarURLConnection) baseJarURL.openConnection()).getJarFile();
+
+ Manifest manifest;
+ Attributes attributes;
+ String classPathString;
+
+ if ((manifest = jarfile.getManifest()) != null
+ && (attributes = manifest.getMainAttributes()) != null
+ && ((classPathString
+ = attributes.getValue(Attributes.Name.CLASS_PATH))
+ != null))
+ {
+ this.classPath = new Vector();
+
+ StringTokenizer st = new StringTokenizer(classPathString, " ");
+ while (st.hasMoreElements ())
+ {
+ String e = st.nextToken ();
+ try
+ {
+ URL url = new URL(baseURL, e);
+ this.classPath.add(url);
+ }
+ catch (java.net.MalformedURLException xx)
+ {
+ // Give up
+ }
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ /* ignored */
+ }
+
+ this.baseJarURL = baseJarURL;
+ this.jarfile = jarfile;
+ }
+
+ /** get resource with the name "name" in the jar url */
+ Resource getResource(String name)
+ {
+ if (jarfile == null)
+ return null;
+
+ if (name.startsWith("/"))
+ name = name.substring(1);
+
+ JarEntry je = jarfile.getJarEntry(name);
+ if (je != null)
+ return new JarURLResource(this, name, je);
+ else
+ return null;
+ }
+
+ Manifest getManifest()
+ {
+ try
+ {
+ return (jarfile == null) ? null : jarfile.getManifest();
+ }
+ catch (IOException ioe)
+ {
+ return null;
+ }
+ }
+
+ Vector getClassPath()
+ {
+ return classPath;
+ }
+ }
+
+ static final class JarURLResource extends Resource
+ {
+ private final JarEntry entry;
+
+ JarURLResource(JarURLLoader loader, String name, JarEntry entry)
+ {
+ super(loader, name);
+ this.entry = entry;
+ }
+
+ InputStream getInputStream() throws IOException
+ {
+ return ((JarURLLoader) loader).jarfile.getInputStream(entry);
+ }
+
+ int getLength()
+ {
+ return (int) entry.getSize();
+ }
+
+ Certificate[] getCertificates()
+ {
+ // We have to get the entry from the jar file again, because the
+ // certificates will not be available until the entire entry has
+ // been read.
+ return ((JarEntry) ((JarURLLoader) loader).jarfile.getEntry(name))
+ .getCertificates();
+ }
+
+ URL getURL()
+ {
+ try
+ {
+ return new URL(((JarURLLoader) loader).baseJarURL, name,
+ loader.classloader.getURLStreamHandler("jar"));
+ }
+ catch (MalformedURLException e)
+ {
+ InternalError ie = new InternalError();
+ ie.initCause(e);
+ throw ie;
+ }
+ }
+ }
+
+ /**
+ * Loader for remote directories.
+ */
+ static final class RemoteURLLoader extends URLLoader
+ {
+ private final String protocol;
+
+ RemoteURLLoader(URLClassLoader classloader, URL url)
+ {
+ super(classloader, url);
+ protocol = url.getProtocol();
+ }
+
+ /**
+ * Get a remote resource.
+ * Returns null if no such resource exists.
+ */
+ Resource getResource(String name)
+ {
+ try
+ {
+ URL url =
+ new URL(baseURL, name, classloader.getURLStreamHandler(protocol));
+ URLConnection connection = url.openConnection();
+
+ // Open the connection and check the stream
+ // just to be sure it exists.
+ int length = connection.getContentLength();
+ InputStream stream = connection.getInputStream();
+
+ // We can do some extra checking if it is a http request
+ if (connection instanceof HttpURLConnection)
+ {
+ int response =
+ ((HttpURLConnection) connection).getResponseCode();
+ if (response / 100 != 2)
+ return null;
+ }
+
+ if (stream != null)
+ return new RemoteResource(this, name, url, stream, length);
+ else
+ return null;
+ }
+ catch (IOException ioe)
+ {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * A resource from some remote location.
+ */
+ static final class RemoteResource extends Resource
+ {
+ private final URL url;
+ private final InputStream stream;
+ private final int length;
+
+ RemoteResource(RemoteURLLoader loader, String name, URL url,
+ InputStream stream, int length)
+ {
+ super(loader, name);
+ this.url = url;
+ this.stream = stream;
+ this.length = length;
+ }
+
+ InputStream getInputStream() throws IOException
+ {
+ return stream;
+ }
+
+ public int getLength()
+ {
+ return length;
+ }
+
+ public URL getURL()
+ {
+ return url;
+ }
+ }
+
+ /**
+ * A <code>FileURLLoader</code> is a type of <code>URLLoader</code>
+ * only loading from file url.
+ */
+ static final class FileURLLoader extends URLLoader
+ {
+ File dir; //the file for this file url
+
+ FileURLLoader(URLClassLoader classloader, URL url)
+ {
+ super(classloader, url);
+ dir = new File(baseURL.getFile());
+ }
+
+ /** get resource with the name "name" in the file url */
+ Resource getResource(String name)
+ {
+ File file = new File(dir, name);
+ if (file.exists() && !file.isDirectory())
+ return new FileResource(this, name, file);
+ return null;
+ }
+ }
+
+ static final class FileResource extends Resource
+ {
+ final File file;
+
+ FileResource(FileURLLoader loader, String name, File file)
+ {
+ super(loader, name);
+ this.file = file;
+ }
+
+ InputStream getInputStream() throws IOException
+ {
+ return new FileInputStream(file);
+ }
+
+ public int getLength()
+ {
+ return (int) file.length();
+ }
+
+ public URL getURL()
+ {
+ try
+ {
+ return new URL(loader.baseURL, name,
+ loader.classloader.getURLStreamHandler("file"));
+ }
+ catch (MalformedURLException e)
+ {
+ InternalError ie = new InternalError();
+ ie.initCause(e);
+ throw ie;
+ }
+ }
+ }
+
+ // Constructors
+
+ /**
+ * Creates a URLClassLoader that gets classes from the supplied URLs.
+ * To determine if this classloader may be created the constructor of
+ * the super class (<code>SecureClassLoader</code>) is called first, which
+ * can throw a SecurityException. Then the supplied URLs are added
+ * in the order given to the URLClassLoader which uses these URLs to
+ * load classes and resources (after using the default parent ClassLoader).
+ *
+ * @exception SecurityException if the SecurityManager disallows the
+ * creation of a ClassLoader.
+ * @param urls Locations that should be searched by this ClassLoader when
+ * resolving Classes or Resources.
+ * @see SecureClassLoader
+ */
+ public URLClassLoader(URL[] urls) throws SecurityException
+ {
+ super();
+ this.factory = null;
+ this.securityContext = null;
+ addURLs(urls);
+ }
+
+ /**
+ * Creates a <code>URLClassLoader</code> that gets classes from the supplied
+ * <code>URL</code>s.
+ * To determine if this classloader may be created the constructor of
+ * the super class (<code>SecureClassLoader</code>) is called first, which
+ * can throw a SecurityException. Then the supplied URLs are added
+ * in the order given to the URLClassLoader which uses these URLs to
+ * load classes and resources (after using the supplied parent ClassLoader).
+ * @exception SecurityException if the SecurityManager disallows the
+ * creation of a ClassLoader.
+ * @exception SecurityException
+ * @param urls Locations that should be searched by this ClassLoader when
+ * resolving Classes or Resources.
+ * @param parent The parent class loader used before trying this class
+ * loader.
+ * @see SecureClassLoader
+ */
+ public URLClassLoader(URL[] urls, ClassLoader parent)
+ throws SecurityException
+ {
+ super(parent);
+ this.factory = null;
+ this.securityContext = null;
+ addURLs(urls);
+ }
+
+ // Package-private to avoid a trampoline constructor.
+ /**
+ * Package-private constructor used by the static
+ * <code>newInstance(URL[])</code> method. Creates an
+ * <code>URLClassLoader</code> with the given parent but without any
+ * <code>URL</code>s yet. This is used to bypass the normal security
+ * check for creating classloaders, but remembers the security
+ * context which will be used when defining classes. The
+ * <code>URL</code>s to load from must be added by the
+ * <code>newInstance()</code> method in the security context of the
+ * caller.
+ *
+ * @param securityContext the security context of the unprivileged code.
+ */
+ URLClassLoader(ClassLoader parent, AccessControlContext securityContext)
+ {
+ super(parent);
+ this.factory = null;
+ this.securityContext = securityContext;
+ }
+
+ /**
+ * Creates a URLClassLoader that gets classes from the supplied URLs.
+ * To determine if this classloader may be created the constructor of
+ * the super class (<CODE>SecureClassLoader</CODE>) is called first, which
+ * can throw a SecurityException. Then the supplied URLs are added
+ * in the order given to the URLClassLoader which uses these URLs to
+ * load classes and resources (after using the supplied parent ClassLoader).
+ * It will use the supplied <CODE>URLStreamHandlerFactory</CODE> to get the
+ * protocol handlers of the supplied URLs.
+ * @exception SecurityException if the SecurityManager disallows the
+ * creation of a ClassLoader.
+ * @exception SecurityException
+ * @param urls Locations that should be searched by this ClassLoader when
+ * resolving Classes or Resources.
+ * @param parent The parent class loader used before trying this class
+ * loader.
+ * @param factory Used to get the protocol handler for the URLs.
+ * @see SecureClassLoader
+ */
+ public URLClassLoader(URL[] urls, ClassLoader parent,
+ URLStreamHandlerFactory factory)
+ throws SecurityException
+ {
+ super(parent);
+ this.securityContext = null;
+ this.factory = factory;
+ addURLs(urls);
+
+ // If this factory is still not in factoryCache, add it,
+ // since we only support three protocols so far, 5 is enough
+ // for cache initial size
+ synchronized (factoryCache)
+ {
+ if (factory != null && factoryCache.get(factory) == null)
+ factoryCache.put(factory, new HashMap(5));
+ }
+ }
+
+ // Methods
+
+ /**
+ * Adds a new location to the end of the internal URL store.
+ * @param newUrl the location to add
+ */
+ protected void addURL(URL newUrl)
+ {
+ urls.add(newUrl);
+ addURLImpl(newUrl);
+ }
+
+ private void addURLImpl(URL newUrl)
+ {
+ synchronized (urlloaders)
+ {
+ if (newUrl == null)
+ return; // Silently ignore...
+
+ // Reset the toString() value.
+ thisString = null;
+
+ // Check global cache to see if there're already url loader
+ // for this url.
+ URLLoader loader = (URLLoader) urlloaders.get(newUrl);
+ if (loader == null)
+ {
+ String file = newUrl.getFile();
+ String protocol = newUrl.getProtocol();
+
+ // Check that it is not a directory
+ if (! (file.endsWith("/") || file.endsWith(File.separator)))
+ loader = new JarURLLoader(this, newUrl);
+ else if ("file".equals(protocol))
+ loader = new FileURLLoader(this, newUrl);
+ else
+ loader = new RemoteURLLoader(this, newUrl);
+
+ // Cache it.
+ urlloaders.put(newUrl, loader);
+ }
+
+ urlinfos.add(loader);
+
+ Vector extraUrls = loader.getClassPath();
+ if (extraUrls != null)
+ {
+ Iterator it = extraUrls.iterator();
+ while (it.hasNext())
+ {
+ URL url = (URL)it.next();
+ URLLoader extraLoader = (URLLoader) urlloaders.get(url);
+ if (! urlinfos.contains (extraLoader))
+ addURLImpl(url);
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Adds an array of new locations to the end of the internal URL store.
+ * @param newUrls the locations to add
+ */
+ private void addURLs(URL[] newUrls)
+ {
+ for (int i = 0; i < newUrls.length; i++)
+ addURL(newUrls[i]);
+ }
+
+ /**
+ * Defines a Package based on the given name and the supplied manifest
+ * information. The manifest indicates the tile, version and
+ * vendor information of the specification and implementation and wheter the
+ * package is sealed. If the Manifest indicates that the package is sealed
+ * then the Package will be sealed with respect to the supplied URL.
+ *
+ * @exception IllegalArgumentException If this package name already exists
+ * in this class loader
+ * @param name The name of the package
+ * @param manifest The manifest describing the specification,
+ * implementation and sealing details of the package
+ * @param url the code source url to seal the package
+ * @return the defined Package
+ */
+ protected Package definePackage(String name, Manifest manifest, URL url)
+ throws IllegalArgumentException
+ {
+ Attributes attr = manifest.getMainAttributes();
+ String specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);
+ String specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
+ String specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);
+ String implTitle = attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
+ String implVersion = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+ String implVendor = attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
+
+ // Look if the Manifest indicates that this package is sealed
+ // XXX - most likely not completely correct!
+ // Shouldn't we also check the sealed attribute of the complete jar?
+ // http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html#bundled
+ // But how do we get that jar manifest here?
+ String sealed = attr.getValue(Attributes.Name.SEALED);
+ if ("false".equals(sealed))
+ // make sure that the URL is null so the package is not sealed
+ url = null;
+
+ return definePackage(name, specTitle, specVersion, specVendor, implTitle,
+ implVersion, implVendor, url);
+ }
+
+ /**
+ * Finds (the first) class by name from one of the locations. The locations
+ * are searched in the order they were added to the URLClassLoader.
+ *
+ * @param className the classname to find
+ * @exception ClassNotFoundException when the class could not be found or
+ * loaded
+ * @return a Class object representing the found class
+ */
+ protected Class findClass(final String className)
+ throws ClassNotFoundException
+ {
+ // Just try to find the resource by the (almost) same name
+ String resourceName = className.replace('.', '/') + ".class";
+ Resource resource = findURLResource(resourceName);
+ if (resource == null)
+ throw new ClassNotFoundException(className + " not found in " + this);
+
+ // Try to read the class data, create the CodeSource, Package and
+ // construct the class (and watch out for those nasty IOExceptions)
+ try
+ {
+ byte[] data;
+ InputStream in = resource.getInputStream();
+ try
+ {
+ int length = resource.getLength();
+ if (length != -1)
+ {
+ // We know the length of the data.
+ // Just try to read it in all at once
+ data = new byte[length];
+ int pos = 0;
+ while (length - pos > 0)
+ {
+ int len = in.read(data, pos, length - pos);
+ if (len == -1)
+ throw new EOFException("Not enough data reading from: "
+ + in);
+ pos += len;
+ }
+ }
+ else
+ {
+ // We don't know the data length.
+ // Have to read it in chunks.
+ ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
+ byte[] b = new byte[4096];
+ int l = 0;
+ while (l != -1)
+ {
+ l = in.read(b);
+ if (l != -1)
+ out.write(b, 0, l);
+ }
+ data = out.toByteArray();
+ }
+ }
+ finally
+ {
+ in.close();
+ }
+ final byte[] classData = data;
+
+ // Now get the CodeSource
+ final CodeSource source = resource.getCodeSource();
+
+ // Find out package name
+ String packageName = null;
+ int lastDot = className.lastIndexOf('.');
+ if (lastDot != -1)
+ packageName = className.substring(0, lastDot);
+
+ if (packageName != null && getPackage(packageName) == null)
+ {
+ // define the package
+ Manifest manifest = resource.loader.getManifest();
+ if (manifest == null)
+ definePackage(packageName, null, null, null, null, null, null,
+ null);
+ else
+ definePackage(packageName, manifest, resource.loader.baseURL);
+ }
+
+ // And finally construct the class!
+ SecurityManager sm = System.getSecurityManager();
+ Class result = null;
+ if (sm != null && securityContext != null)
+ {
+ result = (Class)AccessController.doPrivileged
+ (new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return defineClass(className, classData,
+ 0, classData.length,
+ source);
+ }
+ }, securityContext);
+ }
+ else
+ result = defineClass(className, classData, 0, classData.length, source);
+
+ super.setSigners(result, resource.getCertificates());
+ return result;
+ }
+ catch (IOException ioe)
+ {
+ ClassNotFoundException cnfe;
+ cnfe = new ClassNotFoundException(className + " not found in " + this);
+ cnfe.initCause(ioe);
+ throw cnfe;
+ }
+ }
+
+ // Cached String representation of this URLClassLoader
+ private String thisString;
+
+ /**
+ * Returns a String representation of this URLClassLoader giving the
+ * actual Class name, the URLs that are searched and the parent
+ * ClassLoader.
+ */
+ public String toString()
+ {
+ synchronized (urlloaders)
+ {
+ if (thisString == null)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.getClass().getName());
+ sb.append("{urls=[" );
+ URL[] thisURLs = getURLs();
+ for (int i = 0; i < thisURLs.length; i++)
+ {
+ sb.append(thisURLs[i]);
+ if (i < thisURLs.length - 1)
+ sb.append(',');
+ }
+ sb.append(']');
+ sb.append(", parent=");
+ sb.append(getParent());
+ sb.append('}');
+ thisString = sb.toString();
+ }
+ return thisString;
+ }
+ }
+
+ /**
+ * Finds the first occurrence of a resource that can be found. The locations
+ * are searched in the order they were added to the URLClassLoader.
+ *
+ * @param resourceName the resource name to look for
+ * @return the URLResource for the resource if found, null otherwise
+ */
+ private Resource findURLResource(String resourceName)
+ {
+ int max = urlinfos.size();
+ for (int i = 0; i < max; i++)
+ {
+ URLLoader loader = (URLLoader) urlinfos.elementAt(i);
+ if (loader == null)
+ continue;
+
+ Resource resource = loader.getResource(resourceName);
+ if (resource != null)
+ return resource;
+ }
+ return null;
+ }
+
+ /**
+ * Finds the first occurrence of a resource that can be found.
+ *
+ * @param resourceName the resource name to look for
+ * @return the URL if found, null otherwise
+ */
+ public URL findResource(String resourceName)
+ {
+ Resource resource = findURLResource(resourceName);
+ if (resource != null)
+ return resource.getURL();
+
+ // Resource not found
+ return null;
+ }
+
+ /**
+ * If the URLStreamHandlerFactory has been set this return the appropriate
+ * URLStreamHandler for the given protocol, if not set returns null.
+ *
+ * @param protocol the protocol for which we need a URLStreamHandler
+ * @return the appropriate URLStreamHandler or null
+ */
+ URLStreamHandler getURLStreamHandler(String protocol)
+ {
+ if (factory == null)
+ return null;
+
+ URLStreamHandler handler;
+ synchronized (factoryCache)
+ {
+ // Check if there're handler for the same protocol in cache.
+ HashMap cache = (HashMap) factoryCache.get(factory);
+ handler = (URLStreamHandler) cache.get(protocol);
+ if (handler == null)
+ {
+ // Add it to cache.
+ handler = factory.createURLStreamHandler(protocol);
+ cache.put(protocol, handler);
+ }
+ }
+ return handler;
+ }
+
+ /**
+ * Finds all the resources with a particular name from all the locations.
+ *
+ * @exception IOException when an error occurs accessing one of the
+ * locations
+ * @param resourceName the name of the resource to lookup
+ * @return a (possible empty) enumeration of URLs where the resource can be
+ * found
+ */
+ public Enumeration findResources(String resourceName)
+ throws IOException
+ {
+ Vector resources = new Vector();
+ int max = urlinfos.size();
+ for (int i = 0; i < max; i++)
+ {
+ URLLoader loader = (URLLoader) urlinfos.elementAt(i);
+ Resource resource = loader.getResource(resourceName);
+ if (resource != null)
+ resources.add(resource.getURL());
+ }
+ return resources.elements();
+ }
+
+ /**
+ * Returns the permissions needed to access a particular code
+ * source. These permissions includes those returned by
+ * <code>SecureClassLoader.getPermissions()</code> and the actual
+ * permissions to access the objects referenced by the URL of the
+ * code source. The extra permissions added depend on the protocol
+ * and file portion of the URL in the code source. If the URL has
+ * the "file" protocol ends with a '/' character then it must be a
+ * directory and a file Permission to read everything in that
+ * directory and all subdirectories is added. If the URL had the
+ * "file" protocol and doesn't end with a '/' character then it must
+ * be a normal file and a file permission to read that file is
+ * added. If the <code>URL</code> has any other protocol then a
+ * socket permission to connect and accept connections from the host
+ * portion of the URL is added.
+ *
+ * @param source The codesource that needs the permissions to be accessed
+ * @return the collection of permissions needed to access the code resource
+ * @see java.security.SecureClassLoader#getPermissions()
+ */
+ protected PermissionCollection getPermissions(CodeSource source)
+ {
+ // XXX - This implementation does exactly as the Javadoc describes.
+ // But maybe we should/could use URLConnection.getPermissions()?
+ // First get the permissions that would normally be granted
+ PermissionCollection permissions = super.getPermissions(source);
+
+ // Now add any extra permissions depending on the URL location.
+ URL url = source.getLocation();
+ String protocol = url.getProtocol();
+ if (protocol.equals("file"))
+ {
+ String file = url.getFile();
+
+ // If the file end in / it must be an directory.
+ if (file.endsWith("/") || file.endsWith(File.separator))
+ {
+ // Grant permission to read everything in that directory and
+ // all subdirectories.
+ permissions.add(new FilePermission(file + "-", "read"));
+ }
+ else
+ {
+ // It is a 'normal' file.
+ // Grant permission to access that file.
+ permissions.add(new FilePermission(file, "read"));
+ }
+ }
+ else
+ {
+ // Grant permission to connect to and accept connections from host
+ String host = url.getHost();
+ if (host != null)
+ permissions.add(new SocketPermission(host, "connect,accept"));
+ }
+
+ return permissions;
+ }
+
+ /**
+ * Returns all the locations that this class loader currently uses the
+ * resolve classes and resource. This includes both the initially supplied
+ * URLs as any URLs added later by the loader.
+ * @return All the currently used URLs
+ */
+ public URL[] getURLs()
+ {
+ return (URL[]) urls.toArray(new URL[urls.size()]);
+ }
+
+ /**
+ * Creates a new instance of a <code>URLClassLoader</code> that gets
+ * classes from the supplied <code>URL</code>s. This class loader
+ * will have as parent the standard system class loader.
+ *
+ * @param urls the initial URLs used to resolve classes and
+ * resources
+ *
+ * @return the class loader
+ *
+ * @exception SecurityException when the calling code does not have
+ * permission to access the given <code>URL</code>s
+ */
+ public static URLClassLoader newInstance(URL[] urls)
+ throws SecurityException
+ {
+ return newInstance(urls, null);
+ }
+
+ /**
+ * Creates a new instance of a <code>URLClassLoader</code> that gets
+ * classes from the supplied <code>URL</code>s and with the supplied
+ * loader as parent class loader.
+ *
+ * @param urls the initial URLs used to resolve classes and
+ * resources
+ * @param parent the parent class loader
+ *
+ * @return the class loader
+ *
+ * @exception SecurityException when the calling code does not have
+ * permission to access the given <code>URL</code>s
+ */
+ public static URLClassLoader newInstance(URL[] urls, final ClassLoader parent)
+ throws SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null)
+ return new URLClassLoader(urls, parent);
+ else
+ {
+ final Object securityContext = sm.getSecurityContext();
+
+ // XXX - What to do with anything else then an AccessControlContext?
+ if (! (securityContext instanceof AccessControlContext))
+ throw new SecurityException("securityContext must be AccessControlContext: "
+ + securityContext);
+
+ URLClassLoader loader =
+ (URLClassLoader) AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return new URLClassLoader(parent,
+ (AccessControlContext) securityContext);
+ }
+ });
+ loader.addURLs(urls);
+ return loader;
+ }
+ }
+}
diff --git a/libjava/classpath/java/net/URLConnection.java b/libjava/classpath/java/net/URLConnection.java
new file mode 100644
index 00000000000..0a12d588d9a
--- /dev/null
+++ b/libjava/classpath/java/net/URLConnection.java
@@ -0,0 +1,1021 @@
+/* URLConnection.java -- Abstract superclass for reading from URL's
+ Copyright (C) 1998, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.AllPermission;
+import java.security.Permission;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: One guessContentTypeFrom... methods not implemented.
+ * getContent method assumes content type from response; see comment there.
+ */
+/**
+ * This class models a connection that retrieves the information pointed
+ * to by a URL object. This is typically a connection to a remote node
+ * on the network, but could be a simple disk read.
+ * <p>
+ * A URLConnection object is normally created by calling the openConnection()
+ * method of a URL object. This method is somewhat misnamed because it does
+ * not actually open the connection. Instead, it return an unconnected
+ * instance of this object. The caller then has the opportunity to set
+ * various connection options prior to calling the actual connect() method.
+ * <p>
+ * After the connection has been opened, there are a number of methods in
+ * this class that access various attributes of the data, typically
+ * represented by headers sent in advance of the actual data itself.
+ * <p>
+ * Also of note are the getInputStream and getContent() methods which allow
+ * the caller to retrieve the actual data from the connection. Note that
+ * for some types of connections, writing is also allowed. The setDoOutput()
+ * method must be called prior to connecing in order to enable this, then
+ * the getOutputStream method called after the connection in order to
+ * obtain a stream to write the output to.
+ * <p>
+ * The getContent() method is of particular note. This method returns an
+ * Object that encapsulates the data returned. There is no way do determine
+ * the type of object that will be returned in advance. This is determined
+ * by the actual content handlers as described in the description of that
+ * method.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public abstract class URLConnection
+{
+ /**
+ * This is an object that maps filenames to MIME types. The interface
+ * to do this is implemented by this class, so just create an empty
+ * instance and store it here.
+ */
+ private static FileNameMap fileNameMap;
+
+ /**
+ * This is the ContentHandlerFactory set by the caller, if any
+ */
+ private static ContentHandlerFactory factory;
+
+ /**
+ * This is the default value that will be used to determine whether or
+ * not user interaction should be allowed.
+ */
+ private static boolean defaultAllowUserInteraction;
+
+ /**
+ * This is the default flag indicating whether or not to use caches to
+ * store the data returned from a server
+ */
+ private static boolean defaultUseCaches = true;
+
+ /**
+ * This variable determines whether or not interaction is allowed with
+ * the user. For example, to prompt for a username and password.
+ */
+ protected boolean allowUserInteraction;
+
+ /**
+ * Indicates whether or not a connection has been established to the
+ * destination specified in the URL
+ */
+ protected boolean connected;
+
+ /**
+ * Indicates whether or not input can be read from this URL
+ */
+ protected boolean doInput = true;
+
+ /**
+ * Indicates whether or not output can be sent to this URL
+ */
+ protected boolean doOutput;
+
+ /**
+ * If this flag is set, the protocol is allowed to cache data whenever
+ * it can (caching is not guaranteed). If it is not set, the protocol
+ * must a get a fresh copy of the data.
+ * <p>
+ * This field is set by the setUseCaches method and returned by the
+ * getUseCaches method.
+ *
+ * Its default value is that determined by the last invocation of
+ * setDefaultUseCaches
+ */
+ protected boolean useCaches;
+
+ /**
+ * If this value is non-zero, then the connection will only attempt to
+ * fetch the document pointed to by the URL if the document has been
+ * modified more recently than the date set in this variable. That date
+ * should be specified as the number of seconds since 1/1/1970 GMT.
+ */
+ protected long ifModifiedSince;
+
+ /**
+ * This is the URL associated with this connection
+ */
+ protected URL url;
+ private static SimpleDateFormat[] dateFormats;
+ private static boolean dateformats_initialized;
+
+ /* Cached ParsePosition, used when parsing dates. */
+ private ParsePosition position;
+
+ /**
+ * Creates a URL connection to a given URL. A real connection is not made.
+ * Use #connect to do this.
+ *
+ * @param url The Object to create the URL connection to
+ *
+ * @see URLConnection#connect()
+ */
+ protected URLConnection(URL url)
+ {
+ // Set up all our instance variables
+ this.url = url;
+ allowUserInteraction = defaultAllowUserInteraction;
+ useCaches = defaultUseCaches;
+ }
+
+ /**
+ * Establishes the actual connection to the URL associated with this
+ * connection object
+ *
+ * @exception IOException if an error occurs
+ */
+ public abstract void connect() throws IOException;
+
+ /**
+ * Returns the URL object associated with this connection
+ *
+ * @return The URL for this connection.
+ */
+ public URL getURL()
+ {
+ return url;
+ }
+
+ /**
+ * Returns the value of the content-length header field or -1 if the value
+ * is not known or not present.
+ *
+ * @return The content-length field
+ */
+ public int getContentLength()
+ {
+ return getHeaderFieldInt("content-length", -1);
+ }
+
+ /**
+ * Returns the the content-type of the data pointed to by the URL. This
+ * method first tries looking for a content-type header. If that is not
+ * present, it attempts to use the file name to determine the content's
+ * MIME type. If that is unsuccessful, the method returns null. The caller
+ * may then still attempt to determine the MIME type by a call to
+ * guessContentTypeFromStream()
+ *
+ * @return The content MIME type
+ */
+ public String getContentType()
+ {
+ return getHeaderField("content-type");
+ }
+
+ /**
+ * Returns the value of the content-encoding field or null if it is not
+ * known or not present.
+ *
+ * @return The content-encoding field
+ */
+ public String getContentEncoding()
+ {
+ return getHeaderField("content-encoding");
+ }
+
+ /**
+ * Returns the value of the expires header or 0 if not known or present.
+ * If populated, the return value is number of seconds since midnight
+ * on 1/1/1970 GMT.
+ *
+ * @return The expiration time.
+ */
+ public long getExpiration()
+ {
+ return getHeaderFieldDate("expires", 0L);
+ }
+
+ /**
+ * Returns the date of the document pointed to by the URL as reported in
+ * the date field of the header or 0 if the value is not present or not
+ * known. If populated, the return value is number of seconds since
+ * midnight on 1/1/1970 GMT.
+ *
+ * @return The document date
+ */
+ public long getDate()
+ {
+ return getHeaderFieldDate("date", 0L);
+ }
+
+ /**
+ * Returns the value of the last-modified header field or 0 if not known known
+ * or not present. If populated, the return value is the number of seconds
+ * since midnight on 1/1/1970.
+ *
+ * @return The last modified time
+ */
+ public long getLastModified()
+ {
+ return getHeaderFieldDate("last-modified", 0L);
+ }
+
+ /**
+ * Return a String representing the header value at the specified index.
+ * This allows the caller to walk the list of header fields. The analogous
+ * getHeaderFieldKey(int) method allows access to the corresponding key
+ * for this header field
+ *
+ * @param index The index into the header field list to retrieve the value for
+ *
+ * @return The header value or null if index is past the end of the headers
+ */
+ public String getHeaderField(int index)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ /**
+ * Returns a String representing the value of the header field having
+ * the named key. Returns null if the header field does not exist.
+ *
+ * @param name The key of the header field
+ *
+ * @return The value of the header field as a String
+ */
+ public String getHeaderField(String name)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ /**
+ * Returns a map of all sent header fields
+ *
+ * @return all header fields
+ *
+ * @since 1.4
+ */
+ public Map getHeaderFields()
+ {
+ // Subclasses for specific protocols override this.
+ return Collections.EMPTY_MAP;
+ }
+
+ /**
+ * Returns the value of the named header field as an int. If the field
+ * is not present or cannot be parsed as an integer, the default value
+ * will be returned.
+ *
+ * @param name The header field key to lookup
+ * @param defaultValue The defaule value if the header field is not found
+ * or can't be parsed.
+ *
+ * @return The value of the header field or the default value if the field
+ * is missing or malformed
+ */
+ public int getHeaderFieldInt(String name, int defaultValue)
+ {
+ String value = getHeaderField(name);
+
+ if (value == null)
+ return defaultValue;
+
+ try
+ {
+ return Integer.parseInt(value);
+ }
+ catch (NumberFormatException e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value of the named header field as a date. This date will
+ * be the number of seconds since midnight 1/1/1970 GMT or the default
+ * value if the field is not present or cannot be converted to a date.
+ *
+ * @param name The name of the header field
+ * @param defaultValue The default date if the header field is not found
+ * or can't be converted.
+ *
+ * @return Returns the date value of the header filed or the default value
+ * if the field is missing or malformed
+ */
+ public long getHeaderFieldDate(String name, long defaultValue)
+ {
+ if (! dateformats_initialized)
+ initializeDateFormats();
+
+ if (position == null)
+ position = new ParsePosition(0);
+
+ long result = defaultValue;
+ String str = getHeaderField(name);
+
+ if (str != null)
+ {
+ for (int i = 0; i < dateFormats.length; i++)
+ {
+ SimpleDateFormat df = dateFormats[i];
+ position.setIndex(0);
+ position.setErrorIndex(0);
+ Date date = df.parse(str, position);
+ if (date != null)
+ return date.getTime();
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a String representing the header key at the specified index.
+ * This allows the caller to walk the list of header fields. The analogous
+ * getHeaderField(int) method allows access to the corresponding value for
+ * this tag.
+ *
+ * @param index The index into the header field list to retrieve the key for.
+ *
+ * @return The header field key or null if index is past the end
+ * of the headers.
+ */
+ public String getHeaderFieldKey(int index)
+ {
+ // Subclasses for specific protocols override this.
+ return null;
+ }
+
+ /**
+ * This method returns the content of the document pointed to by the
+ * URL as an Object. The type of object depends on the MIME type of
+ * the object and particular content hander loaded. Most text type
+ * content handlers will return a subclass of
+ * <code>InputStream</code>. Images usually return a class that
+ * implements <code>ImageProducer</code>. There is not guarantee
+ * what type of object will be returned, however.
+ *
+ * <p>This class first determines the MIME type of the content, then
+ * creates a ContentHandler object to process the input. If the
+ * <code>ContentHandlerFactory</code> is set, then that object is
+ * called to load a content handler, otherwise a class called
+ * gnu.java.net.content.&lt;content_type&gt; is tried. If this
+ * handler does not exist, the method will simple return the
+ * <code>InputStream</code> returned by
+ * <code>getInputStream()</code>. Note that the default
+ * implementation of <code>getInputStream()</code> throws a
+ * <code>UnknownServiceException</code> so subclasses are encouraged
+ * to override this method.</p>
+ *
+ * @return the content
+ *
+ * @exception IOException If an error with the connection occurs.
+ * @exception UnknownServiceException If the protocol does not support the
+ * content type at all.
+ */
+ public Object getContent() throws IOException
+ {
+ if (!connected)
+ connect();
+
+ // FIXME: Doc indicates that other criteria should be applied as
+ // heuristics to determine the true content type, e.g. see
+ // guessContentTypeFromName() and guessContentTypeFromStream methods
+ // as well as FileNameMap class & fileNameMap field & get/set methods.
+ String type = getContentType();
+ ContentHandler ch = getContentHandler(type);
+
+ if (ch != null)
+ return ch.getContent(this);
+
+ return getInputStream();
+ }
+
+ /**
+ * Retrieves the content of this URLConnection
+ *
+ * @param classes The allowed classes for the content
+ *
+ * @return the content
+ *
+ * @exception IOException If an error occurs
+ * @exception UnknownServiceException If the protocol does not support the
+ * content type
+ */
+ public Object getContent(Class[] classes) throws IOException
+ {
+ // FIXME: implement this
+ return getContent();
+ }
+
+ /**
+ * This method returns a <code>Permission</code> object representing the
+ * permissions required to access this URL. This method returns
+ * <code>java.security.AllPermission</code> by default. Subclasses should
+ * override it to return a more specific permission. For example, an
+ * HTTP URL should return an instance of <code>SocketPermission</code>
+ * for the appropriate host and port.
+ * <p>
+ * Note that because of items such as HTTP redirects, the permission
+ * object returned might be different before and after connecting.
+ *
+ * @return A Permission object
+ *
+ * @exception IOException If the computation of the permission requires
+ * network or file I/O and an exception occurs while computing it
+ */
+ public Permission getPermission() throws IOException
+ {
+ // Subclasses may override this.
+ return new AllPermission();
+ }
+
+ /**
+ * Returns an InputStream for this connection. As this default
+ * implementation returns null, subclasses should override this method
+ *
+ * @return An InputStream for this connection
+ *
+ * @exception IOException If an error occurs
+ * @exception UnknownServiceException If the protocol does not support input
+ */
+ public InputStream getInputStream() throws IOException
+ {
+ // Subclasses for specific protocols override this.
+ throw new UnknownServiceException("Protocol " + url.getProtocol()
+ + " does not support input.");
+ }
+
+ /**
+ * Returns an OutputStream for this connection. As this default
+ * implementation returns null, subclasses should override this method
+ *
+ * @return An OutputStream for this connection
+ *
+ * @exception IOException If an error occurs
+ * @exception UnknownServiceException If the protocol does not support output
+ */
+ public OutputStream getOutputStream() throws IOException
+ {
+ // Subclasses for specific protocols override this.
+ throw new UnknownServiceException("Protocol " + url.getProtocol()
+ + " does not support output.");
+ }
+
+ /**
+ * The methods prints the value of this object as a String by calling the
+ * toString() method of its associated URL. Overrides Object.toString()
+ *
+ * @return A String representation of this object
+ */
+ public String toString()
+ {
+ return this.getClass().getName() + ":" + url.toString();
+ }
+
+ /**
+ * Returns the value of a flag indicating whether or not input is going
+ * to be done for this connection. This default to true unless the
+ * doOutput flag is set to false, in which case this defaults to false.
+ *
+ * @param input <code>true</code> if input is to be done,
+ * <code>false</code> otherwise
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setDoInput(boolean input)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ doInput = input;
+ }
+
+ /**
+ * Returns the value of a flag indicating whether or not input is going
+ * to be done for this connection. This default to true unless the
+ * doOutput flag is set to false, in which case this defaults to false.
+ *
+ * @return true if input is to be done, false otherwise
+ */
+ public boolean getDoInput()
+ {
+ return doInput;
+ }
+
+ /**
+ * Returns a boolean flag indicating whether or not output will be done
+ * on this connection. The default value is false, so this method can
+ * be used to override the default
+ *
+ * @param output ture if output is to be done, false otherwise
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setDoOutput(boolean output)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ doOutput = output;
+ }
+
+ /**
+ * Returns a boolean flag indicating whether or not output will be done
+ * on this connection. This defaults to false.
+ *
+ * @return true if output is to be done, false otherwise
+ */
+ public boolean getDoOutput()
+ {
+ return doOutput;
+ }
+
+ /**
+ * Sets a boolean flag indicating whether or not user interaction is
+ * allowed for this connection. (For example, in order to prompt for
+ * username and password info.
+ *
+ * @param allow true if user interaction should be allowed, false otherwise.
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setAllowUserInteraction(boolean allow)
+ {
+ allowUserInteraction = allow;
+ }
+
+ /**
+ * Returns a boolean flag indicating whether or not user interaction is
+ * allowed for this connection. (For example, in order to prompt for
+ * username and password info.
+ *
+ * @return true if user interaction is allowed, false otherwise
+ */
+ public boolean getAllowUserInteraction()
+ {
+ return allowUserInteraction;
+ }
+
+ /**
+ * Sets the default flag for whether or not interaction with a user
+ * is allowed. This will be used for all connections unless overridden
+ *
+ * @param allow true to allow user interaction, false otherwise
+ */
+ public static void setDefaultAllowUserInteraction(boolean allow)
+ {
+ defaultAllowUserInteraction = allow;
+ }
+
+ /**
+ * Returns the default flag for whether or not interaction with a user
+ * is allowed. This will be used for all connections unless overridden
+ *
+ * @return true if user interaction is allowed, false otherwise
+ */
+ public static boolean getDefaultAllowUserInteraction()
+ {
+ return defaultAllowUserInteraction;
+ }
+
+ /**
+ * Sets a boolean flag indicating whether or not caching will be used
+ * (if possible) to store data downloaded via the connection.
+ *
+ * @param usecaches The new value
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setUseCaches(boolean usecaches)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ useCaches = usecaches;
+ }
+
+ /**
+ * Returns a boolean flag indicating whether or not caching will be used
+ * (if possible) to store data downloaded via the connection.
+ *
+ * @return true if caching should be used if possible, false otherwise
+ */
+ public boolean getUseCaches()
+ {
+ return useCaches;
+ }
+
+ /**
+ * Sets the ifModified since instance variable. If this value is non
+ * zero and the underlying protocol supports it, the actual document will
+ * not be fetched unless it has been modified since this time. The value
+ * passed should be 0 if this feature is to be disabled or the time expressed
+ * as the number of seconds since midnight 1/1/1970 GMT otherwise.
+ *
+ * @param ifmodifiedsince The new value in milliseconds
+ * since January 1, 1970 GMT
+ *
+ * @exception IllegalStateException If already connected
+ */
+ public void setIfModifiedSince(long ifmodifiedsince)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ ifModifiedSince = ifmodifiedsince;
+ }
+
+ /**
+ * Returns the ifModified since instance variable. If this value is non
+ * zero and the underlying protocol supports it, the actual document will
+ * not be fetched unless it has been modified since this time. The value
+ * returned will be 0 if this feature is disabled or the time expressed
+ * as the number of seconds since midnight 1/1/1970 GMT otherwise
+ *
+ * @return The ifModifiedSince value
+ */
+ public long getIfModifiedSince()
+ {
+ return ifModifiedSince;
+ }
+
+ /**
+ * Returns the default value used to determine whether or not caching
+ * of documents will be done when possible.
+ *
+ * @return true if caches will be used, false otherwise
+ */
+ public boolean getDefaultUseCaches()
+ {
+ return defaultUseCaches;
+ }
+
+ /**
+ * Sets the default value used to determine whether or not caching
+ * of documents will be done when possible.
+ *
+ * @param use true to use caches if possible by default, false otherwise
+ */
+ public void setDefaultUseCaches(boolean use)
+ {
+ defaultUseCaches = use;
+ }
+
+ /**
+ * Sets the value of the named request property
+ *
+ * @param key The name of the property
+ * @param value The value of the property
+ *
+ * @exception IllegalStateException If already connected
+ * @exception NullPointerException If key is null
+ *
+ * @see URLConnection#getRequestProperty(String key)
+ * @see URLConnection#addRequestProperty(String key, String value)
+ *
+ * @since 1.4
+ */
+ public void setRequestProperty(String key, String value)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ if (key == null)
+ throw new NullPointerException("key is null");
+
+ // Do nothing unless overridden by subclasses that support setting
+ // header fields in the request.
+ }
+
+ /**
+ * Adds a new request property by a key/value pair.
+ * This method does not overwrite existing properties with the same key.
+ *
+ * @param key Key of the property to add
+ * @param value Value of the Property to add
+ *
+ * @exception IllegalStateException If already connected
+ * @exception NullPointerException If key is null
+ *
+ * @see URLConnection#getRequestProperty(String key)
+ * @see URLConnection#setRequestProperty(String key, String value)
+ *
+ * @since 1.4
+ */
+ public void addRequestProperty(String key, String value)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ if (key == null)
+ throw new NullPointerException("key is null");
+
+ // Do nothing unless overridden by subclasses that support adding
+ // header fields in the request.
+ }
+
+ /**
+ * Returns the value of the named request property.
+ *
+ * @param key The name of the property
+ *
+ * @return Value of the property
+ *
+ * @exception IllegalStateException If already connected
+ *
+ * @see URLConnection#setRequestProperty(String key, String value)
+ * @see URLConnection#addRequestProperty(String key, String value)
+ */
+ public String getRequestProperty(String key)
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ // Overridden by subclasses that support reading header fields from the
+ // request.
+ return null;
+ }
+
+ /**
+ * Returns an unmodifiable Map containing the request properties.
+ *
+ * @return The map of properties
+ *
+ * @exception IllegalStateException If already connected
+ *
+ * @since 1.4
+ */
+ public Map getRequestProperties()
+ {
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ // Overridden by subclasses that support reading header fields from the
+ // request.
+ return Collections.EMPTY_MAP;
+ }
+
+ /**
+ * Sets the default value of a request property. This will be used
+ * for all connections unless the value of the property is manually
+ * overridden.
+ *
+ * @param key The request property name the default is being set for
+ * @param value The value to set the default to
+ *
+ * @deprecated 1.3 The method setRequestProperty should be used instead.
+ * This method does nothing now.
+ *
+ * @see URLConnection#setRequestProperty(String key, String value)
+ */
+ public static void setDefaultRequestProperty(String key, String value)
+ {
+ // This method does nothing since JDK 1.3.
+ }
+
+ /**
+ * Returns the default value of a request property. This will be used
+ * for all connections unless the value of the property is manually
+ * overridden.
+ *
+ * @param key The request property to return the default value of
+ *
+ * @return The value of the default property or null if not available
+ *
+ * @deprecated 1.3 The method getRequestProperty should be used instead.
+ * This method does nothing now.
+ *
+ * @see URLConnection#getRequestProperty(String key)
+ */
+ public static String getDefaultRequestProperty(String key)
+ {
+ // This method does nothing since JDK 1.3.
+ return null;
+ }
+
+ /**
+ * Set's the ContentHandlerFactory for an application. This can be called
+ * once and only once. If it is called again, then an Error is thrown.
+ * Unlike for other set factory methods, this one does not do a security
+ * check prior to setting the factory.
+ *
+ * @param factory The ContentHandlerFactory for this application
+ *
+ * @exception Error If the factory has already been defined
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ */
+ public static synchronized void setContentHandlerFactory(ContentHandlerFactory factory)
+ {
+ if (URLConnection.factory != null)
+ throw new Error("ContentHandlerFactory already set");
+
+ // Throw an exception if an extant security mgr precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+
+ URLConnection.factory = factory;
+ }
+
+ /**
+ * Returns the MIME type of a file based on the name of the file. This
+ * works by searching for the file's extension in a list of file extensions
+ * and returning the MIME type associated with it. If no type is found,
+ * then a MIME type of "application/octet-stream" will be returned.
+ *
+ * @param filename The filename to determine the MIME type for
+ *
+ * @return The MIME type String
+ *
+ * @specnote public since JDK 1.4
+ */
+ public static String guessContentTypeFromName(String filename)
+ {
+ return getFileNameMap().getContentTypeFor(filename.toLowerCase());
+ }
+
+ /**
+ * Returns the MIME type of a stream based on the first few characters
+ * at the beginning of the stream. This routine can be used to determine
+ * the MIME type if a server is believed to be returning an incorrect
+ * MIME type. This method returns "application/octet-stream" if it
+ * cannot determine the MIME type.
+ * <p>
+ * NOTE: Overriding MIME types sent from the server can be obnoxious
+ * to user's. See Internet Exploder 4 if you don't believe me.
+ *
+ * @param is The InputStream to determine the MIME type from
+ *
+ * @return The MIME type
+ *
+ * @exception IOException If an error occurs
+ */
+ public static String guessContentTypeFromStream(InputStream is)
+ throws IOException
+ {
+ return "application/octet-stream";
+ }
+
+ /**
+ * This method returns the <code>FileNameMap</code> object being used
+ * to decode MIME types by file extension.
+ *
+ * @return The <code>FileNameMap</code>.
+ *
+ * @since 1.2
+ */
+ public static synchronized FileNameMap getFileNameMap()
+ {
+ // Delayed initialization.
+ if (fileNameMap == null)
+ fileNameMap = new MimeTypeMapper();
+
+ return fileNameMap;
+ }
+
+ /**
+ * This method set the <code>FileNameMap</code> object being used
+ * to decode MIME types by file extension.
+ *
+ * @param map The <code>FileNameMap</code>.
+ *
+ * @exception SecurityException If a security manager exists and its
+ * checkSetFactory method doesn't allow the operation
+ *
+ * @since 1.2
+ */
+ public static synchronized void setFileNameMap(FileNameMap map)
+ {
+ // Throw an exception if an extant security manager precludes
+ // setting the factory.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkSetFactory();
+
+ fileNameMap = map;
+ }
+
+ private ContentHandler getContentHandler(String contentType)
+ {
+ // No content type so just handle it as the default.
+ if (contentType == null || contentType.equals(""))
+ return null;
+
+ ContentHandler handler = null;
+
+ // If a non-default factory has been set, use it.
+ if (factory != null)
+ handler = factory.createContentHandler(contentType);
+
+ // Then try our default class.
+ try
+ {
+ String typeClass = contentType.replace('/', '.');
+
+ // Deal with "Content-Type: text/html; charset=ISO-8859-1".
+ int parameterBegin = typeClass.indexOf(';');
+ if (parameterBegin >= 1)
+ typeClass = typeClass.substring(0, parameterBegin);
+
+ Class cls = Class.forName("gnu.java.net.content." + typeClass);
+ Object obj = cls.newInstance();
+
+ if (obj instanceof ContentHandler)
+ {
+ handler = (ContentHandler) obj;
+ return handler;
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ // Ignore.
+ }
+ catch (InstantiationException e)
+ {
+ // Ignore.
+ }
+ catch (IllegalAccessException e)
+ {
+ // Ignore.
+ }
+
+ return handler;
+ }
+
+ // We don't put these in a static initializer, because it creates problems
+ // with initializer co-dependency: SimpleDateFormat's constructors eventually
+ // depend on URLConnection (via the java.text.*Symbols classes).
+ private static synchronized void initializeDateFormats()
+ {
+ if (dateformats_initialized)
+ return;
+
+ Locale locale = new Locale("En", "Us", "Unix");
+ dateFormats = new SimpleDateFormat[3];
+ dateFormats[0] =
+ new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'", locale);
+ dateFormats[1] =
+ new SimpleDateFormat("EEEE, dd-MMM-yy hh:mm:ss 'GMT'", locale);
+ dateFormats[2] = new SimpleDateFormat("EEE MMM d hh:mm:ss yyyy", locale);
+ dateformats_initialized = true;
+ }
+}
diff --git a/libjava/classpath/java/net/URLDecoder.java b/libjava/classpath/java/net/URLDecoder.java
new file mode 100644
index 00000000000..ca40c386a52
--- /dev/null
+++ b/libjava/classpath/java/net/URLDecoder.java
@@ -0,0 +1,180 @@
+/* URLDecoder.java -- Class to decode URL's from encoded form.
+ Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * This utility class contains static methods that converts a
+ * string encoded in the x-www-form-urlencoded format to the original
+ * text. The x-www-form-urlencoded format replaces certain disallowed
+ * characters with encoded equivalents. All upper case and lower case
+ * letters in the US alphabet remain as is, the space character (' ')
+ * is replaced with '+' sign, and all other characters are converted to a
+ * "%XX" format where XX is the hexadecimal representation of that character
+ * in a given character encoding (default is "UTF-8").
+ * <p>
+ * This method is very useful for decoding strings sent to CGI scripts
+ *
+ * Written using on-line Java Platform 1.2/1.4 API Specification.
+ * Status: Believed complete and correct.
+ *
+ * @since 1.2
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com) (documentation comments)
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class URLDecoder
+{
+ /**
+ * Public contructor. Note that this class has only static methods.
+ */
+ public URLDecoder()
+ {
+ }
+
+ /**
+ * This method translates the passed in string from x-www-form-urlencoded
+ * format using the default encoding "UTF-8" to decode the hex encoded
+ * unsafe characters.
+ *
+ * @param s the String to convert
+ *
+ * @return the converted String
+ *
+ * @deprecated
+ */
+ public static String decode(String s)
+ {
+ try
+ {
+ return decode(s, "UTF-8");
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ // Should never happen since UTF-8 encoding should always be supported
+ return s;
+ }
+ }
+
+ /**
+ * This method translates the passed in string from x-www-form-urlencoded
+ * format using the given character encoding to decode the hex encoded
+ * unsafe characters.
+ *
+ * This implementation will decode the string even if it contains
+ * unsafe characters (characters that should have been encoded) or if the
+ * two characters following a % do not represent a hex encoded byte.
+ * In those cases the unsafe character or the % character will be added
+ * verbatim to the decoded result.
+ *
+ * @param s the String to convert
+ * @param encoding the character encoding to use the decode the hex encoded
+ * unsafe characters
+ *
+ * @return the converted String
+ *
+ * @exception UnsupportedEncodingException If the named encoding is not
+ * supported
+ *
+ * @since 1.4
+ */
+ public static String decode(String s, String encoding)
+ throws UnsupportedEncodingException
+ {
+ // First convert all '+' characters to spaces.
+ String str = s.replace('+', ' ');
+
+ // Then go through the whole string looking for byte encoded characters
+ int i;
+ int start = 0;
+ byte[] bytes = null;
+ int length = str.length();
+ StringBuffer result = new StringBuffer(length);
+ while ((i = str.indexOf('%', start)) >= 0)
+ {
+ // Add all non-encoded characters to the result buffer
+ result.append(str.substring(start, i));
+ start = i;
+
+ // Get all consecutive encoded bytes
+ while ((i + 2 < length) && (str.charAt(i) == '%'))
+ i += 3;
+
+ // Decode all these bytes
+ if ((bytes == null) || (bytes.length < ((i - start) / 3)))
+ bytes = new byte[((i - start) / 3)];
+
+ int index = 0;
+ try
+ {
+ while (start < i)
+ {
+ String sub = str.substring(start + 1, start + 3);
+ bytes[index] = (byte) Integer.parseInt(sub, 16);
+ index++;
+ start += 3;
+ }
+ }
+ catch (NumberFormatException nfe)
+ {
+ // One of the hex encoded strings was bad
+ }
+
+ // Add the bytes as characters according to the given encoding
+ result.append(new String(bytes, 0, index, encoding));
+
+ // Make sure we skip to just after a % sign
+ // There might not have been enough encoded characters after the %
+ // or the hex chars were not actually hex chars (NumberFormatException)
+ if (start < length && s.charAt(start) == '%')
+ {
+ result.append('%');
+ start++;
+ }
+ }
+
+ // Add any characters left
+ if (start < str.length())
+ result.append(str.substring(start));
+
+ return result.toString();
+ }
+} // class URLDecoder
diff --git a/libjava/classpath/java/net/URLEncoder.java b/libjava/classpath/java/net/URLEncoder.java
new file mode 100644
index 00000000000..dacc3848e37
--- /dev/null
+++ b/libjava/classpath/java/net/URLEncoder.java
@@ -0,0 +1,184 @@
+/* URLEncoder.java -- Class to convert strings to a properly encoded URL
+ Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.UnsupportedEncodingException;
+
+
+/*
+ * Written using on-line Java Platform 1.2/1.4 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This utility class contains static methods that converts a
+ * string into a fully encoded URL string in x-www-form-urlencoded
+ * format. This format replaces certain disallowed characters with
+ * encoded equivalents. All upper case and lower case letters in the
+ * US alphabet remain as is, the space character (' ') is replaced with
+ * '+' sign, and all other characters are converted to a "%XX" format
+ * where XX is the hexadecimal representation of that character in a
+ * certain encoding (by default, the platform encoding, though the
+ * standard is "UTF-8").
+ * <p>
+ * This method is very useful for encoding strings to be sent to CGI scripts
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class URLEncoder
+{
+ /**
+ * This method translates the passed in string into x-www-form-urlencoded
+ * format using the default encoding. The standard encoding is
+ * "UTF-8", and the two-argument form of this method should be used
+ * instead.
+ *
+ * @param s The String to convert
+ *
+ * @return The converted String
+ *
+ * @deprecated
+ */
+ public static String encode(String s)
+ {
+ try
+ {
+ // We default to 8859_1 for compatibility with the same
+ // default elsewhere in the library.
+ return encode(s, System.getProperty("file.encoding", "8859_1"));
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ // Should never happen since default should always be supported
+ return s;
+ }
+ }
+
+ /**
+ * This method translates the passed in string into x-www-form-urlencoded
+ * format using the character encoding to hex-encode the unsafe characters.
+ *
+ * @param s The String to convert
+ * @param encoding The encoding to use for unsafe characters
+ *
+ * @return The converted String
+ *
+ * @exception UnsupportedEncodingException If the named encoding is not
+ * supported
+ *
+ * @since 1.4
+ */
+ public static String encode(String s, String encoding)
+ throws UnsupportedEncodingException
+ {
+ int length = s.length();
+ int start = 0;
+ int i = 0;
+
+ StringBuffer result = new StringBuffer(length);
+ while (true)
+ {
+ while (i < length && isSafe(s.charAt(i)))
+ i++;
+
+ // Safe character can just be added
+ result.append(s.substring(start, i));
+
+ // Are we done?
+ if (i >= length)
+ return result.toString();
+ else if (s.charAt(i) == ' ')
+ {
+ result.append('+'); // Replace space char with plus symbol.
+ i++;
+ }
+ else
+ {
+ // Get all unsafe characters
+ start = i;
+ char c;
+ while (i < length && (c = s.charAt(i)) != ' ' && ! isSafe(c))
+ i++;
+
+ // Convert them to %XY encoded strings
+ String unsafe = s.substring(start, i);
+ byte[] bytes = unsafe.getBytes(encoding);
+ for (int j = 0; j < bytes.length; j++)
+ {
+ result.append('%');
+ int val = bytes[j];
+ result.append(hex.charAt((val & 0xf0) >> 4));
+ result.append(hex.charAt(val & 0x0f));
+ }
+ }
+ start = i;
+ }
+ }
+
+ /**
+ * Private static method that returns true if the given char is either
+ * a uppercase or lowercase letter from 'a' till 'z', or a digit froim
+ * '0' till '9', or one of the characters '-', '_', '.' or '*'. Such
+ * 'safe' character don't have to be url encoded.
+ */
+ private static boolean isSafe(char c)
+ {
+ return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.'
+ || c == '*');
+ }
+
+ /**
+ * Private constructor that does nothing. Included to avoid a default
+ * public constructor being created by the compiler.
+ */
+ private URLEncoder()
+ {
+ }
+
+ /**
+ * Used to convert to hex. We don't use Integer.toHexString, since
+ * it converts to lower case (and the Sun docs pretty clearly
+ * specify upper case here), and because it doesn't provide a
+ * leading 0.
+ */
+ private static final String hex = "0123456789ABCDEF";
+}
diff --git a/libjava/classpath/java/net/URLStreamHandler.java b/libjava/classpath/java/net/URLStreamHandler.java
new file mode 100644
index 00000000000..57ce2dfa290
--- /dev/null
+++ b/libjava/classpath/java/net/URLStreamHandler.java
@@ -0,0 +1,532 @@
+/* URLStreamHandler.java -- Abstract superclass for all protocol handlers
+ Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.File;
+import java.io.IOException;
+
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This class is the superclass of all URL protocol handlers. The URL
+ * class loads the appropriate protocol handler to establish a connection
+ * to a (possibly) remote service (eg, "http", "ftp") and to do protocol
+ * specific parsing of URL's. Refer to the URL class documentation for
+ * details on how that class locates and loads protocol handlers.
+ * <p>
+ * A protocol handler implementation should override the openConnection()
+ * method, and optionally override the parseURL() and toExternalForm()
+ * methods if necessary. (The default implementations will parse/write all
+ * URL's in the same form as http URL's). A protocol specific subclass
+ * of URLConnection will most likely need to be created as well.
+ * <p>
+ * Note that the instance methods in this class are called as if they
+ * were static methods. That is, a URL object to act on is passed with
+ * every call rather than the caller assuming the URL is stored in an
+ * instance variable of the "this" object.
+ * <p>
+ * The methods in this class are protected and accessible only to subclasses.
+ * URLStreamConnection objects are intended for use by the URL class only,
+ * not by other classes (unless those classes are implementing protocols).
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ *
+ * @see URL
+ */
+public abstract class URLStreamHandler
+{
+ /**
+ * Creates a URLStreamHander
+ */
+ public URLStreamHandler()
+ {
+ }
+
+ /**
+ * Returns a URLConnection for the passed in URL. Note that this should
+ * not actually create the connection to the (possibly) remote host, but
+ * rather simply return a URLConnection object. The connect() method of
+ * URL connection is used to establish the actual connection, possibly
+ * after the caller sets up various connection options.
+ *
+ * @param url The URL to get a connection object for
+ *
+ * @return A URLConnection object for the given URL
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract URLConnection openConnection(URL url)
+ throws IOException;
+
+ /**
+ * This method parses the string passed in as a URL and set's the
+ * instance data fields in the URL object passed in to the various values
+ * parsed out of the string. The start parameter is the position to start
+ * scanning the string. This is usually the position after the ":" which
+ * terminates the protocol name. The end parameter is the position to
+ * stop scanning. This will be either the end of the String, or the
+ * position of the "#" character, which separates the "file" portion of
+ * the URL from the "anchor" portion.
+ * <p>
+ * This method assumes URL's are formatted like http protocol URL's, so
+ * subclasses that implement protocols with URL's the follow a different
+ * syntax should override this method. The lone exception is that if
+ * the protocol name set in the URL is "file", this method will accept
+ * an empty hostname (i.e., "file:///"), which is legal for that protocol
+ *
+ * @param url The URL object in which to store the results
+ * @param spec The String-ized URL to parse
+ * @param start The position in the string to start scanning from
+ * @param end The position in the string to stop scanning
+ */
+ protected void parseURL(URL url, String spec, int start, int end)
+ {
+ String host = url.getHost();
+ int port = url.getPort();
+ String file = url.getFile();
+ String ref = url.getRef();
+ String userInfo = url.getUserInfo();
+ String authority = url.getAuthority();
+ String query = null;
+
+ // On Windows we need to change \ to / for file URLs
+ char separator = File.separatorChar;
+ if (url.getProtocol().equals("file") && separator != '/')
+ {
+ file = file.replace(separator, '/');
+ spec = spec.replace(separator, '/');
+ }
+
+ if (spec.regionMatches(start, "//", 0, 2))
+ {
+ String genuineHost;
+ int hostEnd;
+ int colon;
+ int at_host;
+
+ start += 2;
+ int slash = spec.indexOf('/', start);
+ if (slash >= 0)
+ hostEnd = slash;
+ else
+ hostEnd = end;
+
+ authority = host = spec.substring(start, hostEnd);
+
+ // We first need a genuine host name (with userinfo).
+ // So we check for '@': if it's present check the port in the
+ // section after '@' in the other case check it in the full string.
+ // P.S.: We don't care having '@' at the beginning of the string.
+ if ((at_host = host.indexOf('@')) >= 0)
+ {
+ genuineHost = host.substring(at_host);
+ userInfo = host.substring(0, at_host);
+ }
+ else
+ genuineHost = host;
+
+ // Look for optional port number. It is valid for the non-port
+ // part of the host name to be null (e.g. a URL "http://:80").
+ // TBD: JDK 1.2 in this case sets host to null rather than "";
+ // this is undocumented and likely an unintended side effect in 1.2
+ // so we'll be simple here and stick with "". Note that
+ // "http://" or "http:///" produce a "" host in JDK 1.2.
+ if ((colon = genuineHost.indexOf(':')) >= 0)
+ {
+ try
+ {
+ port = Integer.parseInt(genuineHost.substring(colon + 1));
+ }
+ catch (NumberFormatException e)
+ {
+ // Ignore invalid port values; port is already set to u's
+ // port.
+ }
+
+ // Now we must cut the port number in the original string.
+ if (at_host >= 0)
+ host = host.substring(0, at_host + colon);
+ else
+ host = host.substring(0, colon);
+ }
+ file = null;
+ start = hostEnd;
+ }
+ else if (host == null)
+ host = "";
+
+ if (file == null || file.length() == 0
+ || (start < end && spec.charAt(start) == '/'))
+ {
+ // No file context available; just spec for file.
+ // Or this is an absolute path name; ignore any file context.
+ file = spec.substring(start, end);
+ ref = null;
+ }
+ else if (start < end)
+ {
+ // Context is available, but only override it if there is a new file.
+ int lastSlash = file.lastIndexOf('/');
+ if (lastSlash < 0)
+ file = spec.substring(start, end);
+ else
+ file = (file.substring(0, lastSlash)
+ + '/' + spec.substring(start, end));
+
+ // For URLs constructed relative to a context, we
+ // need to canonicalise the file path.
+ file = canonicalizeFilename(file);
+
+ ref = null;
+ }
+
+ if (ref == null)
+ {
+ // Normally there should be no '#' in the file part,
+ // but we are nice.
+ int hash = file.indexOf('#');
+ if (hash != -1)
+ {
+ ref = file.substring(hash + 1, file.length());
+ file = file.substring(0, hash);
+ }
+ }
+
+ // We care about the query tag only if there is no reference at all.
+ if (ref == null)
+ {
+ int queryTag = file.indexOf('?');
+ if (queryTag != -1)
+ {
+ query = file.substring(queryTag + 1);
+ file = file.substring(0, queryTag);
+ }
+ }
+
+ // XXX - Classpath used to call PlatformHelper.toCanonicalForm() on
+ // the file part. It seems like overhead, but supposedly there is some
+ // benefit in windows based systems (it also lowercased the string).
+ setURL(url, url.getProtocol(), host, port, authority, userInfo, file, query, ref);
+ }
+
+ /*
+ * Canonicalize a filename.
+ */
+ private static String canonicalizeFilename(String file)
+ {
+ // XXX - GNU Classpath has an implementation that might be more appropriate
+ // for Windows based systems (gnu.java.io.PlatformHelper.toCanonicalForm)
+ int index;
+
+ // Replace "/./" with "/". This probably isn't very efficient in
+ // the general case, but it's probably not bad most of the time.
+ while ((index = file.indexOf("/./")) >= 0)
+ file = file.substring(0, index) + file.substring(index + 2);
+
+ // Process "/../" correctly. This probably isn't very efficient in
+ // the general case, but it's probably not bad most of the time.
+ while ((index = file.indexOf("/../")) >= 0)
+ {
+ // Strip of the previous directory - if it exists.
+ int previous = file.lastIndexOf('/', index - 1);
+ if (previous >= 0)
+ file = file.substring(0, previous) + file.substring(index + 3);
+ else
+ break;
+ }
+ return file;
+ }
+
+ /**
+ * Compares two URLs, excluding the fragment component
+ *
+ * @param url1 The first url
+ * @param url2 The second url to compare with the first
+ *
+ * @return True if both URLs point to the same file, false otherwise.
+ *
+ * @specnote Now protected
+ */
+ protected boolean sameFile(URL url1, URL url2)
+ {
+ if (url1 == url2)
+ return true;
+
+ // This comparison is very conservative. It assumes that any
+ // field can be null.
+ if (url1 == null || url2 == null)
+ return false;
+ int p1 = url1.getPort();
+ if (p1 == -1)
+ p1 = url1.ph.getDefaultPort();
+ int p2 = url2.getPort();
+ if (p2 == -1)
+ p2 = url2.ph.getDefaultPort();
+ if (p1 != p2)
+ return false;
+ String s1;
+ String s2;
+ s1 = url1.getProtocol();
+ s2 = url2.getProtocol();
+ if (s1 != s2 && (s1 == null || ! s1.equals(s2)))
+ return false;
+ s1 = url1.getHost();
+ s2 = url2.getHost();
+ if (s1 != s2 && (s1 == null || ! s1.equals(s2)))
+ return false;
+ s1 = canonicalizeFilename(url1.getFile());
+ s2 = canonicalizeFilename(url2.getFile());
+ if (s1 != s2 && (s1 == null || ! s1.equals(s2)))
+ return false;
+ return true;
+ }
+
+ /**
+ * This methods sets the instance variables representing the various fields
+ * of the URL to the values passed in.
+ *
+ * @param u The URL to modify
+ * @param protocol The protocol to set
+ * @param host The host name to et
+ * @param port The port number to set
+ * @param file The filename to set
+ * @param ref The reference
+ *
+ * @exception SecurityException If the protocol handler of the URL is
+ * different from this one
+ *
+ * @deprecated 1.2 Please use
+ * #setURL(URL,String,String,int,String,String,String,String);
+ */
+ protected void setURL(URL u, String protocol, String host, int port,
+ String file, String ref)
+ {
+ u.set(protocol, host, port, file, ref);
+ }
+
+ /**
+ * Sets the fields of the URL argument to the indicated values
+ *
+ * @param u The URL to modify
+ * @param protocol The protocol to set
+ * @param host The host name to set
+ * @param port The port number to set
+ * @param authority The authority to set
+ * @param userInfo The user information to set
+ * @param path The path/filename to set
+ * @param query The query part to set
+ * @param ref The reference
+ *
+ * @exception SecurityException If the protocol handler of the URL is
+ * different from this one
+ */
+ protected void setURL(URL u, String protocol, String host, int port,
+ String authority, String userInfo, String path,
+ String query, String ref)
+ {
+ u.set(protocol, host, port, authority, userInfo, path, query, ref);
+ }
+
+ /**
+ * 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.
+ *
+ * @param url1 An URL object
+ * @param url2 An URL object
+ *
+ * @return True if both given URLs are equal, false otherwise.
+ */
+ protected boolean equals(URL url1, URL url2)
+ {
+ // This comparison is very conservative. It assumes that any
+ // field can be null.
+ return (url1.getPort() == url2.getPort()
+ && ((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)
+ || (url1.getPath() != null && url1.getPath().equals(url2.getPath())))
+ && ((url1.getQuery() == null && url2.getQuery() == null)
+ || (url1.getQuery() != null
+ && url1.getQuery().equals(url2.getQuery())))
+ && ((url1.getRef() == null && url2.getRef() == null)
+ || (url1.getRef() != null && url1.getRef().equals(url2.getRef()))));
+ }
+
+ /**
+ * Compares the host components of two URLs.
+ *
+ * @param url1 The first URL.
+ * @param url2 The second URL.
+ *
+ * @return True if both URLs contain the same host.
+ *
+ * @exception UnknownHostException If an unknown host is found
+ */
+ protected boolean hostsEqual(URL url1, URL url2)
+ {
+ InetAddress addr1 = getHostAddress(url1);
+ InetAddress addr2 = getHostAddress(url2);
+
+ if (addr1 != null && addr2 != null)
+ return addr1.equals(addr2);
+
+ String host1 = url1.getHost();
+ String host2 = url2.getHost();
+
+ if (host1 != null && host2 != null)
+ return host1.equalsIgnoreCase(host2);
+
+ return host1 == null && host2 == null;
+ }
+
+ /**
+ * Get the IP address of our host. An empty host field or a DNS failure will
+ * result in a null return.
+ *
+ * @param url The URL to return the host address for.
+ *
+ * @return The address of the hostname in url.
+ */
+ protected InetAddress getHostAddress(URL url)
+ {
+ String hostname = url.getHost();
+
+ if (hostname.equals(""))
+ return null;
+
+ try
+ {
+ return InetAddress.getByName(hostname);
+ }
+ catch (UnknownHostException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the default port for a URL parsed by this handler. This method is
+ * meant to be overidden by handlers with default port numbers.
+ *
+ * @return The default port number.
+ */
+ protected int getDefaultPort()
+ {
+ return -1;
+ }
+
+ /**
+ * Provides the default hash calculation. May be overidden by handlers for
+ * other protocols that have different requirements for hashCode calculation.
+ *
+ * @param url The URL to calc the hashcode for.
+ *
+ * @return The hashcode for the given URL.
+ */
+ protected int hashCode(URL url)
+ {
+ return url.getProtocol().hashCode()
+ + ((url.getHost() == null) ? 0 : url.getHost().hashCode())
+ + url.getFile().hashCode() + url.getPort();
+ }
+
+ /**
+ * This method converts a URL object into a String. This method creates
+ * Strings in the mold of http URL's, so protocol handlers which use URL's
+ * that have a different syntax should override this method
+ *
+ * @param url The URL object to convert
+ *
+ * @return A string representation of the url
+ */
+ protected String toExternalForm(URL url)
+ {
+ String protocol;
+ String file;
+ String ref;
+ String authority;
+
+ protocol = url.getProtocol();
+ authority = url.getAuthority();
+ if (authority == null)
+ authority = "";
+
+ file = url.getFile();
+ ref = url.getRef();
+
+ // Guess a reasonable size for the string buffer so we have to resize
+ // at most once.
+ int size = protocol.length() + authority.length() + file.length() + 24;
+ StringBuffer sb = new StringBuffer(size);
+
+ if (protocol != null && protocol.length() > 0)
+ {
+ sb.append(protocol);
+ sb.append(":");
+ }
+
+ if (authority.length() != 0)
+ {
+ sb.append("//").append(authority);
+ }
+
+ sb.append(file);
+
+ if (ref != null)
+ sb.append('#').append(ref);
+
+ return sb.toString();
+ }
+}
diff --git a/libjava/classpath/java/net/URLStreamHandlerFactory.java b/libjava/classpath/java/net/URLStreamHandlerFactory.java
new file mode 100644
index 00000000000..c92c71fb2b3
--- /dev/null
+++ b/libjava/classpath/java/net/URLStreamHandlerFactory.java
@@ -0,0 +1,65 @@
+/* URLStreamHandlerFactory.java -- Maps protocols to URLStreamHandlers
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+/**
+ * This interface contains one method which maps the protocol portion of
+ * a URL (eg, "http" in "http://www.urbanophile.com/arenn/") to a
+ * <code>URLStreamHandler</code> object.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public interface URLStreamHandlerFactory
+{
+ /**
+ * This method maps the protocol portion of a URL to a
+ * <code>URLStreamHandler</code> object.
+ *
+ * @param protocol The protocol name to map ("http", "ftp", etc).
+ *
+ * @return The <code>URLStreamHandler</code> for the specified protocol
+ */
+ URLStreamHandler createURLStreamHandler(String protocol);
+} // interface URLStreamHandlerFactory
diff --git a/libjava/classpath/java/net/UnknownHostException.java b/libjava/classpath/java/net/UnknownHostException.java
new file mode 100644
index 00000000000..c5ba18330d3
--- /dev/null
+++ b/libjava/classpath/java/net/UnknownHostException.java
@@ -0,0 +1,77 @@
+/* UnknownHostException.java -- The hostname is unknown
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * This exception indicates that an attempt was made to reference a hostname
+ * or IP address that is not valid. This could possibly indicate that a
+ * DNS problem has occurred, but most often means that the host was not
+ * correctly specified.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner
+ * @status updated to 1.4
+ */
+public class UnknownHostException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4639126076052875403L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public UnknownHostException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message, such as the
+ * name of the host that could not be resolved.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public UnknownHostException(String message)
+ {
+ super(message);
+ }
+} // class UnknownHostException
diff --git a/libjava/classpath/java/net/UnknownServiceException.java b/libjava/classpath/java/net/UnknownServiceException.java
new file mode 100644
index 00000000000..65cc8f59225
--- /dev/null
+++ b/libjava/classpath/java/net/UnknownServiceException.java
@@ -0,0 +1,76 @@
+/* UnknownServiceException.java -- A service error occurred
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import java.io.IOException;
+
+
+/**
+ * Contrary to what you might think, this does not indicate that the
+ * TCP/IP service name specified was invalid. Instead it indicates that
+ * the MIME type returned from a URL could not be determined or that an
+ * attempt was made to write to a read-only URL.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class UnknownServiceException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4169033248853639508L;
+
+ /**
+ * Create a new instance without a descriptive error message.
+ */
+ public UnknownServiceException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message a message describing the error that occurred
+ */
+ public UnknownServiceException(String message)
+ {
+ super(message);
+ }
+} // class UnknownServiceException
diff --git a/libjava/classpath/java/net/class-dependencies.conf b/libjava/classpath/java/net/class-dependencies.conf
new file mode 100644
index 00000000000..8b130f53684
--- /dev/null
+++ b/libjava/classpath/java/net/class-dependencies.conf
@@ -0,0 +1,122 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+java/net/InetAddress: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/net/UnknownHostException.<init>(Ljava/lang/String;)V
+
+java/net/DatagramSocketImpl: \
+ java/net/DatagramSocketImpl.fd(Ljava/io/FileDescriptor;) \
+ java/net/DatagramSocketImpl.localPort(I)
+
+java/net/PlainDatagramSocketImpl: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/io/FileDescriptor.<init>()V \
+ java/lang/Boolean.<init>(Z)V \
+ java/lang/Integer.<init>(I)V \
+ java/net/InetAddress.getByName(Ljava/lang/String;)Ljava/net/InetAddress; \
+ java/net/InetAddress.getAddress()[B \
+ java/lang/Boolean.booleanValue()Z \
+ java/lang/Integer.intValue()I \
+ java/net/SocketException.<init>(Ljava/lang/String;)V \
+ java/net/DatagramPacket.getData()[B \
+ java/net/SocketImpl.address(Ljava/net/InetAddress;) \
+ java/net/PlainSocketImpl.native_fd(I) \
+ java/net/SocketImpl.fd(Ljava/io/FileDescriptor;) \
+ java/net/SocketImpl.address(Ljava/net/InetAddress;) \
+ java/net/PlainDatagramSocketImpl.native_fd(I) \
+ java/net/SocketImpl.localport(I) \
+ java/net/SocketImpl.port(I)
+
+java/net/PlainSocketImpl: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/io/FileDescriptor.<init>()V \
+ java/lang/Boolean.<init>(Z)V \
+ java/lang/Integer.<init>(I)V \
+ java/net/InetAddress.getByName(Ljava/lang/String;)Ljava/net/InetAddress; \
+ java/net/InetAddress.getAddress()[B \
+ java/lang/Boolean.booleanValue()Z \
+ java/lang/Integer.intValue()I \
+ java/net/SocketException.<init>(Ljava/lang/String;)V \
+ java/net/DatagramPacket.getData()[B \
+ java/net/SocketImpl.address(Ljava/net/InetAddress;) \
+ java/net/PlainSocketImpl.native_fd(I) \
+ java/net/SocketImpl.fd(Ljava/io/FileDescriptor;) \
+ java/net/SocketImpl.address(Ljava/net/InetAddress;) \
+ java/net/PlainDatagramSocketImpl.native_fd(I) \
+ java/net/SocketImpl.localport(I) \
+ java/net/SocketImpl.port(I)
+
+# All protocols supported are loaded via URL.getURLStreamHandler from
+# class gnu.java.net.protocol.<protocol>.Handler.
+#
+# This introduces a dependency for all protocols. To allow an easy selection
+# and addition of protocols, the library variable {protocols} can be set to
+# the set of supported protocols.
+#
+{protocols}: http file jar
+
+java/net/URL.getURLStreamHandler(Ljava/lang/String;)Ljava/net/URLStreamHandler;: \
+ gnu/java/net/protocol/{protocols}/Handler.* \
+ com/aicas/java/net/protocol/rom/Handler.*
+
+# end of file
diff --git a/libjava/classpath/java/net/package.html b/libjava/classpath/java/net/package.html
new file mode 100644
index 00000000000..133ee716f02
--- /dev/null
+++ b/libjava/classpath/java/net/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.net package.
+ Copyright (C) 2002 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 - java.net</title></head>
+
+<body>
+<p>Network communication through TCP and UDP sockets or URLs.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/nio/Buffer.java b/libjava/classpath/java/nio/Buffer.java
new file mode 100644
index 00000000000..47dabf29e42
--- /dev/null
+++ b/libjava/classpath/java/nio/Buffer.java
@@ -0,0 +1,361 @@
+/* Buffer.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+import gnu.classpath.RawData;
+
+/**
+ * @since 1.4
+ */
+public abstract class Buffer
+{
+ int cap = 0;
+ int limit = 0;
+ int pos = 0;
+ int mark = -1;
+ RawData address;
+
+ /**
+ * Creates a new Buffer.
+ *
+ * Should be package private.
+ */
+ Buffer (int capacity, int limit, int position, int mark)
+ {
+ if (capacity < 0)
+ throw new IllegalArgumentException ();
+
+ cap = capacity;
+ limit (limit);
+ position (position);
+
+ if (mark >= 0)
+ {
+ if (mark > pos)
+ throw new IllegalArgumentException ();
+
+ this.mark = mark;
+ }
+ }
+
+ /**
+ * Retrieves the capacity of the buffer.
+ *
+ * @return the capacity of the buffer
+ */
+ public final int capacity ()
+ {
+ return cap;
+ }
+
+ /**
+ * Clears the buffer.
+ *
+ * @return this buffer
+ */
+ public final Buffer clear ()
+ {
+ limit = cap;
+ pos = 0;
+ mark = -1;
+ return this;
+ }
+
+ /**
+ * Flips the buffer.
+ *
+ * @return this buffer
+ */
+ public final Buffer flip ()
+ {
+ limit = pos;
+ pos = 0;
+ mark = -1;
+ return this;
+ }
+
+ /**
+ * Tells whether the buffer has remaining data to read or not.
+ *
+ * @return true if the buffer contains remaining data to read,
+ * false otherwise
+ */
+ public final boolean hasRemaining ()
+ {
+ return remaining() > 0;
+ }
+
+ /**
+ * Tells whether this buffer is read only or not.
+ *
+ * @return true if the buffer is read only, false otherwise
+ */
+ public abstract boolean isReadOnly ();
+
+ /**
+ * Retrieves the current limit of the buffer.
+ *
+ * @return the limit of the buffer
+ */
+ public final int limit ()
+ {
+ return limit;
+ }
+
+ /**
+ * Sets this buffer's limit.
+ *
+ * @param newLimit The new limit value; must be non-negative and no larger
+ * than this buffer's capacity.
+ *
+ * @return this buffer
+ *
+ * @exception IllegalArgumentException If the preconditions on newLimit
+ * do not hold.
+ */
+ public final Buffer limit (int newLimit)
+ {
+ if ((newLimit < 0) || (newLimit > cap))
+ throw new IllegalArgumentException ();
+
+ if (newLimit < mark)
+ mark = -1;
+
+ if (pos > newLimit)
+ pos = newLimit;
+
+ limit = newLimit;
+ return this;
+ }
+
+ /**
+ * Sets this buffer's mark at its position.
+ *
+ * @return this buffer
+ */
+ public final Buffer mark ()
+ {
+ mark = pos;
+ return this;
+ }
+
+ /**
+ * Retrieves the current position of this buffer.
+ *
+ * @return the current position of this buffer
+ */
+ public final int position ()
+ {
+ return pos;
+ }
+
+ /**
+ * Sets this buffer's position. If the mark is defined and larger than the
+ * new position then it is discarded.
+ *
+ * @param newPosition The new position value; must be non-negative and no
+ * larger than the current limit.
+ *
+ * @return this buffer
+ *
+ * @exception IllegalArgumentException If the preconditions on newPosition
+ * do not hold
+ */
+ public final Buffer position (int newPosition)
+ {
+ if ((newPosition < 0) || (newPosition > limit))
+ throw new IllegalArgumentException ();
+
+ if (newPosition <= mark)
+ mark = -1;
+
+ pos = newPosition;
+ return this;
+ }
+
+ /**
+ * Returns the number of elements between the current position and the limit.
+ *
+ * @return the number of remaining elements
+ */
+ public final int remaining()
+ {
+ return limit - pos;
+ }
+
+ /**
+ * Resets this buffer's position to the previously-marked position.
+ *
+ * @return this buffer
+ *
+ * @exception InvalidMarkException If the mark has not been set.
+ */
+ public final Buffer reset()
+ {
+ if (mark == -1)
+ throw new InvalidMarkException ();
+
+ pos = mark;
+ return this;
+ }
+
+ /**
+ * Rewinds this buffer. The position is set to zero and the mark
+ * is discarded.
+ *
+ * @return this buffer
+ */
+ public final Buffer rewind()
+ {
+ pos = 0;
+ mark = -1;
+ return this;
+ }
+
+ /**
+ * Checks for underflow. This method is used internally to check
+ * whether a buffer has enough elements left to satisfy a read
+ * request.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * elements in this buffer.
+ */
+ final void checkForUnderflow()
+ {
+ if (!hasRemaining())
+ throw new BufferUnderflowException();
+ }
+
+ /**
+ * Checks for underflow. This method is used internally to check
+ * whether a buffer has enough elements left to satisfy a read
+ * request for a given number of elements.
+ *
+ * @param length The length of a sequence of elements.
+ *
+ * @exception BufferUnderflowException If there are not enough
+ * remaining elements in this buffer.
+ */
+ final void checkForUnderflow(int length)
+ {
+ if (remaining() < length)
+ throw new BufferUnderflowException();
+ }
+
+ /**
+ * Checks for overflow. This method is used internally to check
+ * whether a buffer has enough space left to satisfy a write
+ * request.
+ *
+ * @exception BufferOverflowException If there is no remaining
+ * space in this buffer.
+ */
+ final void checkForOverflow()
+ {
+ if (!hasRemaining())
+ throw new BufferOverflowException();
+ }
+
+ /**
+ * Checks for overflow. This method is used internally to check
+ * whether a buffer has enough space left to satisfy a write
+ * request for a given number of elements.
+ *
+ * @param length The length of a sequence of elements.
+ *
+ * @exception BufferUnderflowException If there is not enough
+ * remaining space in this buffer.
+ */
+ final void checkForOverflow(int length)
+ {
+ if (remaining() < length)
+ throw new BufferOverflowException();
+ }
+
+ /**
+ * Checks if index is negative or not smaller than the buffer's
+ * limit. This method is used internally to check whether
+ * an indexed request can be fulfilled.
+ *
+ * @param index The requested position in the buffer.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ final void checkIndex(int index)
+ {
+ if (index < 0
+ || index >= limit ())
+ throw new IndexOutOfBoundsException ();
+ }
+
+ /**
+ * Checks if buffer is read-only. This method is used internally to
+ * check if elements can be put into a buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ final void checkIfReadOnly()
+ {
+ if (isReadOnly())
+ throw new ReadOnlyBufferException ();
+ }
+
+ /**
+ * Checks whether an array is large enough to hold the given number of
+ * elements at the given offset. This method is used internally to
+ * check if an array is big enough.
+ *
+ * @param arraylength The length of the array.
+ * @param offset The offset within the array of the first byte to be read;
+ * must be non-negative and no larger than arraylength.
+ * @param length The number of bytes to be read from the given array;
+ * must be non-negative and no larger than arraylength - offset.
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ static final void checkArraySize(int arraylength, int offset, int length)
+ {
+ if ((offset < 0) ||
+ (length < 0) ||
+ (arraylength < length + offset))
+ throw new IndexOutOfBoundsException ();
+ }
+}
diff --git a/libjava/classpath/java/nio/BufferOverflowException.java b/libjava/classpath/java/nio/BufferOverflowException.java
new file mode 100644
index 00000000000..588c03290a1
--- /dev/null
+++ b/libjava/classpath/java/nio/BufferOverflowException.java
@@ -0,0 +1,51 @@
+/* BufferOverflowException.java --
+ Copyright (C) 2002 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.nio;
+
+/**
+ * @since 1.4
+ */
+public class BufferOverflowException extends RuntimeException
+{
+ /**
+ * Creates the exception
+ */
+ public BufferOverflowException ()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/BufferUnderflowException.java b/libjava/classpath/java/nio/BufferUnderflowException.java
new file mode 100644
index 00000000000..4b4161c647c
--- /dev/null
+++ b/libjava/classpath/java/nio/BufferUnderflowException.java
@@ -0,0 +1,51 @@
+/* BufferUnderflowException.java --
+ Copyright (C) 2002 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.nio;
+
+/**
+ * @since 1.4
+ */
+public class BufferUnderflowException extends RuntimeException
+{
+ /**
+ * Creates the exception
+ */
+ public BufferUnderflowException ()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/ByteBuffer.java b/libjava/classpath/java/nio/ByteBuffer.java
new file mode 100644
index 00000000000..0ccf7663cfa
--- /dev/null
+++ b/libjava/classpath/java/nio/ByteBuffer.java
@@ -0,0 +1,651 @@
+/* ByteBuffer.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @since 1.4
+ */
+public abstract class ByteBuffer extends Buffer
+ implements Comparable
+{
+ ByteOrder endian = ByteOrder.BIG_ENDIAN;
+
+ int array_offset;
+ byte[] backing_buffer;
+
+ ByteBuffer (int capacity, int limit, int position, int mark)
+ {
+ super (capacity, limit, position, mark);
+ }
+
+ /**
+ * Allocates a new direct byte buffer.
+ */
+ public static ByteBuffer allocateDirect (int capacity)
+ {
+ return DirectByteBufferImpl.allocate (capacity);
+ }
+
+ /**
+ * Allocates a new <code>ByteBuffer</code> object with a given capacity.
+ */
+ public static ByteBuffer allocate (int capacity)
+ {
+ return wrap(new byte[capacity], 0, capacity);
+ }
+
+ /**
+ * Wraps a <code>byte</code> array into a <code>ByteBuffer</code>
+ * object.
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ public static final ByteBuffer wrap (byte[] array, int offset, int length)
+ {
+ // FIXME: In GCJ and other implementations where arrays may not
+ // move we might consider, at least when offset==0:
+ // return new DirectByteBufferImpl(array,
+ // address_of_data(array) + offset,
+ // length, length, 0, false);
+ // This may be more efficient, mainly because we can then use the
+ // same logic for all ByteBuffers.
+
+ return new ByteBufferImpl (array, 0, array.length, offset + length, offset, -1, false);
+ }
+
+ /**
+ * Wraps a <code>byte</code> array into a <code>ByteBuffer</code>
+ * object.
+ */
+ public static final ByteBuffer wrap (byte[] array)
+ {
+ return wrap (array, 0, array.length);
+ }
+
+ /**
+ * This method transfers <code>byte</code>s from this buffer into the given
+ * destination array. Before the transfer, it checks if there are fewer than
+ * length <code>byte</code>s remaining in this buffer.
+ *
+ * @param dst The destination array
+ * @param offset The offset within the array of the first <code>byte</code>
+ * to be written; must be non-negative and no larger than dst.length.
+ * @param length The maximum number of bytes to be written to the given array;
+ * must be non-negative and no larger than dst.length - offset.
+ *
+ * @exception BufferUnderflowException If there are fewer than length
+ * <code>byte</code>s remaining in this buffer.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold.
+ */
+ public ByteBuffer get (byte[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ {
+ dst [i] = get ();
+ }
+
+ return this;
+ }
+
+ /**
+ * This method transfers <code>byte</code>s from this buffer into the given
+ * destination array.
+ *
+ * @param dst The byte array to write into.
+ *
+ * @exception BufferUnderflowException If there are fewer than dst.length
+ * <code>byte</code>s remaining in this buffer.
+ */
+ public ByteBuffer get (byte[] dst)
+ {
+ return get (dst, 0, dst.length);
+ }
+
+ /**
+ * Writes the content of the the <code>ByteBUFFER</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * <code>src.remaining()</code> space remaining in this buffer.
+ *
+ * @param src The source data.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>byte</code>s in the source buffer.
+ * @exception IllegalArgumentException If the source buffer is this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public ByteBuffer put (ByteBuffer src)
+ {
+ if (src == this)
+ throw new IllegalArgumentException ();
+
+ checkForOverflow(src.remaining());
+
+ if (src.remaining () > 0)
+ {
+ byte[] toPut = new byte [src.remaining ()];
+ src.get (toPut);
+ put (toPut);
+ }
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>byte array</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * length space remaining in this buffer.
+ *
+ * @param src The array to copy into the buffer.
+ * @param offset The offset within the array of the first byte to be read;
+ * must be non-negative and no larger than src.length.
+ * @param length The number of bytes to be read from the given array;
+ * must be non-negative and no larger than src.length - offset.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>byte</code>s in the source array.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public ByteBuffer put (byte[] src, int offset, int length)
+ {
+ checkArraySize(src.length, offset, length);
+ checkForOverflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ put (src [i]);
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>byte array</code> src
+ * into the buffer.
+ *
+ * @param src The array to copy into the buffer.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>byte</code>s in the source array.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public final ByteBuffer put (byte[] src)
+ {
+ return put (src, 0, src.length);
+ }
+
+ /**
+ * Tells whether ot not this buffer is backed by an accessible
+ * <code>byte</code> array.
+ */
+ public final boolean hasArray ()
+ {
+ return (backing_buffer != null
+ && !isReadOnly ());
+ }
+
+ /**
+ * Returns the <code>byte</code> array that backs this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final byte[] array ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return backing_buffer;
+ }
+
+ /**
+ * Returns the offset within this buffer's backing array of the first element.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final int arrayOffset ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return array_offset;
+ }
+
+ /**
+ * Calculates a hash code for this buffer.
+ *
+ * This is done with <code>int</code> arithmetic,
+ * where ** represents exponentiation, by this formula:<br>
+ * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
+ * (s[limit()-1]+30)*31**(limit()-1)</code>.
+ * Where s is the buffer data. Note that the hashcode is dependent
+ * on buffer content, and therefore is not useful if the buffer
+ * content may change.
+ *
+ * @return the hash code
+ */
+ public int hashCode ()
+ {
+ int hashCode = get(position()) + 31;
+ int multiplier = 1;
+ for (int i = position() + 1; i < limit(); ++i)
+ {
+ multiplier *= 31;
+ hashCode += (get(i) + 30)*multiplier;
+ }
+ return hashCode;
+ }
+
+ /**
+ * Checks if this buffer is equal to obj.
+ */
+ public boolean equals (Object obj)
+ {
+ if (obj instanceof ByteBuffer)
+ {
+ return compareTo (obj) == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compares two <code>ByteBuffer</code> objects.
+ *
+ * @exception ClassCastException If obj is not an object derived from
+ * <code>ByteBuffer</code>.
+ */
+ public int compareTo (Object obj)
+ {
+ ByteBuffer other = (ByteBuffer) obj;
+
+ int num = Math.min(remaining(), other.remaining());
+ int pos_this = position();
+ int pos_other = other.position();
+
+ for (int count = 0; count < num; count++)
+ {
+ byte a = get(pos_this++);
+ byte b = other.get(pos_other++);
+
+ if (a == b)
+ continue;
+
+ if (a < b)
+ return -1;
+
+ return 1;
+ }
+
+ return remaining() - other.remaining();
+ }
+
+ /**
+ * Returns the byte order of this buffer.
+ */
+ public final ByteOrder order ()
+ {
+ return endian;
+ }
+
+ /**
+ * Modifies this buffer's byte order.
+ */
+ public final ByteBuffer order (ByteOrder endian)
+ {
+ this.endian = endian;
+ return this;
+ }
+
+ /**
+ * Reads the <code>byte</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>byte</code>s in this buffer.
+ */
+ public abstract byte get ();
+
+ /**
+ * Writes the <code>byte</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * <code>byte</code>s in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract ByteBuffer put (byte b);
+
+ /**
+ * Absolute get method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public abstract byte get (int index);
+
+ /**
+ * Absolute put method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract ByteBuffer put (int index, byte b);
+
+ /**
+ * Compacts this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract ByteBuffer compact ();
+
+ void shiftDown (int dst_offset, int src_offset, int count)
+ {
+ for (int i = 0; i < count; i++)
+ put(dst_offset + i, get(src_offset + i));
+ }
+
+ /**
+ * Tells whether or not this buffer is direct.
+ */
+ public abstract boolean isDirect ();
+
+ /**
+ * Creates a new <code>ByteBuffer</code> whose content is a shared
+ * subsequence of this buffer's content.
+ */
+ public abstract ByteBuffer slice ();
+
+ /**
+ * Creates a new <code>ByteBuffer</code> that shares this buffer's
+ * content.
+ */
+ public abstract ByteBuffer duplicate ();
+
+ /**
+ * Creates a new read-only <code>ByteBuffer</code> that shares this
+ * buffer's content.
+ */
+ public abstract ByteBuffer asReadOnlyBuffer ();
+
+ /**
+ * Creates a view of this byte buffer as a short buffer.
+ */
+ public abstract ShortBuffer asShortBuffer ();
+
+ /**
+ * Creates a view of this byte buffer as a char buffer.
+ */
+ public abstract CharBuffer asCharBuffer ();
+
+ /**
+ * Creates a view of this byte buffer as an integer buffer.
+ */
+ public abstract IntBuffer asIntBuffer ();
+
+ /**
+ * Creates a view of this byte buffer as a long buffer.
+ */
+ public abstract LongBuffer asLongBuffer ();
+
+ /**
+ * Creates a view of this byte buffer as a float buffer.
+ */
+ public abstract FloatBuffer asFloatBuffer ();
+
+ /**
+ * Creates a view of this byte buffer as a double buffer.
+ */
+ public abstract DoubleBuffer asDoubleBuffer ();
+
+ /**
+ * Relative get method for reading a character value.
+ *
+ * @exception BufferUnderflowException If there are fewer than two bytes
+ * remaining in this buffer.
+ */
+ public abstract char getChar ();
+
+ /**
+ * Relative put method for writing a character value.
+ *
+ * @exception BufferOverflowException If this buffer's current position is
+ * not smaller than its limit.
+ */
+ public abstract ByteBuffer putChar (char value);
+
+ /**
+ * Absolute get method for reading a character value.
+ *
+ * @exception IndexOutOfBoundsException If there are fewer than two bytes
+ * remaining in this buffer
+ */
+ public abstract char getChar (int index);
+
+ /**
+ * Absolute put method for writing a character value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus one.
+ */
+ public abstract ByteBuffer putChar (int index, char value);
+
+ /**
+ * Relative get method for reading a short value.
+ *
+ * @exception BufferUnderflowException If index is negative or not smaller
+ * than the buffer's limit, minus one.
+ */
+ public abstract short getShort ();
+
+ /**
+ * Relative put method for writing a short value.
+ *
+ * @exception BufferOverflowException If this buffer's current position is
+ * not smaller than its limit.
+ */
+ public abstract ByteBuffer putShort (short value);
+
+ /**
+ * Absolute get method for reading a short value.
+ *
+ * @exception IndexOutOfBoundsException If there are fewer than two bytes
+ * remaining in this buffer
+ */
+ public abstract short getShort (int index);
+
+ /**
+ * Absolute put method for writing a short value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus one.
+ */
+ public abstract ByteBuffer putShort (int index, short value);
+
+ /**
+ * Relative get method for reading an integer value.
+ *
+ * @exception BufferUnderflowException If there are fewer than four bytes
+ * remaining in this buffer.
+ */
+ public abstract int getInt ();
+
+ /**
+ * Relative put method for writing an integer value.
+ *
+ * @exception BufferOverflowException If this buffer's current position is
+ * not smaller than its limit.
+ */
+ public abstract ByteBuffer putInt (int value);
+
+ /**
+ * Absolute get method for reading an integer value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus three.
+ */
+ public abstract int getInt (int index);
+
+ /**
+ * Absolute put method for writing an integer value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus three.
+ */
+ public abstract ByteBuffer putInt (int index, int value);
+
+ /**
+ * Relative get method for reading a long value.
+ *
+ * @exception BufferUnderflowException If there are fewer than eight bytes
+ * remaining in this buffer.
+ */
+ public abstract long getLong ();
+
+ /**
+ * Relative put method for writing a long value.
+ *
+ * @exception BufferOverflowException If this buffer's current position is
+ * not smaller than its limit.
+ */
+ public abstract ByteBuffer putLong (long value);
+
+ /**
+ * Absolute get method for reading a long value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus seven.
+ */
+ public abstract long getLong (int index);
+
+ /**
+ * Absolute put method for writing a float value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus seven.
+ */
+ public abstract ByteBuffer putLong (int index, long value);
+
+ /**
+ * Relative get method for reading a float value.
+ *
+ * @exception BufferUnderflowException If there are fewer than four bytes
+ * remaining in this buffer.
+ */
+ public abstract float getFloat ();
+
+ /**
+ * Relative put method for writing a float value.
+ *
+ * @exception BufferOverflowException If there are fewer than four bytes
+ * remaining in this buffer.
+ */
+ public abstract ByteBuffer putFloat (float value);
+
+ /**
+ * Absolute get method for reading a float value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus three.
+ */
+ public abstract float getFloat (int index);
+
+ /**
+ * Relative put method for writing a float value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus three.
+ */
+ public abstract ByteBuffer putFloat (int index, float value);
+
+ /**
+ * Relative get method for reading a double value.
+ *
+ * @exception BufferUnderflowException If there are fewer than eight bytes
+ * remaining in this buffer.
+ */
+ public abstract double getDouble ();
+
+ /**
+ * Relative put method for writing a double value.
+ *
+ * @exception BufferOverflowException If this buffer's current position is
+ * not smaller than its limit.
+ */
+ public abstract ByteBuffer putDouble (double value);
+
+ /**
+ * Absolute get method for reading a double value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus seven.
+ */
+ public abstract double getDouble (int index);
+
+ /**
+ * Absolute put method for writing a double value.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit, minus seven.
+ */
+ public abstract ByteBuffer putDouble (int index, double value);
+
+ /**
+ * Returns a string summarizing the state of this buffer.
+ */
+ public String toString ()
+ {
+ return getClass ().getName () +
+ "[pos=" + position () +
+ " lim=" + limit () +
+ " cap=" + capacity () + "]";
+ }
+}
diff --git a/libjava/classpath/java/nio/ByteBufferHelper.java b/libjava/classpath/java/nio/ByteBufferHelper.java
new file mode 100644
index 00000000000..6c46ca5d7ab
--- /dev/null
+++ b/libjava/classpath/java/nio/ByteBufferHelper.java
@@ -0,0 +1,344 @@
+/* ByteBufferImpl.java --
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ */
+final class ByteBufferHelper
+{
+ public static char getChar (ByteBuffer buffer, ByteOrder order)
+ {
+ return (char) getShort (buffer, order);
+ }
+
+ public static void putChar (ByteBuffer buffer, char value, ByteOrder order)
+ {
+ putShort (buffer, (short) value, order);
+ }
+
+ public static char getChar (ByteBuffer buffer, int index, ByteOrder order)
+ {
+ return (char) getShort (buffer, index, order);
+ }
+
+ public static void putChar (ByteBuffer buffer, int index,
+ char value, ByteOrder order)
+ {
+ putShort (buffer, index, (short) value, order);
+ }
+
+ public static short getShort (ByteBuffer buffer, ByteOrder order)
+ {
+ buffer.checkForUnderflow(2);
+
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ return (short) ((buffer.get() & 0xff)
+ + (buffer.get() << 8));
+ }
+
+ return (short) ((buffer.get() << 8)
+ + (buffer.get() & 0xff));
+ }
+
+ public static void putShort (ByteBuffer buffer, short value, ByteOrder order)
+ {
+ buffer.checkForOverflow(2);
+
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ buffer.put ((byte) value);
+ buffer.put ((byte) (value >> 8));
+ }
+ else
+ {
+ buffer.put ((byte) (value >> 8));
+ buffer.put ((byte) value);
+ }
+ }
+
+ public static short getShort (ByteBuffer buffer,
+ int index, ByteOrder order)
+ {
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ return (short) ((buffer.get (index) & 0xff)
+ + (buffer.get (++index) << 8));
+ }
+
+ return (short) ((buffer.get (index) << 8)
+ + (buffer.get (++index) & 0xff));
+ }
+
+ public static void putShort (ByteBuffer buffer, int index,
+ short value, ByteOrder order)
+ {
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ buffer.put (index, (byte) value);
+ buffer.put (++index, (byte) (value >> 8));
+ }
+ else
+ {
+ buffer.put (index, (byte) (value >> 8));
+ buffer.put (++index, (byte) value);
+ }
+ }
+
+ public static int getInt (ByteBuffer buffer, ByteOrder order)
+ {
+ buffer.checkForUnderflow(4);
+
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ return ((buffer.get() & 0xff)
+ + ((buffer.get() & 0xff) << 8)
+ + ((buffer.get() & 0xff) << 16)
+ + (buffer.get() << 24));
+ }
+
+ return (int) ((buffer.get() << 24)
+ + ((buffer.get() & 0xff) << 16)
+ + ((buffer.get() & 0xff) << 8)
+ + (buffer.get() & 0xff));
+ }
+
+ public static void putInt (ByteBuffer buffer, int value, ByteOrder order)
+ {
+ buffer.checkForOverflow(4);
+
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ buffer.put ((byte) value);
+ buffer.put ((byte) (value >> 8));
+ buffer.put ((byte) (value >> 16));
+ buffer.put ((byte) (value >> 24));
+ }
+ else
+ {
+ buffer.put ((byte) (value >> 24));
+ buffer.put ((byte) (value >> 16));
+ buffer.put ((byte) (value >> 8));
+ buffer.put ((byte) value);
+ }
+ }
+
+ public static int getInt (ByteBuffer buffer, int index, ByteOrder order)
+ {
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ return ((buffer.get (index) & 0xff)
+ + ((buffer.get (++index) & 0xff) << 8)
+ + ((buffer.get (++index) & 0xff) << 16)
+ + (buffer.get (++index) << 24));
+ }
+
+ return ((buffer.get (index) << 24)
+ + ((buffer.get (++index) & 0xff) << 16)
+ + ((buffer.get (++index) & 0xff) << 8)
+ + (buffer.get (++index) & 0xff));
+ }
+
+ public static void putInt (ByteBuffer buffer, int index,
+ int value, ByteOrder order)
+ {
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ buffer.put (index, (byte) value);
+ buffer.put (++index, (byte) (value >> 8));
+ buffer.put (++index, (byte) (value >> 16));
+ buffer.put (++index, (byte) (value >> 24));
+ }
+ else
+ {
+ buffer.put (index, (byte) (value >> 24));
+ buffer.put (++index, (byte) (value >> 16));
+ buffer.put (++index, (byte) (value >> 8));
+ buffer.put (++index, (byte) value);
+ }
+ }
+
+ public static long getLong (ByteBuffer buffer, ByteOrder order)
+ {
+ buffer.checkForUnderflow(8);
+
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ return ((buffer.get() & 0xff)
+ + (((buffer.get() & 0xff)) << 8)
+ + (((buffer.get() & 0xff)) << 16)
+ + (((buffer.get() & 0xffL)) << 24)
+ + (((buffer.get() & 0xffL)) << 32)
+ + (((buffer.get() & 0xffL)) << 40)
+ + (((buffer.get() & 0xffL)) << 48)
+ + (((long) buffer.get()) << 56));
+ }
+
+ return ((((long) buffer.get()) << 56)
+ + ((buffer.get() & 0xffL) << 48)
+ + ((buffer.get() & 0xffL) << 40)
+ + ((buffer.get() & 0xffL) << 32)
+ + ((buffer.get() & 0xffL) << 24)
+ + ((buffer.get() & 0xff) << 16)
+ + ((buffer.get() & 0xff) << 8)
+ + (buffer.get() & 0xff));
+ }
+
+ public static void putLong (ByteBuffer buffer, long value, ByteOrder order)
+ {
+ buffer.checkForOverflow(8);
+
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ buffer.put ((byte) value);
+ buffer.put ((byte) (value >> 8));
+ buffer.put ((byte) (value >> 16));
+ buffer.put ((byte) (value >> 24));
+ buffer.put ((byte) (value >> 32));
+ buffer.put ((byte) (value >> 40));
+ buffer.put ((byte) (value >> 48));
+ buffer.put ((byte) (value >> 56));
+ }
+ else
+ {
+ buffer.put ((byte) (value >> 56));
+ buffer.put ((byte) (value >> 48));
+ buffer.put ((byte) (value >> 40));
+ buffer.put ((byte) (value >> 32));
+ buffer.put ((byte) (value >> 24));
+ buffer.put ((byte) (value >> 16));
+ buffer.put ((byte) (value >> 8));
+ buffer.put ((byte) value);
+ }
+ }
+
+ public static long getLong (ByteBuffer buffer, int index, ByteOrder order)
+ {
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ return ((buffer.get (index) & 0xff)
+ + ((buffer.get (++index) & 0xff) << 8)
+ + ((buffer.get (++index) & 0xff) << 16)
+ + ((buffer.get (++index) & 0xffL) << 24)
+ + ((buffer.get (++index) & 0xffL) << 32)
+ + ((buffer.get (++index) & 0xffL) << 40)
+ + ((buffer.get (++index) & 0xffL) << 48)
+ + (((long) buffer.get (++index)) << 56));
+ }
+
+ return ((((long) buffer.get (index)) << 56)
+ + ((buffer.get (++index) & 0xffL) << 48)
+ + ((buffer.get (++index) & 0xffL) << 40)
+ + ((buffer.get (++index) & 0xffL) << 32)
+ + ((buffer.get (++index) & 0xffL) << 24)
+ + ((buffer.get (++index) & 0xff) << 16)
+ + ((buffer.get (++index) & 0xff) << 8)
+ + (buffer.get (++index) & 0xff));
+ }
+
+ public static void putLong (ByteBuffer buffer, int index,
+ long value, ByteOrder order)
+ {
+ if (order == ByteOrder.LITTLE_ENDIAN)
+ {
+ buffer.put (index, (byte) value);
+ buffer.put (++index, (byte) (value >> 8));
+ buffer.put (++index, (byte) (value >> 16));
+ buffer.put (++index, (byte) (value >> 24));
+ buffer.put (++index, (byte) (value >> 32));
+ buffer.put (++index, (byte) (value >> 40));
+ buffer.put (++index, (byte) (value >> 48));
+ buffer.put (++index, (byte) (value >> 56));
+ }
+ else
+ {
+ buffer.put (index, (byte) (value >> 56));
+ buffer.put (++index, (byte) (value >> 48));
+ buffer.put (++index, (byte) (value >> 40));
+ buffer.put (++index, (byte) (value >> 32));
+ buffer.put (++index, (byte) (value >> 24));
+ buffer.put (++index, (byte) (value >> 16));
+ buffer.put (++index, (byte) (value >> 8));
+ buffer.put (++index, (byte) value);
+ }
+ }
+
+ public static float getFloat (ByteBuffer buffer, ByteOrder order)
+ {
+ return Float.intBitsToFloat (getInt (buffer, order));
+ }
+
+ public static void putFloat (ByteBuffer buffer, float value, ByteOrder order)
+ {
+ putInt (buffer, Float.floatToRawIntBits (value), order);
+ }
+
+ public static float getFloat (ByteBuffer buffer, int index, ByteOrder order)
+ {
+ return Float.intBitsToFloat (getInt (buffer, index, order));
+ }
+
+ public static void putFloat (ByteBuffer buffer, int index,
+ float value, ByteOrder order)
+ {
+ putInt (buffer, index, Float.floatToRawIntBits (value), order);
+ }
+
+ public static double getDouble (ByteBuffer buffer, ByteOrder order)
+ {
+ return Double.longBitsToDouble (getLong (buffer, order));
+ }
+
+ public static void putDouble (ByteBuffer buffer, double value, ByteOrder order)
+ {
+ putLong (buffer, Double.doubleToRawLongBits (value), order);
+ }
+
+ public static double getDouble (ByteBuffer buffer, int index, ByteOrder order)
+ {
+ return Double.longBitsToDouble (getLong (buffer, index, order));
+ }
+
+ public static void putDouble (ByteBuffer buffer, int index,
+ double value, ByteOrder order)
+ {
+ putLong (buffer, index, Double.doubleToRawLongBits (value), order);
+ }
+} // ByteBufferHelper
+
diff --git a/libjava/classpath/java/nio/ByteBufferImpl.java b/libjava/classpath/java/nio/ByteBufferImpl.java
new file mode 100644
index 00000000000..48d7152000b
--- /dev/null
+++ b/libjava/classpath/java/nio/ByteBufferImpl.java
@@ -0,0 +1,379 @@
+/* ByteBufferImpl.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * This is a Heap memory implementation
+ */
+final class ByteBufferImpl extends ByteBuffer
+{
+ private boolean readOnly;
+
+ ByteBufferImpl (byte[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly)
+ {
+ super (capacity, limit, position, mark);
+ this.backing_buffer = buffer;
+ this.array_offset = offset;
+ this.readOnly = readOnly;
+ }
+
+ public CharBuffer asCharBuffer ()
+ {
+ return new CharViewBufferImpl (this, remaining() >> 1);
+ }
+
+ public ShortBuffer asShortBuffer ()
+ {
+ return new ShortViewBufferImpl (this, remaining() >> 1);
+ }
+
+ public IntBuffer asIntBuffer ()
+ {
+ return new IntViewBufferImpl (this, remaining() >> 2);
+ }
+
+ public LongBuffer asLongBuffer ()
+ {
+ return new LongViewBufferImpl (this, remaining() >> 3);
+ }
+
+ public FloatBuffer asFloatBuffer ()
+ {
+ return new FloatViewBufferImpl (this, remaining() >> 2);
+ }
+
+ public DoubleBuffer asDoubleBuffer ()
+ {
+ return new DoubleViewBufferImpl (this, remaining() >> 3);
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public ByteBuffer slice ()
+ {
+ return new ByteBufferImpl (backing_buffer, array_offset + position (), remaining (), remaining (), 0, -1, isReadOnly ());
+ }
+
+ public ByteBuffer duplicate ()
+ {
+ return new ByteBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, isReadOnly ());
+ }
+
+ public ByteBuffer asReadOnlyBuffer ()
+ {
+ return new ByteBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, true);
+ }
+
+ void shiftDown (int dst_offset, int src_offset, int count)
+ {
+ System.arraycopy(backing_buffer, array_offset + src_offset,
+ backing_buffer, array_offset + dst_offset,
+ count);
+ }
+
+ public ByteBuffer compact ()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int pos = position();
+ if (pos > 0)
+ {
+ int count = remaining();
+ shiftDown(0, pos, count);
+ position(count);
+ limit(capacity());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public boolean isDirect ()
+ {
+ return false;
+ }
+
+ /**
+ * Reads the <code>byte</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>bytes</code> in this buffer.
+ */
+ public byte get ()
+ {
+ if (pos >= limit)
+ throw new BufferUnderflowException();
+
+ return backing_buffer [(pos++) + array_offset];
+ }
+
+ /**
+ * Bulk get
+ */
+ public ByteBuffer get (byte[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ if ( (limit - pos) < length) // check for overflow
+ throw new BufferUnderflowException();
+
+ System.arraycopy(backing_buffer, pos + array_offset,
+ dst, offset, length);
+ pos += length;
+
+ return this;
+ }
+
+ /**
+ * Relative bulk put(), overloads the ByteBuffer impl.
+ */
+ public ByteBuffer put (byte[] src, int offset, int length)
+ {
+ if ( (limit - pos) < length) // check for overflow
+ throw new BufferOverflowException();
+ checkArraySize(src.length, offset, length);
+
+ System.arraycopy(src, offset, backing_buffer, pos + array_offset, length);
+ pos += length;
+
+ return this;
+ }
+
+ /**
+ * Relative put method. Writes <code>value</code> to the next position
+ * in the buffer.
+ *
+ * @exception BufferOverflowException If there is no remaining
+ * space in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public ByteBuffer put (byte value)
+ {
+ if (readOnly)
+ throw new ReadOnlyBufferException();
+ if (pos >= limit)
+ throw new BufferOverflowException();
+
+ backing_buffer [(pos++) + array_offset] = value;
+ return this;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>byte</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public byte get (int index)
+ {
+ checkIndex(index);
+
+ return backing_buffer [index + array_offset];
+ }
+
+ /**
+ * Absolute put method. Writes <code>value</code> to position
+ * <code>index</code> in the buffer.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public ByteBuffer put (int index, byte value)
+ {
+ checkIfReadOnly();
+ checkIndex(index);
+
+ backing_buffer [index + array_offset] = value;
+ return this;
+ }
+
+ public char getChar ()
+ {
+ return ByteBufferHelper.getChar(this, order());
+ }
+
+ public ByteBuffer putChar (char value)
+ {
+ if (readOnly)
+ throw new ReadOnlyBufferException ();
+ if ( (limit-pos) < 2)
+ throw new BufferOverflowException();
+
+ if (endian == ByteOrder.LITTLE_ENDIAN)
+ {
+ backing_buffer [(pos++) + array_offset] = (byte)(value&0xFF);
+ backing_buffer [(pos++) + array_offset] = (byte)(value>>8);
+ }
+ else
+ {
+ backing_buffer [(pos++) + array_offset] = (byte)(value>>8);
+ backing_buffer [(pos++) + array_offset] = (byte)(value&0xFF);
+ }
+ return this;
+ }
+
+ public char getChar (int index)
+ {
+ return ByteBufferHelper.getChar(this, index, order());
+ }
+
+ public ByteBuffer putChar (int index, char value)
+ {
+ ByteBufferHelper.putChar(this, index, value, order());
+ return this;
+ }
+
+ public short getShort ()
+ {
+ return ByteBufferHelper.getShort(this, order());
+ }
+
+ public ByteBuffer putShort (short value)
+ {
+ ByteBufferHelper.putShort(this, value, order());
+ return this;
+ }
+
+ public short getShort (int index)
+ {
+ return ByteBufferHelper.getShort(this, index, order());
+ }
+
+ public ByteBuffer putShort (int index, short value)
+ {
+ ByteBufferHelper.putShort(this, index, value, order());
+ return this;
+ }
+
+ public int getInt ()
+ {
+ return ByteBufferHelper.getInt(this, order());
+ }
+
+ public ByteBuffer putInt (int value)
+ {
+ ByteBufferHelper.putInt(this, value, order());
+ return this;
+ }
+
+ public int getInt (int index)
+ {
+ return ByteBufferHelper.getInt(this, index, order());
+ }
+
+ public ByteBuffer putInt (int index, int value)
+ {
+ ByteBufferHelper.putInt(this, index, value, order());
+ return this;
+ }
+
+ public long getLong ()
+ {
+ return ByteBufferHelper.getLong(this, order());
+ }
+
+ public ByteBuffer putLong (long value)
+ {
+ ByteBufferHelper.putLong (this, value, order());
+ return this;
+ }
+
+ public long getLong (int index)
+ {
+ return ByteBufferHelper.getLong (this, index, order());
+ }
+
+ public ByteBuffer putLong (int index, long value)
+ {
+ ByteBufferHelper.putLong (this, index, value, order());
+ return this;
+ }
+
+ public float getFloat ()
+ {
+ return ByteBufferHelper.getFloat (this, order());
+ }
+
+ public ByteBuffer putFloat (float value)
+ {
+ ByteBufferHelper.putFloat (this, value, order());
+ return this;
+ }
+
+ public float getFloat (int index)
+ {
+ return ByteBufferHelper.getFloat (this, index, order());
+ }
+
+ public ByteBuffer putFloat (int index, float value)
+ {
+ ByteBufferHelper.putFloat (this, index, value, order());
+ return this;
+ }
+
+ public double getDouble ()
+ {
+ return ByteBufferHelper.getDouble (this, order());
+ }
+
+ public ByteBuffer putDouble (double value)
+ {
+ ByteBufferHelper.putDouble (this, value, order());
+ return this;
+ }
+
+ public double getDouble (int index)
+ {
+ return ByteBufferHelper.getDouble (this, index, order());
+ }
+
+ public ByteBuffer putDouble (int index, double value)
+ {
+ ByteBufferHelper.putDouble (this, index, value, order());
+ return this;
+ }
+}
diff --git a/libjava/classpath/java/nio/ByteOrder.java b/libjava/classpath/java/nio/ByteOrder.java
new file mode 100644
index 00000000000..39a3ff893bd
--- /dev/null
+++ b/libjava/classpath/java/nio/ByteOrder.java
@@ -0,0 +1,82 @@
+/* ByteOrder.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.4
+ */
+public final class ByteOrder
+{
+ /**
+ * Constant indicating big endian byte order.
+ */
+ public static final ByteOrder BIG_ENDIAN = new ByteOrder();
+
+ /**
+ * Constant indicating little endian byte order.
+ */
+ public static final ByteOrder LITTLE_ENDIAN = new ByteOrder();
+
+ /**
+ * Returns the native byte order of the platform currently running.
+ *
+ * @return the native byte order
+ */
+ public static ByteOrder nativeOrder()
+ {
+ return (System.getProperty ("gnu.cpu.endian").equals("big")
+ ? BIG_ENDIAN : LITTLE_ENDIAN);
+ }
+
+ /**
+ * Returns a string representation of the byte order.
+ *
+ * @return the string
+ */
+ public String toString()
+ {
+ return this == BIG_ENDIAN ? "BIG_ENDIAN" : "LITTLE_ENDIAN";
+ }
+
+ // This class can only be instantiated here.
+ private ByteOrder()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/CharBuffer.java b/libjava/classpath/java/nio/CharBuffer.java
new file mode 100644
index 00000000000..6551555e20b
--- /dev/null
+++ b/libjava/classpath/java/nio/CharBuffer.java
@@ -0,0 +1,508 @@
+/* CharBuffer.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @since 1.4
+ */
+public abstract class CharBuffer extends Buffer
+ implements Comparable, CharSequence
+{
+ int array_offset;
+ char[] backing_buffer;
+
+ CharBuffer (int capacity, int limit, int position, int mark)
+ {
+ super (capacity, limit, position, mark);
+ array_offset = 0;
+ }
+
+ /**
+ * Allocates a new <code>CharBuffer</code> object with a given capacity.
+ */
+ public static CharBuffer allocate (int capacity)
+ {
+ return new CharBufferImpl (capacity);
+ }
+
+ /**
+ * Wraps a <code>char</code> array into a <code>CharBuffer</code>
+ * object.
+ *
+ * @param array the array to wrap
+ * @param offset the offset of the region in the array to wrap
+ * @param length the length of the region in the array to wrap
+ *
+ * @return a new <code>CharBuffer</code> object
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ public static final CharBuffer wrap(char[] array, int offset, int length)
+ {
+ return new CharBufferImpl(array, 0, array.length, offset + length, offset, -1, false);
+ }
+
+ /**
+ * Wraps a character sequence into a <code>CharBuffer</code> object.
+ *
+ * @param seq the sequence to wrap
+ *
+ * @return a new <code>CharBuffer</code> object
+ */
+ public static final CharBuffer wrap(CharSequence seq)
+ {
+ return wrap(seq, 0, seq.length());
+ }
+
+ /**
+ * Wraps a character sequence into a <code>CharBuffer</code> object.
+ *
+ * @param seq the sequence to wrap
+ * @param start the index of the first character to wrap
+ * @param end the index of the first character not to wrap
+ *
+ * @return a new <code>CharBuffer</code> object
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ public static final CharBuffer wrap(CharSequence seq, int start, int end)
+ {
+ // FIXME: implement better handling of java.lang.String.
+ // Probably share data with String via reflection.
+
+ if ((start < 0)
+ || (start > seq.length())
+ || (end < start)
+ || (end > (seq.length() - start)))
+ throw new IndexOutOfBoundsException();
+
+ int len = end - start;
+ char[] buffer = new char[len];
+
+ for (int i = 0; i < len; i++)
+ buffer[i] = seq.charAt(i + start);
+
+ return wrap(buffer, 0, len).asReadOnlyBuffer();
+ }
+
+ /**
+ * Wraps a <code>char</code> array into a <code>CharBuffer</code>
+ * object.
+ *
+ * @param array the array to wrap
+ *
+ * @return a new <code>CharBuffer</code> object
+ */
+ public static final CharBuffer wrap(char[] array)
+ {
+ return wrap(array, 0, array.length);
+ }
+
+ /**
+ * This method transfers <code>char</code>s from this buffer into the given
+ * destination array. Before the transfer, it checks if there are fewer than
+ * length <code>char</code>s remaining in this buffer.
+ *
+ * @param dst The destination array
+ * @param offset The offset within the array of the first <code>char</code>
+ * to be written; must be non-negative and no larger than dst.length.
+ * @param length The maximum number of bytes to be written to the given array;
+ * must be non-negative and no larger than dst.length - offset.
+ *
+ * @exception BufferUnderflowException If there are fewer than length
+ * <code>char</code>s remaining in this buffer.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold.
+ */
+ public CharBuffer get (char[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ {
+ dst [i] = get ();
+ }
+
+ return this;
+ }
+
+ /**
+ * This method transfers <code>char</code>s from this buffer into the given
+ * destination array.
+ *
+ * @param dst The byte array to write into.
+ *
+ * @exception BufferUnderflowException If there are fewer than dst.length
+ * <code>char</code>s remaining in this buffer.
+ */
+ public CharBuffer get (char[] dst)
+ {
+ return get (dst, 0, dst.length);
+ }
+
+ /**
+ * Writes the content of the the <code>CharBUFFER</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * <code>src.remaining()</code> space remaining in this buffer.
+ *
+ * @param src The source data.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>char</code>s in the source buffer.
+ * @exception IllegalArgumentException If the source buffer is this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public CharBuffer put (CharBuffer src)
+ {
+ if (src == this)
+ throw new IllegalArgumentException ();
+
+ checkForOverflow(src.remaining());
+
+ if (src.remaining () > 0)
+ {
+ char[] toPut = new char [src.remaining ()];
+ src.get (toPut);
+ put (toPut);
+ }
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>char array</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * length space remaining in this buffer.
+ *
+ * @param src The array to copy into the buffer.
+ * @param offset The offset within the array of the first byte to be read;
+ * must be non-negative and no larger than src.length.
+ * @param length The number of bytes to be read from the given array;
+ * must be non-negative and no larger than src.length - offset.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>char</code>s in the source array.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public CharBuffer put (char[] src, int offset, int length)
+ {
+ checkArraySize(src.length, offset, length);
+ checkForOverflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ put (src [i]);
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>char array</code> src
+ * into the buffer.
+ *
+ * @param src The array to copy into the buffer.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>char</code>s in the source array.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public final CharBuffer put (char[] src)
+ {
+ return put (src, 0, src.length);
+ }
+
+ /**
+ * Tells whether ot not this buffer is backed by an accessible
+ * <code>char</code> array.
+ */
+ public final boolean hasArray ()
+ {
+ return (backing_buffer != null
+ && !isReadOnly ());
+ }
+
+ /**
+ * Returns the <code>char</code> array that backs this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final char[] array ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return backing_buffer;
+ }
+
+ /**
+ * Returns the offset within this buffer's backing array of the first element.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final int arrayOffset ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return array_offset;
+ }
+
+ /**
+ * Calculates a hash code for this buffer.
+ *
+ * This is done with int arithmetic,
+ * where ** represents exponentiation, by this formula:<br>
+ * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
+ * (s[limit()-1]+30)*31**(limit()-1)</code>.
+ * Where s is the buffer data. Note that the hashcode is dependent
+ * on buffer content, and therefore is not useful if the buffer
+ * content may change.
+ */
+ public int hashCode ()
+ {
+ int hashCode = get(position()) + 31;
+ int multiplier = 1;
+ for (int i = position() + 1; i < limit(); ++i)
+ {
+ multiplier *= 31;
+ hashCode += (get(i) + 30)*multiplier;
+ }
+ return hashCode;
+ }
+
+ /**
+ * Checks if this buffer is equal to obj.
+ */
+ public boolean equals (Object obj)
+ {
+ if (obj instanceof CharBuffer)
+ {
+ return compareTo (obj) == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compares two <code>CharBuffer</code> objects.
+ *
+ * @exception ClassCastException If obj is not an object derived from
+ * <code>CharBuffer</code>.
+ */
+ public int compareTo (Object obj)
+ {
+ CharBuffer other = (CharBuffer) obj;
+
+ int num = Math.min(remaining(), other.remaining());
+ int pos_this = position();
+ int pos_other = other.position();
+
+ for (int count = 0; count < num; count++)
+ {
+ char a = get(pos_this++);
+ char b = other.get(pos_other++);
+
+ if (a == b)
+ continue;
+
+ if (a < b)
+ return -1;
+
+ return 1;
+ }
+
+ return remaining() - other.remaining();
+ }
+
+ /**
+ * Returns the byte order of this buffer.
+ */
+ public abstract ByteOrder order ();
+
+ /**
+ * Reads the <code>char</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>char</code>s in this buffer.
+ */
+ public abstract char get ();
+
+ /**
+ * Writes the <code>char</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * <code>char</code>s in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract CharBuffer put (char b);
+
+ /**
+ * Absolute get method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public abstract char get (int index);
+
+ /**
+ * Absolute put method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract CharBuffer put (int index, char b);
+
+ /**
+ * Compacts this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract CharBuffer compact ();
+
+ /**
+ * Tells wether or not this buffer is direct.
+ */
+ public abstract boolean isDirect ();
+
+ /**
+ * Creates a new <code>CharBuffer</code> whose content is a shared
+ * subsequence of this buffer's content.
+ */
+ public abstract CharBuffer slice ();
+
+ /**
+ * Creates a new <code>CharBuffer</code> that shares this buffer's
+ * content.
+ */
+ public abstract CharBuffer duplicate ();
+
+ /**
+ * Creates a new read-only <code>CharBuffer</code> that shares this
+ * buffer's content.
+ */
+ public abstract CharBuffer asReadOnlyBuffer ();
+
+ /**
+ * Returns the remaining content of the buffer as a string.
+ */
+ public String toString ()
+ {
+ if (hasArray ())
+ return new String (array (), position (), length ());
+
+ char[] buf = new char [length ()];
+ int pos = position ();
+ get (buf, 0, buf.length);
+ position (pos);
+ return new String (buf);
+ }
+
+ /**
+ * Returns the length of the remaining chars in this buffer.
+ */
+ public final int length ()
+ {
+ return remaining ();
+ }
+
+ /**
+ * Creates a new character buffer that represents the specified subsequence
+ * of this buffer, relative to the current position.
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on start and
+ * end do not hold.
+ */
+ public abstract CharSequence subSequence (int start, int length);
+
+ /**
+ * Relative put method.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer.
+ * @exception IndexOutOfBoundsException If the preconditions on the start
+ * and end parameters do not hold.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public CharBuffer put (String str, int start, int length)
+ {
+ return put (str.toCharArray (), start, length);
+ }
+
+ /**
+ * Relative put method.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public final CharBuffer put (String str)
+ {
+ return put (str.toCharArray (), 0, str.length ());
+ }
+
+ /**
+ * Returns the character at <code>position() + index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative not smaller than
+ * <code>remaining()</code>.
+ */
+ public final char charAt (int index)
+ {
+ if (index < 0
+ || index >= remaining ())
+ throw new IndexOutOfBoundsException ();
+
+ return get (position () + index);
+ }
+}
diff --git a/libjava/classpath/java/nio/CharBufferImpl.java b/libjava/classpath/java/nio/CharBufferImpl.java
new file mode 100644
index 00000000000..33f8dab983f
--- /dev/null
+++ b/libjava/classpath/java/nio/CharBufferImpl.java
@@ -0,0 +1,219 @@
+/* CharBufferImpl.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * This is a Heap memory implementation
+ */
+final class CharBufferImpl extends CharBuffer
+{
+ private boolean readOnly;
+
+ CharBufferImpl (int capacity)
+ {
+ this (new char [capacity], 0, capacity, capacity, 0, -1, false);
+ }
+
+ CharBufferImpl (char[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly)
+ {
+ super (capacity, limit, position, mark);
+ this.backing_buffer = buffer;
+ this.array_offset = offset;
+ this.readOnly = readOnly;
+ }
+
+ public CharBufferImpl (CharBufferImpl copy)
+ {
+ super (copy.capacity (), copy.limit (), copy.position (), 0);
+ backing_buffer = copy.backing_buffer;
+ array_offset = copy.array_offset;
+ readOnly = copy.isReadOnly ();
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public CharBuffer slice ()
+ {
+ return new CharBufferImpl (backing_buffer, array_offset + position (), remaining (), remaining (), 0, -1, isReadOnly ());
+ }
+
+ public CharBuffer duplicate ()
+ {
+ return new CharBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, isReadOnly ());
+ }
+
+ public CharBuffer asReadOnlyBuffer ()
+ {
+ return new CharBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, true);
+ }
+
+ public CharBuffer compact ()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int copied = 0;
+
+ while (remaining () > 0)
+ {
+ put (copied, get ());
+ copied++;
+ }
+
+ position (copied);
+ limit(capacity());
+ return this;
+ }
+
+ public boolean isDirect ()
+ {
+ return false;
+ }
+
+ public CharSequence subSequence (int start, int end)
+ {
+ if (start < 0
+ || start > length ()
+ || end < start
+ || end > length ())
+ throw new IndexOutOfBoundsException ();
+
+ return new CharBufferImpl (backing_buffer, array_offset, capacity (), position () + end, position () + start, -1, isReadOnly ());
+ }
+
+ /**
+ * Reads the <code>char</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>char</code>s in this buffer.
+ */
+ public char get ()
+ {
+ if (pos >= limit)
+ throw new BufferUnderflowException();
+
+ return backing_buffer [(pos++) + array_offset];
+ }
+
+ /**
+ * Relative put method. Writes <code>value</code> to the next position
+ * in the buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public CharBuffer put (char value)
+ {
+ if (readOnly)
+ throw new ReadOnlyBufferException();
+ if (pos >= limit)
+ throw new BufferOverflowException();
+
+ backing_buffer [(pos++) + array_offset] = value;
+ return this;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>char</code> at position
+ * <code>index</code>.
+ *
+ * @param index Position to read the <code>char</code> from.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public char get (int index)
+ {
+ checkIndex(index);
+
+ return backing_buffer [index + array_offset];
+ }
+
+ /**
+ * Bulk get, overloaded for speed.
+ */
+ public CharBuffer get (char[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ System.arraycopy(backing_buffer, pos + array_offset,
+ dst, offset, length);
+ pos += length;
+ return this;
+ }
+
+ /**
+ * Bulk put, overloaded for speed.
+ */
+ public CharBuffer put (char[] src, int offset, int length)
+ {
+ checkArraySize(src.length, offset, length);
+ checkForOverflow(length);
+
+ System.arraycopy(src, offset,
+ backing_buffer, pos + array_offset, length);
+ pos += length;
+ return this;
+ }
+
+ /**
+ * Absolute put method. Writes <code>value</code> to position
+ * <code>index</code> in the buffer.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public CharBuffer put (int index, char value)
+ {
+ checkIndex(index);
+ checkIfReadOnly();
+
+ backing_buffer [index + array_offset] = value;
+ return this;
+ }
+
+ public ByteOrder order ()
+ {
+ return ByteOrder.nativeOrder ();
+ }
+}
diff --git a/libjava/classpath/java/nio/CharViewBufferImpl.java b/libjava/classpath/java/nio/CharViewBufferImpl.java
new file mode 100644
index 00000000000..31983154461
--- /dev/null
+++ b/libjava/classpath/java/nio/CharViewBufferImpl.java
@@ -0,0 +1,187 @@
+/* CharViewBufferImpl.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+class CharViewBufferImpl extends CharBuffer
+{
+ /** Position in bb (i.e. a byte offset) where this buffer starts. */
+ private int offset;
+ private ByteBuffer bb;
+ private boolean readOnly;
+ private ByteOrder endian;
+
+ CharViewBufferImpl (ByteBuffer bb, int capacity)
+ {
+ super (capacity, capacity, 0, -1);
+ this.bb = bb;
+ this.offset = bb.position();
+ this.readOnly = bb.isReadOnly();
+ this.endian = bb.order();
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ public CharViewBufferImpl (ByteBuffer bb, int offset, int capacity,
+ int limit, int position, int mark,
+ boolean readOnly, ByteOrder endian)
+ {
+ super (capacity, limit, position, mark);
+ this.bb = bb;
+ this.offset = offset;
+ this.readOnly = readOnly;
+ this.endian = endian;
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ /**
+ * Reads the <code>char</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>char</code>s in this buffer.
+ */
+ public char get ()
+ {
+ int p = position();
+ char result = ByteBufferHelper.getChar(bb, (p << 1) + offset, endian);
+ position(p + 1);
+ return result;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>char</code> at position
+ * <code>index</code>.
+ *
+ * @param index Position to read the <code>char</code> from.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public char get (int index)
+ {
+ return ByteBufferHelper.getChar(bb, (index << 1) + offset, endian);
+ }
+
+ public CharBuffer put (char value)
+ {
+ int p = position();
+ ByteBufferHelper.putChar(bb, (p << 1) + offset, value, endian);
+ position(p + 1);
+ return this;
+ }
+
+ public CharBuffer put (int index, char value)
+ {
+ ByteBufferHelper.putChar(bb, (index << 1) + offset, value, endian);
+ return this;
+ }
+
+ public CharBuffer compact ()
+ {
+ if (position () > 0)
+ {
+ int count = limit () - position ();
+ bb.shiftDown(offset, offset + 2 * position(), 2 * count);
+ position (count);
+ limit (capacity ());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public CharBuffer slice ()
+ {
+ // Create a sliced copy of this object that shares its content.
+ return new CharViewBufferImpl (bb, (position () >> 1) + offset,
+ remaining (), remaining (), 0, -1,
+ isReadOnly (), endian);
+ }
+
+ CharBuffer duplicate (boolean readOnly)
+ {
+ int pos = position();
+ reset();
+ int mark = position();
+ position(pos);
+ return new CharViewBufferImpl (bb, offset, capacity(), limit(),
+ pos, mark, readOnly, endian);
+ }
+
+ public CharBuffer duplicate ()
+ {
+ return duplicate(readOnly);
+ }
+
+ public CharBuffer asReadOnlyBuffer ()
+ {
+ return duplicate(true);
+ }
+
+ public CharSequence subSequence (int start, int end)
+ {
+ if (start < 0
+ || end < start
+ || end > length ())
+ throw new IndexOutOfBoundsException ();
+
+ return new CharViewBufferImpl (bb, array_offset, capacity (),
+ position () + end, position () + start,
+ -1, isReadOnly (), endian);
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public boolean isDirect ()
+ {
+ return bb.isDirect ();
+ }
+
+ public ByteOrder order ()
+ {
+ return endian;
+ }
+}
diff --git a/libjava/classpath/java/nio/DirectByteBufferImpl.java b/libjava/classpath/java/nio/DirectByteBufferImpl.java
new file mode 100644
index 00000000000..16672993add
--- /dev/null
+++ b/libjava/classpath/java/nio/DirectByteBufferImpl.java
@@ -0,0 +1,419 @@
+/* DirectByteBufferImpl.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+import gnu.classpath.RawData;
+
+abstract class DirectByteBufferImpl extends ByteBuffer
+{
+ /**
+ * The owner is used to keep alive the object that actually owns the
+ * memory. There are three possibilities:
+ * 1) owner == this: We allocated the memory and we should free it,
+ * but *only* in finalize (if we've been sliced
+ * other objects will also have access to the
+ * memory).
+ * 2) owner == null: The byte buffer was created thru
+ * JNI.NewDirectByteBuffer. The JNI code is
+ * responsible for freeing the memory.
+ * 3) owner == some other object: The other object allocated the
+ * memory and should free it.
+ */
+ private final Object owner;
+
+ static final class ReadOnly extends DirectByteBufferImpl
+ {
+ ReadOnly(Object owner, RawData address,
+ int capacity, int limit,
+ int position)
+ {
+ super(owner, address, capacity, limit, position);
+ }
+
+ public ByteBuffer put(byte value)
+ {
+ throw new ReadOnlyBufferException ();
+ }
+
+ public ByteBuffer put(int index, byte value)
+ {
+ throw new ReadOnlyBufferException ();
+ }
+
+ public boolean isReadOnly()
+ {
+ return true;
+ }
+ }
+
+ static final class ReadWrite extends DirectByteBufferImpl
+ {
+ ReadWrite(int capacity)
+ {
+ super(capacity);
+ }
+
+ ReadWrite(Object owner, RawData address,
+ int capacity, int limit,
+ int position)
+ {
+ super(owner, address, capacity, limit, position);
+ }
+
+ public boolean isReadOnly()
+ {
+ return false;
+ }
+ }
+
+ DirectByteBufferImpl(int capacity)
+ {
+ super(capacity, capacity, 0, -1);
+ this.owner = this;
+ this.address = VMDirectByteBuffer.allocate(capacity);
+ }
+
+ DirectByteBufferImpl(Object owner, RawData address,
+ int capacity, int limit,
+ int position)
+ {
+ super(capacity, limit, position, -1);
+ this.owner = owner;
+ this.address = address;
+ }
+
+ /**
+ * Allocates a new direct byte buffer.
+ */
+ public static ByteBuffer allocate(int capacity)
+ {
+ return new DirectByteBufferImpl.ReadWrite(capacity);
+ }
+
+ protected void finalize() throws Throwable
+ {
+ if (owner == this)
+ VMDirectByteBuffer.free(address);
+ }
+
+ public byte get()
+ {
+ checkForUnderflow();
+
+ int pos = position();
+ byte result = VMDirectByteBuffer.get(address, pos);
+ position(pos + 1);
+ return result;
+ }
+
+ public byte get(int index)
+ {
+ checkIndex(index);
+
+ return VMDirectByteBuffer.get(address, index);
+ }
+
+ public ByteBuffer get(byte[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ int index = position();
+ VMDirectByteBuffer.get(address, index, dst, offset, length);
+ position(index+length);
+
+ return this;
+ }
+
+ public ByteBuffer put(byte value)
+ {
+ checkForOverflow();
+
+ int pos = position();
+ VMDirectByteBuffer.put(address, pos, value);
+ position(pos + 1);
+ return this;
+ }
+
+ public ByteBuffer put(int index, byte value)
+ {
+ checkIndex(index);
+
+ VMDirectByteBuffer.put(address, index, value);
+ return this;
+ }
+
+ void shiftDown(int dst_offset, int src_offset, int count)
+ {
+ VMDirectByteBuffer.shiftDown(address, dst_offset, src_offset, count);
+ }
+
+ public ByteBuffer compact()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int pos = position();
+ if (pos > 0)
+ {
+ int count = remaining();
+ VMDirectByteBuffer.shiftDown(address, 0, pos, count);
+ position(count);
+ limit(capacity());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public ByteBuffer slice()
+ {
+ int rem = remaining();
+ if (isReadOnly())
+ return new DirectByteBufferImpl.ReadOnly
+ (owner, VMDirectByteBuffer.adjustAddress(address, position()),
+ rem, rem, 0);
+ else
+ return new DirectByteBufferImpl.ReadWrite
+ (owner, VMDirectByteBuffer.adjustAddress(address, position()),
+ rem, rem, 0);
+ }
+
+ private ByteBuffer duplicate(boolean readOnly)
+ {
+ int pos = position();
+ reset();
+ int mark = position();
+ position(pos);
+ DirectByteBufferImpl result;
+ if (readOnly)
+ result = new DirectByteBufferImpl.ReadOnly(owner, address, capacity(),
+ limit(), pos);
+ else
+ result = new DirectByteBufferImpl.ReadWrite(owner, address, capacity(),
+ limit(), pos);
+
+ if (mark != pos)
+ {
+ result.position(mark);
+ result.mark();
+ result.position(pos);
+ }
+ return result;
+ }
+
+ public ByteBuffer duplicate()
+ {
+ return duplicate(isReadOnly());
+ }
+
+ public ByteBuffer asReadOnlyBuffer()
+ {
+ return duplicate(true);
+ }
+
+ public boolean isDirect()
+ {
+ return true;
+ }
+
+ public CharBuffer asCharBuffer()
+ {
+ return new CharViewBufferImpl(this, remaining() >> 1);
+ }
+
+ public ShortBuffer asShortBuffer()
+ {
+ return new ShortViewBufferImpl(this, remaining() >> 1);
+ }
+
+ public IntBuffer asIntBuffer()
+ {
+ return new IntViewBufferImpl(this, remaining() >> 2);
+ }
+
+ public LongBuffer asLongBuffer()
+ {
+ return new LongViewBufferImpl(this, remaining() >> 3);
+ }
+
+ public FloatBuffer asFloatBuffer()
+ {
+ return new FloatViewBufferImpl(this, remaining() >> 2);
+ }
+
+ public DoubleBuffer asDoubleBuffer()
+ {
+ return new DoubleViewBufferImpl(this, remaining() >> 3);
+ }
+
+ public char getChar()
+ {
+ return ByteBufferHelper.getChar(this, order());
+ }
+
+ public ByteBuffer putChar(char value)
+ {
+ ByteBufferHelper.putChar(this, value, order());
+ return this;
+ }
+
+ public char getChar(int index)
+ {
+ return ByteBufferHelper.getChar(this, index, order());
+ }
+
+ public ByteBuffer putChar(int index, char value)
+ {
+ ByteBufferHelper.putChar(this, index, value, order());
+ return this;
+ }
+
+ public short getShort()
+ {
+ return ByteBufferHelper.getShort(this, order());
+ }
+
+ public ByteBuffer putShort(short value)
+ {
+ ByteBufferHelper.putShort(this, value, order());
+ return this;
+ }
+
+ public short getShort(int index)
+ {
+ return ByteBufferHelper.getShort(this, index, order());
+ }
+
+ public ByteBuffer putShort(int index, short value)
+ {
+ ByteBufferHelper.putShort(this, index, value, order());
+ return this;
+ }
+
+ public int getInt()
+ {
+ return ByteBufferHelper.getInt(this, order());
+ }
+
+ public ByteBuffer putInt(int value)
+ {
+ ByteBufferHelper.putInt(this, value, order());
+ return this;
+ }
+
+ public int getInt(int index)
+ {
+ return ByteBufferHelper.getInt(this, index, order());
+ }
+
+ public ByteBuffer putInt(int index, int value)
+ {
+ ByteBufferHelper.putInt(this, index, value, order());
+ return this;
+ }
+
+ public long getLong()
+ {
+ return ByteBufferHelper.getLong(this, order());
+ }
+
+ public ByteBuffer putLong(long value)
+ {
+ ByteBufferHelper.putLong(this, value, order());
+ return this;
+ }
+
+ public long getLong(int index)
+ {
+ return ByteBufferHelper.getLong(this, index, order());
+ }
+
+ public ByteBuffer putLong(int index, long value)
+ {
+ ByteBufferHelper.putLong(this, index, value, order());
+ return this;
+ }
+
+ public float getFloat()
+ {
+ return ByteBufferHelper.getFloat(this, order());
+ }
+
+ public ByteBuffer putFloat(float value)
+ {
+ ByteBufferHelper.putFloat(this, value, order());
+ return this;
+ }
+
+ public float getFloat(int index)
+ {
+ return ByteBufferHelper.getFloat(this, index, order());
+ }
+
+ public ByteBuffer putFloat(int index, float value)
+ {
+ ByteBufferHelper.putFloat(this, index, value, order());
+ return this;
+ }
+
+ public double getDouble()
+ {
+ return ByteBufferHelper.getDouble(this, order());
+ }
+
+ public ByteBuffer putDouble(double value)
+ {
+ ByteBufferHelper.putDouble(this, value, order());
+ return this;
+ }
+
+ public double getDouble(int index)
+ {
+ return ByteBufferHelper.getDouble(this, index, order());
+ }
+
+ public ByteBuffer putDouble(int index, double value)
+ {
+ ByteBufferHelper.putDouble(this, index, value, order());
+ return this;
+ }
+}
diff --git a/libjava/classpath/java/nio/DoubleBuffer.java b/libjava/classpath/java/nio/DoubleBuffer.java
new file mode 100644
index 00000000000..381bb716636
--- /dev/null
+++ b/libjava/classpath/java/nio/DoubleBuffer.java
@@ -0,0 +1,383 @@
+/* DoubleBuffer.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @since 1.4
+ */
+public abstract class DoubleBuffer extends Buffer
+ implements Comparable
+{
+ int array_offset;
+ double[] backing_buffer;
+
+ DoubleBuffer (int capacity, int limit, int position, int mark)
+ {
+ super (capacity, limit, position, mark);
+ array_offset = 0;
+ }
+
+ /**
+ * Allocates a new <code>DoubleBuffer</code> object with a given capacity.
+ */
+ public static DoubleBuffer allocate (int capacity)
+ {
+ return new DoubleBufferImpl (capacity);
+ }
+
+ /**
+ * Wraps a <code>double</code> array into a <code>DoubleBuffer</code>
+ * object.
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ public static final DoubleBuffer wrap (double[] array, int offset, int length)
+ {
+ return new DoubleBufferImpl (array, 0, array.length, offset + length, offset, -1, false);
+ }
+
+ /**
+ * Wraps a <code>double</code> array into a <code>DoubleBuffer</code>
+ * object.
+ */
+ public static final DoubleBuffer wrap (double[] array)
+ {
+ return wrap (array, 0, array.length);
+ }
+
+ /**
+ * This method transfers <code>double</code>s from this buffer into the given
+ * destination array. Before the transfer, it checks if there are fewer than
+ * length <code>double</code>s remaining in this buffer.
+ *
+ * @param dst The destination array
+ * @param offset The offset within the array of the first <code>double</code>
+ * to be written; must be non-negative and no larger than dst.length.
+ * @param length The maximum number of bytes to be written to the given array;
+ * must be non-negative and no larger than dst.length - offset.
+ *
+ * @exception BufferUnderflowException If there are fewer than length
+ * <code>double</code>s remaining in this buffer.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold.
+ */
+ public DoubleBuffer get (double[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ {
+ dst [i] = get ();
+ }
+
+ return this;
+ }
+
+ /**
+ * This method transfers <code>double</code>s from this buffer into the given
+ * destination array.
+ *
+ * @param dst The byte array to write into.
+ *
+ * @exception BufferUnderflowException If there are fewer than dst.length
+ * <code>double</code>s remaining in this buffer.
+ */
+ public DoubleBuffer get (double[] dst)
+ {
+ return get (dst, 0, dst.length);
+ }
+
+ /**
+ * Writes the content of the the <code>DoubleBUFFER</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * <code>src.remaining()</code> space remaining in this buffer.
+ *
+ * @param src The source data.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>double</code>s in the source buffer.
+ * @exception IllegalArgumentException If the source buffer is this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public DoubleBuffer put (DoubleBuffer src)
+ {
+ if (src == this)
+ throw new IllegalArgumentException ();
+
+ checkForOverflow(src.remaining ());
+
+ if (src.remaining () > 0)
+ {
+ double[] toPut = new double [src.remaining ()];
+ src.get (toPut);
+ put (toPut);
+ }
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>double array</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * length space remaining in this buffer.
+ *
+ * @param src The array to copy into the buffer.
+ * @param offset The offset within the array of the first byte to be read;
+ * must be non-negative and no larger than src.length.
+ * @param length The number of bytes to be read from the given array;
+ * must be non-negative and no larger than src.length - offset.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>double</code>s in the source array.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public DoubleBuffer put (double[] src, int offset, int length)
+ {
+ checkArraySize(src.length, offset, length);
+ checkForOverflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ put (src [i]);
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>double array</code> src
+ * into the buffer.
+ *
+ * @param src The array to copy into the buffer.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>double</code>s in the source array.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public final DoubleBuffer put (double[] src)
+ {
+ return put (src, 0, src.length);
+ }
+
+ /**
+ * Tells whether ot not this buffer is backed by an accessible
+ * <code>double</code> array.
+ */
+ public final boolean hasArray ()
+ {
+ return (backing_buffer != null
+ && !isReadOnly ());
+ }
+
+ /**
+ * Returns the <code>double</code> array that backs this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final double[] array ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return backing_buffer;
+ }
+
+ /**
+ * Returns the offset within this buffer's backing array of the first element.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final int arrayOffset ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return array_offset;
+ }
+
+ /**
+ * Calculates a hash code for this buffer.
+ *
+ * This is done with <code>long</code> arithmetic,
+ * where ** represents exponentiation, by this formula:<br>
+ * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
+ * (s[limit()-1]+30)*31**(limit()-1)</code>.
+ * Where s is the buffer data, in Double.doubleToLongBits() form
+ * Note that the hashcode is dependent on buffer content,
+ * and therefore is not useful if the buffer content may change.
+ *
+ * @return the hash code (casted to int)
+ */
+ public int hashCode ()
+ {
+ long hashCode = Double.doubleToLongBits(get(position())) + 31;
+ long multiplier = 1;
+ for (int i = position() + 1; i < limit(); ++i)
+ {
+ multiplier *= 31;
+ hashCode += (Double.doubleToLongBits(get(i)) + 30)*multiplier;
+ }
+ return ((int)hashCode);
+ }
+
+ /**
+ * Checks if this buffer is equal to obj.
+ */
+ public boolean equals (Object obj)
+ {
+ if (obj instanceof DoubleBuffer)
+ {
+ return compareTo (obj) == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compares two <code>DoubleBuffer</code> objects.
+ *
+ * @exception ClassCastException If obj is not an object derived from
+ * <code>DoubleBuffer</code>.
+ */
+ public int compareTo (Object obj)
+ {
+ DoubleBuffer other = (DoubleBuffer) obj;
+
+ int num = Math.min(remaining(), other.remaining());
+ int pos_this = position();
+ int pos_other = other.position();
+
+ for (int count = 0; count < num; count++)
+ {
+ double a = get(pos_this++);
+ double b = other.get(pos_other++);
+
+ if (a == b)
+ continue;
+
+ if (a < b)
+ return -1;
+
+ return 1;
+ }
+
+ return remaining() - other.remaining();
+ }
+
+ /**
+ * Returns the byte order of this buffer.
+ */
+ public abstract ByteOrder order ();
+
+ /**
+ * Reads the <code>double</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>double</code>s in this buffer.
+ */
+ public abstract double get ();
+
+ /**
+ * Writes the <code>double</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * <code>double</code>s in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract DoubleBuffer put (double b);
+
+ /**
+ * Absolute get method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public abstract double get (int index);
+
+ /**
+ * Absolute put method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract DoubleBuffer put (int index, double b);
+
+ /**
+ * Compacts this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract DoubleBuffer compact ();
+
+ /**
+ * Tells wether or not this buffer is direct.
+ */
+ public abstract boolean isDirect ();
+
+ /**
+ * Creates a new <code>DoubleBuffer</code> whose content is a shared
+ * subsequence of this buffer's content.
+ */
+ public abstract DoubleBuffer slice ();
+
+ /**
+ * Creates a new <code>DoubleBuffer</code> that shares this buffer's
+ * content.
+ */
+ public abstract DoubleBuffer duplicate ();
+
+ /**
+ * Creates a new read-only <code>DoubleBuffer</code> that shares this
+ * buffer's content.
+ */
+ public abstract DoubleBuffer asReadOnlyBuffer ();
+}
diff --git a/libjava/classpath/java/nio/DoubleBufferImpl.java b/libjava/classpath/java/nio/DoubleBufferImpl.java
new file mode 100644
index 00000000000..248ab45e7c2
--- /dev/null
+++ b/libjava/classpath/java/nio/DoubleBufferImpl.java
@@ -0,0 +1,172 @@
+/* DoubleBufferImpl.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * This is a Heap memory implementation
+ */
+final class DoubleBufferImpl extends DoubleBuffer
+{
+ private boolean readOnly;
+
+ DoubleBufferImpl (int capacity)
+ {
+ this (new double [capacity], 0, capacity, capacity, 0, -1, false);
+ }
+
+ DoubleBufferImpl (double[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly)
+ {
+ super (capacity, limit, position, mark);
+ this.backing_buffer = buffer;
+ this.array_offset = offset;
+ this.readOnly = readOnly;
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public DoubleBuffer slice ()
+ {
+ return new DoubleBufferImpl (backing_buffer, array_offset + position (), remaining (), remaining (), 0, -1, isReadOnly ());
+ }
+
+ public DoubleBuffer duplicate ()
+ {
+ return new DoubleBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, isReadOnly ());
+ }
+
+ public DoubleBuffer asReadOnlyBuffer ()
+ {
+ return new DoubleBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, true);
+ }
+
+ public DoubleBuffer compact ()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int copied = 0;
+
+ while (remaining () > 0)
+ {
+ put (copied, get ());
+ copied++;
+ }
+
+ position (copied);
+ limit(capacity());
+ return this;
+ }
+
+ public boolean isDirect ()
+ {
+ return false;
+ }
+
+ /**
+ * Reads the <code>double</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>double</code>s in this buffer.
+ */
+ public double get ()
+ {
+ checkForUnderflow();
+
+ double result = backing_buffer [position ()];
+ position (position () + 1);
+ return result;
+ }
+
+ /**
+ * Relative put method. Writes <code>value</code> to the next position
+ * in the buffer.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * space in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public DoubleBuffer put (double value)
+ {
+ checkIfReadOnly();
+ checkForOverflow();
+
+ backing_buffer [position ()] = value;
+ position (position () + 1);
+ return this;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>double</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public double get (int index)
+ {
+ checkIndex(index);
+
+ return backing_buffer [index];
+ }
+
+ /**
+ * Absolute put method. Writes <code>value</code> to position
+ * <code>index</code> in the buffer.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public DoubleBuffer put (int index, double value)
+ {
+ checkIfReadOnly();
+ checkIndex(index);
+
+ backing_buffer [index] = value;
+ return this;
+ }
+
+ public ByteOrder order ()
+ {
+ return ByteOrder.nativeOrder ();
+ }
+}
diff --git a/libjava/classpath/java/nio/DoubleViewBufferImpl.java b/libjava/classpath/java/nio/DoubleViewBufferImpl.java
new file mode 100644
index 00000000000..e860f2f808d
--- /dev/null
+++ b/libjava/classpath/java/nio/DoubleViewBufferImpl.java
@@ -0,0 +1,172 @@
+/* DoubleViewBufferImpl.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+final class DoubleViewBufferImpl extends DoubleBuffer
+{
+ /** Position in bb (i.e. a byte offset) where this buffer starts. */
+ private int offset;
+ private ByteBuffer bb;
+ private boolean readOnly;
+ private ByteOrder endian;
+
+ DoubleViewBufferImpl (ByteBuffer bb, int capacity)
+ {
+ super (capacity, capacity, 0, -1);
+ this.bb = bb;
+ this.offset = bb.position();
+ this.readOnly = bb.isReadOnly();
+ this.endian = bb.order();
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ public DoubleViewBufferImpl (ByteBuffer bb, int offset, int capacity,
+ int limit, int position, int mark,
+ boolean readOnly, ByteOrder endian)
+ {
+ super (capacity, limit, position, mark);
+ this.bb = bb;
+ this.offset = offset;
+ this.readOnly = readOnly;
+ this.endian = endian;
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ /**
+ * Reads the <code>double</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>double</code>s in this buffer.
+ */
+ public double get ()
+ {
+ int p = position();
+ double result = ByteBufferHelper.getDouble(bb, (p << 3) + offset, endian);
+ position(p + 1);
+ return result;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>double</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public double get (int index)
+ {
+ return ByteBufferHelper.getDouble(bb, (index << 3) + offset, endian);
+ }
+
+ public DoubleBuffer put (double value)
+ {
+ int p = position();
+ ByteBufferHelper.putDouble(bb, (p << 3) + offset, value, endian);
+ position(p + 1);
+ return this;
+ }
+
+ public DoubleBuffer put (int index, double value)
+ {
+ ByteBufferHelper.putDouble(bb, (index << 3) + offset, value, endian);
+ return this;
+ }
+
+ public DoubleBuffer compact ()
+ {
+ if (position () > 0)
+ {
+ int count = limit () - position ();
+ bb.shiftDown(offset, offset + 8 * position(), 8 * count);
+ position (count);
+ limit (capacity ());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public DoubleBuffer slice ()
+ {
+ return new DoubleViewBufferImpl (bb, (position () >> 3) + offset,
+ remaining(), remaining(), 0, -1,
+ readOnly, endian);
+ }
+
+ DoubleBuffer duplicate (boolean readOnly)
+ {
+ int pos = position();
+ reset();
+ int mark = position();
+ position(pos);
+ return new DoubleViewBufferImpl (bb, offset, capacity(), limit(),
+ pos, mark, readOnly, endian);
+ }
+
+ public DoubleBuffer duplicate ()
+ {
+ return duplicate(readOnly);
+ }
+
+ public DoubleBuffer asReadOnlyBuffer ()
+ {
+ return duplicate(true);
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public boolean isDirect ()
+ {
+ return bb.isDirect ();
+ }
+
+ public ByteOrder order ()
+ {
+ return endian;
+ }
+}
diff --git a/libjava/classpath/java/nio/FloatBuffer.java b/libjava/classpath/java/nio/FloatBuffer.java
new file mode 100644
index 00000000000..8042333cbac
--- /dev/null
+++ b/libjava/classpath/java/nio/FloatBuffer.java
@@ -0,0 +1,383 @@
+/* FloatBuffer.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @since 1.4
+ */
+public abstract class FloatBuffer extends Buffer
+ implements Comparable
+{
+ int array_offset;
+ float[] backing_buffer;
+
+ FloatBuffer (int capacity, int limit, int position, int mark)
+ {
+ super (capacity, limit, position, mark);
+ array_offset = 0;
+ }
+
+ /**
+ * Allocates a new <code>FloatBuffer</code> object with a given capacity.
+ */
+ public static FloatBuffer allocate (int capacity)
+ {
+ return new FloatBufferImpl (capacity);
+ }
+
+ /**
+ * Wraps a <code>float</code> array into a <code>FloatBuffer</code>
+ * object.
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ public static final FloatBuffer wrap (float[] array, int offset, int length)
+ {
+ return new FloatBufferImpl (array, 0, array.length, offset + length, offset, -1, false);
+ }
+
+ /**
+ * Wraps a <code>float</code> array into a <code>FloatBuffer</code>
+ * object.
+ */
+ public static final FloatBuffer wrap (float[] array)
+ {
+ return wrap (array, 0, array.length);
+ }
+
+ /**
+ * This method transfers <code>float</code>s from this buffer into the given
+ * destination array. Before the transfer, it checks if there are fewer than
+ * length <code>float</code>s remaining in this buffer.
+ *
+ * @param dst The destination array
+ * @param offset The offset within the array of the first <code>float</code>
+ * to be written; must be non-negative and no larger than dst.length.
+ * @param length The maximum number of bytes to be written to the given array;
+ * must be non-negative and no larger than dst.length - offset.
+ *
+ * @exception BufferUnderflowException If there are fewer than length
+ * <code>float</code>s remaining in this buffer.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold.
+ */
+ public FloatBuffer get (float[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ {
+ dst [i] = get ();
+ }
+
+ return this;
+ }
+
+ /**
+ * This method transfers <code>float</code>s from this buffer into the given
+ * destination array.
+ *
+ * @param dst The byte array to write into.
+ *
+ * @exception BufferUnderflowException If there are fewer than dst.length
+ * <code>float</code>s remaining in this buffer.
+ */
+ public FloatBuffer get (float[] dst)
+ {
+ return get (dst, 0, dst.length);
+ }
+
+ /**
+ * Writes the content of the the <code>FloatBUFFER</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * <code>src.remaining()</code> space remaining in this buffer.
+ *
+ * @param src The source data.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>float</code>s in the source buffer.
+ * @exception IllegalArgumentException If the source buffer is this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public FloatBuffer put (FloatBuffer src)
+ {
+ if (src == this)
+ throw new IllegalArgumentException ();
+
+ checkForOverflow(src.remaining());
+
+ if (src.remaining () > 0)
+ {
+ float[] toPut = new float [src.remaining ()];
+ src.get (toPut);
+ put (toPut);
+ }
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>float array</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * length space remaining in this buffer.
+ *
+ * @param src The array to copy into the buffer.
+ * @param offset The offset within the array of the first byte to be read;
+ * must be non-negative and no larger than src.length.
+ * @param length The number of bytes to be read from the given array;
+ * must be non-negative and no larger than src.length - offset.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>float</code>s in the source array.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public FloatBuffer put (float[] src, int offset, int length)
+ {
+ checkArraySize(src.length, offset, length);
+ checkForOverflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ put (src [i]);
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>float array</code> src
+ * into the buffer.
+ *
+ * @param src The array to copy into the buffer.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>float</code>s in the source array.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public final FloatBuffer put (float[] src)
+ {
+ return put (src, 0, src.length);
+ }
+
+ /**
+ * Tells whether ot not this buffer is backed by an accessible
+ * <code>float</code> array.
+ */
+ public final boolean hasArray ()
+ {
+ return (backing_buffer != null
+ && !isReadOnly ());
+ }
+
+ /**
+ * Returns the <code>float</code> array that backs this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final float[] array ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return backing_buffer;
+ }
+
+ /**
+ * Returns the offset within this buffer's backing array of the first element.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final int arrayOffset ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return array_offset;
+ }
+
+ /**
+ * Calculates a hash code for this buffer.
+ *
+ * This is done with <code>int</code> arithmetic,
+ * where ** represents exponentiation, by this formula:<br>
+ * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
+ * (s[limit()-1]+30)*31**(limit()-1)</code>.
+ * Where s is the buffer data, in Float.floatToIntBits() form
+ * Note that the hashcode is dependent on buffer content,
+ * and therefore is not useful if the buffer content may change.
+ *
+ * @return the hash code
+ */
+ public int hashCode ()
+ {
+ int hashCode = Float.floatToIntBits(get(position())) + 31;
+ int multiplier = 1;
+ for (int i = position() + 1; i < limit(); ++i)
+ {
+ multiplier *= 31;
+ hashCode += (Float.floatToIntBits(get(i)) + 30)*multiplier;
+ }
+ return hashCode;
+ }
+
+ /**
+ * Checks if this buffer is equal to obj.
+ */
+ public boolean equals (Object obj)
+ {
+ if (obj instanceof FloatBuffer)
+ {
+ return compareTo (obj) == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compares two <code>FloatBuffer</code> objects.
+ *
+ * @exception ClassCastException If obj is not an object derived from
+ * <code>FloatBuffer</code>.
+ */
+ public int compareTo (Object obj)
+ {
+ FloatBuffer other = (FloatBuffer) obj;
+
+ int num = Math.min(remaining(), other.remaining());
+ int pos_this = position();
+ int pos_other = other.position();
+
+ for (int count = 0; count < num; count++)
+ {
+ float a = get(pos_this++);
+ float b = other.get(pos_other++);
+
+ if (a == b)
+ continue;
+
+ if (a < b)
+ return -1;
+
+ return 1;
+ }
+
+ return remaining() - other.remaining();
+ }
+
+ /**
+ * Returns the byte order of this buffer.
+ */
+ public abstract ByteOrder order ();
+
+ /**
+ * Reads the <code>float</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>float</code>s in this buffer.
+ */
+ public abstract float get ();
+
+ /**
+ * Writes the <code>float</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * <code>float</code>s in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract FloatBuffer put (float b);
+
+ /**
+ * Absolute get method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public abstract float get (int index);
+
+ /**
+ * Absolute put method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract FloatBuffer put (int index, float b);
+
+ /**
+ * Compacts this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract FloatBuffer compact ();
+
+ /**
+ * Tells wether or not this buffer is direct.
+ */
+ public abstract boolean isDirect ();
+
+ /**
+ * Creates a new <code>FloatBuffer</code> whose content is a shared
+ * subsequence of this buffer's content.
+ */
+ public abstract FloatBuffer slice ();
+
+ /**
+ * Creates a new <code>FloatBuffer</code> that shares this buffer's
+ * content.
+ */
+ public abstract FloatBuffer duplicate ();
+
+ /**
+ * Creates a new read-only <code>FloatBuffer</code> that shares this
+ * buffer's content.
+ */
+ public abstract FloatBuffer asReadOnlyBuffer ();
+}
diff --git a/libjava/classpath/java/nio/FloatBufferImpl.java b/libjava/classpath/java/nio/FloatBufferImpl.java
new file mode 100644
index 00000000000..b4868780c42
--- /dev/null
+++ b/libjava/classpath/java/nio/FloatBufferImpl.java
@@ -0,0 +1,172 @@
+/* FloatBufferImpl.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * This is a Heap memory implementation
+ */
+final class FloatBufferImpl extends FloatBuffer
+{
+ private boolean readOnly;
+
+ FloatBufferImpl (int capacity)
+ {
+ this (new float [capacity], 0, capacity, capacity, 0, -1, false);
+ }
+
+ FloatBufferImpl (float[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly)
+ {
+ super (capacity, limit, position, mark);
+ this.backing_buffer = buffer;
+ this.array_offset = offset;
+ this.readOnly = readOnly;
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public FloatBuffer slice ()
+ {
+ return new FloatBufferImpl (backing_buffer, array_offset + position (), remaining (), remaining (), 0, -1, isReadOnly ());
+ }
+
+ public FloatBuffer duplicate ()
+ {
+ return new FloatBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, isReadOnly ());
+ }
+
+ public FloatBuffer asReadOnlyBuffer ()
+ {
+ return new FloatBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, true);
+ }
+
+ public FloatBuffer compact ()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int copied = 0;
+
+ while (remaining () > 0)
+ {
+ put (copied, get ());
+ copied++;
+ }
+
+ position (copied);
+ limit(capacity());
+ return this;
+ }
+
+ public boolean isDirect ()
+ {
+ return false;
+ }
+
+ /**
+ * Reads the <code>float</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>floats</code> in this buffer.
+ */
+ public float get ()
+ {
+ checkForUnderflow();
+
+ float result = backing_buffer [position ()];
+ position (position () + 1);
+ return result;
+ }
+
+ /**
+ * Relative put method. Writes <code>value</code> to the next position
+ * in the buffer.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * space in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public FloatBuffer put (float value)
+ {
+ checkIfReadOnly();
+ checkForOverflow();
+
+ backing_buffer [position ()] = value;
+ position (position () + 1);
+ return this;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>float</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public float get (int index)
+ {
+ checkIndex(index);
+
+ return backing_buffer [index];
+ }
+
+ /**
+ * Absolute put method. Writes <code>value</code> to position
+ * <code>index</code> in the buffer.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public FloatBuffer put (int index, float value)
+ {
+ checkIfReadOnly();
+ checkIndex(index);
+
+ backing_buffer [index] = value;
+ return this;
+ }
+
+ public ByteOrder order ()
+ {
+ return ByteOrder.nativeOrder ();
+ }
+}
diff --git a/libjava/classpath/java/nio/FloatViewBufferImpl.java b/libjava/classpath/java/nio/FloatViewBufferImpl.java
new file mode 100644
index 00000000000..55770d52a29
--- /dev/null
+++ b/libjava/classpath/java/nio/FloatViewBufferImpl.java
@@ -0,0 +1,173 @@
+/* FloatViewBufferImpl.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+final class FloatViewBufferImpl extends FloatBuffer
+{
+ /** Position in bb (i.e. a byte offset) where this buffer starts. */
+ private int offset;
+ private ByteBuffer bb;
+ private boolean readOnly;
+ private ByteOrder endian;
+
+ FloatViewBufferImpl (ByteBuffer bb, int capacity)
+ {
+ super (capacity, capacity, 0, -1);
+ this.bb = bb;
+ this.offset = bb.position();
+ this.readOnly = bb.isReadOnly();
+ this.endian = bb.order();
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ public FloatViewBufferImpl (ByteBuffer bb, int offset, int capacity,
+ int limit, int position, int mark,
+ boolean readOnly, ByteOrder endian)
+ {
+ super (capacity, limit, position, mark);
+ this.bb = bb;
+ this.offset = offset;
+ this.readOnly = readOnly;
+ this.endian = endian;
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ /**
+ * Reads the <code>float</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>floats</code> in this buffer.
+ */
+ public float get ()
+ {
+ int p = position();
+ float result = ByteBufferHelper.getFloat(bb, (p << 2) + offset, endian);
+ position(p + 1);
+ return result;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>float</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public float get (int index)
+ {
+ return ByteBufferHelper.getFloat(bb, (index << 2) + offset, endian);
+ }
+
+ public FloatBuffer put (float value)
+ {
+ int p = position();
+ ByteBufferHelper.putFloat(bb, (p << 2) + offset, value, endian);
+ position(p + 1);
+ return this;
+ }
+
+ public FloatBuffer put (int index, float value)
+ {
+ ByteBufferHelper.putFloat(bb, (index << 2) + offset, value, endian);
+ return this;
+ }
+
+ public FloatBuffer compact ()
+ {
+ if (position () > 0)
+ {
+ int count = limit () - position ();
+ bb.shiftDown(offset, offset + 4 * position(), 4 * count);
+ position (count);
+ limit (capacity ());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public FloatBuffer slice ()
+ {
+ // Create a sliced copy of this object that shares its content.
+ return new FloatViewBufferImpl (bb, (position () >> 2) + offset,
+ remaining(), remaining(), 0, -1,
+ readOnly, endian);
+ }
+
+ FloatBuffer duplicate (boolean readOnly)
+ {
+ int pos = position();
+ reset();
+ int mark = position();
+ position(pos);
+ return new FloatViewBufferImpl (bb, offset, capacity(), limit(),
+ pos, mark, readOnly, endian);
+ }
+
+ public FloatBuffer duplicate ()
+ {
+ return duplicate(readOnly);
+ }
+
+ public FloatBuffer asReadOnlyBuffer ()
+ {
+ return duplicate(true);
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public boolean isDirect ()
+ {
+ return bb.isDirect ();
+ }
+
+ public ByteOrder order ()
+ {
+ return endian;
+ }
+}
diff --git a/libjava/classpath/java/nio/IntBuffer.java b/libjava/classpath/java/nio/IntBuffer.java
new file mode 100644
index 00000000000..1e1fe9c7565
--- /dev/null
+++ b/libjava/classpath/java/nio/IntBuffer.java
@@ -0,0 +1,383 @@
+/* IntBuffer.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @since 1.4
+ */
+public abstract class IntBuffer extends Buffer
+ implements Comparable
+{
+ int array_offset;
+ int[] backing_buffer;
+
+ IntBuffer (int capacity, int limit, int position, int mark)
+ {
+ super (capacity, limit, position, mark);
+ array_offset = 0;
+ }
+
+ /**
+ * Allocates a new <code>IntBuffer</code> object with a given capacity.
+ */
+ public static IntBuffer allocate (int capacity)
+ {
+ return new IntBufferImpl (capacity);
+ }
+
+ /**
+ * Wraps a <code>int</code> array into a <code>IntBuffer</code>
+ * object.
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ public static final IntBuffer wrap (int[] array, int offset, int length)
+ {
+ return new IntBufferImpl (array, 0, array.length, offset + length, offset, -1, false);
+ }
+
+ /**
+ * Wraps a <code>int</code> array into a <code>IntBuffer</code>
+ * object.
+ */
+ public static final IntBuffer wrap (int[] array)
+ {
+ return wrap (array, 0, array.length);
+ }
+
+ /**
+ * This method transfers <code>int</code>s from this buffer into the given
+ * destination array. Before the transfer, it checks if there are fewer than
+ * length <code>int</code>s remaining in this buffer.
+ *
+ * @param dst The destination array
+ * @param offset The offset within the array of the first <code>int</code>
+ * to be written; must be non-negative and no larger than dst.length.
+ * @param length The maximum number of bytes to be written to the given array;
+ * must be non-negative and no larger than dst.length - offset.
+ *
+ * @exception BufferUnderflowException If there are fewer than length
+ * <code>int</code>s remaining in this buffer.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold.
+ */
+ public IntBuffer get (int[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ {
+ dst [i] = get ();
+ }
+
+ return this;
+ }
+
+ /**
+ * This method transfers <code>int</code>s from this buffer into the given
+ * destination array.
+ *
+ * @param dst The byte array to write into.
+ *
+ * @exception BufferUnderflowException If there are fewer than dst.length
+ * <code>int</code>s remaining in this buffer.
+ */
+ public IntBuffer get (int[] dst)
+ {
+ return get (dst, 0, dst.length);
+ }
+
+ /**
+ * Writes the content of the the <code>IntBUFFER</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * <code>src.remaining()</code> space remaining in this buffer.
+ *
+ * @param src The source data.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>int</code>s in the source buffer.
+ * @exception IllegalArgumentException If the source buffer is this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public IntBuffer put (IntBuffer src)
+ {
+ if (src == this)
+ throw new IllegalArgumentException ();
+
+ checkForOverflow(src.remaining ());
+
+ if (src.remaining () > 0)
+ {
+ int[] toPut = new int [src.remaining ()];
+ src.get (toPut);
+ put (toPut);
+ }
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>int array</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * length space remaining in this buffer.
+ *
+ * @param src The array to copy into the buffer.
+ * @param offset The offset within the array of the first byte to be read;
+ * must be non-negative and no larger than src.length.
+ * @param length The number of bytes to be read from the given array;
+ * must be non-negative and no larger than src.length - offset.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>int</code>s in the source array.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public IntBuffer put (int[] src, int offset, int length)
+ {
+ checkArraySize(src.length, offset, length);
+ checkForOverflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ put (src [i]);
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>int array</code> src
+ * into the buffer.
+ *
+ * @param src The array to copy into the buffer.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>int</code>s in the source array.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public final IntBuffer put (int[] src)
+ {
+ return put (src, 0, src.length);
+ }
+
+ /**
+ * Tells whether ot not this buffer is backed by an accessible
+ * <code>int</code> array.
+ */
+ public final boolean hasArray ()
+ {
+ return (backing_buffer != null
+ && !isReadOnly ());
+ }
+
+ /**
+ * Returns the <code>int</code> array that backs this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final int[] array ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return backing_buffer;
+ }
+
+ /**
+ * Returns the offset within this buffer's backing array of the first element.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final int arrayOffset ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return array_offset;
+ }
+
+ /**
+ * Calculates a hash code for this buffer.
+ *
+ * This is done with <code>int</code> arithmetic,
+ * where ** represents exponentiation, by this formula:<br>
+ * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
+ * (s[limit()-1]+30)*31**(limit()-1)</code>.
+ * Where s is the buffer data. Note that the hashcode is dependent
+ * on buffer content, and therefore is not useful if the buffer
+ * content may change.
+ *
+ * @return the hash code
+ */
+ public int hashCode ()
+ {
+ int hashCode = get(position()) + 31;
+ int multiplier = 1;
+ for (int i = position() + 1; i < limit(); ++i)
+ {
+ multiplier *= 31;
+ hashCode += (get(i) + 30)*multiplier;
+ }
+ return hashCode;
+ }
+
+ /**
+ * Checks if this buffer is equal to obj.
+ */
+ public boolean equals (Object obj)
+ {
+ if (obj instanceof IntBuffer)
+ {
+ return compareTo (obj) == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compares two <code>IntBuffer</code> objects.
+ *
+ * @exception ClassCastException If obj is not an object derived from
+ * <code>IntBuffer</code>.
+ */
+ public int compareTo (Object obj)
+ {
+ IntBuffer other = (IntBuffer) obj;
+
+ int num = Math.min(remaining(), other.remaining());
+ int pos_this = position();
+ int pos_other = other.position();
+
+ for (int count = 0; count < num; count++)
+ {
+ int a = get(pos_this++);
+ int b = other.get(pos_other++);
+
+ if (a == b)
+ continue;
+
+ if (a < b)
+ return -1;
+
+ return 1;
+ }
+
+ return remaining() - other.remaining();
+ }
+
+ /**
+ * Returns the byte order of this buffer.
+ */
+ public abstract ByteOrder order ();
+
+ /**
+ * Reads the <code>int</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>int</code>s in this buffer.
+ */
+ public abstract int get ();
+
+ /**
+ * Writes the <code>int</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * <code>int</code>s in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract IntBuffer put (int b);
+
+ /**
+ * Absolute get method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public abstract int get (int index);
+
+ /**
+ * Absolute put method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract IntBuffer put (int index, int b);
+
+ /**
+ * Compacts this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract IntBuffer compact ();
+
+ /**
+ * Tells wether or not this buffer is direct.
+ */
+ public abstract boolean isDirect ();
+
+ /**
+ * Creates a new <code>IntBuffer</code> whose content is a shared
+ * subsequence of this buffer's content.
+ */
+ public abstract IntBuffer slice ();
+
+ /**
+ * Creates a new <code>IntBuffer</code> that shares this buffer's
+ * content.
+ */
+ public abstract IntBuffer duplicate ();
+
+ /**
+ * Creates a new read-only <code>IntBuffer</code> that shares this
+ * buffer's content.
+ */
+ public abstract IntBuffer asReadOnlyBuffer ();
+}
diff --git a/libjava/classpath/java/nio/IntBufferImpl.java b/libjava/classpath/java/nio/IntBufferImpl.java
new file mode 100644
index 00000000000..22657482b42
--- /dev/null
+++ b/libjava/classpath/java/nio/IntBufferImpl.java
@@ -0,0 +1,172 @@
+/* IntBufferImpl.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * This is a Heap memory implementation
+ */
+final class IntBufferImpl extends IntBuffer
+{
+ private boolean readOnly;
+
+ IntBufferImpl (int capacity)
+ {
+ this (new int [capacity], 0, capacity, capacity, 0, -1, false);
+ }
+
+ IntBufferImpl (int[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly)
+ {
+ super (capacity, limit, position, mark);
+ this.backing_buffer = buffer;
+ this.array_offset = offset;
+ this.readOnly = readOnly;
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public IntBuffer slice ()
+ {
+ return new IntBufferImpl (backing_buffer, array_offset + position (), remaining (), remaining (), 0, -1, isReadOnly ());
+ }
+
+ public IntBuffer duplicate ()
+ {
+ return new IntBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, isReadOnly ());
+ }
+
+ public IntBuffer asReadOnlyBuffer ()
+ {
+ return new IntBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, true);
+ }
+
+ public IntBuffer compact ()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int copied = 0;
+
+ while (remaining () > 0)
+ {
+ put (copied, get ());
+ copied++;
+ }
+
+ position (copied);
+ limit(capacity());
+ return this;
+ }
+
+ public boolean isDirect ()
+ {
+ return false;
+ }
+
+ /**
+ * Reads the <code>int</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>ints</code> in this buffer.
+ */
+ public int get ()
+ {
+ checkForUnderflow();
+
+ int result = backing_buffer [position ()];
+ position (position () + 1);
+ return result;
+ }
+
+ /**
+ * Relative put method. Writes <code>value</code> to the next position
+ * in the buffer.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * space in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public IntBuffer put (int value)
+ {
+ checkIfReadOnly();
+ checkForOverflow();
+
+ backing_buffer [position ()] = value;
+ position (position () + 1);
+ return this;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>int</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public int get (int index)
+ {
+ checkIndex(index);
+
+ return backing_buffer [index];
+ }
+
+ /**
+ * Absolute put method. Writes <code>value</code> to position
+ * <code>index</code> in the buffer.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public IntBuffer put (int index, int value)
+ {
+ checkIfReadOnly();
+ checkIndex(index);
+
+ backing_buffer [index] = value;
+ return this;
+ }
+
+ public ByteOrder order ()
+ {
+ return ByteOrder.nativeOrder ();
+ }
+}
diff --git a/libjava/classpath/java/nio/IntViewBufferImpl.java b/libjava/classpath/java/nio/IntViewBufferImpl.java
new file mode 100644
index 00000000000..d0b0057c117
--- /dev/null
+++ b/libjava/classpath/java/nio/IntViewBufferImpl.java
@@ -0,0 +1,173 @@
+/* IntViewBufferImpl.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+final class IntViewBufferImpl extends IntBuffer
+{
+ /** Position in bb (i.e. a byte offset) where this buffer starts. */
+ private int offset;
+ private ByteBuffer bb;
+ private boolean readOnly;
+ private ByteOrder endian;
+
+ IntViewBufferImpl (ByteBuffer bb, int capacity)
+ {
+ super (capacity, capacity, 0, -1);
+ this.bb = bb;
+ this.offset = bb.position();
+ this.readOnly = bb.isReadOnly();
+ this.endian = bb.order();
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ public IntViewBufferImpl (ByteBuffer bb, int offset, int capacity,
+ int limit, int position, int mark,
+ boolean readOnly, ByteOrder endian)
+ {
+ super (capacity, limit, position, mark);
+ this.bb = bb;
+ this.offset = offset;
+ this.readOnly = readOnly;
+ this.endian = endian;
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ /**
+ * Reads the <code>int</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>ints</code> in this buffer.
+ */
+ public int get ()
+ {
+ int p = position();
+ int result = ByteBufferHelper.getInt(bb, (p << 2) + offset, endian);
+ position(p + 1);
+ return result;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>int</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public int get (int index)
+ {
+ return ByteBufferHelper.getInt(bb, (index << 2) + offset, endian);
+ }
+
+ public IntBuffer put (int value)
+ {
+ int p = position();
+ ByteBufferHelper.putInt(bb, (p << 2) + offset, value, endian);
+ position(p + 1);
+ return this;
+ }
+
+ public IntBuffer put (int index, int value)
+ {
+ ByteBufferHelper.putInt(bb, (index << 2) + offset, value, endian);
+ return this;
+ }
+
+ public IntBuffer compact ()
+ {
+ if (position () > 0)
+ {
+ int count = limit () - position ();
+ bb.shiftDown(offset, offset + 4 * position(), 4 * count);
+ position (count);
+ limit (capacity ());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public IntBuffer slice ()
+ {
+ // Create a sliced copy of this object that shares its content.
+ return new IntViewBufferImpl (bb, (position () >> 2) + offset,
+ remaining(), remaining(), 0, -1,
+ readOnly, endian);
+ }
+
+ IntBuffer duplicate (boolean readOnly)
+ {
+ int pos = position();
+ reset();
+ int mark = position();
+ position(pos);
+ return new IntViewBufferImpl (bb, offset, capacity(), limit(),
+ pos, mark, readOnly, endian);
+ }
+
+ public IntBuffer duplicate ()
+ {
+ return duplicate(readOnly);
+ }
+
+ public IntBuffer asReadOnlyBuffer ()
+ {
+ return duplicate(true);
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public boolean isDirect ()
+ {
+ return bb.isDirect ();
+ }
+
+ public ByteOrder order ()
+ {
+ return endian;
+ }
+}
diff --git a/libjava/classpath/java/nio/InvalidMarkException.java b/libjava/classpath/java/nio/InvalidMarkException.java
new file mode 100644
index 00000000000..937d417ab13
--- /dev/null
+++ b/libjava/classpath/java/nio/InvalidMarkException.java
@@ -0,0 +1,52 @@
+/* InvalidMarkException.java --
+ Copyright (C) 2002 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.nio;
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class InvalidMarkException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public InvalidMarkException ()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/LongBuffer.java b/libjava/classpath/java/nio/LongBuffer.java
new file mode 100644
index 00000000000..b3d3557edcf
--- /dev/null
+++ b/libjava/classpath/java/nio/LongBuffer.java
@@ -0,0 +1,383 @@
+/* LongBuffer.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @since 1.4
+ */
+public abstract class LongBuffer extends Buffer
+ implements Comparable
+{
+ int array_offset;
+ long[] backing_buffer;
+
+ LongBuffer (int capacity, int limit, int position, int mark)
+ {
+ super (capacity, limit, position, mark);
+ array_offset = 0;
+ }
+
+ /**
+ * Allocates a new <code>LongBuffer</code> object with a given capacity.
+ */
+ public static LongBuffer allocate (int capacity)
+ {
+ return new LongBufferImpl (capacity);
+ }
+
+ /**
+ * Wraps a <code>long</code> array into a <code>LongBuffer</code>
+ * object.
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ public static final LongBuffer wrap (long[] array, int offset, int length)
+ {
+ return new LongBufferImpl (array, 0, array.length, offset + length, offset, -1, false);
+ }
+
+ /**
+ * Wraps a <code>long</code> array into a <code>LongBuffer</code>
+ * object.
+ */
+ public static final LongBuffer wrap (long[] array)
+ {
+ return wrap (array, 0, array.length);
+ }
+
+ /**
+ * This method transfers <code>long</code>s from this buffer into the given
+ * destination array. Before the transfer, it checks if there are fewer than
+ * length <code>long</code>s remaining in this buffer.
+ *
+ * @param dst The destination array
+ * @param offset The offset within the array of the first <code>long</code>
+ * to be written; must be non-negative and no larger than dst.length.
+ * @param length The maximum number of bytes to be written to the given array;
+ * must be non-negative and no larger than dst.length - offset.
+ *
+ * @exception BufferUnderflowException If there are fewer than length
+ * <code>long</code>s remaining in this buffer.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold.
+ */
+ public LongBuffer get (long[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ {
+ dst [i] = get ();
+ }
+
+ return this;
+ }
+
+ /**
+ * This method transfers <code>long</code>s from this buffer into the given
+ * destination array.
+ *
+ * @param dst The byte array to write into.
+ *
+ * @exception BufferUnderflowException If there are fewer than dst.length
+ * <code>long</code>s remaining in this buffer.
+ */
+ public LongBuffer get (long[] dst)
+ {
+ return get (dst, 0, dst.length);
+ }
+
+ /**
+ * Writes the content of the the <code>LongBUFFER</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * <code>src.remaining()</code> space remaining in this buffer.
+ *
+ * @param src The source data.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>long</code>s in the source buffer.
+ * @exception IllegalArgumentException If the source buffer is this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public LongBuffer put (LongBuffer src)
+ {
+ if (src == this)
+ throw new IllegalArgumentException ();
+
+ checkForOverflow(src.remaining ());
+
+ if (src.remaining () > 0)
+ {
+ long[] toPut = new long [src.remaining ()];
+ src.get (toPut);
+ put (toPut);
+ }
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>long array</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * length space remaining in this buffer.
+ *
+ * @param src The array to copy into the buffer.
+ * @param offset The offset within the array of the first byte to be read;
+ * must be non-negative and no larger than src.length.
+ * @param length The number of bytes to be read from the given array;
+ * must be non-negative and no larger than src.length - offset.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>long</code>s in the source array.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public LongBuffer put (long[] src, int offset, int length)
+ {
+ checkArraySize(src.length, offset, length);
+ checkForOverflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ put (src [i]);
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>long array</code> src
+ * into the buffer.
+ *
+ * @param src The array to copy into the buffer.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>long</code>s in the source array.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public final LongBuffer put (long[] src)
+ {
+ return put (src, 0, src.length);
+ }
+
+ /**
+ * Tells whether ot not this buffer is backed by an accessible
+ * <code>long</code> array.
+ */
+ public final boolean hasArray ()
+ {
+ return (backing_buffer != null
+ && !isReadOnly ());
+ }
+
+ /**
+ * Returns the <code>long</code> array that backs this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final long[] array ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return backing_buffer;
+ }
+
+ /**
+ * Returns the offset within this buffer's backing array of the first element.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final int arrayOffset ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return array_offset;
+ }
+
+ /**
+ * Calculates a hash code for this buffer.
+ *
+ * This is done with <code>long</code> arithmetic,
+ * where ** represents exponentiation, by this formula:<br>
+ * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
+ * (s[limit()-1]+30)*31**(limit()-1)</code>.
+ * Where s is the buffer data. Note that the hashcode is dependent
+ * on buffer content, and therefore is not useful if the buffer
+ * content may change.
+ *
+ * @return the hash code (casted to int)
+ */
+ public int hashCode ()
+ {
+ long hashCode = get(position()) + 31;
+ long multiplier = 1;
+ for (int i = position() + 1; i < limit(); ++i)
+ {
+ multiplier *= 31;
+ hashCode += (get(i) + 30)*multiplier;
+ }
+ return ((int)hashCode);
+ }
+
+ /**
+ * Checks if this buffer is equal to obj.
+ */
+ public boolean equals (Object obj)
+ {
+ if (obj instanceof LongBuffer)
+ {
+ return compareTo (obj) == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compares two <code>LongBuffer</code> objects.
+ *
+ * @exception ClassCastException If obj is not an object derived from
+ * <code>LongBuffer</code>.
+ */
+ public int compareTo (Object obj)
+ {
+ LongBuffer other = (LongBuffer) obj;
+
+ int num = Math.min(remaining(), other.remaining());
+ int pos_this = position();
+ int pos_other = other.position();
+
+ for (int count = 0; count < num; count++)
+ {
+ long a = get(pos_this++);
+ long b = other.get(pos_other++);
+
+ if (a == b)
+ continue;
+
+ if (a < b)
+ return -1;
+
+ return 1;
+ }
+
+ return remaining() - other.remaining();
+ }
+
+ /**
+ * Returns the byte order of this buffer.
+ */
+ public abstract ByteOrder order ();
+
+ /**
+ * Reads the <code>long</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>long</code>s in this buffer.
+ */
+ public abstract long get ();
+
+ /**
+ * Writes the <code>long</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * <code>long</code>s in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract LongBuffer put (long b);
+
+ /**
+ * Absolute get method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public abstract long get (int index);
+
+ /**
+ * Absolute put method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract LongBuffer put (int index, long b);
+
+ /**
+ * Compacts this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract LongBuffer compact ();
+
+ /**
+ * Tells wether or not this buffer is direct.
+ */
+ public abstract boolean isDirect ();
+
+ /**
+ * Creates a new <code>LongBuffer</code> whose content is a shared
+ * subsequence of this buffer's content.
+ */
+ public abstract LongBuffer slice ();
+
+ /**
+ * Creates a new <code>LongBuffer</code> that shares this buffer's
+ * content.
+ */
+ public abstract LongBuffer duplicate ();
+
+ /**
+ * Creates a new read-only <code>LongBuffer</code> that shares this
+ * buffer's content.
+ */
+ public abstract LongBuffer asReadOnlyBuffer ();
+}
diff --git a/libjava/classpath/java/nio/LongBufferImpl.java b/libjava/classpath/java/nio/LongBufferImpl.java
new file mode 100644
index 00000000000..8772f618c19
--- /dev/null
+++ b/libjava/classpath/java/nio/LongBufferImpl.java
@@ -0,0 +1,172 @@
+/* LongBufferImpl.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * This is a Heap memory implementation
+ */
+final class LongBufferImpl extends LongBuffer
+{
+ private boolean readOnly;
+
+ LongBufferImpl (int capacity)
+ {
+ this (new long [capacity], 0, capacity, capacity, 0, -1, false);
+ }
+
+ LongBufferImpl (long[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly)
+ {
+ super (capacity, limit, position, mark);
+ this.backing_buffer = buffer;
+ this.array_offset = offset;
+ this.readOnly = readOnly;
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public LongBuffer slice ()
+ {
+ return new LongBufferImpl (backing_buffer, array_offset + position (), remaining (), remaining (), 0, -1, isReadOnly ());
+ }
+
+ public LongBuffer duplicate ()
+ {
+ return new LongBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, isReadOnly ());
+ }
+
+ public LongBuffer asReadOnlyBuffer ()
+ {
+ return new LongBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, true);
+ }
+
+ public LongBuffer compact ()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int copied = 0;
+
+ while (remaining () > 0)
+ {
+ put (copied, get ());
+ copied++;
+ }
+
+ position (copied);
+ limit(capacity());
+ return this;
+ }
+
+ public boolean isDirect ()
+ {
+ return false;
+ }
+
+ /**
+ * Reads the <code>long</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>longs</code> in this buffer.
+ */
+ public long get ()
+ {
+ checkForUnderflow();
+
+ long result = backing_buffer [position ()];
+ position (position () + 1);
+ return result;
+ }
+
+ /**
+ * Relative put method. Writes <code>value</code> to the next position
+ * in the buffer.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public LongBuffer put (long value)
+ {
+ checkIfReadOnly();
+ checkForOverflow();
+
+ backing_buffer [position ()] = value;
+ position (position () + 1);
+ return this;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>long</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public long get (int index)
+ {
+ checkIndex(index);
+
+ return backing_buffer [index];
+ }
+
+ /**
+ * Absolute put method. Writes <code>value</code> to position
+ * <code>index</code> in the buffer.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public LongBuffer put (int index, long value)
+ {
+ checkIfReadOnly();
+ checkIndex(index);
+
+ backing_buffer [index] = value;
+ return this;
+ }
+
+ public ByteOrder order ()
+ {
+ return ByteOrder.nativeOrder ();
+ }
+}
diff --git a/libjava/classpath/java/nio/LongViewBufferImpl.java b/libjava/classpath/java/nio/LongViewBufferImpl.java
new file mode 100644
index 00000000000..9c3452ae809
--- /dev/null
+++ b/libjava/classpath/java/nio/LongViewBufferImpl.java
@@ -0,0 +1,173 @@
+/* LongViewBufferImpl.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+final class LongViewBufferImpl extends LongBuffer
+{
+ /** Position in bb (i.e. a byte offset) where this buffer starts. */
+ private int offset;
+ private ByteBuffer bb;
+ private boolean readOnly;
+ private ByteOrder endian;
+
+ LongViewBufferImpl (ByteBuffer bb, int capacity)
+ {
+ super (capacity, capacity, 0, -1);
+ this.bb = bb;
+ this.offset = bb.position();
+ this.readOnly = bb.isReadOnly();
+ this.endian = bb.order();
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ public LongViewBufferImpl (ByteBuffer bb, int offset, int capacity,
+ int limit, int position, int mark,
+ boolean readOnly, ByteOrder endian)
+ {
+ super (capacity, limit, position, mark);
+ this.bb = bb;
+ this.offset = offset;
+ this.readOnly = readOnly;
+ this.endian = endian;
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ /**
+ * Reads the <code>long</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>longs</code> in this buffer.
+ */
+ public long get ()
+ {
+ int p = position();
+ long result = ByteBufferHelper.getLong(bb, (p << 3) + offset, endian);
+ position(p + 1);
+ return result;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>long</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public long get (int index)
+ {
+ return ByteBufferHelper.getLong(bb, (index << 3) + offset, endian);
+ }
+
+ public LongBuffer put (long value)
+ {
+ int p = position();
+ ByteBufferHelper.putLong(bb, (p << 3) + offset, value, endian);
+ position(p + 1);
+ return this;
+ }
+
+ public LongBuffer put (int index, long value)
+ {
+ ByteBufferHelper.putLong(bb, (index << 3) + offset, value, endian);
+ return this;
+ }
+
+ public LongBuffer compact ()
+ {
+ if (position () > 0)
+ {
+ int count = limit () - position ();
+ bb.shiftDown(offset, offset + 8 * position(), 8 * count);
+ position (count);
+ limit (capacity ());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public LongBuffer slice ()
+ {
+ // Create a sliced copy of this object that shares its content.
+ return new LongViewBufferImpl (bb, (position () >> 3) + offset,
+ remaining(), remaining(), 0, -1,
+ readOnly, endian);
+ }
+
+ LongBuffer duplicate (boolean readOnly)
+ {
+ int pos = position();
+ reset();
+ int mark = position();
+ position(pos);
+ return new LongViewBufferImpl (bb, offset, capacity(), limit(),
+ pos, mark, readOnly, endian);
+ }
+
+ public LongBuffer duplicate ()
+ {
+ return duplicate(readOnly);
+ }
+
+ public LongBuffer asReadOnlyBuffer ()
+ {
+ return duplicate(true);
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public boolean isDirect ()
+ {
+ return bb.isDirect ();
+ }
+
+ public ByteOrder order ()
+ {
+ return endian;
+ }
+}
diff --git a/libjava/classpath/java/nio/MappedByteBuffer.java b/libjava/classpath/java/nio/MappedByteBuffer.java
new file mode 100644
index 00000000000..fa25bb7f1e7
--- /dev/null
+++ b/libjava/classpath/java/nio/MappedByteBuffer.java
@@ -0,0 +1,93 @@
+/* MappedByteBuffer.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.4
+ */
+public abstract class MappedByteBuffer extends ByteBuffer
+{
+ MappedByteBuffer (int capacity, int limit, int position, int mark)
+ {
+ super (capacity, limit, position, mark);
+ }
+
+ void forceImpl()
+ {
+ }
+
+ public final MappedByteBuffer force ()
+ {
+ forceImpl();
+ return this;
+ }
+
+ boolean isLoadedImpl()
+ {
+ load();
+ return true;
+ }
+
+ public final boolean isLoaded ()
+ {
+ return isLoadedImpl();
+ }
+
+ void loadImpl()
+ {
+ }
+
+ public final MappedByteBuffer load ()
+ {
+ loadImpl();
+ return this;
+ }
+
+ void unmapImpl ()
+ {
+ forceImpl();
+ }
+
+ public void finalize()
+ throws Throwable
+ {
+ unmapImpl();
+ }
+}
diff --git a/libjava/classpath/java/nio/MappedByteBufferImpl.java b/libjava/classpath/java/nio/MappedByteBufferImpl.java
new file mode 100644
index 00000000000..1b075d8753e
--- /dev/null
+++ b/libjava/classpath/java/nio/MappedByteBufferImpl.java
@@ -0,0 +1,360 @@
+/* MappedByteBufferImpl.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+import gnu.classpath.RawData;
+
+import java.io.IOException;
+
+final class MappedByteBufferImpl extends MappedByteBuffer
+{
+ boolean readOnly;
+
+ /** Posix uses this for the pointer returned by mmap;
+ * Win32 uses it for the pointer returned by MapViewOfFile. */
+ public RawData implPtr;
+ /** Posix uses this for the actual length passed to mmap;
+ * Win32 uses it for the pointer returned by CreateFileMapping. */
+ public long implLen;
+
+ public MappedByteBufferImpl(RawData address, int size, boolean readOnly)
+ throws IOException
+ {
+ super(size, size, 0, -1);
+ this.address = address;
+ this.readOnly = readOnly;
+ }
+
+ public boolean isReadOnly()
+ {
+ return readOnly;
+ }
+
+ public byte get()
+ {
+ checkForUnderflow();
+
+ int pos = position();
+ byte result = VMDirectByteBuffer.get(address, pos);
+ position(pos + 1);
+ return result;
+ }
+
+ public ByteBuffer put(byte value)
+ {
+ checkIfReadOnly();
+ checkForOverflow();
+
+ int pos = position();
+ VMDirectByteBuffer.put(address, pos, value);
+ position(pos + 1);
+ return this;
+ }
+
+ public byte get(int index)
+ {
+ checkIndex(index);
+
+ return VMDirectByteBuffer.get(address, index);
+ }
+
+ public ByteBuffer get(byte[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ int index = position();
+ VMDirectByteBuffer.get(address, index, dst, offset, length);
+ position(index+length);
+
+ return this;
+ }
+
+ public ByteBuffer put(int index, byte value)
+ {
+ checkIfReadOnly();
+ checkIndex(index);
+
+ VMDirectByteBuffer.put(address, index, value);
+ return this;
+ }
+
+ public ByteBuffer compact()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int pos = position();
+ if (pos > 0)
+ {
+ int count = remaining();
+ // Call shiftDown method optimized for direct buffers.
+ VMDirectByteBuffer.shiftDown(address, 0, pos, count);
+ position(count);
+ limit(capacity());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public boolean isDirect()
+ {
+ return true;
+ }
+
+ public ByteBuffer slice()
+ {
+ int rem = remaining();
+ if (isReadOnly())
+ return new DirectByteBufferImpl.ReadOnly
+ (this, VMDirectByteBuffer.adjustAddress(address, position()),
+ rem, rem, 0);
+ else
+ return new DirectByteBufferImpl.ReadWrite
+ (this, VMDirectByteBuffer.adjustAddress(address, position()),
+ rem, rem, 0);
+ }
+
+ private ByteBuffer duplicate(boolean readOnly)
+ {
+ int pos = position();
+ reset();
+ int mark = position();
+ position(pos);
+ DirectByteBufferImpl result;
+ if (readOnly)
+ result = new DirectByteBufferImpl.ReadOnly(this, address, capacity(),
+ limit(), pos);
+ else
+ result = new DirectByteBufferImpl.ReadWrite(this, address, capacity(),
+ limit(), pos);
+
+ if (mark != pos)
+ {
+ result.position(mark);
+ result.mark();
+ result.position(pos);
+ }
+ return result;
+ }
+
+ public ByteBuffer duplicate()
+ {
+ return duplicate(isReadOnly());
+ }
+
+ public ByteBuffer asReadOnlyBuffer()
+ {
+ return duplicate(true);
+ }
+
+ public CharBuffer asCharBuffer()
+ {
+ return new CharViewBufferImpl(this, remaining() >> 1);
+ }
+
+ public ShortBuffer asShortBuffer()
+ {
+ return new ShortViewBufferImpl(this, remaining() >> 1);
+ }
+
+ public IntBuffer asIntBuffer()
+ {
+ return new IntViewBufferImpl(this, remaining() >> 2);
+ }
+
+ public LongBuffer asLongBuffer()
+ {
+ return new LongViewBufferImpl(this, remaining() >> 3);
+ }
+
+ public FloatBuffer asFloatBuffer()
+ {
+ return new FloatViewBufferImpl(this, remaining() >> 2);
+ }
+
+ public DoubleBuffer asDoubleBuffer()
+ {
+ return new DoubleViewBufferImpl(this, remaining() >> 3);
+ }
+
+ public char getChar()
+ {
+ return ByteBufferHelper.getChar(this, order());
+ }
+
+ public ByteBuffer putChar(char value)
+ {
+ ByteBufferHelper.putChar(this, value, order());
+ return this;
+ }
+
+ public char getChar(int index)
+ {
+ return ByteBufferHelper.getChar(this, index, order());
+ }
+
+ public ByteBuffer putChar(int index, char value)
+ {
+ ByteBufferHelper.putChar(this, index, value, order());
+ return this;
+ }
+
+ public short getShort()
+ {
+ return ByteBufferHelper.getShort(this, order());
+ }
+
+ public ByteBuffer putShort(short value)
+ {
+ ByteBufferHelper.putShort(this, value, order());
+ return this;
+ }
+
+ public short getShort(int index)
+ {
+ return ByteBufferHelper.getShort(this, index, order());
+ }
+
+ public ByteBuffer putShort(int index, short value)
+ {
+ ByteBufferHelper.putShort(this, index, value, order());
+ return this;
+ }
+
+ public int getInt()
+ {
+ return ByteBufferHelper.getInt(this, order());
+ }
+
+ public ByteBuffer putInt(int value)
+ {
+ ByteBufferHelper.putInt(this, value, order());
+ return this;
+ }
+
+ public int getInt(int index)
+ {
+ return ByteBufferHelper.getInt(this, index, order());
+ }
+
+ public ByteBuffer putInt(int index, int value)
+ {
+ ByteBufferHelper.putInt(this, index, value, order());
+ return this;
+ }
+
+ public long getLong()
+ {
+ return ByteBufferHelper.getLong(this, order());
+ }
+
+ public ByteBuffer putLong(long value)
+ {
+ ByteBufferHelper.putLong(this, value, order());
+ return this;
+ }
+
+ public long getLong(int index)
+ {
+ return ByteBufferHelper.getLong(this, index, order());
+ }
+
+ public ByteBuffer putLong(int index, long value)
+ {
+ ByteBufferHelper.putLong(this, index, value, order());
+ return this;
+ }
+
+ public float getFloat()
+ {
+ return ByteBufferHelper.getFloat(this, order());
+ }
+
+ public ByteBuffer putFloat(float value)
+ {
+ ByteBufferHelper.putFloat(this, value, order());
+ return this;
+ }
+
+ public float getFloat(int index)
+ {
+ return ByteBufferHelper.getFloat(this, index, order());
+ }
+
+ public ByteBuffer putFloat(int index, float value)
+ {
+ ByteBufferHelper.putFloat(this, index, value, order());
+ return this;
+ }
+
+ public double getDouble()
+ {
+ return ByteBufferHelper.getDouble(this, order());
+ }
+
+ public ByteBuffer putDouble(double value)
+ {
+ ByteBufferHelper.putDouble(this, value, order());
+ return this;
+ }
+
+ public double getDouble(int index)
+ {
+ return ByteBufferHelper.getDouble(this, index, order());
+ }
+
+ public ByteBuffer putDouble(int index, double value)
+ {
+ ByteBufferHelper.putDouble(this, index, value, order());
+ return this;
+ }
+
+ // NOTE: In libgcj these methods are implemented in natFileChannelXxx.cc,
+ // because they're small, and to put them next to FileChannelImpl::mapImpl.
+ native void unmapImpl();
+ native boolean isLoadedImpl();
+ // FIXME: Try to load all pages into memory.
+ native void loadImpl();
+
+ native void forceImpl();
+}
diff --git a/libjava/classpath/java/nio/ReadOnlyBufferException.java b/libjava/classpath/java/nio/ReadOnlyBufferException.java
new file mode 100644
index 00000000000..d710e1b26a1
--- /dev/null
+++ b/libjava/classpath/java/nio/ReadOnlyBufferException.java
@@ -0,0 +1,52 @@
+/* ReadOnlyBufferException.java --
+ Copyright (C) 2002 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.nio;
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class ReadOnlyBufferException extends UnsupportedOperationException
+{
+ /**
+ * Creates the exception
+ */
+ public ReadOnlyBufferException ()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/ShortBuffer.java b/libjava/classpath/java/nio/ShortBuffer.java
new file mode 100644
index 00000000000..958fe8cd6b6
--- /dev/null
+++ b/libjava/classpath/java/nio/ShortBuffer.java
@@ -0,0 +1,383 @@
+/* ShortBuffer.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * @since 1.4
+ */
+public abstract class ShortBuffer extends Buffer
+ implements Comparable
+{
+ int array_offset;
+ short[] backing_buffer;
+
+ ShortBuffer (int capacity, int limit, int position, int mark)
+ {
+ super (capacity, limit, position, mark);
+ array_offset = 0;
+ }
+
+ /**
+ * Allocates a new <code>ShortBuffer</code> object with a given capacity.
+ */
+ public static ShortBuffer allocate (int capacity)
+ {
+ return new ShortBufferImpl (capacity);
+ }
+
+ /**
+ * Wraps a <code>short</code> array into a <code>ShortBuffer</code>
+ * object.
+ *
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ */
+ public static final ShortBuffer wrap (short[] array, int offset, int length)
+ {
+ return new ShortBufferImpl (array, 0, array.length, offset + length, offset, -1, false);
+ }
+
+ /**
+ * Wraps a <code>short</code> array into a <code>ShortBuffer</code>
+ * object.
+ */
+ public static final ShortBuffer wrap (short[] array)
+ {
+ return wrap (array, 0, array.length);
+ }
+
+ /**
+ * This method transfers <code>short</code>s from this buffer into the given
+ * destination array. Before the transfer, it checks if there are fewer than
+ * length <code>short</code>s remaining in this buffer.
+ *
+ * @param dst The destination array
+ * @param offset The offset within the array of the first <code>short</code>
+ * to be written; must be non-negative and no larger than dst.length.
+ * @param length The maximum number of bytes to be written to the given array;
+ * must be non-negative and no larger than dst.length - offset.
+ *
+ * @exception BufferUnderflowException If there are fewer than length
+ * <code>short</code>s remaining in this buffer.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold.
+ */
+ public ShortBuffer get (short[] dst, int offset, int length)
+ {
+ checkArraySize(dst.length, offset, length);
+ checkForUnderflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ {
+ dst [i] = get ();
+ }
+
+ return this;
+ }
+
+ /**
+ * This method transfers <code>short</code>s from this buffer into the given
+ * destination array.
+ *
+ * @param dst The byte array to write into.
+ *
+ * @exception BufferUnderflowException If there are fewer than dst.length
+ * <code>short</code>s remaining in this buffer.
+ */
+ public ShortBuffer get (short[] dst)
+ {
+ return get (dst, 0, dst.length);
+ }
+
+ /**
+ * Writes the content of the the <code>ShortBUFFER</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * <code>src.remaining()</code> space remaining in this buffer.
+ *
+ * @param src The source data.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>short</code>s in the source buffer.
+ * @exception IllegalArgumentException If the source buffer is this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public ShortBuffer put (ShortBuffer src)
+ {
+ if (src == this)
+ throw new IllegalArgumentException ();
+
+ checkForOverflow(src.remaining ());
+
+ if (src.remaining () > 0)
+ {
+ short[] toPut = new short [src.remaining ()];
+ src.get (toPut);
+ put (toPut);
+ }
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>short array</code> src
+ * into the buffer. Before the transfer, it checks if there is fewer than
+ * length space remaining in this buffer.
+ *
+ * @param src The array to copy into the buffer.
+ * @param offset The offset within the array of the first byte to be read;
+ * must be non-negative and no larger than src.length.
+ * @param length The number of bytes to be read from the given array;
+ * must be non-negative and no larger than src.length - offset.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>short</code>s in the source array.
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public ShortBuffer put (short[] src, int offset, int length)
+ {
+ checkArraySize(src.length, offset, length);
+ checkForOverflow(length);
+
+ for (int i = offset; i < offset + length; i++)
+ put (src [i]);
+
+ return this;
+ }
+
+ /**
+ * Writes the content of the the <code>short array</code> src
+ * into the buffer.
+ *
+ * @param src The array to copy into the buffer.
+ *
+ * @exception BufferOverflowException If there is insufficient space in this
+ * buffer for the remaining <code>short</code>s in the source array.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public final ShortBuffer put (short[] src)
+ {
+ return put (src, 0, src.length);
+ }
+
+ /**
+ * Tells whether ot not this buffer is backed by an accessible
+ * <code>short</code> array.
+ */
+ public final boolean hasArray ()
+ {
+ return (backing_buffer != null
+ && !isReadOnly ());
+ }
+
+ /**
+ * Returns the <code>short</code> array that backs this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final short[] array ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return backing_buffer;
+ }
+
+ /**
+ * Returns the offset within this buffer's backing array of the first element.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ * @exception UnsupportedOperationException If this buffer is not backed
+ * by an accessible array.
+ */
+ public final int arrayOffset ()
+ {
+ if (backing_buffer == null)
+ throw new UnsupportedOperationException ();
+
+ checkIfReadOnly();
+
+ return array_offset;
+ }
+
+ /**
+ * Calculates a hash code for this buffer.
+ *
+ * This is done with <code>int</code> arithmetic,
+ * where ** represents exponentiation, by this formula:<br>
+ * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
+ * (s[limit()-1]+30)*31**(limit()-1)</code>.
+ * Where s is the buffer data. Note that the hashcode is dependent
+ * on buffer content, and therefore is not useful if the buffer
+ * content may change.
+ *
+ * @return the hash code
+ */
+ public int hashCode ()
+ {
+ int hashCode = get(position()) + 31;
+ int multiplier = 1;
+ for (int i = position() + 1; i < limit(); ++i)
+ {
+ multiplier *= 31;
+ hashCode += (get(i) + 30)*multiplier;
+ }
+ return hashCode;
+ }
+
+ /**
+ * Checks if this buffer is equal to obj.
+ */
+ public boolean equals (Object obj)
+ {
+ if (obj instanceof ShortBuffer)
+ {
+ return compareTo (obj) == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compares two <code>ShortBuffer</code> objects.
+ *
+ * @exception ClassCastException If obj is not an object derived from
+ * <code>ShortBuffer</code>.
+ */
+ public int compareTo (Object obj)
+ {
+ ShortBuffer other = (ShortBuffer) obj;
+
+ int num = Math.min(remaining(), other.remaining());
+ int pos_this = position();
+ int pos_other = other.position();
+
+ for (int count = 0; count < num; count++)
+ {
+ short a = get(pos_this++);
+ short b = other.get(pos_other++);
+
+ if (a == b)
+ continue;
+
+ if (a < b)
+ return -1;
+
+ return 1;
+ }
+
+ return remaining() - other.remaining();
+ }
+
+ /**
+ * Returns the byte order of this buffer.
+ */
+ public abstract ByteOrder order ();
+
+ /**
+ * Reads the <code>short</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>short</code>s in this buffer.
+ */
+ public abstract short get ();
+
+ /**
+ * Writes the <code>short</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * <code>short</code>s in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract ShortBuffer put (short b);
+
+ /**
+ * Absolute get method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public abstract short get (int index);
+
+ /**
+ * Absolute put method.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract ShortBuffer put (int index, short b);
+
+ /**
+ * Compacts this buffer.
+ *
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public abstract ShortBuffer compact ();
+
+ /**
+ * Tells wether or not this buffer is direct.
+ */
+ public abstract boolean isDirect ();
+
+ /**
+ * Creates a new <code>ShortBuffer</code> whose content is a shared
+ * subsequence of this buffer's content.
+ */
+ public abstract ShortBuffer slice ();
+
+ /**
+ * Creates a new <code>ShortBuffer</code> that shares this buffer's
+ * content.
+ */
+ public abstract ShortBuffer duplicate ();
+
+ /**
+ * Creates a new read-only <code>ShortBuffer</code> that shares this
+ * buffer's content.
+ */
+ public abstract ShortBuffer asReadOnlyBuffer ();
+}
diff --git a/libjava/classpath/java/nio/ShortBufferImpl.java b/libjava/classpath/java/nio/ShortBufferImpl.java
new file mode 100644
index 00000000000..ee5bff2f95b
--- /dev/null
+++ b/libjava/classpath/java/nio/ShortBufferImpl.java
@@ -0,0 +1,172 @@
+/* ShortBufferImpl.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+/**
+ * This is a Heap memory implementation
+ */
+final class ShortBufferImpl extends ShortBuffer
+{
+ private boolean readOnly;
+
+ ShortBufferImpl (int capacity)
+ {
+ this (new short [capacity], 0, capacity, capacity, 0, -1, false);
+ }
+
+ ShortBufferImpl (short[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly)
+ {
+ super (capacity, limit, position, mark);
+ this.backing_buffer = buffer;
+ this.array_offset = offset;
+ this.readOnly = readOnly;
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public ShortBuffer slice ()
+ {
+ return new ShortBufferImpl (backing_buffer, array_offset + position (), remaining (), remaining (), 0, -1, isReadOnly ());
+ }
+
+ public ShortBuffer duplicate ()
+ {
+ return new ShortBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, isReadOnly ());
+ }
+
+ public ShortBuffer asReadOnlyBuffer ()
+ {
+ return new ShortBufferImpl (backing_buffer, array_offset, capacity (), limit (), position (), mark, true);
+ }
+
+ public ShortBuffer compact ()
+ {
+ checkIfReadOnly();
+ mark = -1;
+ int copied = 0;
+
+ while (remaining () > 0)
+ {
+ put (copied, get ());
+ copied++;
+ }
+
+ position (copied);
+ limit(capacity());
+ return this;
+ }
+
+ public boolean isDirect ()
+ {
+ return false;
+ }
+
+ /**
+ * Reads the <code>short</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>short</code>s in this buffer.
+ */
+ public short get ()
+ {
+ checkForUnderflow();
+
+ short result = backing_buffer [position ()];
+ position (position () + 1);
+ return result;
+ }
+
+ /**
+ * Relative put method. Writes <code>value</code> to the next position
+ * in the buffer.
+ *
+ * @exception BufferOverflowException If there no remaining
+ * space in this buffer.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public ShortBuffer put (short value)
+ {
+ checkIfReadOnly();
+ checkForOverflow();
+
+ backing_buffer [position ()] = value;
+ position (position () + 1);
+ return this;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>short</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public short get (int index)
+ {
+ checkIndex(index);
+
+ return backing_buffer [index];
+ }
+
+ /**
+ * Absolute put method. Writes <code>value</code> to position
+ * <code>index</code> in the buffer.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ * @exception ReadOnlyBufferException If this buffer is read-only.
+ */
+ public ShortBuffer put (int index, short value)
+ {
+ checkIfReadOnly();
+ checkIndex(index);
+
+ backing_buffer [index] = value;
+ return this;
+ }
+
+ public ByteOrder order ()
+ {
+ return ByteOrder.nativeOrder ();
+ }
+}
diff --git a/libjava/classpath/java/nio/ShortViewBufferImpl.java b/libjava/classpath/java/nio/ShortViewBufferImpl.java
new file mode 100644
index 00000000000..cdd559522ff
--- /dev/null
+++ b/libjava/classpath/java/nio/ShortViewBufferImpl.java
@@ -0,0 +1,173 @@
+/* ShortViewBufferImpl.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio;
+
+final class ShortViewBufferImpl extends ShortBuffer
+{
+ /** Position in bb (i.e. a byte offset) where this buffer starts. */
+ private int offset;
+ private ByteBuffer bb;
+ private boolean readOnly;
+ private ByteOrder endian;
+
+ ShortViewBufferImpl (ByteBuffer bb, int capacity)
+ {
+ super (capacity, capacity, 0, -1);
+ this.bb = bb;
+ this.offset = bb.position();
+ this.readOnly = bb.isReadOnly();
+ this.endian = bb.order();
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ public ShortViewBufferImpl (ByteBuffer bb, int offset, int capacity,
+ int limit, int position, int mark,
+ boolean readOnly, ByteOrder endian)
+ {
+ super (capacity, limit, position, mark);
+ this.bb = bb;
+ this.offset = offset;
+ this.readOnly = readOnly;
+ this.endian = endian;
+ if (bb.isDirect())
+ this.address = VMDirectByteBuffer.adjustAddress(bb.address, offset);
+ }
+
+ /**
+ * Reads the <code>short</code> at this buffer's current position,
+ * and then increments the position.
+ *
+ * @exception BufferUnderflowException If there are no remaining
+ * <code>short</code>s in this buffer.
+ */
+ public short get ()
+ {
+ int p = position();
+ short result = ByteBufferHelper.getShort(bb, (p << 1) + offset, endian);
+ position(p + 1);
+ return result;
+ }
+
+ /**
+ * Absolute get method. Reads the <code>short</code> at position
+ * <code>index</code>.
+ *
+ * @exception IndexOutOfBoundsException If index is negative or not smaller
+ * than the buffer's limit.
+ */
+ public short get (int index)
+ {
+ return ByteBufferHelper.getShort(bb, (index << 1) + offset, endian);
+ }
+
+ public ShortBuffer put (short value)
+ {
+ int p = position();
+ ByteBufferHelper.putShort(bb, (p << 1) + offset, value, endian);
+ position(p + 1);
+ return this;
+ }
+
+ public ShortBuffer put (int index, short value)
+ {
+ ByteBufferHelper.putShort(bb, (index << 1) + offset, value, endian);
+ return this;
+ }
+
+ public ShortBuffer compact ()
+ {
+ if (position () > 0)
+ {
+ int count = limit () - position ();
+ bb.shiftDown(offset, offset + 2 * position(), 2 * count);
+ position (count);
+ limit (capacity ());
+ }
+ else
+ {
+ position(limit());
+ limit(capacity());
+ }
+ return this;
+ }
+
+ public ShortBuffer slice ()
+ {
+ // Create a sliced copy of this object that shares its content.
+ return new ShortViewBufferImpl (bb, (position () >> 1) + offset,
+ remaining(), remaining(), 0, -1,
+ readOnly, endian);
+ }
+
+ ShortBuffer duplicate (boolean readOnly)
+ {
+ int pos = position();
+ reset();
+ int mark = position();
+ position(pos);
+ return new ShortViewBufferImpl (bb, offset, capacity(), limit(),
+ pos, mark, readOnly, endian);
+ }
+
+ public ShortBuffer duplicate ()
+ {
+ return duplicate(readOnly);
+ }
+
+ public ShortBuffer asReadOnlyBuffer ()
+ {
+ return duplicate(true);
+ }
+
+ public boolean isReadOnly ()
+ {
+ return readOnly;
+ }
+
+ public boolean isDirect ()
+ {
+ return bb.isDirect ();
+ }
+
+ public ByteOrder order ()
+ {
+ return endian;
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/AlreadyConnectedException.java b/libjava/classpath/java/nio/channels/AlreadyConnectedException.java
new file mode 100644
index 00000000000..133547ef308
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/AlreadyConnectedException.java
@@ -0,0 +1,48 @@
+/* AlreadyConnectedException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+public class AlreadyConnectedException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public AlreadyConnectedException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/AsynchronousCloseException.java b/libjava/classpath/java/nio/channels/AsynchronousCloseException.java
new file mode 100644
index 00000000000..f45fdd81ab4
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/AsynchronousCloseException.java
@@ -0,0 +1,53 @@
+/* AsynchronousCloseException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class AsynchronousCloseException extends ClosedChannelException
+{
+ /**
+ * Creates the exception
+ */
+ public AsynchronousCloseException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/ByteChannel.java b/libjava/classpath/java/nio/channels/ByteChannel.java
new file mode 100644
index 00000000000..d7d7a451b4d
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/ByteChannel.java
@@ -0,0 +1,43 @@
+/* ByteChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+public interface ByteChannel extends ReadableByteChannel,
+ WritableByteChannel
+{
+}
diff --git a/libjava/classpath/java/nio/channels/CancelledKeyException.java b/libjava/classpath/java/nio/channels/CancelledKeyException.java
new file mode 100644
index 00000000000..02108f6c7b3
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/CancelledKeyException.java
@@ -0,0 +1,53 @@
+/* CancelledKeyException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class CancelledKeyException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public CancelledKeyException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/Channel.java b/libjava/classpath/java/nio/channels/Channel.java
new file mode 100644
index 00000000000..d488bd27dd0
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/Channel.java
@@ -0,0 +1,59 @@
+/* Channel.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio.channels;
+
+import java.io.IOException;
+
+public interface Channel
+{
+ /**
+ * Tells whether this channel is open or not
+ *
+ * @return <code>true</code>if channel is open,
+ * <code>false</code> otherwise
+ */
+ boolean isOpen();
+
+ /**
+ * Closes this channel
+ *
+ * @exception IOException If an error occurs
+ */
+ void close() throws IOException;
+}
diff --git a/libjava/classpath/java/nio/channels/Channels.java b/libjava/classpath/java/nio/channels/Channels.java
new file mode 100644
index 00000000000..cdb2e833e9d
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/Channels.java
@@ -0,0 +1,143 @@
+/* Channels.java --
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio.channels;
+
+import gnu.java.nio.ChannelReader;
+import gnu.java.nio.InputStreamChannel;
+import gnu.java.nio.OutputStreamChannel;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+
+
+/**
+ * @since 1.4
+ */
+public final class Channels
+{
+ /**
+ * This class isn't intended to be instantiated.
+ */
+ private Channels()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Constructs a stream that reads bytes from the given channel.
+ */
+ public static InputStream newInputStream(ReadableByteChannel ch)
+ {
+ return VMChannels.newInputStream(ch);
+ }
+
+ /**
+ * Constructs a stream that writes bytes to the given channel.
+ */
+ public static OutputStream newOutputStream(WritableByteChannel ch)
+ {
+ return VMChannels.newOutputStream(ch);
+ }
+
+ /**
+ * Constructs a channel that reads bytes from the given stream.
+ */
+ public static ReadableByteChannel newChannel(InputStream in)
+ {
+ return new InputStreamChannel(in);
+ }
+
+ /**
+ * Constructs a channel that writes bytes to the given stream.
+ */
+ public static WritableByteChannel newChannel(OutputStream out)
+ {
+ return new OutputStreamChannel(out);
+ }
+
+ /**
+ * Constructs a reader that decodes bytes from the given channel using the
+ * given decoder.
+ */
+ public static Reader newReader(ReadableByteChannel ch, CharsetDecoder dec,
+ int minBufferCap)
+ {
+ return new ChannelReader(ch, dec, minBufferCap);
+ }
+
+ /**
+ * Constructs a reader that decodes bytes from the given channel according to
+ * the named charset.
+ *
+ * @exception UnsupportedCharsetException If no support for the named charset
+ * is available in this instance of the Java virtual machine.
+ */
+ public static Reader newReader(ReadableByteChannel ch, String csName)
+ {
+ return newReader(ch, Charset.forName(csName).newDecoder(), -1);
+ }
+
+ /**
+ * Constructs a writer that encodes characters using the given encoder and
+ * writes the resulting bytes to the given channel.
+ */
+ public static Writer newWriter(WritableByteChannel ch, CharsetEncoder enc,
+ int minBufferCap)
+ {
+ // FIXME: implement java.nio.channels.Channel.newWriter(WritableByteChannel, CharsetEncoder, int)
+ throw new Error("not implemented");
+ }
+
+ /**
+ * Constructs a writer that encodes characters according to the named charset
+ * and writes the resulting bytes to the given channel.
+ *
+ * @exception UnsupportedCharsetException If no support for the named charset
+ * is available in this instance of the Java virtual machine.
+ */
+ public static Writer newWriter(WritableByteChannel ch, String csName)
+ {
+ return newWriter(ch, Charset.forName(csName).newEncoder(), -1);
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/ClosedByInterruptException.java b/libjava/classpath/java/nio/channels/ClosedByInterruptException.java
new file mode 100644
index 00000000000..17858f613c6
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/ClosedByInterruptException.java
@@ -0,0 +1,53 @@
+/* ClosedByInterruptException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class ClosedByInterruptException extends AsynchronousCloseException
+{
+ /**
+ * Creates the exception
+ */
+ public ClosedByInterruptException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/ClosedChannelException.java b/libjava/classpath/java/nio/channels/ClosedChannelException.java
new file mode 100644
index 00000000000..0f8df9b26c4
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/ClosedChannelException.java
@@ -0,0 +1,55 @@
+/* ClosedChannelException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class ClosedChannelException extends IOException
+{
+ /**
+ * Creates the exception
+ */
+ public ClosedChannelException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/ClosedSelectorException.java b/libjava/classpath/java/nio/channels/ClosedSelectorException.java
new file mode 100644
index 00000000000..e1b7a8ce939
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/ClosedSelectorException.java
@@ -0,0 +1,53 @@
+/* ClosedSelectorException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class ClosedSelectorException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public ClosedSelectorException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/ConnectionPendingException.java b/libjava/classpath/java/nio/channels/ConnectionPendingException.java
new file mode 100644
index 00000000000..b0b71294f7e
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/ConnectionPendingException.java
@@ -0,0 +1,53 @@
+/* ConnectionPendingException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class ConnectionPendingException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public ConnectionPendingException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/DatagramChannel.java b/libjava/classpath/java/nio/channels/DatagramChannel.java
new file mode 100644
index 00000000000..d257ff33865
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/DatagramChannel.java
@@ -0,0 +1,210 @@
+/* DatagramChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+
+/**
+ * @since 1.4
+ */
+public abstract class DatagramChannel extends AbstractSelectableChannel
+ implements ByteChannel, ScatteringByteChannel, GatheringByteChannel
+{
+ /**
+ * Initializes the channel.
+ */
+ protected DatagramChannel(SelectorProvider provider)
+ {
+ super(provider);
+ }
+
+ /**
+ * Opens a datagram channel.
+ *
+ * @exception IOException If an error occurs
+ */
+ public static DatagramChannel open() throws IOException
+ {
+ return SelectorProvider.provider().openDatagramChannel();
+ }
+
+ /**
+ * Reads data from this channel.
+ */
+ public final long read(ByteBuffer[] dsts) throws IOException
+ {
+ long b = 0;
+
+ for (int i = 0; i < dsts.length; i++)
+ b += read(dsts[i]);
+
+ return b;
+ }
+
+ /**
+ * Writes data to this channel.
+ *
+ * @exception IOException If an error occurs
+ * @exception NotYetConnectedException The channel's socket is not connected.
+ */
+ public final long write(ByteBuffer[] srcs) throws IOException
+ {
+ long b = 0;
+
+ for (int i = 0; i < srcs.length; i++)
+ b += write(srcs[i]);
+
+ return b;
+ }
+
+ /**
+ * Connects this channel's socket.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the connect operation is in progress.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the read operation is in progress, thereby closing the
+ * channel and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IOException If an error occurs.
+ * @exception SecurityException If a security manager has been installed and
+ * it does not permit datagrams to be sent to the given address.
+ */
+ public abstract DatagramChannel connect(SocketAddress remote)
+ throws IOException;
+
+ /**
+ * Disonnects this channel's socket.
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract DatagramChannel disconnect() throws IOException;
+
+ /**
+ * Tells whether or not this channel's socket is connected.
+ *
+ * @exception IOException If an error occurs.
+ * @exception NotYetConnectedException The channel's socket is not connected.
+ */
+ public abstract boolean isConnected();
+
+ /**
+ * Reads data from this channel.
+ */
+ public abstract int read(ByteBuffer dst) throws IOException;
+
+ /**
+ * Reads data from this channel.
+ *
+ * @exception IOException If an error occurs.
+ * @exception NotYetConnectedException The channel's socket is not connected.
+ */
+ public abstract long read(ByteBuffer[] dsts, int offset, int length)
+ throws IOException;
+
+ /**
+ * Receives a datagram via this channel.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the connect operation is in progress.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the read operation is in progress, thereby closing the
+ * channel and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager has been installed and
+ * it does not permit datagrams to be sent to the given address.
+ */
+ public abstract SocketAddress receive(ByteBuffer dst)
+ throws IOException;
+
+ /**
+ * Sends a datagram via this channel.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the connect operation is in progress.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the read operation is in progress, thereby closing the
+ * channel and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager has been installed and
+ * it does not permit datagrams to be sent to the given address.
+ */
+ public abstract int send(ByteBuffer src, SocketAddress target)
+ throws IOException;
+
+ /**
+ * Retrieves the channel's socket.
+ */
+ public abstract DatagramSocket socket();
+
+ /**
+ * Writes data to this channel.
+ *
+ * @exception IOException If an error occurs.
+ * @exception NotYetConnectedException The channel's socket is not connected.
+ */
+ public abstract int write(ByteBuffer src) throws IOException;
+
+ /**
+ * Writes data to this channel.
+ *
+ * @exception IOException If an error occurs.
+ * @exception NotYetConnectedException The channel's socket is not connected.
+ */
+ public abstract long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException;
+
+ /**
+ * Retrieves the valid operations for this channel.
+ *
+ * @exception IOException If an error occurs.
+ * @exception NotYetConnectedException The channel's socket is not connected.
+ */
+ public final int validOps()
+ {
+ return SelectionKey.OP_READ | SelectionKey.OP_WRITE;
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/FileChannel.java b/libjava/classpath/java/nio/channels/FileChannel.java
new file mode 100644
index 00000000000..944ec0b8f3e
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/FileChannel.java
@@ -0,0 +1,367 @@
+/* FileChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class FileChannel extends AbstractInterruptibleChannel
+ implements ByteChannel, GatheringByteChannel, ScatteringByteChannel
+{
+ public static class MapMode
+ {
+ int m;
+ public static final MapMode READ_ONLY = new MapMode(0);
+ public static final MapMode READ_WRITE = new MapMode(1);
+ public static final MapMode PRIVATE = new MapMode(2);
+
+ /**
+ * Initializes the MapMode.
+ */
+ MapMode(int a)
+ {
+ m = a;
+ }
+
+ /**
+ * Returns a string representation of the <code>MapMode</code> object.
+ */
+ public String toString()
+ {
+ if (this == READ_ONLY)
+ return "READ_ONLY";
+ else if (this == READ_WRITE)
+ return "READ_WRITE";
+
+ return "PRIVATE";
+ }
+ }
+
+ /**
+ * Initializes the channel.
+ */
+ protected FileChannel()
+ {
+ }
+
+ /**
+ * Maps the file into the memory.
+ *
+ * @exception IllegalArgumentException If the preconditions on the parameters
+ * do not hold.
+ * @exception IOException If an I/O error occurs.
+ * @exception NonReadableChannelException If mode is READ_ONLY but this channel was
+ * not opened for reading.
+ * @exception NonWritableChannelException If mode is READ_WRITE or PRIVATE but this
+ * channel was not opened for writing.
+ */
+ public abstract MappedByteBuffer map(MapMode mode, long position, long size)
+ throws IOException;
+
+ /**
+ * Return the size of the file thus far
+ *
+ * @exception ClosedChannelException If this channel is closed.
+ */
+ public abstract long size() throws IOException;
+
+ /**
+ * Writes data to the channel.
+ *
+ * @exception IOException If an I/O error occurs.
+ */
+ public final long write(ByteBuffer[] srcs) throws IOException
+ {
+ long result = 0;
+
+ for (int i = 0; i < srcs.length; i++)
+ result += write(srcs[i]);
+
+ return result;
+ }
+
+ /**
+ * Writes data to the channel.
+ *
+ * @exception IOException If an I/O error occurs.
+ */
+ public abstract int write(ByteBuffer src) throws IOException;
+
+ /**
+ * Writes data to the channel.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the transfer is in progress.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the transfer is in progress, thereby closing both
+ * channels and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If position is negative.
+ * @exception IOException If an I/O error occurs.
+ * @exception NonWritableChannelException If this channel was not opened for
+ * writing.
+ */
+ public abstract int write(ByteBuffer srcs, long position)
+ throws IOException;
+
+ /**
+ * Writes data to the channel.
+ *
+ * @exception IOException If an I/O error occurs.
+ */
+ public abstract long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException;
+
+ /**
+ * Reads data from the channel.
+ *
+ * @exception IOException If an I/O error occurs.
+ */
+ public abstract long read(ByteBuffer[] dsts, int offset, int length)
+ throws IOException;
+
+ /**
+ * Reads data from the channel.
+ *
+ * @exception IOException If an I/O error occurs.
+ */
+ public final long read(ByteBuffer[] dsts) throws IOException
+ {
+ long result = 0;
+
+ for (int i = 0; i < dsts.length; i++)
+ read(dsts[i]);
+
+ return result;
+ }
+
+ /**
+ * Reads data from the channel.
+ *
+ * @exception IOException If an I/O error occurs.
+ */
+ public abstract int read(ByteBuffer dst) throws IOException;
+
+ /**
+ * Reads data from the channel.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the transfer is in progress.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the transfer is in progress, thereby closing both
+ * channels and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If position is negative.
+ * @exception IOException If an I/O error occurs.
+ * @exception NonReadableChannelException If this channel was not opened for
+ * reading.
+ */
+ public abstract int read(ByteBuffer dst, long position)
+ throws IOException;
+
+ /**
+ * Closes the channel.
+ *
+ * This is called from @see close.
+ *
+ * @exception IOException If an I/O error occurs.
+ */
+ protected abstract void implCloseChannel() throws IOException;
+
+ /**
+ * msync with the disk
+ *
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IOException If an I/O error occurs.
+ */
+ public abstract void force(boolean metaData) throws IOException;
+
+ /**
+ * Creates a file lock for the whole assoziated file.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the transfer is in progress.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception FileLockInterruptionException If the invoking thread is
+ * interrupted while blocked in this method.
+ * @exception IOException If an I/O error occurs.
+ * @exception NonReadableChannelException If shared is true and this channel
+ * was not opened for reading.
+ * @exception NonWritableChannelException If shared is false and this channel
+ * was not opened for writing.
+ * @exception OverlappingFileLockException If a lock that overlaps the
+ * requested region is already held by this Java virtual machine, or if
+ * another thread is already blocked in this method and is attempting to lock
+ * an overlapping region.
+ */
+ public final FileLock lock() throws IOException
+ {
+ return lock(0, Long.MAX_VALUE, false);
+ }
+
+ /**
+ * Creates a file lock for a region of the assoziated file.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the transfer is in progress.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception FileLockInterruptionException If the invoking thread is
+ * interrupted while blocked in this method.
+ * @exception IllegalArgumentException If the preconditions on the parameters
+ * do not hold.
+ * @exception IOException If an I/O error occurs.
+ * @exception OverlappingFileLockException If a lock that overlaps the
+ * requested region is already held by this Java virtual machine, or if
+ * another thread is already blocked in this method and is attempting to lock
+ * an overlapping region.
+ * @exception NonReadableChannelException If shared is true and this channel
+ * was not opened for reading.
+ * @exception NonWritableChannelException If shared is false and this channel
+ * was not opened for writing.
+ */
+ public abstract FileLock lock(long position, long size, boolean shared)
+ throws IOException;
+
+ /**
+ * Tries to aqquire alock on the whole assoziated file.
+ *
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IOException If an I/O error occurs.
+ * @exception OverlappingFileLockException If a lock that overlaps the
+ * requested region is already held by this Java virtual machine, or if
+ * another thread is already blocked in this method and is attempting to lock
+ * an overlapping region.
+ */
+ public final FileLock tryLock() throws IOException
+ {
+ return tryLock(0, Long.MAX_VALUE, false);
+ }
+
+ /**
+ * Tries to aqquire a lock on a region of the assoziated file.
+ *
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If the preconditions on the parameters
+ * do not hold.
+ * @exception IOException If an I/O error occurs.
+ * @exception OverlappingFileLockException If a lock that overlaps the
+ * requested region is already held by this Java virtual machine, or if
+ * another thread is already blocked in this method and is attempting to lock
+ * an overlapping region.
+ */
+ public abstract FileLock tryLock(long position, long size, boolean shared)
+ throws IOException;
+
+ /**
+ * Returns the current position on the file.
+ *
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IOException If an I/O error occurs.
+ */
+ public abstract long position() throws IOException;
+
+ /**
+ * Sets the position of the channel on the assoziated file.
+ *
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If newPosition is negative.
+ * @exception IOException If an I/O error occurs.
+ */
+ public abstract FileChannel position(long newPosition)
+ throws IOException;
+
+ /**
+ * Transfers bytes from this channel's file to the given writable byte
+ * channel.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the transfer is in progress.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the transfer is in progress, thereby closing both
+ * channels and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If the preconditions on the parameters
+ * do not hold.
+ * @exception IOException If an I/O error occurs.
+ * @exception NonReadableChannelException If this channel was not opened for
+ * reading.
+ * @exception NonWritableChannelException If the target channel was not
+ * opened for writing.
+ */
+ public abstract long transferTo(long position, long count,
+ WritableByteChannel target)
+ throws IOException;
+
+ /**
+ * Transfers bytes from the given readable channel into this channel.
+ *
+ * @exception AsynchronousCloseException If another thread closes this channel
+ * while the transfer is in progress.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the transfer is in progress, thereby closing both
+ * channels and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If the preconditions on the parameters
+ * do not hold.
+ * @exception IOException If an I/O error occurs.
+ * @exception NonReadableChannelException If the source channel was not
+ * opened for reading.
+ * @exception NonWritableChannelException If this channel was not opened for
+ * writing.
+ */
+ public abstract long transferFrom(ReadableByteChannel src, long position,
+ long count) throws IOException;
+
+ /**
+ * Truncates the channel's file at <code>size</code>.
+ *
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If size is negative.
+ * @exception IOException If an I/O error occurs.
+ * @exception NonWritableChannelException If this channel was not opened for
+ * writing.
+ */
+ public abstract FileChannel truncate(long size) throws IOException;
+}
diff --git a/libjava/classpath/java/nio/channels/FileLock.java b/libjava/classpath/java/nio/channels/FileLock.java
new file mode 100644
index 00000000000..151c23f9f6b
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/FileLock.java
@@ -0,0 +1,150 @@
+/* FileLock.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.channels;
+
+import java.io.IOException;
+
+
+/**
+ * @since 1.4
+ */
+public abstract class FileLock
+{
+ FileChannel channel;
+ long position;
+ long size;
+ boolean shared;
+
+ /**
+ * Initializes the file lock.
+ *
+ * @exception IllegalArgumentException If the preconditions on the parameters do not hold
+ */
+ protected FileLock(FileChannel channel, long position, long size,
+ boolean shared)
+ {
+ if (position < 0 || size < 0)
+ throw new IllegalArgumentException();
+
+ this.channel = channel;
+ this.position = position;
+ this.size = size;
+ this.shared = shared;
+ }
+
+ /**
+ * Tells whether or not this lock is valid.
+ */
+ public abstract boolean isValid();
+
+ /**
+ * Releases this lock.
+ *
+ * @exception IOException If an error occurs
+ * @exception ClosedChannelException If the locked channel is no longer open.
+ */
+ public abstract void release() throws IOException;
+
+ /**
+ * Returns the file channel upon whose file this lock is held.
+ */
+ public final FileChannel channel()
+ {
+ return channel;
+ }
+
+ /**
+ * Tells whether this lock is shared.
+ */
+ public final boolean isShared()
+ {
+ return shared;
+ }
+
+ /**
+ * Tells whether or not this lock overlaps the given lock range.
+ */
+ public final boolean overlaps(long position, long size)
+ {
+ if (position > this.position + this.size)
+ return false;
+
+ if (position + size < this.position)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Returns the position within the file of the first byte of the
+ * locked region.
+ */
+ public final long position()
+ {
+ return position;
+ }
+
+ /**
+ * Returns the size of the locked region in bytes.
+ */
+ public final long size()
+ {
+ return size;
+ }
+
+ /**
+ * Returns a string describing the range, type, and validity of this lock.
+ */
+ public final String toString()
+ {
+ StringBuffer buf = new StringBuffer(getClass().getName());
+ buf.append("[");
+ buf.append(position);
+ buf.append(":");
+ buf.append(size);
+ if (shared)
+ buf.append(" shared");
+ else
+ buf.append(" exclusive");
+ if (isValid())
+ buf.append(" valid]");
+ else
+ buf.append(" invalid]");
+ return buf.toString();
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/FileLockInterruptionException.java b/libjava/classpath/java/nio/channels/FileLockInterruptionException.java
new file mode 100644
index 00000000000..7d9e620464f
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/FileLockInterruptionException.java
@@ -0,0 +1,55 @@
+/* FileLockInterruptionException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class FileLockInterruptionException extends IOException
+{
+ /**
+ * Creates the exception
+ */
+ public FileLockInterruptionException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/GatheringByteChannel.java b/libjava/classpath/java/nio/channels/GatheringByteChannel.java
new file mode 100644
index 00000000000..822ea232a5c
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/GatheringByteChannel.java
@@ -0,0 +1,79 @@
+/* GatheringByteChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+
+public interface GatheringByteChannel extends WritableByteChannel
+{
+ /**
+ * Writes a sequence of bytes to this channel from a subsequence of
+ * the given buffers
+ *
+ * @exception AsynchronousCloseException If another thread closes this
+ * channel while the write operation is in progress
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the write operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status
+ * @exception ClosedChannelException If this channel is closed
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception IOException If an error occurs
+ * @exception NonWritableChannelException If this channel was not opened for
+ * writing
+ */
+ long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException;
+
+ /**
+ * Writes a sequence of bytes to this channel from the given buffers
+ *
+ * @exception AsynchronousCloseException If another thread closes this
+ * channel while the write operation is in progress
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the write operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status
+ * @exception ClosedChannelException If this channel is closed
+ * @exception IOException If an error occurs
+ * @exception NonWritableChannelException If this channel was not opened for
+ * writing
+ */
+ long write(ByteBuffer[] srcs) throws IOException;
+}
diff --git a/libjava/classpath/java/nio/channels/IllegalBlockingModeException.java b/libjava/classpath/java/nio/channels/IllegalBlockingModeException.java
new file mode 100644
index 00000000000..7352b54f7f1
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/IllegalBlockingModeException.java
@@ -0,0 +1,57 @@
+/* IllegalBlockingModeException.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.channels;
+
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.4
+ *
+ * Written using JDK 1.4.1 Online API from Sun
+ * Status: JDK 1.4 complete
+ */
+public class IllegalBlockingModeException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public IllegalBlockingModeException()
+ {
+ super();
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/IllegalSelectorException.java b/libjava/classpath/java/nio/channels/IllegalSelectorException.java
new file mode 100644
index 00000000000..049a8d594f4
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/IllegalSelectorException.java
@@ -0,0 +1,53 @@
+/* IllegalSelectorException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class IllegalSelectorException extends IllegalArgumentException
+{
+ /**
+ * Creates the exception
+ */
+ public IllegalSelectorException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/InterruptibleChannel.java b/libjava/classpath/java/nio/channels/InterruptibleChannel.java
new file mode 100644
index 00000000000..54122ceadbc
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/InterruptibleChannel.java
@@ -0,0 +1,51 @@
+/* InterruptibleChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+
+
+public interface InterruptibleChannel extends Channel
+{
+ /**
+ * Closes this channel
+ *
+ * @exception IOException If an error occurs
+ */
+ void close() throws IOException;
+}
diff --git a/libjava/classpath/java/nio/channels/NoConnectionPendingException.java b/libjava/classpath/java/nio/channels/NoConnectionPendingException.java
new file mode 100644
index 00000000000..afefebf9807
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/NoConnectionPendingException.java
@@ -0,0 +1,53 @@
+/* NoConnectionPendingException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class NoConnectionPendingException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public NoConnectionPendingException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/NonReadableChannelException.java b/libjava/classpath/java/nio/channels/NonReadableChannelException.java
new file mode 100644
index 00000000000..e6852a73d3f
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/NonReadableChannelException.java
@@ -0,0 +1,53 @@
+/* NonReadableChannelException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class NonReadableChannelException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public NonReadableChannelException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/NonWritableChannelException.java b/libjava/classpath/java/nio/channels/NonWritableChannelException.java
new file mode 100644
index 00000000000..61d40bbc4d6
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/NonWritableChannelException.java
@@ -0,0 +1,53 @@
+/* NonWritableChannelException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class NonWritableChannelException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public NonWritableChannelException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/NotYetBoundException.java b/libjava/classpath/java/nio/channels/NotYetBoundException.java
new file mode 100644
index 00000000000..7d0c66388cd
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/NotYetBoundException.java
@@ -0,0 +1,53 @@
+/* NotYetBoundException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class NotYetBoundException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public NotYetBoundException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/NotYetConnectedException.java b/libjava/classpath/java/nio/channels/NotYetConnectedException.java
new file mode 100644
index 00000000000..463e05934a8
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/NotYetConnectedException.java
@@ -0,0 +1,53 @@
+/* NotYetConnectedException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class NotYetConnectedException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public NotYetConnectedException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/OverlappingFileLockException.java b/libjava/classpath/java/nio/channels/OverlappingFileLockException.java
new file mode 100644
index 00000000000..ce0900c6a49
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/OverlappingFileLockException.java
@@ -0,0 +1,53 @@
+/* OverlappingFileLockException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class OverlappingFileLockException extends IllegalStateException
+{
+ /**
+ * Creates the exception
+ */
+ public OverlappingFileLockException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/Pipe.java b/libjava/classpath/java/nio/channels/Pipe.java
new file mode 100644
index 00000000000..c7b04c88c8f
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/Pipe.java
@@ -0,0 +1,121 @@
+/* Pipe.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class Pipe
+{
+ public abstract static class SinkChannel extends AbstractSelectableChannel
+ implements WritableByteChannel, GatheringByteChannel
+ {
+ /**
+ * Initializes the channel.
+ */
+ protected SinkChannel(SelectorProvider provider)
+ {
+ super(provider);
+ }
+
+ /**
+ * Returns an operation set that is valid on this channel.
+ *
+ * The only valid operation on this channel is @see SelectionKey.OP_WRITE.
+ */
+ public final int validOps()
+ {
+ return SelectionKey.OP_WRITE;
+ }
+ }
+
+ public abstract static class SourceChannel extends AbstractSelectableChannel
+ implements ReadableByteChannel, ScatteringByteChannel
+ {
+ /**
+ * Initializes the channel.
+ */
+ protected SourceChannel(SelectorProvider provider)
+ {
+ super(provider);
+ }
+
+ /**
+ * Returns an operation set that is valid on this channel.
+ *
+ * The only valid operation on this channel is @see SelectionKey.OP_READ.
+ */
+ public final int validOps()
+ {
+ return SelectionKey.OP_READ;
+ }
+ }
+
+ /**
+ * Initializes the pipe.
+ */
+ protected Pipe()
+ {
+ }
+
+ /**
+ * Opens a pipe.
+ *
+ * @exception IOException If an error occurs
+ */
+ public static Pipe open() throws IOException
+ {
+ return SelectorProvider.provider().openPipe();
+ }
+
+ /**
+ * Returns a pipe's sink channel.
+ */
+ public abstract Pipe.SinkChannel sink();
+
+ /**
+ * Returns a pipe's source channel
+ */
+ public abstract Pipe.SourceChannel source();
+}
diff --git a/libjava/classpath/java/nio/channels/ReadableByteChannel.java b/libjava/classpath/java/nio/channels/ReadableByteChannel.java
new file mode 100644
index 00000000000..889662de054
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/ReadableByteChannel.java
@@ -0,0 +1,64 @@
+/* ReadableByteChannel.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+
+public interface ReadableByteChannel extends Channel
+{
+ /**
+ * Reads a sequence of bytes from this channel into the given buffer
+ *
+ * @param dst the buffer to put the read data into
+ *
+ * @return the numer of bytes read
+ *
+ * @exception AsynchronousCloseException If another thread closes this
+ * channel while the read operation is in progress
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the read operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status
+ * @exception ClosedChannelException If this channel is closed
+ * @exception IOException If an error occurs
+ * @exception NonReadableChannelException If this channel was not opened for
+ * reading
+ */
+ int read(ByteBuffer dst) throws IOException;
+}
diff --git a/libjava/classpath/java/nio/channels/ScatteringByteChannel.java b/libjava/classpath/java/nio/channels/ScatteringByteChannel.java
new file mode 100644
index 00000000000..5437ea15818
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/ScatteringByteChannel.java
@@ -0,0 +1,79 @@
+/* ScatteringByteChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+
+public interface ScatteringByteChannel extends ReadableByteChannel
+{
+ /**
+ * Reads a sequence of bytes from this channel into a subsequence of the
+ * given buffers
+ *
+ * @exception AsynchronousCloseException If another thread closes this
+ * channel while the write operation is in progress
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the write operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status
+ * @exception ClosedChannelException If this channel is closed
+ * @exception IndexOutOfBoundsException If the preconditions on the offset
+ * and length parameters do not hold
+ * @exception IOException If an error occurs
+ * @exception NonReadableChannelException If this channel was not opened for
+ * reading
+ */
+ long read(ByteBuffer[] srcs, int offset, int length)
+ throws IOException;
+
+ /**
+ * Reads a sequence of bytes from this channel into the given buffers
+ *
+ * @exception AsynchronousCloseException If another thread closes this
+ * channel while the write operation is in progress
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the write operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status
+ * @exception ClosedChannelException If this channel is closed
+ * @exception IOException If an error occurs
+ * @exception NonReadableChannelException If this channel was not opened for
+ * reading
+ */
+ long read(ByteBuffer[] srcs) throws IOException;
+}
diff --git a/libjava/classpath/java/nio/channels/SelectableChannel.java b/libjava/classpath/java/nio/channels/SelectableChannel.java
new file mode 100644
index 00000000000..70fa785ce54
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/SelectableChannel.java
@@ -0,0 +1,140 @@
+/* SelectableChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class SelectableChannel extends AbstractInterruptibleChannel
+{
+ /**
+ * Initializes the channel.
+ */
+ protected SelectableChannel()
+ {
+ }
+
+ /**
+ * Returns the lock of this channel.
+ */
+ public abstract Object blockingLock();
+
+ /**
+ * Adjusts this channel's blocking mode.
+ *
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalBlockingModeException If block is true and this channel
+ * is registered with one or more selectors.
+ * @exception IOException If an error occurs.
+ */
+ public abstract SelectableChannel configureBlocking(boolean block)
+ throws IOException;
+
+ /**
+ * Tells whether this channel is blocking or not.
+ */
+ public abstract boolean isBlocking();
+
+ /**
+ * Tells whether or not this channel is currently registered with
+ * any selectors.
+ */
+ public abstract boolean isRegistered();
+
+ /**
+ * Retrieves the key representing the channel's registration with
+ * the given selector.
+ */
+ public abstract SelectionKey keyFor(Selector sel);
+
+ /**
+ * Returns the provider that created this channel.
+ */
+ public abstract SelectorProvider provider();
+
+ /**
+ * Registers this channel with the given selector,
+ * returning a selection key.
+ *
+ * @exception CancelledKeyException If this channel is currently registered
+ * with the given selector but the corresponding key has already been cancelled
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If a bit in ops does not correspond
+ * to an operation that is supported by this channel, that is, if
+ * set &amp; ~validOps() != 0.
+ * @exception IllegalBlockingModeException If block is true and this channel
+ * is registered with one or more selectors.
+ * @exception IllegalSelectorException If this channel was not created by
+ * the same provider as the given selector.
+ */
+ public final SelectionKey register(Selector sel, int ops)
+ throws ClosedChannelException
+ {
+ return register(sel, ops, null);
+ }
+
+ /**
+ * Registers this channel with the given selector,
+ * returning a selection key.
+ *
+ * @exception CancelledKeyException If this channel is currently registered
+ * with the given selector but the corresponding key has already been
+ * cancelled.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IllegalArgumentException If a bit in ops does not correspond
+ * to an operation that is supported by this channel, that is, if
+ * set &amp; ~validOps() != 0.
+ * @exception IllegalBlockingModeException If block is true and this channel
+ * is registered with one or more selectors.
+ * @exception IllegalSelectorException If this channel was not created by
+ * the same provider as the given selector.
+ */
+ public abstract SelectionKey register(Selector sel, int ops, Object att)
+ throws ClosedChannelException;
+
+ /**
+ * Returns a set of valid operations on this channel.
+ */
+ public abstract int validOps();
+}
diff --git a/libjava/classpath/java/nio/channels/SelectionKey.java b/libjava/classpath/java/nio/channels/SelectionKey.java
new file mode 100644
index 00000000000..5219b6bff84
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/SelectionKey.java
@@ -0,0 +1,164 @@
+/* SelectionKey.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class SelectionKey
+{
+ public static final int OP_ACCEPT = 16;
+ public static final int OP_CONNECT = 8;
+ public static final int OP_READ = 1;
+ public static final int OP_WRITE = 4;
+ Object attached;
+
+ /**
+ * Initializes the selection key.
+ */
+ protected SelectionKey()
+ {
+ }
+
+ /**
+ * Attaches obj to the key and returns the old attached object.
+ */
+ public final Object attach(Object obj)
+ {
+ Object old = attached;
+ attached = obj;
+ return old;
+ }
+
+ /**
+ * Returns the object attached to the key.
+ */
+ public final Object attachment()
+ {
+ return attached;
+ }
+
+ /**
+ * Tests if the channel attached to this key is ready to accept
+ * a new socket connection.
+ *
+ * @exception CancelledKeyException If this key has been cancelled
+ */
+ public final boolean isAcceptable()
+ {
+ return (readyOps() & OP_ACCEPT) != 0;
+ }
+
+ /**
+ * Tests whether this key's channel has either finished,
+ * or failed to finish, its socket-connection operation.
+ *
+ * @exception CancelledKeyException If this key has been cancelled
+ */
+ public final boolean isConnectable()
+ {
+ return (readyOps() & OP_CONNECT) != 0;
+ }
+
+ /**
+ * Tests if the channel attached to the key is readable.
+ *
+ * @exception CancelledKeyException If this key has been cancelled
+ */
+ public final boolean isReadable()
+ {
+ return (readyOps() & OP_READ) != 0;
+ }
+
+ /**
+ * Tests if the channel attached to the key is writable.
+ *
+ * @exception CancelledKeyException If this key has been cancelled
+ */
+ public final boolean isWritable()
+ {
+ return (readyOps() & OP_WRITE) != 0;
+ }
+
+ /**
+ * Requests that the registration of this key's channel with
+ * its selector be cancelled.
+ */
+ public abstract void cancel();
+
+ /**
+ * return the channel attached to the key.
+ */
+ public abstract SelectableChannel channel();
+
+ /**
+ * Returns the key's interest set.
+ *
+ * @exception CancelledKeyException If this key has been cancelled
+ */
+ public abstract int interestOps();
+
+ /**
+ * Sets this key's interest set to the given value.
+ *
+ * @exception CancelledKeyException If this key has been cancelled
+ * @exception IllegalArgumentException If a bit in the set does not
+ * correspond to an operation that is supported by this key's channel,
+ * that is, if set &amp; ~(channel().validOps()) != 0
+ */
+ public abstract SelectionKey interestOps(int ops);
+
+ /**
+ * Tells whether or not this key is valid.
+ */
+ public abstract boolean isValid();
+
+ /**
+ * Retrieves this key's ready-operation set.
+ *
+ * @exception CancelledKeyException If this key has been cancelled
+ */
+ public abstract int readyOps();
+
+ /**
+ * Returns the selector for which this key was created.
+ */
+ public abstract Selector selector();
+}
diff --git a/libjava/classpath/java/nio/channels/Selector.java b/libjava/classpath/java/nio/channels/Selector.java
new file mode 100644
index 00000000000..2c883efd1a1
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/Selector.java
@@ -0,0 +1,134 @@
+/* Selector.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Set;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class Selector
+{
+ /**
+ * Initializes the selector.
+ */
+ protected Selector()
+ {
+ }
+
+ /**
+ * Opens a selector.
+ *
+ * @exception IOException If an error occurs
+ */
+ public static Selector open() throws IOException
+ {
+ return SelectorProvider.provider().openSelector();
+ }
+
+ /**
+ * Closes the selector.
+ *
+ * @exception IOException If an error occurs
+ */
+ public abstract void close() throws IOException;
+
+ /**
+ * Tells whether the selector is open or not.
+ */
+ public abstract boolean isOpen();
+
+ /**
+ * Returns this selector's key set.
+ *
+ * @exception ClosedSelectorException If this selector is closed.
+ */
+ public abstract Set keys();
+
+ /**
+ * Returns the SelectorProvider that created the selector.
+ */
+ public abstract SelectorProvider provider();
+
+ /**
+ * Selects a set of keys whose corresponding channels are ready
+ * for I/O operations.
+ *
+ * @exception ClosedSelectorException If this selector is closed.
+ * @exception IOException If an error occurs
+ */
+ public abstract int select() throws IOException;
+
+ /**
+ * Selects a set of keys whose corresponding channels are ready
+ * for I/O operations.
+ *
+ * @param timeout The timeout to use.
+ *
+ * @exception ClosedSelectorException If this selector is closed.
+ * @exception IllegalArgumentException If the timeout value is negative.
+ * @exception IOException If an error occurs
+ */
+ public abstract int select(long timeout) throws IOException;
+
+ /**
+ * Returns this selector's selected-key set.
+ *
+ * @exception ClosedSelectorException If this selector is closed.
+ */
+ public abstract Set selectedKeys();
+
+ /**
+ * Selects a set of keys whose corresponding channels are ready
+ * for I/O operations.
+ *
+ * @exception ClosedSelectorException If this selector is closed.
+ * @exception IOException If an error occurs
+ */
+ public abstract int selectNow() throws IOException;
+
+ /**
+ * Causes the first selection operation that has not yet returned to
+ * return immediately.
+ */
+ public abstract Selector wakeup();
+}
diff --git a/libjava/classpath/java/nio/channels/ServerSocketChannel.java b/libjava/classpath/java/nio/channels/ServerSocketChannel.java
new file mode 100644
index 00000000000..105d17f94ec
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/ServerSocketChannel.java
@@ -0,0 +1,98 @@
+/* ServerSocketChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class ServerSocketChannel extends AbstractSelectableChannel
+{
+ /**
+ * Initializes this channel.
+ */
+ protected ServerSocketChannel(SelectorProvider provider)
+ {
+ super(provider);
+ }
+
+ /**
+ * Accepts a connection made to this channel's socket.
+ *
+ * @exception IOException If an error occurs
+ * @exception AsynchronousCloseException If another thread closes this
+ * channel while the accept operation is in progress.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the accept operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If the channel is closed.
+ * @exception NotYetBoundException If the channel's socket is not yet bound.
+ * @exception SecurityException If a security manager has been installed and
+ * it does not permit access to the remote endpoint of the new connection.
+ */
+ public abstract SocketChannel accept() throws IOException;
+
+ /**
+ * Retrieves the channels socket.
+ */
+ public abstract ServerSocket socket();
+
+ /**
+ * Opens a server socket channel.
+ *
+ * @exception IOException If an error occurs
+ */
+ public static ServerSocketChannel open() throws IOException
+ {
+ return SelectorProvider.provider().openServerSocketChannel();
+ }
+
+ /**
+ * Retrieves the valid operations for this channel.
+ */
+ public final int validOps()
+ {
+ return SelectionKey.OP_ACCEPT;
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/SocketChannel.java b/libjava/classpath/java/nio/channels/SocketChannel.java
new file mode 100644
index 00000000000..50f21368c88
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/SocketChannel.java
@@ -0,0 +1,248 @@
+/* SocketChannel.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio.channels;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.4
+ */
+public abstract class SocketChannel extends AbstractSelectableChannel
+ implements ByteChannel, ScatteringByteChannel, GatheringByteChannel
+{
+ /**
+ * Initializes this socket channel.
+ */
+ protected SocketChannel(SelectorProvider provider)
+ {
+ super(provider);
+ }
+
+ /**
+ * Opens a socket channel.
+ *
+ * @return the new <code>SocketChannel</code> object
+ *
+ * @exception IOException If an error occurs
+ */
+ public static SocketChannel open() throws IOException
+ {
+ return SelectorProvider.provider().openSocketChannel();
+ }
+
+ /**
+ * Opens a channel and connects it to a remote address.
+ *
+ * @return the new <code>SocketChannel</code> object
+ *
+ * @exception AsynchronousCloseException If this channel is already connected.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the connect operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status.
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager has been installed and
+ * it does not permit access to the given remote endpoint.
+ * @exception UnresolvedAddressException If the given remote address is not
+ * fully resolved.
+ * @exception UnsupportedAddressTypeException If the type of the given remote
+ * address is not supported.
+ */
+ public static SocketChannel open(SocketAddress remote)
+ throws IOException
+ {
+ SocketChannel ch = open();
+ ch.connect(remote);
+ return ch;
+ }
+
+ /**
+ * Reads data from the channel.
+ *
+ * @return the number of bytes read, zero is valid too, -1 if end of stream
+ * is reached
+ *
+ * @exception IOException If an error occurs
+ * @exception NotYetConnectedException If this channel is not yet connected.
+ */
+ public final long read(ByteBuffer[] dsts) throws IOException
+ {
+ long b = 0;
+
+ for (int i = 0; i < dsts.length; i++)
+ b += read(dsts[i]);
+
+ return b;
+ }
+
+ /**
+ * Writes data to the channel.
+ *
+ * @return the number of bytes written, zero is valid too
+ *
+ * @exception IOException If an error occurs
+ * @exception NotYetConnectedException If this channel is not yet connected.
+ */
+ public final long write(ByteBuffer[] dsts) throws IOException
+ {
+ long b = 0;
+
+ for (int i = 0; i < dsts.length; i++)
+ b += write(dsts[i]);
+
+ return b;
+ }
+
+ /**
+ * Retrieves the valid operations for this channel.
+ *
+ * @return the valid operations
+ */
+ public final int validOps()
+ {
+ return SelectionKey.OP_CONNECT | SelectionKey.OP_READ
+ | SelectionKey.OP_WRITE;
+ }
+
+ /**
+ * Reads data from the channel.
+ *
+ * @return the number of bytes read, zero is valid too, -1 if end of stream
+ * is reached
+ *
+ * @exception IOException If an error occurs
+ * @exception NotYetConnectedException If this channel is not yet connected.
+ */
+ public abstract int read(ByteBuffer dst) throws IOException;
+
+ /**
+ * Connects the channel's socket to the remote address.
+ *
+ * @return <code>true</code> if the channel got successfully connected,
+ * <code>false</code> if the channel is in non-blocking mode and connection
+ * operation is still in progress.
+ *
+ * @exception AlreadyConnectedException If this channel is already connected.
+ * @exception AsynchronousCloseException If this channel is already connected.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the connect operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception ConnectionPendingException If a non-blocking connection
+ * operation is already in progress on this channel.
+ * @exception IOException If an error occurs
+ * @exception SecurityException If a security manager has been installed and
+ * it does not permit access to the given remote endpoint.
+ * @exception UnresolvedAddressException If the given remote address is not
+ * fully resolved.
+ * @exception UnsupportedAddressTypeException If the type of the given remote
+ * address is not supported.
+ */
+ public abstract boolean connect(SocketAddress remote)
+ throws IOException;
+
+ /**
+ * Finishes the process of connecting a socket channel.
+ *
+ * @exception AsynchronousCloseException If this channel is already connected.
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the connect operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status.
+ * @exception ClosedChannelException If this channel is closed.
+ * @exception IOException If an error occurs
+ * @exception NoConnectionPendingException If this channel is not connected
+ * and a connection operation has not been initiated.
+ */
+ public abstract boolean finishConnect() throws IOException;
+
+ /**
+ * Tells whether or not the channel's socket is connected.
+ */
+ public abstract boolean isConnected();
+
+ /**
+ * Tells whether or not a connection operation is in progress on this channel.
+ */
+ public abstract boolean isConnectionPending();
+
+ /**
+ * Reads data from the channel.
+ *
+ * @return the number of bytes read, zero is valid too, -1 if end of stream
+ * is reached
+ *
+ * @exception IOException If an error occurs
+ * @exception NotYetConnectedException If this channel is not yet connected.
+ */
+ public abstract long read(ByteBuffer[] dsts, int offset, int length)
+ throws IOException;
+
+ /**
+ * Retrieves the channel's socket.
+ *
+ * @return the socket
+ */
+ public abstract Socket socket();
+
+ /**
+ * Writes data to the channel.
+ *
+ * @return the number of bytes written, zero is valid too
+ *
+ * @exception IOException If an error occurs
+ * @exception NotYetConnectedException If this channel is not yet connected.
+ */
+ public abstract int write(ByteBuffer src) throws IOException;
+
+ /**
+ * Writes data to the channel.
+ *
+ * @return the number of bytes written, zero is valid too
+ *
+ * @exception IOException If an error occurs
+ * @exception NotYetConnectedException If this channel is not yet connected.
+ */
+ public abstract long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException;
+}
diff --git a/libjava/classpath/java/nio/channels/UnresolvedAddressException.java b/libjava/classpath/java/nio/channels/UnresolvedAddressException.java
new file mode 100644
index 00000000000..4db95a7ffdd
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/UnresolvedAddressException.java
@@ -0,0 +1,53 @@
+/* UnresolvedAddressException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class UnresolvedAddressException extends IllegalArgumentException
+{
+ /**
+ * Creates the exception
+ */
+ public UnresolvedAddressException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/UnsupportedAddressTypeException.java b/libjava/classpath/java/nio/channels/UnsupportedAddressTypeException.java
new file mode 100644
index 00000000000..7c16c813fb0
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/UnsupportedAddressTypeException.java
@@ -0,0 +1,53 @@
+/* UnsupportedAddressTypeException.java --
+ Copyright (C) 2002 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.nio.channels;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class UnsupportedAddressTypeException extends IllegalArgumentException
+{
+ /**
+ * Creates the exception
+ */
+ public UnsupportedAddressTypeException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/WritableByteChannel.java b/libjava/classpath/java/nio/channels/WritableByteChannel.java
new file mode 100644
index 00000000000..3845723bca0
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/WritableByteChannel.java
@@ -0,0 +1,60 @@
+/* WritableByteChannel.java --
+ Copyright (C) 2002 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.nio.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+
+public interface WritableByteChannel extends Channel
+{
+ /**
+ * Writes a sequence of bytes to this channel from the given buffer
+ *
+ * @exception AsynchronousCloseException If another thread closes this
+ * channel while the write operation is in progress
+ * @exception ClosedByInterruptException If another thread interrupts the
+ * current thread while the write operation is in progress, thereby closing
+ * the channel and setting the current thread's interrupt status
+ * @exception ClosedChannelException If this channel is closed
+ * @exception IOException If an error occurs
+ * @exception NonWritableChannelException If this channel was not opened for
+ * writing
+ */
+ int write(ByteBuffer src) throws IOException;
+}
diff --git a/libjava/classpath/java/nio/channels/package.html b/libjava/classpath/java/nio/channels/package.html
new file mode 100644
index 00000000000..4e2bbc9f6ce
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.nio.channels package.
+ Copyright (C) 2002 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 - java.nio.channels</title></head>
+
+<body>
+<p>Classes for creating, selecting and non-blocking reading and writing of
+buffers from files and sockets.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/nio/channels/spi/AbstractInterruptibleChannel.java b/libjava/classpath/java/nio/channels/spi/AbstractInterruptibleChannel.java
new file mode 100644
index 00000000000..25e8785c08e
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/spi/AbstractInterruptibleChannel.java
@@ -0,0 +1,119 @@
+/* AbstractInterruptibleChannel.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.Channel;
+import java.nio.channels.InterruptibleChannel;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class AbstractInterruptibleChannel
+ implements Channel, InterruptibleChannel
+{
+ private boolean closed;
+
+ /**
+ * Initializes the channel.
+ */
+ protected AbstractInterruptibleChannel()
+ {
+ }
+
+ /**
+ * Marks the beginning of an I/O operation that might block indefinitely.
+ */
+ protected final void begin()
+ {
+ }
+
+ /**
+ * Closes the channel.
+ *
+ * @exception IOException If an error occurs
+ */
+ public final void close() throws IOException
+ {
+ if (! closed)
+ {
+ closed = true;
+ implCloseChannel();
+ }
+ }
+
+ /**
+ * Marks the end of an I/O operation that might block indefinitely.
+ *
+ * @param completed true if the task completed successfully,
+ * false otherwise
+ *
+ * @exception IOException if an error occurs
+ * @exception AsynchronousCloseException If the channel was asynchronously
+ * closed.
+ * @exception ClosedByInterruptException If the thread blocked in the
+ * I/O operation was interrupted.
+ */
+ protected final void end(boolean completed)
+ throws AsynchronousCloseException
+ {
+ // FIXME: check more here.
+
+ if (closed) throw new AsynchronousCloseException();
+ }
+
+ /**
+ * Closes the channel.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void implCloseChannel() throws IOException;
+
+ /**
+ * Tells whether or not this channel is open.
+ *
+ * @return true if the channel is open, false otherwise
+ */
+ public final boolean isOpen()
+ {
+ return ! closed;
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java b/libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java
new file mode 100644
index 00000000000..42ceab7e2c1
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java
@@ -0,0 +1,256 @@
+/* AbstractSelectableChannel.java
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+public abstract class AbstractSelectableChannel extends SelectableChannel
+{
+ private boolean blocking = true;
+ private Object LOCK = new Object();
+ private SelectorProvider provider;
+ private LinkedList keys = new LinkedList();
+
+ /**
+ * Initializes the channel
+ *
+ * @param provider the provider that created this channel
+ */
+ protected AbstractSelectableChannel(SelectorProvider provider)
+ {
+ this.provider = provider;
+ }
+
+ /**
+ * Retrieves the object upon which the configureBlocking and register
+ * methods synchronize.
+ *
+ * @return the blocking lock
+ */
+ public final Object blockingLock()
+ {
+ return LOCK;
+ }
+
+ /**
+ * Adjusts this channel's blocking mode.
+ *
+ * @param blocking true if blocking should be enabled, false otherwise
+ *
+ * @return this channel
+ *
+ * @exception IOException If an error occurs
+ */
+ public final SelectableChannel configureBlocking(boolean blocking)
+ throws IOException
+ {
+ synchronized (blockingLock())
+ {
+ if (this.blocking != blocking)
+ {
+ implConfigureBlocking(blocking);
+ this.blocking = blocking;
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Closes this channel.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected final void implCloseChannel() throws IOException
+ {
+ implCloseSelectableChannel();
+ }
+
+ /**
+ * Closes this selectable channel.
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void implCloseSelectableChannel()
+ throws IOException;
+
+ /**
+ * Adjusts this channel's blocking mode.
+ *
+ * @param blocking true if blocking should be enabled, false otherwise
+ *
+ * @exception IOException If an error occurs
+ */
+ protected abstract void implConfigureBlocking(boolean blocking)
+ throws IOException;
+
+ /**
+ * Tells whether or not every I/O operation on this channel will block
+ * until it completes.
+ *
+ * @return true of this channel is blocking, false otherwise
+ */
+ public final boolean isBlocking()
+ {
+ return blocking;
+ }
+
+ /**
+ * Tells whether or not this channel is currently registered with
+ * any selectors.
+ *
+ * @return true if this channel is registered, false otherwise
+ */
+ public final boolean isRegistered()
+ {
+ return ! keys.isEmpty();
+ }
+
+ /**
+ * Retrieves the key representing the channel's registration with the
+ * given selector.
+ *
+ * @param selector the selector to get a selection key for
+ *
+ * @return the selection key this channel is registered with
+ */
+ public final SelectionKey keyFor(Selector selector)
+ {
+ if (! isOpen())
+ return null;
+
+ try
+ {
+ synchronized (blockingLock())
+ {
+ return locate(selector);
+ }
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the provider that created this channel.
+ *
+ * @return the selector provider that created this channel
+ */
+ public final SelectorProvider provider()
+ {
+ return provider;
+ }
+
+ private SelectionKey locate(Selector selector)
+ {
+ ListIterator it = keys.listIterator();
+
+ while (it.hasNext())
+ {
+ SelectionKey key = (SelectionKey) it.next();
+
+ if (key.selector() == selector)
+ return key;
+ }
+
+ return null;
+ }
+
+ /**
+ * Registers this channel with the given selector, returning a selection key.
+ *
+ * @param selin the seletor to use
+ * @param ops the interested operations
+ * @param att an attachment for the returned selection key
+ *
+ * @return the registered selection key
+ *
+ * @exception ClosedChannelException If the channel is already closed.
+ */
+ public final SelectionKey register(Selector selin, int ops, Object att)
+ throws ClosedChannelException
+ {
+ if (! isOpen())
+ throw new ClosedChannelException();
+
+ if ((ops & ~validOps()) != 0)
+ throw new IllegalArgumentException();
+
+ SelectionKey key = null;
+ AbstractSelector selector = (AbstractSelector) selin;
+
+ synchronized (blockingLock())
+ {
+ key = locate(selector);
+
+ if (key != null && key.isValid())
+ {
+ if (att != null)
+ key.attach(att);
+ }
+ else
+ {
+ key = selector.register(this, ops, att);
+
+ if (key != null)
+ addSelectionKey(key);
+ }
+ }
+
+ return key;
+ }
+
+ void addSelectionKey(SelectionKey key)
+ {
+ keys.add(key);
+ }
+
+ // This method gets called by AbstractSelector.deregister().
+ void removeSelectionKey(SelectionKey key)
+ {
+ keys.remove(key);
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/spi/AbstractSelectionKey.java b/libjava/classpath/java/nio/channels/spi/AbstractSelectionKey.java
new file mode 100644
index 00000000000..5ab8468bf2e
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/spi/AbstractSelectionKey.java
@@ -0,0 +1,78 @@
+/* AbstractSelectionKey.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.channels.spi;
+
+import java.nio.channels.SelectionKey;
+
+
+/**
+ * @since 1.4
+ */
+public abstract class AbstractSelectionKey extends SelectionKey
+{
+ private boolean cancelled;
+
+ /**
+ * Initializes the key.
+ */
+ protected AbstractSelectionKey()
+ {
+ }
+
+ /**
+ * Cancels this key.
+ */
+ public final void cancel()
+ {
+ if (isValid())
+ {
+ ((AbstractSelector) selector()).cancelKey(this);
+ cancelled = true;
+ }
+ }
+
+ /**
+ * Tells whether this key is valid or not.
+ *
+ * @return true if this key is valid, false otherwise
+ */
+ public final boolean isValid()
+ {
+ return ! cancelled;
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/spi/AbstractSelector.java b/libjava/classpath/java/nio/channels/spi/AbstractSelector.java
new file mode 100644
index 00000000000..78380738a2c
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/spi/AbstractSelector.java
@@ -0,0 +1,167 @@
+/* AbstractSelector.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.util.HashSet;
+import java.util.Set;
+
+
+public abstract class AbstractSelector extends Selector
+{
+ private boolean closed;
+ private SelectorProvider provider;
+ private HashSet cancelledKeys;
+
+ /**
+ * Initializes the slector.
+ *
+ * @param provider the provider that created this selector
+ */
+ protected AbstractSelector(SelectorProvider provider)
+ {
+ this.provider = provider;
+ this.cancelledKeys = new HashSet();
+ }
+
+ /**
+ * Closes the channel.
+ *
+ * @exception IOException If an error occurs
+ */
+ public final synchronized void close() throws IOException
+ {
+ if (closed)
+ return;
+
+ implCloseSelector();
+ closed = true;
+ }
+
+ /**
+ * Tells whether this channel is open or not.
+ *
+ * @return true if channel is open, false otherwise.
+ */
+ public final boolean isOpen()
+ {
+ return ! closed;
+ }
+
+ /**
+ * Marks the beginning of an I/O operation that might block indefinitely.
+ */
+ protected final void begin()
+ {
+ }
+
+ /**
+ * Marks the end of an I/O operation that might block indefinitely.
+ */
+ protected final void end()
+ {
+ }
+
+ /**
+ * Returns the provider for this selector object.
+ *
+ * @return the SelectorProvider object that created this seletor
+ */
+ public final SelectorProvider provider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the cancelled keys set.
+ *
+ * @return the cancelled keys set
+ */
+ protected final Set cancelledKeys()
+ {
+ if (! isOpen())
+ throw new ClosedSelectorException();
+
+ return cancelledKeys;
+ }
+
+ /**
+ * Cancels a selection key.
+ */
+
+ // This method is only called by AbstractSelectionKey.cancel().
+ final void cancelKey(AbstractSelectionKey key)
+ {
+ synchronized (cancelledKeys)
+ {
+ cancelledKeys.add(key);
+ }
+ }
+
+ /**
+ * Closes the channel.
+ *
+ * @exception IOException if an error occurs
+ */
+ protected abstract void implCloseSelector() throws IOException;
+
+ /**
+ * Registers a channel for the selection process.
+ *
+ * @param ch the channel register
+ * @param ops the interested operations
+ * @param att an attachement to the selection key
+ *
+ * @return the registered selection key
+ */
+ protected abstract SelectionKey register(AbstractSelectableChannel ch,
+ int ops, Object att);
+
+ /**
+ * Deregisters the given selection key.
+ *
+ * @param key the key to deregister
+ */
+ protected final void deregister(AbstractSelectionKey key)
+ {
+ ((AbstractSelectableChannel) key.channel()).removeSelectionKey(key);
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/spi/SelectorProvider.java b/libjava/classpath/java/nio/channels/spi/SelectorProvider.java
new file mode 100644
index 00000000000..db4e65fe14e
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/spi/SelectorProvider.java
@@ -0,0 +1,151 @@
+/* SelectorProvider.java
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.channels.spi;
+
+import gnu.java.nio.SelectorProviderImpl;
+
+import java.io.IOException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class SelectorProvider
+{
+ private static SelectorProvider systemDefaultProvider;
+
+ /**
+ * Initializes the selector provider.
+ *
+ * @exception SecurityException If a security manager has been installed and
+ * it denies @see RuntimePermission ("selectorProvider").
+ */
+ protected SelectorProvider()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("selectorProvider"));
+ }
+
+ /**
+ * Opens a datagram channel.
+ *
+ * @return a new datagram channel object
+ *
+ * @exception IOException if an error occurs
+ */
+ public abstract DatagramChannel openDatagramChannel()
+ throws IOException;
+
+ /**
+ * Opens a pipe.
+ *
+ * @return a new pipe object
+ *
+ * @exception IOException if an error occurs
+ */
+ public abstract Pipe openPipe() throws IOException;
+
+ /**
+ * Opens a selector.
+ *
+ * @return a new selector object
+ *
+ * @exception IOException if an error occurs
+ */
+ public abstract AbstractSelector openSelector() throws IOException;
+
+ /**
+ * Opens a server socket channel.
+ *
+ * @return a new server socket channel object
+ *
+ * @exception IOException if an error occurs
+ */
+ public abstract ServerSocketChannel openServerSocketChannel()
+ throws IOException;
+
+ /**
+ * Opens a socket channel.
+ *
+ * @return a new socket channel object
+ *
+ * @exception IOException if an error occurs
+ */
+ public abstract SocketChannel openSocketChannel() throws IOException;
+
+ /**
+ * Returns the system-wide default selector provider for this invocation
+ * of the Java virtual machine.
+ *
+ * @return the default seletor provider
+ */
+ public static synchronized SelectorProvider provider()
+ {
+ if (systemDefaultProvider == null)
+ {
+ String propertyValue =
+ System.getProperty("java.nio.channels.spi.SelectorProvider");
+
+ if (propertyValue == null || propertyValue.equals(""))
+ systemDefaultProvider = new SelectorProviderImpl();
+ else
+ {
+ try
+ {
+ systemDefaultProvider =
+ (SelectorProvider) Class.forName(propertyValue)
+ .newInstance();
+ }
+ catch (Exception e)
+ {
+ System.err.println("Could not instantiate class: "
+ + propertyValue);
+ systemDefaultProvider = new SelectorProviderImpl();
+ }
+ }
+ }
+
+ return systemDefaultProvider;
+ }
+}
diff --git a/libjava/classpath/java/nio/channels/spi/package.html b/libjava/classpath/java/nio/channels/spi/package.html
new file mode 100644
index 00000000000..133fb04f2d7
--- /dev/null
+++ b/libjava/classpath/java/nio/channels/spi/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.nio.channels.spi package.
+ Copyright (C) 2002 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 - java.nio.channels.spi</title></head>
+
+<body>
+<p>Utility classes and interfaces for implementing channels.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/nio/charset/CharacterCodingException.java b/libjava/classpath/java/nio/charset/CharacterCodingException.java
new file mode 100644
index 00000000000..6812ebb18a9
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/CharacterCodingException.java
@@ -0,0 +1,53 @@
+/* CharacterCodingException.java --
+ Copyright (C) 2002 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.nio.charset;
+
+import java.io.IOException;
+
+/**
+ * @since 1.4
+ */
+public class CharacterCodingException extends IOException
+{
+ /**
+ * Creates the exception
+ */
+ public CharacterCodingException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/Charset.java b/libjava/classpath/java/nio/charset/Charset.java
new file mode 100644
index 00000000000..6de2917f7cb
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/Charset.java
@@ -0,0 +1,406 @@
+/* Charset.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.nio.charset;
+
+import gnu.classpath.SystemProperties;
+
+import gnu.java.nio.charset.Provider;
+import gnu.java.nio.charset.iconv.IconvProvider;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.spi.CharsetProvider;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * @author Jesse Rosenstock
+ * @since 1.4
+ * @status updated to 1.5
+ */
+public abstract class Charset implements Comparable
+{
+ private CharsetEncoder cachedEncoder;
+ private CharsetDecoder cachedDecoder;
+
+ /**
+ * Charset providers.
+ */
+ private static CharsetProvider[] providers;
+
+ private final String canonicalName;
+ private final String[] aliases;
+
+ protected Charset (String canonicalName, String[] aliases)
+ {
+ checkName (canonicalName);
+ if (aliases != null)
+ {
+ int n = aliases.length;
+ for (int i = 0; i < n; ++i)
+ checkName (aliases[i]);
+ }
+
+ cachedEncoder = null;
+ cachedDecoder = null;
+ this.canonicalName = canonicalName;
+ this.aliases = aliases;
+ }
+
+ /**
+ * @throws IllegalCharsetNameException if the name is illegal
+ */
+ private static void checkName (String name)
+ {
+ int n = name.length ();
+
+ if (n == 0)
+ throw new IllegalCharsetNameException (name);
+
+ char ch = name.charAt (0);
+ if (!(('A' <= ch && ch <= 'Z')
+ || ('a' <= ch && ch <= 'z')
+ || ('0' <= ch && ch <= '9')))
+ throw new IllegalCharsetNameException (name);
+
+ for (int i = 1; i < n; ++i)
+ {
+ ch = name.charAt (i);
+ if (!(('A' <= ch && ch <= 'Z')
+ || ('a' <= ch && ch <= 'z')
+ || ('0' <= ch && ch <= '9')
+ || ch == '-' || ch == '.' || ch == ':' || ch == '_'))
+ throw new IllegalCharsetNameException (name);
+ }
+ }
+
+ /**
+ * Returns the system default charset.
+ *
+ * This may be set by the user or VM with the file.encoding
+ * property.
+ */
+ public static Charset defaultCharset()
+ {
+ String encoding;
+
+ try
+ {
+ encoding = SystemProperties.getProperty("file.encoding");
+ }
+ catch(SecurityException e)
+ {
+ // Use fallback.
+ encoding = "ISO-8859-1";
+ }
+ catch(IllegalArgumentException e)
+ {
+ // Use fallback.
+ encoding = "ISO-8859-1";
+ }
+
+ try
+ {
+ return forName(encoding);
+ }
+ catch(UnsupportedCharsetException e)
+ {
+ // Ignore.
+ }
+ catch(IllegalCharsetNameException e)
+ {
+ // Ignore.
+ }
+ catch(IllegalArgumentException e)
+ {
+ // Ignore.
+ }
+
+ throw new IllegalStateException("Can't get default charset!");
+ }
+
+ public static boolean isSupported (String charsetName)
+ {
+ return charsetForName (charsetName) != null;
+ }
+
+ /**
+ * Returns the Charset instance for the charset of the given name.
+ *
+ * @param charsetName
+ * @return
+ * @throws UnsupportedCharsetException if this VM does not support
+ * the charset of the given name.
+ * @throws IllegalCharsetNameException if the given charset name is
+ * legal.
+ * @throws IllegalArgumentException if <code>charsetName</code> is null.
+ */
+ public static Charset forName (String charsetName)
+ {
+ // Throws IllegalArgumentException as the JDK does.
+ if(charsetName == null)
+ throw new IllegalArgumentException("Charset name must not be null.");
+
+ Charset cs = charsetForName (charsetName);
+ if (cs == null)
+ throw new UnsupportedCharsetException (charsetName);
+ return cs;
+ }
+
+ /**
+ * Retrieves a charset for the given charset name.
+ *
+ * @return A charset object for the charset with the specified name, or
+ * <code>null</code> if no such charset exists.
+ *
+ * @throws IllegalCharsetNameException if the name is illegal
+ */
+ private static Charset charsetForName(String charsetName)
+ {
+ checkName (charsetName);
+ Charset cs = null;
+ CharsetProvider[] providers = providers2();
+ for (int i = 0; i < providers.length; i++)
+ {
+ cs = providers[i].charsetForName(charsetName);
+ if (cs != null)
+ break;
+ }
+ return cs;
+ }
+
+ public static SortedMap availableCharsets()
+ {
+ TreeMap charsets = new TreeMap(String.CASE_INSENSITIVE_ORDER);
+
+ CharsetProvider[] providers = providers2();
+ for (int j = 0; j < providers.length; j++)
+ {
+ for (Iterator i = providers[j].charsets(); i.hasNext(); )
+ {
+ Charset cs = (Charset) i.next();
+ charsets.put(cs.name(), cs);
+ }
+ }
+
+ return Collections.unmodifiableSortedMap(charsets);
+ }
+
+ private static CharsetProvider provider()
+ {
+ String useIconv = SystemProperties.getProperty
+ ("gnu.classpath.nio.charset.provider.iconv");
+
+ if (useIconv != null)
+ return IconvProvider.provider();
+
+ return Provider.provider();
+ }
+
+ /**
+ * We need to support multiple providers, reading them from
+ * java.nio.charset.spi.CharsetProvider in the resource directory
+ * META-INF/services.
+ */
+ private static CharsetProvider[] providers2()
+ {
+ if (providers == null)
+ {
+ try
+ {
+ Enumeration en = ClassLoader.getSystemResources
+ ("META-INF/services/java.nio.charset.spi.CharsetProvider");
+ LinkedHashSet set = new LinkedHashSet();
+ set.add(provider());
+ while (en.hasMoreElements())
+ {
+ BufferedReader rdr = new BufferedReader(new InputStreamReader
+ (((URL) (en.nextElement())).openStream()));
+ while (true)
+ {
+ String s = rdr.readLine();
+ if (s == null)
+ break;
+ CharsetProvider p =
+ (CharsetProvider) ((Class.forName(s)).newInstance());
+ set.add(p);
+ }
+ }
+
+ providers = new CharsetProvider[set.size()];
+ set.toArray(providers);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ return providers;
+ }
+
+ public final String name ()
+ {
+ return canonicalName;
+ }
+
+ public final Set aliases ()
+ {
+ if (aliases == null)
+ return Collections.EMPTY_SET;
+
+ // should we cache the aliasSet instead?
+ int n = aliases.length;
+ HashSet aliasSet = new HashSet (n);
+ for (int i = 0; i < n; ++i)
+ aliasSet.add (aliases[i]);
+ return Collections.unmodifiableSet (aliasSet);
+ }
+
+ public String displayName ()
+ {
+ return canonicalName;
+ }
+
+ public String displayName (Locale locale)
+ {
+ return canonicalName;
+ }
+
+ public final boolean isRegistered ()
+ {
+ return (!canonicalName.startsWith ("x-")
+ && !canonicalName.startsWith ("X-"));
+ }
+
+ public abstract boolean contains (Charset cs);
+
+ public abstract CharsetDecoder newDecoder ();
+
+ public abstract CharsetEncoder newEncoder ();
+
+ public boolean canEncode ()
+ {
+ return true;
+ }
+
+ // NB: This implementation serializes different threads calling
+ // Charset.encode(), a potential performance problem. It might
+ // be better to remove the cache, or use ThreadLocal to cache on
+ // a per-thread basis.
+ public final synchronized ByteBuffer encode (CharBuffer cb)
+ {
+ try
+ {
+ if (cachedEncoder == null)
+ {
+ cachedEncoder = newEncoder ()
+ .onMalformedInput (CodingErrorAction.REPLACE)
+ .onUnmappableCharacter (CodingErrorAction.REPLACE);
+ } else
+ cachedEncoder.reset();
+ return cachedEncoder.encode (cb);
+ }
+ catch (CharacterCodingException e)
+ {
+ throw new AssertionError (e);
+ }
+ }
+
+ public final ByteBuffer encode (String str)
+ {
+ return encode (CharBuffer.wrap (str));
+ }
+
+ // NB: This implementation serializes different threads calling
+ // Charset.decode(), a potential performance problem. It might
+ // be better to remove the cache, or use ThreadLocal to cache on
+ // a per-thread basis.
+ public final synchronized CharBuffer decode (ByteBuffer bb)
+ {
+ try
+ {
+ if (cachedDecoder == null)
+ {
+ cachedDecoder = newDecoder ()
+ .onMalformedInput (CodingErrorAction.REPLACE)
+ .onUnmappableCharacter (CodingErrorAction.REPLACE);
+ } else
+ cachedDecoder.reset();
+
+ return cachedDecoder.decode (bb);
+ }
+ catch (CharacterCodingException e)
+ {
+ throw new AssertionError (e);
+ }
+ }
+
+ public final int compareTo (Object ob)
+ {
+ return canonicalName.compareToIgnoreCase (((Charset) ob).canonicalName);
+ }
+
+ public final int hashCode ()
+ {
+ return canonicalName.hashCode ();
+ }
+
+ public final boolean equals (Object ob)
+ {
+ if (ob instanceof Charset)
+ return canonicalName.equalsIgnoreCase (((Charset) ob).canonicalName);
+ else
+ return false;
+ }
+
+ public final String toString ()
+ {
+ return canonicalName;
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/CharsetDecoder.java b/libjava/classpath/java/nio/charset/CharsetDecoder.java
new file mode 100644
index 00000000000..c86f1c8a4ad
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/CharsetDecoder.java
@@ -0,0 +1,317 @@
+/* CharsetDecoder.java --
+ Copyright (C) 2002 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.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+/**
+ * @author Jesse Rosenstock
+ * @since 1.4
+ */
+public abstract class CharsetDecoder
+{
+ private static final int STATE_RESET = 0;
+ private static final int STATE_CODING = 1;
+ private static final int STATE_END = 2;
+ private static final int STATE_FLUSHED = 3;
+
+ private static final String DEFAULT_REPLACEMENT = "\uFFFD";
+
+ private final Charset charset;
+ private final float averageCharsPerByte;
+ private final float maxCharsPerByte;
+ private String replacement;
+
+ private int state = STATE_RESET;
+
+ private CodingErrorAction malformedInputAction
+ = CodingErrorAction.REPORT;
+ private CodingErrorAction unmappableCharacterAction
+ = CodingErrorAction.REPORT;
+
+ private CharsetDecoder (Charset cs, float averageCharsPerByte,
+ float maxCharsPerByte, String replacement)
+ {
+ if (averageCharsPerByte <= 0.0f)
+ throw new IllegalArgumentException ("Non-positive averageCharsPerByte");
+ if (maxCharsPerByte <= 0.0f)
+ throw new IllegalArgumentException ("Non-positive maxCharsPerByte");
+
+ this.charset = cs;
+ this.averageCharsPerByte
+ = averageCharsPerByte;
+ this.maxCharsPerByte
+ = maxCharsPerByte;
+ this.replacement = replacement;
+ implReplaceWith (replacement);
+ }
+
+ protected CharsetDecoder (Charset cs, float averageCharsPerByte,
+ float maxCharsPerByte)
+ {
+ this (cs, averageCharsPerByte, maxCharsPerByte, DEFAULT_REPLACEMENT);
+ }
+
+ public final float averageCharsPerByte ()
+ {
+ return averageCharsPerByte;
+ }
+
+ public final Charset charset ()
+ {
+ return charset;
+ }
+
+ public final CharBuffer decode (ByteBuffer in)
+ throws CharacterCodingException
+ {
+ // XXX: Sun's Javadoc seems to contradict itself saying an
+ // IllegalStateException is thrown "if a decoding operation is already
+ // in progress" and also that "it resets this Decoder".
+ // Should we check to see that the state is reset, or should we
+ // call reset()?
+ if (state != STATE_RESET)
+ throw new IllegalStateException ();
+
+ // REVIEW: Using max instead of average may allocate a very large
+ // buffer. Maybe we should do something more efficient?
+ int remaining = in.remaining ();
+ int n = (int) (remaining * maxCharsPerByte ());
+ CharBuffer out = CharBuffer.allocate (n);
+
+ if (remaining == 0)
+ {
+ state = STATE_FLUSHED;
+ return out;
+ }
+
+ CoderResult cr = decode (in, out, true);
+ if (cr.isError ())
+ cr.throwException ();
+
+ cr = flush (out);
+ if (cr.isError ())
+ cr.throwException ();
+
+ reset();
+ out.flip ();
+
+ // Unfortunately, resizing the actual charbuffer array is required.
+ char[] resized = new char[out.remaining()];
+ out.get(resized);
+ return CharBuffer.wrap(resized);
+ }
+
+ public final CoderResult decode (ByteBuffer in, CharBuffer out,
+ boolean endOfInput)
+ {
+ int newState = endOfInput ? STATE_END : STATE_CODING;
+ // XXX: Need to check for "previous step was an invocation [not] of
+ // this method with a value of true for the endOfInput parameter but
+ // a return value indicating an incomplete decoding operation"
+ // XXX: We will not check the previous return value, just
+ // that the previous call passed true for endOfInput
+ if (state != STATE_RESET && state != STATE_CODING
+ && !(endOfInput && state == STATE_END))
+ throw new IllegalStateException ();
+ state = newState;
+
+ for (;;)
+ {
+ CoderResult cr;
+ try
+ {
+ cr = decodeLoop (in, out);
+ }
+ catch (RuntimeException e)
+ {
+ throw new CoderMalfunctionError (e);
+ }
+
+ if (cr.isOverflow ())
+ return cr;
+
+ if (cr.isUnderflow ())
+ {
+ if (endOfInput && in.hasRemaining ())
+ cr = CoderResult.malformedForLength (in.remaining ());
+ else
+ return cr;
+ }
+
+ CodingErrorAction action = cr.isMalformed ()
+ ? malformedInputAction
+ : unmappableCharacterAction;
+
+ if (action == CodingErrorAction.REPORT)
+ return cr;
+
+ if (action == CodingErrorAction.REPLACE)
+ {
+ if (out.remaining () < replacement.length ())
+ return CoderResult.OVERFLOW;
+ out.put (replacement);
+ }
+
+ in.position (in.position () + cr.length ());
+ }
+ }
+
+ protected abstract CoderResult decodeLoop (ByteBuffer in, CharBuffer out);
+
+ public Charset detectedCharset ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public final CoderResult flush (CharBuffer out)
+ {
+ // It seems weird that you can flush after reset, but Sun's javadoc
+ // says an IllegalStateException is thrown "If the previous step of the
+ // current decoding operation was an invocation neither of the reset
+ // method nor ... of the three-argument decode method with a value of
+ // true for the endOfInput parameter."
+ // Further note that flush() only requires that there not be
+ // an IllegalStateException if the previous step was a call to
+ // decode with true as the last argument. It does not require
+ // that the call succeeded. decode() does require that it succeeded.
+ // XXX: test this to see if reality matches javadoc
+ if (state != STATE_RESET && state != STATE_END)
+ throw new IllegalStateException ();
+
+ state = STATE_FLUSHED;
+ return implFlush (out);
+ }
+
+ protected CoderResult implFlush (CharBuffer out)
+ {
+ return CoderResult.UNDERFLOW;
+ }
+
+ public final CharsetDecoder onMalformedInput (CodingErrorAction newAction)
+ {
+ if (newAction == null)
+ throw new IllegalArgumentException ("Null action");
+
+ malformedInputAction = newAction;
+ implOnMalformedInput (newAction);
+ return this;
+ }
+
+ protected void implOnMalformedInput (CodingErrorAction newAction)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implOnUnmappableCharacter (CodingErrorAction newAction)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implReplaceWith (String newReplacement)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implReset ()
+ {
+ // default implementation does nothing
+ }
+
+ public boolean isAutoDetecting ()
+ {
+ return false;
+ }
+
+ public boolean isCharsetDetected ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public CodingErrorAction malformedInputAction ()
+ {
+ return malformedInputAction;
+ }
+
+ public final float maxCharsPerByte ()
+ {
+ return maxCharsPerByte;
+ }
+
+ public final CharsetDecoder onUnmappableCharacter
+ (CodingErrorAction newAction)
+ {
+ if (newAction == null)
+ throw new IllegalArgumentException ("Null action");
+
+ unmappableCharacterAction = newAction;
+ implOnUnmappableCharacter (newAction);
+ return this;
+ }
+
+ public final String replacement ()
+ {
+ return replacement;
+ }
+
+ public final CharsetDecoder replaceWith (String newReplacement)
+ {
+ if (newReplacement == null)
+ throw new IllegalArgumentException ("Null replacement");
+ if (newReplacement.length () == 0)
+ throw new IllegalArgumentException ("Empty replacement");
+ // XXX: what about maxCharsPerByte?
+
+ this.replacement = newReplacement;
+ implReplaceWith (newReplacement);
+ return this;
+ }
+
+ public final CharsetDecoder reset ()
+ {
+ state = STATE_RESET;
+ implReset ();
+ return this;
+ }
+
+ public CodingErrorAction unmappableCharacterAction ()
+ {
+ return unmappableCharacterAction;
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/CharsetEncoder.java b/libjava/classpath/java/nio/charset/CharsetEncoder.java
new file mode 100644
index 00000000000..932fe355df9
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/CharsetEncoder.java
@@ -0,0 +1,369 @@
+/* CharsetEncoder.java --
+ Copyright (C) 2002 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.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+/**
+ * @author Jesse Rosenstock
+ * @since 1.4
+ */
+public abstract class CharsetEncoder
+{
+ private static final int STATE_RESET = 0;
+ private static final int STATE_CODING = 1;
+ private static final int STATE_END = 2;
+ private static final int STATE_FLUSHED = 3;
+
+ private static final byte[] DEFAULT_REPLACEMENT = {(byte)'?'};
+
+ private final Charset charset;
+ private final float averageBytesPerChar;
+ private final float maxBytesPerChar;
+ private byte[] replacement;
+
+ private int state = STATE_RESET;
+
+ private CodingErrorAction malformedInputAction
+ = CodingErrorAction.REPORT;
+ private CodingErrorAction unmappableCharacterAction
+ = CodingErrorAction.REPORT;
+
+ protected CharsetEncoder (Charset cs, float averageBytesPerChar,
+ float maxBytesPerChar)
+ {
+ this (cs, averageBytesPerChar, maxBytesPerChar, DEFAULT_REPLACEMENT);
+ }
+
+ protected CharsetEncoder (Charset cs, float averageBytesPerChar,
+ float maxBytesPerChar, byte[] replacement)
+ {
+ if (averageBytesPerChar <= 0.0f)
+ throw new IllegalArgumentException ("Non-positive averageBytesPerChar");
+ if (maxBytesPerChar <= 0.0f)
+ throw new IllegalArgumentException ("Non-positive maxBytesPerChar");
+
+ this.charset = cs;
+ this.averageBytesPerChar
+ = averageBytesPerChar;
+ this.maxBytesPerChar
+ = maxBytesPerChar;
+ this.replacement = replacement;
+ implReplaceWith (replacement);
+ }
+
+ public final float averageBytesPerChar ()
+ {
+ return averageBytesPerChar;
+ }
+
+ public boolean canEncode (char c)
+ {
+ CharBuffer cb = CharBuffer.allocate (1).put (c);
+ cb.flip ();
+ return canEncode (cb);
+ }
+
+ public boolean canEncode (CharSequence cs)
+ {
+ CharBuffer cb;
+ if (cs instanceof CharBuffer)
+ cb = ((CharBuffer) cs).duplicate ();
+ else
+ cb = CharBuffer.wrap (cs);
+ return canEncode (cb);
+ }
+
+ private boolean canEncode (CharBuffer cb)
+ {
+ // It is an error if a coding operation is "in progress"
+ // I take that to mean the state is not reset or flushed.
+ // XXX: check "in progress" everywhere
+ if (state == STATE_FLUSHED)
+ reset ();
+ else if (state != STATE_RESET)
+ throw new IllegalStateException ();
+
+ CodingErrorAction oldMalformedInputAction = malformedInputAction;
+ CodingErrorAction oldUnmappableCharacterAction
+ = unmappableCharacterAction;
+
+ try
+ {
+ if (oldMalformedInputAction != CodingErrorAction.REPORT)
+ onMalformedInput (CodingErrorAction.REPORT);
+ if (oldUnmappableCharacterAction != CodingErrorAction.REPORT)
+ onUnmappableCharacter (CodingErrorAction.REPORT);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ finally
+ {
+ if (oldMalformedInputAction != CodingErrorAction.REPORT)
+ onMalformedInput (oldMalformedInputAction);
+ if (oldUnmappableCharacterAction != CodingErrorAction.REPORT)
+ onUnmappableCharacter (oldUnmappableCharacterAction);
+ }
+
+ return true;
+ }
+
+ public final Charset charset ()
+ {
+ return charset;
+ }
+
+ public final ByteBuffer encode (CharBuffer in)
+ throws CharacterCodingException
+ {
+ // XXX: Sun's Javadoc seems to contradict itself saying an
+ // IllegalStateException is thrown "if a decoding operation is already
+ // in progress" and also that "it resets this Encoder".
+ // Should we check to see that the state is reset, or should we
+ // call reset()?
+ if (state != STATE_RESET)
+ throw new IllegalStateException ();
+
+ // REVIEW: Using max instead of average may allocate a very large
+ // buffer. Maybe we should do something more efficient?
+ int remaining = in.remaining ();
+ int n = (int) (remaining * maxBytesPerChar ());
+ ByteBuffer out = ByteBuffer.allocate (n);
+
+ if (remaining == 0)
+ {
+ state = STATE_FLUSHED;
+ return out;
+ }
+
+ CoderResult cr = encode (in, out, true);
+ if (cr.isError ())
+ cr.throwException ();
+
+ cr = flush (out);
+ if (cr.isError ())
+ cr.throwException ();
+
+ out.flip ();
+
+ // Unfortunately, resizing the actual bytebuffer array is required.
+ byte[] resized = new byte[out.remaining()];
+ out.get(resized);
+ return ByteBuffer.wrap(resized);
+ }
+
+ public final CoderResult encode (CharBuffer in, ByteBuffer out,
+ boolean endOfInput)
+ {
+ int newState = endOfInput ? STATE_END : STATE_CODING;
+ // XXX: Need to check for "previous step was an invocation [not] of
+ // this method with a value of true for the endOfInput parameter but
+ // a return value indicating an incomplete decoding operation"
+ // XXX: We will not check the previous return value, just
+ // that the previous call passed true for endOfInput
+ if (state != STATE_RESET && state != STATE_CODING
+ && !(endOfInput && state == STATE_END))
+ throw new IllegalStateException ();
+ state = newState;
+
+ for (;;)
+ {
+ CoderResult cr;
+ try
+ {
+ cr = encodeLoop (in, out);
+ }
+ catch (RuntimeException e)
+ {
+ throw new CoderMalfunctionError (e);
+ }
+
+ if (cr.isOverflow ())
+ return cr;
+
+ if (cr.isUnderflow ())
+ {
+ if (endOfInput && in.hasRemaining ())
+ cr = CoderResult.malformedForLength (in.remaining ());
+ else
+ return cr;
+ }
+
+ CodingErrorAction action = cr.isMalformed ()
+ ? malformedInputAction
+ : unmappableCharacterAction;
+
+ if (action == CodingErrorAction.REPORT)
+ return cr;
+
+ if (action == CodingErrorAction.REPLACE)
+ {
+ if (out.remaining () < replacement.length)
+ return CoderResult.OVERFLOW;
+ out.put (replacement);
+ }
+
+ in.position (in.position () + cr.length ());
+ }
+ }
+
+ protected abstract CoderResult encodeLoop (CharBuffer in, ByteBuffer out);
+
+ public final CoderResult flush (ByteBuffer out)
+ {
+ // It seems weird that you can flush after reset, but Sun's javadoc
+ // says an IllegalStateException is thrown "If the previous step of the
+ // current decoding operation was an invocation neither of the reset
+ // method nor ... of the three-argument encode method with a value of
+ // true for the endOfInput parameter."
+ // Further note that flush() only requires that there not be
+ // an IllegalStateException if the previous step was a call to
+ // encode with true as the last argument. It does not require
+ // that the call succeeded. encode() does require that it succeeded.
+ // XXX: test this to see if reality matches javadoc
+ if (state != STATE_RESET && state != STATE_END)
+ throw new IllegalStateException ();
+
+ state = STATE_FLUSHED;
+ return implFlush (out);
+ }
+
+ protected CoderResult implFlush (ByteBuffer out)
+ {
+ return CoderResult.UNDERFLOW;
+ }
+
+ protected void implOnMalformedInput (CodingErrorAction newAction)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implOnUnmappableCharacter (CodingErrorAction newAction)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implReplaceWith (byte[] newReplacement)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implReset ()
+ {
+ // default implementation does nothing
+ }
+
+ public boolean isLegalReplacement (byte[] replacement)
+ {
+ // TODO: cache the decoder
+ // error actions will be REPORT after construction
+ CharsetDecoder decoder = charset.newDecoder ();
+ ByteBuffer bb = ByteBuffer.wrap (replacement);
+ CharBuffer cb
+ = CharBuffer.allocate ((int) (replacement.length
+ * decoder.maxCharsPerByte ()));
+ return !decoder.decode (bb, cb, true).isError ();
+ }
+
+ public CodingErrorAction malformedInputAction ()
+ {
+ return malformedInputAction;
+ }
+
+ public final float maxBytesPerChar ()
+ {
+ return maxBytesPerChar;
+ }
+
+ public final CharsetEncoder onMalformedInput (CodingErrorAction newAction)
+ {
+ if (newAction == null)
+ throw new IllegalArgumentException ("Null action");
+
+ malformedInputAction = newAction;
+ implOnMalformedInput (newAction);
+ return this;
+ }
+
+ public CodingErrorAction unmappableCharacterAction ()
+ {
+ return unmappableCharacterAction;
+ }
+
+ public final CharsetEncoder onUnmappableCharacter
+ (CodingErrorAction newAction)
+ {
+ if (newAction == null)
+ throw new IllegalArgumentException ("Null action");
+
+ unmappableCharacterAction = newAction;
+ implOnUnmappableCharacter (newAction);
+ return this;
+ }
+
+ public final byte[] replacement ()
+ {
+ return replacement;
+ }
+
+ public final CharsetEncoder replaceWith (byte[] newReplacement)
+ {
+ if (newReplacement == null)
+ throw new IllegalArgumentException ("Null replacement");
+ if (newReplacement.length == 0)
+ throw new IllegalArgumentException ("Empty replacement");
+ // XXX: what about maxBytesPerChar?
+
+ if (!isLegalReplacement (newReplacement))
+ throw new IllegalArgumentException ("Illegal replacement");
+
+ this.replacement = newReplacement;
+ implReplaceWith (newReplacement);
+ return this;
+ }
+
+ public final CharsetEncoder reset ()
+ {
+ state = STATE_RESET;
+ implReset ();
+ return this;
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/CoderMalfunctionError.java b/libjava/classpath/java/nio/charset/CoderMalfunctionError.java
new file mode 100644
index 00000000000..08294cafb20
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/CoderMalfunctionError.java
@@ -0,0 +1,52 @@
+/* CoderMalfunctionError.java --
+ Copyright (C) 2002 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.nio.charset;
+
+/**
+ * @since 1.4
+ */
+public class CoderMalfunctionError extends Error
+{
+ /**
+ * Creates the error
+ */
+ public CoderMalfunctionError(Exception cause)
+ {
+ super (cause);
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/CoderResult.java b/libjava/classpath/java/nio/charset/CoderResult.java
new file mode 100644
index 00000000000..664215d9a68
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/CoderResult.java
@@ -0,0 +1,189 @@
+/* CoderResult.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.charset;
+
+import java.lang.ref.WeakReference;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.util.HashMap;
+
+/**
+ * @author Jesse Rosenstock
+ * @since 1.4
+ */
+public class CoderResult
+{
+ private static final int TYPE_MALFORMED = 0;
+ private static final int TYPE_OVERFLOW = 1;
+ private static final int TYPE_UNDERFLOW = 2;
+ private static final int TYPE_UNMAPPABLE = 3;
+
+ public static final CoderResult OVERFLOW
+ = new CoderResult (TYPE_OVERFLOW, 0);
+ public static final CoderResult UNDERFLOW
+ = new CoderResult (TYPE_UNDERFLOW, 0);
+
+ private static final String[] names
+ = { "MALFORMED", "OVERFLOW", "UNDERFLOW", "UNMAPPABLE" };
+
+ private static final Cache malformedCache
+ = new Cache ()
+ {
+ protected CoderResult make (int length)
+ {
+ return new CoderResult (TYPE_MALFORMED, length);
+ }
+ };
+
+ private static final Cache unmappableCache
+ = new Cache ()
+ {
+ protected CoderResult make (int length)
+ {
+ return new CoderResult (TYPE_UNMAPPABLE, length);
+ }
+ };
+
+ private final int type;
+ private final int length;
+
+ // Package-private to avoid a trampoline constructor.
+ CoderResult (int type, int length)
+ {
+ this.type = type;
+ this.length = length;
+ }
+
+ public boolean isError ()
+ {
+ return length > 0;
+ }
+
+ public boolean isMalformed ()
+ {
+ return type == TYPE_MALFORMED;
+ }
+
+ public boolean isOverflow ()
+ {
+ return type == TYPE_OVERFLOW;
+ }
+
+ public boolean isUnderflow ()
+ {
+ return type == TYPE_UNDERFLOW;
+ }
+
+ public boolean isUnmappable ()
+ {
+ return type == TYPE_UNMAPPABLE;
+ }
+
+ public int length ()
+ {
+ if (length <= 0)
+ throw new UnsupportedOperationException ();
+ else
+ return length;
+ }
+
+ public static CoderResult malformedForLength (int length)
+ {
+ return malformedCache.get (length);
+ }
+
+ public void throwException ()
+ throws CharacterCodingException
+ {
+ switch (type)
+ {
+ case TYPE_MALFORMED:
+ throw new MalformedInputException (length);
+ case TYPE_OVERFLOW:
+ throw new BufferOverflowException ();
+ case TYPE_UNDERFLOW:
+ throw new BufferUnderflowException ();
+ case TYPE_UNMAPPABLE:
+ throw new UnmappableCharacterException (length);
+ }
+ }
+
+ public String toString ()
+ {
+ String name = names[type];
+ return (length > 0) ? name + '[' + length + ']' : name;
+ }
+
+ public static CoderResult unmappableForLength (int length)
+ {
+ return unmappableCache.get (length);
+ }
+
+ private abstract static class Cache
+ {
+ private final HashMap cache;
+
+ // Package-private to avoid a trampoline constructor.
+ Cache ()
+ {
+ cache = new HashMap ();
+ }
+
+ // Package-private to avoid a trampoline.
+ synchronized CoderResult get (int length)
+ {
+ if (length <= 0)
+ throw new IllegalArgumentException ("Non-positive length");
+
+ Integer len = new Integer (length);
+ CoderResult cr = null;
+ Object o;
+ if ((o = cache.get (len)) != null)
+ cr = (CoderResult) ((WeakReference) o).get ();
+ if (cr == null)
+ {
+ cr = make (length);
+ cache.put (len, new WeakReference (cr));
+ }
+
+ return cr;
+ }
+
+ protected abstract CoderResult make (int length);
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/CodingErrorAction.java b/libjava/classpath/java/nio/charset/CodingErrorAction.java
new file mode 100644
index 00000000000..592c15934ac
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/CodingErrorAction.java
@@ -0,0 +1,66 @@
+/* CodingErrorAction.java --
+ Copyright (C) 2002 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.nio.charset;
+
+public class CodingErrorAction
+{
+ public static final CodingErrorAction IGNORE
+ = new CodingErrorAction("ignore");
+ public static final CodingErrorAction REPLACE
+ = new CodingErrorAction("replace");
+ public static final CodingErrorAction REPORT
+ = new CodingErrorAction("report");
+
+ private final String name;
+
+ /**
+ * Private constructor only used to create the constant CodingErrorActions.
+ */
+ private CodingErrorAction(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * Returns the name of the CodingErrorAction.
+ */
+ public String toString ()
+ {
+ return name;
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/IllegalCharsetNameException.java b/libjava/classpath/java/nio/charset/IllegalCharsetNameException.java
new file mode 100644
index 00000000000..7baeac3234e
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/IllegalCharsetNameException.java
@@ -0,0 +1,73 @@
+/* IllegalCharsetNameException.java --
+ Copyright (C) 2002 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.nio.charset;
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class IllegalCharsetNameException extends IllegalArgumentException
+{
+ /**
+ * Compatible with JDK 1.4+
+ */
+ private static final long serialVersionUID = 1457525358470002989L;
+
+ private String charsetName;
+
+ /**
+ * Creates the exception
+ *
+ * @param charsetName name of the illegal charset
+ */
+ public IllegalCharsetNameException (String charsetName)
+ {
+ super ();
+ this.charsetName = charsetName;
+ }
+
+ /**
+ * Retrieves the illegal charset name
+ *
+ * @return the illegal charset name
+ */
+ public String getCharsetName ()
+ {
+ return charsetName;
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/MalformedInputException.java b/libjava/classpath/java/nio/charset/MalformedInputException.java
new file mode 100644
index 00000000000..0beceb40cb3
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/MalformedInputException.java
@@ -0,0 +1,77 @@
+/* MalformedInputException.java --
+ Copyright (C) 2002 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.nio.charset;
+
+/**
+ * @since 1.4
+ */
+public class MalformedInputException extends CharacterCodingException
+{
+ private int inputLength;
+
+ /**
+ * Creates the exception
+ *
+ * @param inputLength the position of malformed input in the input stream
+ */
+ public MalformedInputException (int inputLength)
+ {
+ super ();
+ this.inputLength = inputLength;
+ }
+
+ /**
+ * Retrieves the position of the malformed input in the input stream.
+ *
+ * @return the position
+ */
+ public int getInputLength ()
+ {
+ return inputLength;
+ }
+
+ /**
+ * Returns the detail message string of this throwable
+ *
+ * @return the message
+ */
+ public String getMessage ()
+ {
+ return "Input length = " + inputLength;
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/UnmappableCharacterException.java b/libjava/classpath/java/nio/charset/UnmappableCharacterException.java
new file mode 100644
index 00000000000..71906510849
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/UnmappableCharacterException.java
@@ -0,0 +1,71 @@
+/* UnmappableCharacterException.java --
+ Copyright (C) 2002 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.nio.charset;
+
+/**
+ * @since 1.4
+ */
+public class UnmappableCharacterException extends CharacterCodingException
+{
+ private int inputLength;
+
+ /**
+ * Creates the exception
+ */
+ public UnmappableCharacterException (int inputLength)
+ {
+ super ();
+ this.inputLength = inputLength;
+ }
+
+ /**
+ * Retrieves the illegal charset name
+ */
+ public int getInputLength ()
+ {
+ return inputLength;
+ }
+
+ /**
+ * Returns the detail message string of this throwable
+ */
+ public String getMessage ()
+ {
+ return "Input length = " + inputLength;
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/UnsupportedCharsetException.java b/libjava/classpath/java/nio/charset/UnsupportedCharsetException.java
new file mode 100644
index 00000000000..39536baa563
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/UnsupportedCharsetException.java
@@ -0,0 +1,69 @@
+/* UnsupportedCharsetException.java --
+ Copyright (C) 2002 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.nio.charset;
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public class UnsupportedCharsetException extends IllegalArgumentException
+{
+ /**
+ * Compatible with JDK 1.4+
+ */
+ private static final long serialVersionUID = 1490765524727386367L;
+
+ String charsetName;
+
+ /**
+ * Creates the exception
+ */
+ public UnsupportedCharsetException (String charsetName)
+ {
+ super ();
+ this.charsetName = charsetName;
+ }
+
+ /**
+ * Retrieves the illegal charset name
+ */
+ public String getCharsetName ()
+ {
+ return charsetName;
+ }
+}
diff --git a/libjava/classpath/java/nio/charset/package.html b/libjava/classpath/java/nio/charset/package.html
new file mode 100644
index 00000000000..acc7c020333
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.nio.charset package.
+ Copyright (C) 2002 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 - java.nio.charset</title></head>
+
+<body>
+<p>Classes to manipulate, encode and decode different character sets from
+and to bytes.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/nio/charset/spi/CharsetProvider.java b/libjava/classpath/java/nio/charset/spi/CharsetProvider.java
new file mode 100644
index 00000000000..f0d40ab8591
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/spi/CharsetProvider.java
@@ -0,0 +1,91 @@
+/* CharsetProvider.java -- charset service provider interface
+ Copyright (C) 2002 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.nio.charset.spi;
+
+import java.nio.charset.Charset;
+import java.util.Iterator;
+
+
+/**
+ * This class allows an implementor to provide additional character sets. The
+ * subclass must have a nullary constructor, and be attached to charset
+ * implementation classes. These extensions are loaded via the context class
+ * loader. To provide the charset extension, all files named
+ * <code>META-INF/services/java.nio.charset.spi.CharsetProvider</code> are
+ * read from the classpath. Each one should be a UTF-8 encoded list of
+ * fully-qualified names of concrete subclasses of this class; whitespace is
+ * ignored, and '#' starts comments. Duplicates are ignored. The
+ * implementations must be accessible to the classloader that requests them.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Charset
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class CharsetProvider
+{
+ /**
+ * Initialize a new charset provider. This performs a security check on
+ * RuntimePermission("charsetProvider").
+ *
+ * @throws SecurityException if building a new set is not allowed
+ */
+ protected CharsetProvider()
+ {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkPermission(new RuntimePermission("charsetProvider"));
+ }
+
+ /**
+ * Returns an iterator over the charsets defined by this provider.
+ *
+ * @return the iterator
+ * @see Charset#availableCharsets()
+ */
+ public abstract Iterator charsets();
+
+ /**
+ * Returns the named charset, by canonical name or alias.
+ *
+ * @param name the name of the character
+ *
+ * @return the charset, or null if not supported
+ */
+ public abstract Charset charsetForName(String name);
+} // class CharsetProvider
diff --git a/libjava/classpath/java/nio/charset/spi/package.html b/libjava/classpath/java/nio/charset/spi/package.html
new file mode 100644
index 00000000000..dd47a250be7
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/spi/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.nio.charset.spi package.
+ Copyright (C) 2002 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 - java.nio.charset.spi</title></head>
+
+<body>
+<p>Classes to provide new character sets.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/nio/class-dependencies.conf b/libjava/classpath/java/nio/class-dependencies.conf
new file mode 100644
index 00000000000..4fbf75eb1ce
--- /dev/null
+++ b/libjava/classpath/java/nio/class-dependencies.conf
@@ -0,0 +1,58 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+# end of file
diff --git a/libjava/classpath/java/nio/package.html b/libjava/classpath/java/nio/package.html
new file mode 100644
index 00000000000..274498be3ff
--- /dev/null
+++ b/libjava/classpath/java/nio/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.nio package.
+ Copyright (C) 2002 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 - java.nio</title></head>
+
+<body>
+<p>Abstract classes for manipulating buffers of different primitive types.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/rmi/AccessException.java b/libjava/classpath/java/rmi/AccessException.java
new file mode 100644
index 00000000000..b470780046c
--- /dev/null
+++ b/libjava/classpath/java/rmi/AccessException.java
@@ -0,0 +1,76 @@
+/* AccessException.java -- thrown if the caller does not have access
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown to indicate that the caller does not have permission to access
+ * certain data, such as <code>bind</code> in an ActivationSystem.
+ *
+ * @author unknown
+ * @see Naming
+ * @see ActivationSystem
+ * @since 1.1
+ */
+public class AccessException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 6314925228044966088l;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public AccessException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public AccessException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/AlreadyBoundException.java b/libjava/classpath/java/rmi/AlreadyBoundException.java
new file mode 100644
index 00000000000..091c0ee5862
--- /dev/null
+++ b/libjava/classpath/java/rmi/AlreadyBoundException.java
@@ -0,0 +1,73 @@
+/* AlreadyBoundException.java -- thrown if a binding is already bound
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown on an attempt to bind an object in the registry that is already
+ * bound.
+ *
+ * @author unknown
+ * @see Naming#bind(String, Remote)
+ * @see Registry#bind(String, Remote)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class AlreadyBoundException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 9218657361741657110L;
+
+ /**
+ * Create an exception with no message.
+ */
+ public AlreadyBoundException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public AlreadyBoundException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/rmi/ConnectException.java b/libjava/classpath/java/rmi/ConnectException.java
new file mode 100644
index 00000000000..dc3abd19741
--- /dev/null
+++ b/libjava/classpath/java/rmi/ConnectException.java
@@ -0,0 +1,74 @@
+/* ConnectException.java -- thrown if a connection is refused
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown if a connection is refused for a remote call.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ConnectException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4863550261346652506L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ConnectException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public ConnectException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/ConnectIOException.java b/libjava/classpath/java/rmi/ConnectIOException.java
new file mode 100644
index 00000000000..dde753ad558
--- /dev/null
+++ b/libjava/classpath/java/rmi/ConnectIOException.java
@@ -0,0 +1,74 @@
+/* ConnectIOException.java -- thrown if an IO exception occurs during connect
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Wraps an I/O Exception thrown while connecting for a remote call.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ConnectIOException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -8087809532704668744L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ConnectIOException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public ConnectIOException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/MarshalException.java b/libjava/classpath/java/rmi/MarshalException.java
new file mode 100644
index 00000000000..e5c10a4bf79
--- /dev/null
+++ b/libjava/classpath/java/rmi/MarshalException.java
@@ -0,0 +1,76 @@
+/* MarshalException.java -- wraps error while marshalling parameters
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown if an exception occurs while marshalling data to send in a remote
+ * call. The call may not be retransmitted, if the "at most once" semantics
+ * are to be preserved.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class MarshalException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 6223554758134037936L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public MarshalException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public MarshalException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/MarshalledObject.java b/libjava/classpath/java/rmi/MarshalledObject.java
new file mode 100644
index 00000000000..9ec0ace0e70
--- /dev/null
+++ b/libjava/classpath/java/rmi/MarshalledObject.java
@@ -0,0 +1,113 @@
+/* MarshalledObject.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi;
+
+import gnu.java.rmi.RMIMarshalledObjectInputStream;
+import gnu.java.rmi.RMIMarshalledObjectOutputStream;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Serializable;
+
+/**
+ * FIXME - doc missing
+ */
+public final class MarshalledObject implements Serializable
+{
+ //The following fields are from Java API Documentation "Serialized form"
+ private static final long serialVersionUID = 8988374069173025854L;
+ byte[] objBytes;
+ byte[] locBytes;
+ int hash;
+
+ public MarshalledObject(Object obj) throws java.io.IOException
+ {
+ ByteArrayOutputStream objStream = new ByteArrayOutputStream();
+ RMIMarshalledObjectOutputStream stream = new RMIMarshalledObjectOutputStream(objStream);
+ stream.writeObject(obj);
+ stream.flush();
+ objBytes = objStream.toByteArray();
+ locBytes = stream.getLocBytes();
+
+ //The following algorithm of calculating hashCode is similar to String
+ hash = 0;
+ for (int i = 0; i < objBytes.length; i++)
+ hash = hash * 31 + objBytes[i];
+ if(locBytes != null)
+ for (int i = 0; i < locBytes.length; i++)
+ hash = hash * 31 + locBytes[i];
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof MarshalledObject))
+ return false;
+
+ // hashCode even differs, don't do the time-consuming comparisons
+ if (obj.hashCode() != hash)
+ return false;
+
+ MarshalledObject aobj = (MarshalledObject)obj;
+ if (objBytes == null || aobj.objBytes == null)
+ return objBytes == aobj.objBytes;
+ if (objBytes.length != aobj.objBytes.length)
+ return false;
+ for (int i = 0; i < objBytes.length; i++)
+ {
+ if (objBytes[i] != aobj.objBytes[i])
+ return false;
+ }
+ // Ignore comparison of locBytes(annotation)
+ return true;
+ }
+
+public Object get()
+ throws java.io.IOException, java.lang.ClassNotFoundException
+{
+ if(objBytes == null)
+ return null;
+ RMIMarshalledObjectInputStream stream =
+ new RMIMarshalledObjectInputStream(objBytes, locBytes);
+ return stream.readObject();
+}
+
+ public int hashCode() {
+ return hash;
+ }
+
+}
diff --git a/libjava/classpath/java/rmi/Naming.java b/libjava/classpath/java/rmi/Naming.java
new file mode 100644
index 00000000000..d48df069d8d
--- /dev/null
+++ b/libjava/classpath/java/rmi/Naming.java
@@ -0,0 +1,220 @@
+/* Naming.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+
+/**
+ * <p>
+ * The <code>Naming</code> class handles interactions with RMI registries.
+ * Each method takes a URL in <code>String</code> form, which points to
+ * the RMI registry. The scheme of the URL is irrelevant. The relevant
+ * part is:
+ * </p>
+ * <p>
+ * <code>//host:port/name</code>
+ * </p>
+ * <p>
+ * which tells the method how to locate and access the registry. The host
+ * and port are both optional, and default to `localhost' and the standard
+ * RMI registry port (1099) respectively. The name is simply a string
+ * used to refer to a particular service hosted by the registry. The
+ * registry does not attempt to interpret this further.
+ * </p>
+ * <p>
+ * RMI services are registered using one of these names, and the same name
+ * is later used by the client to lookup the service and access its methods.
+ * Registries can be shared by multiple services, or a service can create
+ * its own registry using <code>createRegistry()</code>.
+ * </p>
+ *
+ * @author Original author unknown.
+ * @author Ingo Proetel (proetel@aicas.com)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.1
+ */
+public final class Naming {
+
+ /**
+ * This class isn't intended to be instantiated.
+ */
+ private Naming() {}
+
+/**
+ * Looks for the remote object that is associated with the named service.
+ * Name and location is given in form of a URL without a scheme:
+ *
+ * <pre>
+ * //host:port/service-name
+ * </pre>
+ *
+ * The port is optional.
+ *
+ * @param name the service name and location
+ * @return Remote-object that implements the named service
+ * @throws NotBoundException if no object implements the service
+ * @throws MalformedURLException
+ * @throws RemoteException
+ */
+public static Remote lookup(String name) throws NotBoundException, MalformedURLException, RemoteException {
+ URL u = parseURL(name);
+ String serviceName = getName(u);
+ return (getRegistry(u).lookup(serviceName));
+}
+
+/**
+ * Try to bind the given object to the given service name.
+ * @param name
+ * @param obj
+ * @throws AlreadyBoundException
+ * @throws MalformedURLException
+ * @throws RemoteException
+ */
+public static void bind(String name, Remote obj) throws AlreadyBoundException, MalformedURLException, RemoteException {
+ URL u = parseURL(name);
+ String serviceName = getName(u);
+ getRegistry(u).bind(serviceName, obj);
+}
+
+/**
+ * Remove a binding for a given service name.
+ * @param name
+ * @throws RemoteException
+ * @throws NotBoundException
+ * @throws MalformedURLException
+ */
+public static void unbind(String name) throws RemoteException, NotBoundException, MalformedURLException {
+ URL u = parseURL(name);
+ String serviceName = getName(u);
+ getRegistry(u).unbind(serviceName);
+}
+
+/**
+ * Forces the binding between the given Remote-object and the given service name, even
+ * if there was already an object bound to this name.
+ * @param name
+ * @param obj
+ * @throws RemoteException
+ * @throws MalformedURLException
+ */
+public static void rebind(String name, Remote obj) throws RemoteException, MalformedURLException {
+ URL u = parseURL(name);
+ String serviceName = getName(u);
+ getRegistry(u).rebind(serviceName, obj);
+}
+
+/**
+ * Lists all services at the named registry.
+ * @param name url that specifies the registry
+ * @return list of services at the name registry
+ * @throws RemoteException
+ * @throws MalformedURLException
+ */
+public static String[] list(String name) throws RemoteException, MalformedURLException {
+ return (getRegistry(parseURL(name)).list());
+}
+
+private static Registry getRegistry(URL u) throws RemoteException {
+ if (u.getPort() == -1) {
+ return (LocateRegistry.getRegistry(u.getHost()));
+ }
+ else {
+ return (LocateRegistry.getRegistry(u.getHost(), u.getPort()));
+ }
+}
+
+ /**
+ * Parses the supplied URL and converts it to use the HTTP
+ * protocol. From an RMI perspective, the scheme is irrelevant
+ * and we want to be able to create a URL for which a handler is
+ * available.
+ *
+ * @param name the URL in String form.
+ * @throws MalformedURLException if the URL is invalid.
+ */
+ private static URL parseURL(String name)
+ throws MalformedURLException
+ {
+ try
+ {
+ URI uri = new URI(name);
+ String host = uri.getHost();
+ int port = uri.getPort();
+ String query = uri.getQuery();
+ String path = uri.getPath();
+ return new URL("http",
+ (host == null ? "localhost" : host),
+ (port == -1 ? 1099 : port),
+ uri.getPath() + (query == null ? "" : query));
+ }
+ catch (URISyntaxException e)
+ {
+ throw new MalformedURLException("The URL syntax was invalid: " +
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Checks that the URL contains a name, and removes any leading
+ * slashes.
+ *
+ * @param url the URL to check.
+ * @throws MalformedURLException if no name is specified.
+ */
+ private static String getName(URL url)
+ throws MalformedURLException
+ {
+ String filename = url.getFile();
+ if (filename.length() == 0)
+ throw new MalformedURLException("No path specified: " + url);
+ // If the filename begins with a slash we must cut it for
+ // name resolution.
+ if (filename.charAt(0) == '/')
+ return filename.substring(1);
+ return filename;
+ }
+
+}
diff --git a/libjava/classpath/java/rmi/NoSuchObjectException.java b/libjava/classpath/java/rmi/NoSuchObjectException.java
new file mode 100644
index 00000000000..69f7d6c52fb
--- /dev/null
+++ b/libjava/classpath/java/rmi/NoSuchObjectException.java
@@ -0,0 +1,68 @@
+/* NoSuchObjectException.java -- thrown if the remote object no longer exists
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown on an attempt to invoke a call on an object that no longer exists
+ * in the remote Virtual Machine. The call may be retransmitted and still
+ * obey the semantics of "at most once".
+ *
+ * @author unknown
+ * @see RemoteObject#toStub(Remote)
+ * @see UnicastRemoteObject#unexportObject(Remote, boolean)
+ * @see Activatable#unexportObject(Remote, boolean)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class NoSuchObjectException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 6619395951570472985L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NoSuchObjectException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/rmi/NotBoundException.java b/libjava/classpath/java/rmi/NotBoundException.java
new file mode 100644
index 00000000000..b8bc0a5320a
--- /dev/null
+++ b/libjava/classpath/java/rmi/NotBoundException.java
@@ -0,0 +1,75 @@
+/* NotBoundException.java -- attempt to use a registry name with no binding
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown on an attempt to lookup or unbind a registry name that has no
+ * associated binding.
+ *
+ * @author unknown
+ * @see Naming#lookup(String)
+ * @see Naming#unbind(String)
+ * @see Registry#lookup(String)
+ * @see Registry#unbind(String)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class NotBoundException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -1857741824849069317l;
+
+ /**
+ * Create an exception with no message.
+ */
+ public NotBoundException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NotBoundException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/rmi/RMISecurityException.java b/libjava/classpath/java/rmi/RMISecurityException.java
new file mode 100644
index 00000000000..a44a67e2a02
--- /dev/null
+++ b/libjava/classpath/java/rmi/RMISecurityException.java
@@ -0,0 +1,77 @@
+/* RMISecurityException.java -- deprecated version of SecurityException
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Never thrown, but originally intended to wrap a java.lang.SecurityException.
+ *
+ * @author unknown
+ * @since 1.1
+ * @deprecated use {@link SecurityException} instead
+ * @status updated to 1.4
+ */
+public class RMISecurityException extends SecurityException
+{
+ /**
+ * Compatible with JDK 1.1.
+ */
+ private static final long serialVersionUID = -8433406075740433514L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ * @deprecated no longer needed
+ */
+ public RMISecurityException(String n)
+ {
+ super(n);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ * @deprecated no longer needed
+ */
+ public RMISecurityException(String n, String a)
+ {
+ super(n);
+ }
+}
diff --git a/libjava/classpath/java/rmi/RMISecurityManager.java b/libjava/classpath/java/rmi/RMISecurityManager.java
new file mode 100644
index 00000000000..a8eb13e1a0a
--- /dev/null
+++ b/libjava/classpath/java/rmi/RMISecurityManager.java
@@ -0,0 +1,48 @@
+/* RMISecurityManager.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2003 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.rmi;
+
+/**
+ * @since 1.1
+ */
+public class RMISecurityManager extends SecurityManager
+{
+ public RMISecurityManager()
+ {
+ }
+}
diff --git a/libjava/classpath/java/rmi/Remote.java b/libjava/classpath/java/rmi/Remote.java
new file mode 100644
index 00000000000..93c8d0aa127
--- /dev/null
+++ b/libjava/classpath/java/rmi/Remote.java
@@ -0,0 +1,41 @@
+/* Remote.java
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi;
+
+public interface Remote {
+}
diff --git a/libjava/classpath/java/rmi/RemoteException.java b/libjava/classpath/java/rmi/RemoteException.java
new file mode 100644
index 00000000000..cbbb26299c3
--- /dev/null
+++ b/libjava/classpath/java/rmi/RemoteException.java
@@ -0,0 +1,127 @@
+/* RemoteException.java -- common superclass for exceptions in java.rmi
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+import java.io.IOException;
+
+/**
+ * The superclass of exceptions related to RMI (remote method invocation).
+ * Classes that implement <code>java.rmi.Remote</code> should list this
+ * exception in their throws clause.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class RemoteException extends IOException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -5148567311918794206l;
+
+ /**
+ * The cause of this exception. This pre-dates the exception chaining
+ * of Throwable; and although you can change this field, you are wiser
+ * to leave it alone.
+ *
+ * @serial the exception cause
+ */
+ public Throwable detail;
+
+ /**
+ * Create an exception with no message, and cause initialized to null.
+ */
+ public RemoteException()
+ {
+ this(null, null);
+ }
+
+ /**
+ * Create an exception with the given message, and cause initialized to null.
+ *
+ * @param s the message
+ */
+ public RemoteException(String s)
+ {
+ this(s, null);
+ }
+
+ /**
+ * Create an exception with the given message and cause.
+ *
+ * @param s the message
+ * @param ex the cause
+ */
+ public RemoteException(String s, Throwable e)
+ {
+ super(s);
+ initCause(e);
+ detail = e;
+ }
+
+ /**
+ * This method returns a message indicating what went wrong, in this
+ * format:
+ * <code>super.getMessage() + (detail == null ? ""
+ * : "; nested exception is:\n\t" + detail)</code>.
+ *
+ * @return the chained message
+ */
+ public String getMessage()
+ {
+ if (detail == this || detail == null)
+ return super.getMessage();
+ return super.getMessage() + "; nested exception is:\n\t" + detail;
+ }
+
+ /**
+ * Returns the cause of this exception. Note that this may not be the
+ * original cause, thanks to the <code>detail</code> field being public
+ * and non-final (yuck). However, to avoid violating the contract of
+ * Throwable.getCause(), this returns null if <code>detail == this</code>,
+ * as no exception can be its own cause.
+ *
+ * @return the cause
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return detail == this ? null : detail;
+ }
+}
diff --git a/libjava/classpath/java/rmi/ServerError.java b/libjava/classpath/java/rmi/ServerError.java
new file mode 100644
index 00000000000..b1a15b02e74
--- /dev/null
+++ b/libjava/classpath/java/rmi/ServerError.java
@@ -0,0 +1,64 @@
+/* ServerError.java -- wraps an error while creating the server
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Wraps any error thrown while processing the server of a remote call.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ServerError extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 8455284893909696482L;
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public ServerError(String s, Error e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/ServerException.java b/libjava/classpath/java/rmi/ServerException.java
new file mode 100644
index 00000000000..5170aa7b0b5
--- /dev/null
+++ b/libjava/classpath/java/rmi/ServerException.java
@@ -0,0 +1,74 @@
+/* ServerException.java -- wraps an exception while creating the server
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Wraps any exception thrown while processing the server of a remote call.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ServerException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -4775845313121906682l;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ServerException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public ServerException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/ServerRuntimeException.java b/libjava/classpath/java/rmi/ServerRuntimeException.java
new file mode 100644
index 00000000000..1f0813739a6
--- /dev/null
+++ b/libjava/classpath/java/rmi/ServerRuntimeException.java
@@ -0,0 +1,67 @@
+/* ServerRuntimeException.java -- wraps an exception while creating the server
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Wraps any runtime exception thrown while processing the server of a
+ * remote call. Note, this exception is no longer used.
+ *
+ * @author unknown
+ * @since 1.1
+ * @deprecated no replacement
+ * @status updated to 1.4
+ */
+public class ServerRuntimeException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1.
+ */
+ private static final long serialVersionUID = 7054464920481467219L;
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ * @deprecated no longer needed
+ */
+ public ServerRuntimeException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/StubNotFoundException.java b/libjava/classpath/java/rmi/StubNotFoundException.java
new file mode 100644
index 00000000000..2f9e0f5ff59
--- /dev/null
+++ b/libjava/classpath/java/rmi/StubNotFoundException.java
@@ -0,0 +1,77 @@
+/* StubNotFoundException.java -- thrown if a valid stub is not found
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown if a valid stub class is not found for an object when it is exported.
+ *
+ * @author unknown
+ * @see UnicastRemoteObject
+ * @see Activatable
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class StubNotFoundException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -7088199405468872373L;
+
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public StubNotFoundException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public StubNotFoundException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/UnexpectedException.java b/libjava/classpath/java/rmi/UnexpectedException.java
new file mode 100644
index 00000000000..e9e0d6a9d48
--- /dev/null
+++ b/libjava/classpath/java/rmi/UnexpectedException.java
@@ -0,0 +1,75 @@
+/* UnexpectedException.java -- an unexpected checked exception was received
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown if an unexpected checked exception was received in a remote
+ * procedure call.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class UnexpectedException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 1800467484195073863L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public UnexpectedException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public UnexpectedException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/UnknownHostException.java b/libjava/classpath/java/rmi/UnknownHostException.java
new file mode 100644
index 00000000000..e21b9944c6b
--- /dev/null
+++ b/libjava/classpath/java/rmi/UnknownHostException.java
@@ -0,0 +1,75 @@
+/* UnknownHostException.java -- wraps java.net.UnknownHostException in RMI
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown if a java.net.UnknownHostException occurs during a remote
+ * procedure call.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class UnknownHostException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -8152710247442114228L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public UnknownHostException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public UnknownHostException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/UnmarshalException.java b/libjava/classpath/java/rmi/UnmarshalException.java
new file mode 100644
index 00000000000..6567062a523
--- /dev/null
+++ b/libjava/classpath/java/rmi/UnmarshalException.java
@@ -0,0 +1,88 @@
+/* UnmarshalException.java -- wraps error while unmarshalling parameters
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi;
+
+/**
+ * Thrown if an exception occurs while unmarshalling parameters or results
+ * of a remote method call. This includes:<br><ul>
+ * <li>if an exception occurs while unmarshalling the call header</li>
+ * <li>if the protocol for the return value is invalid</li>
+ * <li>if a java.io.IOException occurs unmarshalling parameters (on the
+ * server side) or the return value (on the client side).</li>
+ * <li>if a java.lang.ClassNotFoundException occurs during unmarshalling
+ * parameters or return values</li>
+ * <li>if no skeleton can be loaded on the server-side; note that skeletons
+ * are required in the 1.1 stub protocol, but not in the 1.2 stub
+ * protocol.</li>
+ * <li>if the method hash is invalid (i.e., missing method).</li>
+ * <li>if there is a failure to create a remote reference object for a remote
+ * object's stub when it is unmarshalled.</li>
+ * </ul>
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class UnmarshalException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 594380845140740218l;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public UnmarshalException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public UnmarshalException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/activation/Activatable.java b/libjava/classpath/java/rmi/activation/Activatable.java
new file mode 100644
index 00000000000..b4c38bf61a8
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/Activatable.java
@@ -0,0 +1,105 @@
+/* Activatable.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.activation;
+
+import java.rmi.MarshalledObject;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RemoteServer;
+
+public abstract class Activatable extends RemoteServer
+{
+static final long serialVersionUID = -3120617863591563455L;
+
+protected Activatable(String location, MarshalledObject data, boolean restart, int port) throws ActivationException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+protected Activatable(String location, MarshalledObject data, boolean restart, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws ActivationException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+protected Activatable(ActivationID id, int port) throws RemoteException {
+ throw new Error("Not implemented");
+}
+
+protected Activatable(ActivationID id, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException {
+ throw new Error("Not implemented");
+}
+
+protected ActivationID getID() {
+ throw new Error("Not implemented");
+}
+
+public static Remote register(ActivationDesc desc) throws UnknownGroupException, ActivationException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+public static boolean inactive(ActivationID id) throws UnknownObjectException, ActivationException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+public static void unregister(ActivationID id) throws UnknownObjectException, ActivationException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+public static ActivationID exportObject(Remote obj, String location, MarshalledObject data, boolean restart, int port) throws ActivationException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+public static ActivationID exportObject(Remote obj, String location, MarshalledObject data, boolean restart, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws ActivationException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+public static Remote exportObject(Remote obj, ActivationID id, int port) throws RemoteException {
+ throw new Error("Not implemented");
+}
+
+public static Remote exportObject(Remote obj, ActivationID id, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException {
+ throw new Error("Not implemented");
+}
+
+public static boolean unexportObject(Remote obj, boolean force) throws NoSuchObjectException {
+ throw new Error("Not implemented");
+}
+
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivateFailedException.java b/libjava/classpath/java/rmi/activation/ActivateFailedException.java
new file mode 100644
index 00000000000..1c2e10ee3e6
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivateFailedException.java
@@ -0,0 +1,76 @@
+/* ActivateFailedException.java -- thrown when activation fails
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.activation;
+
+import java.rmi.RemoteException;
+
+/**
+ * Thrown when activation fails on a remote call to an activatable object.
+ *
+ * @author unknown
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class ActivateFailedException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 4863550261346652506L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ActivateFailedException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param ex the cause
+ */
+ public ActivateFailedException(String s, Exception ex)
+ {
+ super(s, ex);
+ }
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationDesc.java b/libjava/classpath/java/rmi/activation/ActivationDesc.java
new file mode 100644
index 00000000000..65894f808d2
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationDesc.java
@@ -0,0 +1,113 @@
+/* ActivationDecc.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.activation;
+
+import java.io.Serializable;
+import java.rmi.MarshalledObject;
+
+public final class ActivationDesc implements Serializable
+{
+ static final long serialVersionUID = 7455834104417690957L;
+
+private ActivationGroupID groupid;
+private String classname;
+private String location;
+private MarshalledObject data;
+private boolean restart;
+
+public ActivationDesc(String className, String location, MarshalledObject data) throws ActivationException {
+ this(ActivationGroup.currentGroupID(), className, location, data, false);
+}
+
+public ActivationDesc(String className, String location, MarshalledObject data, boolean restart) throws ActivationException {
+ this(ActivationGroup.currentGroupID(), className, location, data, restart);
+}
+
+public ActivationDesc(ActivationGroupID groupID, String className, String location, MarshalledObject data) {
+ this(groupID, className, location, data, false);
+}
+
+public ActivationDesc(ActivationGroupID groupID, String className, String location, MarshalledObject data, boolean restart) {
+ this.groupid = groupID;
+ this.classname = className;
+ this.location = location;
+ this.data = data;
+ this.restart = restart;
+}
+
+public ActivationGroupID getGroupID() {
+ return (groupid);
+}
+
+public String getClassName() {
+ return (classname);
+}
+
+public String getLocation() {
+ return (location);
+}
+
+public MarshalledObject getData() {
+ return (data);
+}
+
+public boolean getRestartMode() {
+ return (restart);
+}
+
+public boolean equals(Object obj) {
+ if (!(obj instanceof ActivationDesc)) {
+ return (false);
+ }
+ ActivationDesc that = (ActivationDesc)obj;
+
+ if (this.groupid.equals(that.groupid) &&
+ this.classname.equals(that.classname) &&
+ this.location.equals(that.location) &&
+ this.data.equals(that.data) &&
+ this.restart == that.restart) {
+ return (true);
+ }
+ return (false);
+}
+
+public int hashCode() {
+ return (groupid.hashCode() ^ classname.hashCode() ^ location.hashCode() ^ data.hashCode());
+}
+
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationException.java b/libjava/classpath/java/rmi/activation/ActivationException.java
new file mode 100644
index 00000000000..418f4385757
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationException.java
@@ -0,0 +1,122 @@
+/* ActivationException.java -- general Activation exception
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.activation;
+
+/**
+ * General exception class for <code>java.rmi.activation</code>.
+ *
+ * @author unknown
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class ActivationException extends Exception
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -4320118837291406071L;
+
+ /**
+ * The cause of this exception. This pre-dates the exception chaining
+ * of Throwable; and although you can change this field, you are wiser
+ * to leave it alone.
+ *
+ * @serial the exception cause
+ */
+ public Throwable detail;
+
+ /**
+ * Create an exception with no message, and cause initialized to null.
+ */
+ public ActivationException()
+ {
+ this(null, null);
+ }
+
+ /**
+ * Create an exception with the given message, and cause initialized to null.
+ *
+ * @param s the message
+ */
+ public ActivationException(String s)
+ {
+ this(s, null);
+ }
+
+ /**
+ * Create an exception with the given message and cause.
+ *
+ * @param s the message
+ * @param ex the cause
+ */
+ public ActivationException(String s, Throwable ex)
+ {
+ super(s, ex);
+ detail = ex;
+ }
+
+ /**
+ * This method returns a message indicating what went wrong, in this
+ * format:
+ * <code>super.getMessage() + (detail == null ? ""
+ * : "; nested exception is:\n\t" + detail)</code>.
+ *
+ * @return the chained message
+ */
+ public String getMessage()
+ {
+ if (detail == this || detail == null)
+ return super.getMessage();
+ return super.getMessage() + "; nested exception is:\n\t" + detail;
+ }
+
+ /**
+ * Returns the cause of this exception. Note that this may not be the
+ * original cause, thanks to the <code>detail</code> field being public
+ * and non-final (yuck). However, to avoid violating the contract of
+ * Throwable.getCause(), this returns null if <code>detail == this</code>,
+ * as no exception can be its own cause.
+ *
+ * @return the cause
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return detail == this ? null : detail;
+ }
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationGroup.java b/libjava/classpath/java/rmi/activation/ActivationGroup.java
new file mode 100644
index 00000000000..e5774a1b961
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationGroup.java
@@ -0,0 +1,85 @@
+/* ActivationGroup.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.activation;
+
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+public abstract class ActivationGroup extends UnicastRemoteObject
+ implements ActivationInstantiator
+{
+static final long serialVersionUID = -7696947875314805420L;
+
+protected ActivationGroup(ActivationGroupID groupID) throws RemoteException {
+ throw new Error("Not implemented");
+}
+
+public boolean inactiveObject(ActivationID id) throws ActivationException, UnknownObjectException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+public abstract void activeObject(ActivationID id, Remote obj) throws ActivationException, UnknownObjectException, RemoteException;
+
+public static ActivationGroup createGroup(ActivationGroupID id, ActivationGroupDesc desc, long incarnation) throws ActivationException {
+ throw new Error("Not implemented");
+}
+
+public static ActivationGroupID currentGroupID() {
+ throw new Error("Not implemented");
+}
+
+public static void setSystem(ActivationSystem system) throws ActivationException {
+ throw new Error("Not implemented");
+}
+
+public static ActivationSystem getSystem() throws ActivationException {
+ throw new Error("Not implemented");
+}
+
+protected void activeObject(ActivationID id, MarshalledObject mobj) throws ActivationException, UnknownObjectException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+protected void inactiveGroup() throws UnknownGroupException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationGroupDesc.java b/libjava/classpath/java/rmi/activation/ActivationGroupDesc.java
new file mode 100644
index 00000000000..35b546e3294
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationGroupDesc.java
@@ -0,0 +1,134 @@
+/* ActivationGroupDesc.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.activation;
+
+import java.io.Serializable;
+import java.rmi.MarshalledObject;
+import java.util.Properties;
+
+public final class ActivationGroupDesc implements Serializable
+{
+ static final long serialVersionUID = -4936225423168276595L;
+
+public static class CommandEnvironment
+ implements Serializable {
+
+static final long serialVersionUID = 6165754737887770191L;
+
+private String cmdpath;
+private String[] argv;
+
+public CommandEnvironment(String cmdpath, String[] argv) {
+ this.cmdpath = cmdpath;
+ this.argv = argv;
+}
+
+public String getCommandPath() {
+ return (cmdpath);
+}
+
+public String[] getCommandOptions() {
+ return (argv);
+}
+
+public boolean equals(Object obj) {
+ if (!(obj instanceof CommandEnvironment)) {
+ return (false);
+ }
+ CommandEnvironment that = (CommandEnvironment)obj;
+
+ if (!this.cmdpath.equals(that.cmdpath)) {
+ return (false);
+ }
+
+ int len = this.argv.length;
+ if (len != that.argv.length) {
+ return (false);
+ }
+ for (int i = 0; i < len; i++) {
+ if (!this.argv[i].equals(that.argv[i])) {
+ return (false);
+ }
+ }
+ return (true);
+}
+
+public int hashCode() {
+ return (cmdpath.hashCode()); // Not a very good hash code.
+}
+
+}
+
+public ActivationGroupDesc(Properties overrides, ActivationGroupDesc.CommandEnvironment cmd) {
+ throw new Error("Not implemented");
+}
+
+public ActivationGroupDesc(String className, String location, MarshalledObject data, Properties overrides, ActivationGroupDesc.CommandEnvironment cmd) {
+ throw new Error("Not implemented");
+}
+
+public String getClassName() {
+ throw new Error("Not implemented");
+}
+
+public String getLocation() {
+ throw new Error("Not implemented");
+}
+
+public MarshalledObject getData() {
+ throw new Error("Not implemented");
+}
+
+public Properties getPropertyOverrides() {
+ throw new Error("Not implemented");
+}
+
+public ActivationGroupDesc.CommandEnvironment getCommandEnvironment() {
+ throw new Error("Not implemented");
+}
+
+public boolean equals(Object obj) {
+ throw new Error("Not implemented");
+}
+
+public int hashCode() {
+ throw new Error("Not implemented");
+}
+
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationGroupID.java b/libjava/classpath/java/rmi/activation/ActivationGroupID.java
new file mode 100644
index 00000000000..5e0b96442e8
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationGroupID.java
@@ -0,0 +1,70 @@
+/* ActivationGroupID.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.activation;
+
+import java.io.Serializable;
+
+public class ActivationGroupID implements Serializable
+{
+ static final long serialVersionUID = -1648432278909740833L;
+
+private ActivationSystem system;
+
+public ActivationGroupID(ActivationSystem system) {
+ this.system = system;
+}
+
+public ActivationSystem getSystem() {
+ return (system);
+}
+
+public int hashCode() {
+ return (system.hashCode());
+}
+
+public boolean equals(Object obj) {
+ if (obj instanceof ActivationGroupID) {
+ ActivationGroupID that = (ActivationGroupID)obj;
+ if (this.system.equals(that.system)) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationID.java b/libjava/classpath/java/rmi/activation/ActivationID.java
new file mode 100644
index 00000000000..23ed853a478
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationID.java
@@ -0,0 +1,72 @@
+/* ActivationID.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.activation;
+
+import java.io.Serializable;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public class ActivationID implements Serializable
+{
+ static final long serialVersionUID = -4608673054848209235L;
+
+private Activator activator;
+
+public ActivationID(Activator activator) {
+ this.activator = activator;
+}
+
+public Remote activate(boolean force) throws ActivationException, UnknownObjectException, RemoteException {
+ throw new Error("Not implemented");
+}
+
+public int hashCode() {
+ return (activator.hashCode());
+}
+
+public boolean equals(Object obj) {
+ if (obj instanceof ActivationID) {
+ ActivationID that = (ActivationID)obj;
+ if (this.activator.equals(that.activator)) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationInstantiator.java b/libjava/classpath/java/rmi/activation/ActivationInstantiator.java
new file mode 100644
index 00000000000..0aceb7a4ad6
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationInstantiator.java
@@ -0,0 +1,50 @@
+/* ActivationInstantiator.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.activation;
+
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface ActivationInstantiator
+ extends Remote
+{
+ MarshalledObject newInstance (ActivationID id, ActivationDesc desc)
+ throws ActivationException, RemoteException;
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationMonitor.java b/libjava/classpath/java/rmi/activation/ActivationMonitor.java
new file mode 100644
index 00000000000..1e64257edd1
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationMonitor.java
@@ -0,0 +1,55 @@
+/* ActivationMonitor.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.activation;
+
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface ActivationMonitor extends Remote
+{
+ void inactiveObject (ActivationID id)
+ throws UnknownObjectException, RemoteException;
+
+ void activeObject (ActivationID id, MarshalledObject obj)
+ throws UnknownObjectException, RemoteException;
+
+ void inactiveGroup (ActivationGroupID id, long incarnation)
+ throws UnknownGroupException, RemoteException;
+}
diff --git a/libjava/classpath/java/rmi/activation/ActivationSystem.java b/libjava/classpath/java/rmi/activation/ActivationSystem.java
new file mode 100644
index 00000000000..4b92d40cb44
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/ActivationSystem.java
@@ -0,0 +1,78 @@
+/* ActivationSystem.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.activation;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface ActivationSystem extends Remote
+{
+ int SYSTEM_PORT = 1098;
+
+ ActivationID registerObject (ActivationDesc desc)
+ throws ActivationException, UnknownGroupException, RemoteException;
+
+ void unregisterObject (ActivationID id)
+ throws ActivationException, UnknownObjectException, RemoteException;
+
+ ActivationGroupID registerGroup (ActivationGroupDesc desc)
+ throws ActivationException, RemoteException;
+
+ ActivationMonitor activeGroup (ActivationGroupID id,
+ ActivationInstantiator group, long incarnation)
+ throws UnknownGroupException, ActivationException, RemoteException;
+
+ void unregisterGroup (ActivationGroupID id)
+ throws ActivationException, UnknownGroupException, RemoteException;
+
+ void shutdown()
+ throws RemoteException;
+
+ ActivationDesc setActivationDesc (ActivationID id, ActivationDesc desc)
+ throws ActivationException, UnknownObjectException, UnknownGroupException,
+ RemoteException;
+
+ ActivationGroupDesc setActivationGroupDesc (ActivationGroupID id,
+ ActivationGroupDesc desc)
+ throws ActivationException, UnknownGroupException, RemoteException;
+
+ ActivationDesc getActivationDesc (ActivationID id) throws ActivationException, UnknownObjectException, RemoteException;
+
+ ActivationGroupDesc getActivationGroupDesc (ActivationGroupID id) throws ActivationException, UnknownGroupException, RemoteException;
+}
diff --git a/libjava/classpath/java/rmi/activation/Activator.java b/libjava/classpath/java/rmi/activation/Activator.java
new file mode 100644
index 00000000000..2fb5a581002
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/Activator.java
@@ -0,0 +1,50 @@
+/* Activator.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.activation;
+
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Activator
+ extends Remote
+{
+ MarshalledObject activate (ActivationID id, boolean force)
+ throws ActivationException, UnknownObjectException, RemoteException;
+}
diff --git a/libjava/classpath/java/rmi/activation/UnknownGroupException.java b/libjava/classpath/java/rmi/activation/UnknownGroupException.java
new file mode 100644
index 00000000000..91890a9073d
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/UnknownGroupException.java
@@ -0,0 +1,69 @@
+/* UnknownGroupException.java -- thrown on an invalid ActivationGroupID
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.activation;
+
+/**
+ * Thrown when an <code>ActivationGroupID</code> parameter is invalid or
+ * unknown.
+ *
+ * @author unknown
+ * @see Activatable
+ * @see ActivationGroup
+ * @see ActivationID
+ * @see ActivationMonitor
+ * @see ActivationSystem
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class UnknownGroupException extends ActivationException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 7056094974750002460L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public UnknownGroupException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/rmi/activation/UnknownObjectException.java b/libjava/classpath/java/rmi/activation/UnknownObjectException.java
new file mode 100644
index 00000000000..8dbeb0e6050
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/UnknownObjectException.java
@@ -0,0 +1,69 @@
+/* UnknownObjectException.java -- thrown on an invalid ActivationID
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.activation;
+
+/**
+ * Thrown when an <code>ActivationID</code> parameter is invalid or unknown.
+ *
+ * @author unknown
+ * @see Activatable
+ * @see ActivationGroup
+ * @see ActivationID
+ * @see ActivationMonitor
+ * @see ActivationSystem
+ * @see Activator
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class UnknownObjectException extends ActivationException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 3425547551622251430L;
+
+ /**
+ * Create an exception with an error message.
+ *
+ * @param s the message
+ */
+ public UnknownObjectException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/rmi/activation/package.html b/libjava/classpath/java/rmi/activation/package.html
new file mode 100644
index 00000000000..444782dd721
--- /dev/null
+++ b/libjava/classpath/java/rmi/activation/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.rmi.activation package.
+ Copyright (C) 2002 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 - java.rmi.activation</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/rmi/dgc/DGC.java b/libjava/classpath/java/rmi/dgc/DGC.java
new file mode 100644
index 00000000000..e78ec2a3aa7
--- /dev/null
+++ b/libjava/classpath/java/rmi/dgc/DGC.java
@@ -0,0 +1,51 @@
+/* DGC.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.dgc;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.ObjID;
+
+public interface DGC extends Remote
+{
+ Lease dirty (ObjID[] ids, long sequenceNum, Lease lease)
+ throws RemoteException;
+
+ void clean (ObjID[] ids, long sequenceNum, VMID vmid, boolean strong)
+ throws RemoteException;
+}
diff --git a/libjava/classpath/java/rmi/dgc/Lease.java b/libjava/classpath/java/rmi/dgc/Lease.java
new file mode 100644
index 00000000000..d3d7f695216
--- /dev/null
+++ b/libjava/classpath/java/rmi/dgc/Lease.java
@@ -0,0 +1,67 @@
+/* Lease.java
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.dgc;
+
+import java.io.Serializable;
+
+public final class Lease
+ implements Serializable {
+
+static final long serialVersionUID = -5713411624328831948L;
+
+private VMID vmid;
+private long value;
+
+public Lease(VMID id, long duration) {
+ vmid = id;
+ value = duration;
+}
+
+public VMID getVMID() {
+ return (vmid);
+}
+
+public long getValue() {
+ return (value);
+}
+
+public String toString() {
+ return ("[" + vmid.toString() + ", " + Long.toString(value) + "]");
+}
+
+}
diff --git a/libjava/classpath/java/rmi/dgc/VMID.java b/libjava/classpath/java/rmi/dgc/VMID.java
new file mode 100644
index 00000000000..f960d9ccd79
--- /dev/null
+++ b/libjava/classpath/java/rmi/dgc/VMID.java
@@ -0,0 +1,138 @@
+/* VMID.java
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.dgc;
+
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.rmi.server.UID;
+
+public final class VMID implements Serializable
+{
+ static final long serialVersionUID = -538642295484486218L;
+
+ static final boolean areWeUnique;
+
+ static byte[] localAddr;
+
+ private byte[] addr;
+
+ private UID uid;
+
+ static
+ {
+ byte[] addr;
+ boolean awu = true;
+ try {
+ addr = InetAddress.getLocalHost().getAddress();
+ if (addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) {
+ awu = false;
+ }
+ }
+ catch (UnknownHostException _) {
+ addr = new byte[]{ 127, 0, 0, 1 };
+ awu = false;
+ }
+ localAddr = addr;
+ areWeUnique = awu;
+ }
+
+ public VMID()
+ {
+ addr = localAddr;
+ uid = new UID();
+ }
+
+ /**
+ * @deprecated
+ */
+ public static boolean isUnique ()
+ {
+ return areWeUnique;
+ }
+
+ public int hashCode ()
+ {
+ return super.hashCode();
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (!(obj instanceof VMID))
+ {
+ return false;
+ }
+
+ VMID other = (VMID) obj;
+ if (addr.length != other.addr.length)
+ {
+ return false;
+ }
+
+ for (int i = addr.length - 1; i >= 0; i--)
+ {
+ if (addr[i] != other.addr[i])
+ {
+ return false;
+ }
+ }
+
+ return uid.equals(other.uid);
+ }
+
+ public String toString ()
+ {
+ StringBuffer buf = new StringBuffer ("[VMID: ");
+
+ for (int i = 0; i < addr.length; i++)
+ {
+ if (i > 0)
+ {
+ buf.append (".");
+ }
+
+ buf.append (Integer.toString (addr [i]));
+ }
+
+ buf.append (" ");
+ buf.append (uid.toString ());
+ buf.append ("]");
+
+ return buf.toString();
+ }
+}
diff --git a/libjava/classpath/java/rmi/dgc/package.html b/libjava/classpath/java/rmi/dgc/package.html
new file mode 100644
index 00000000000..9458d4c25f9
--- /dev/null
+++ b/libjava/classpath/java/rmi/dgc/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.rmi.dgc package.
+ Copyright (C) 2002 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 - java.rmi.dgc</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/rmi/package.html b/libjava/classpath/java/rmi/package.html
new file mode 100644
index 00000000000..a7bf8502056
--- /dev/null
+++ b/libjava/classpath/java/rmi/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.rmi package.
+ Copyright (C) 2002 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 - java.rmi</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/rmi/registry/LocateRegistry.java b/libjava/classpath/java/rmi/registry/LocateRegistry.java
new file mode 100644
index 00000000000..3547a7ad0f4
--- /dev/null
+++ b/libjava/classpath/java/rmi/registry/LocateRegistry.java
@@ -0,0 +1,87 @@
+/* LocateRegistry.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.registry;
+
+import gnu.java.rmi.registry.RegistryImpl;
+import gnu.java.rmi.registry.RegistryImpl_Stub;
+import gnu.java.rmi.server.UnicastRef;
+
+import java.rmi.RemoteException;
+import java.rmi.server.ObjID;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
+import java.rmi.server.RemoteRef;
+
+public final class LocateRegistry {
+ /**
+ * This class isn't intended to be instantiated.
+ */
+ private LocateRegistry() {}
+
+public static Registry getRegistry() throws RemoteException {
+ return (getRegistry("localhost", Registry.REGISTRY_PORT));
+}
+
+public static Registry getRegistry(int port) throws RemoteException {
+ return (getRegistry("localhost", port));
+}
+
+public static Registry getRegistry(String host) throws RemoteException {
+ return (getRegistry(host, Registry.REGISTRY_PORT));
+}
+
+public static Registry getRegistry(String host, int port) throws RemoteException {
+ return (getRegistry(host, port, RMISocketFactory.getSocketFactory()));
+}
+
+public static Registry getRegistry(String host, int port, RMIClientSocketFactory csf) throws RemoteException {
+ RemoteRef ref = new UnicastRef(new ObjID(ObjID.REGISTRY_ID), host, port, csf);
+ return (new RegistryImpl_Stub(ref));
+}
+
+public static Registry createRegistry(int port) throws RemoteException {
+ return (createRegistry(port, RMISocketFactory.getSocketFactory(), RMISocketFactory.getSocketFactory()));
+}
+
+public static Registry createRegistry(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException {
+ return (new RegistryImpl(port, csf, ssf));
+}
+
+}
diff --git a/libjava/classpath/java/rmi/registry/Registry.java b/libjava/classpath/java/rmi/registry/Registry.java
new file mode 100644
index 00000000000..6cd2a04a685
--- /dev/null
+++ b/libjava/classpath/java/rmi/registry/Registry.java
@@ -0,0 +1,65 @@
+/* Registry.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.registry;
+
+import java.rmi.AccessException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Registry extends Remote
+{
+ int REGISTRY_PORT = 1099;
+
+ Remote lookup(String name)
+ throws RemoteException, NotBoundException, AccessException;
+
+ void bind(String name, Remote obj)
+ throws RemoteException, AlreadyBoundException, AccessException;
+
+ void unbind(String name)
+ throws RemoteException, NotBoundException, AccessException;
+
+ void rebind(String name, Remote obj)
+ throws RemoteException, AccessException;
+
+ String[] list()
+ throws RemoteException, AccessException;
+}
diff --git a/libjava/classpath/java/rmi/registry/RegistryHandler.java b/libjava/classpath/java/rmi/registry/RegistryHandler.java
new file mode 100644
index 00000000000..b9b45092305
--- /dev/null
+++ b/libjava/classpath/java/rmi/registry/RegistryHandler.java
@@ -0,0 +1,58 @@
+/* RegistryHandler.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.registry;
+
+import java.rmi.RemoteException;
+import java.rmi.UnknownHostException;
+
+/**
+ * @deprecated
+ */
+public interface RegistryHandler
+{
+ /**
+ * @deprecated
+ */
+ Registry registryStub (String host, int port)
+ throws RemoteException, UnknownHostException;
+
+ /**
+ * @deprecated
+ */
+ Registry registryImpl (int port) throws RemoteException;
+}
diff --git a/libjava/classpath/java/rmi/registry/package.html b/libjava/classpath/java/rmi/registry/package.html
new file mode 100644
index 00000000000..4e16672709c
--- /dev/null
+++ b/libjava/classpath/java/rmi/registry/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.rmi.registry package.
+ Copyright (C) 2002 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 - java.rmi.registry</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/rmi/server/ExportException.java b/libjava/classpath/java/rmi/server/ExportException.java
new file mode 100644
index 00000000000..b2d5bfca52e
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/ExportException.java
@@ -0,0 +1,78 @@
+/* ExportException.java -- an export attempt failed
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.server;
+
+import java.rmi.RemoteException;
+
+/**
+ * Thrown if an attempt to export a remote object fails.
+ *
+ * @author unknown
+ * @see UnicastRemoteObject
+ * @see Activatable
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ExportException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -9155485338494060170L;
+
+ /**
+ * Create an exception with the specified message.
+ *
+ * @param s the message
+ */
+ public ExportException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with the specified message and cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public ExportException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/LoaderHandler.java b/libjava/classpath/java/rmi/server/LoaderHandler.java
new file mode 100644
index 00000000000..189085710b4
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/LoaderHandler.java
@@ -0,0 +1,66 @@
+/* LoaderHandler.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.server;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * @deprecated
+ */
+public interface LoaderHandler
+{
+ String packagePrefix = "";
+
+ /**
+ * @deprecated
+ */
+ Class loadClass(String name)
+ throws MalformedURLException, ClassNotFoundException;
+
+ /**
+ * @deprecated
+ */
+ Class loadClass(URL codebase, String name)
+ throws MalformedURLException, ClassNotFoundException;
+
+ /**
+ * @deprecated
+ */
+ Object getSecurityContext(ClassLoader loader);
+}
diff --git a/libjava/classpath/java/rmi/server/LogStream.java b/libjava/classpath/java/rmi/server/LogStream.java
new file mode 100644
index 00000000000..a2dfbb47fcc
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/LogStream.java
@@ -0,0 +1,146 @@
+/* LogStream.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+/**
+ * @deprecated
+ */
+public class LogStream extends PrintStream
+{
+ public static final int SILENT = 0;
+ public static final int BRIEF = 10;
+ public static final int VERBOSE = 20;
+
+ private static PrintStream defStream;
+
+ private LogStream (OutputStream s)
+ {
+ super (s);
+ }
+
+ /**
+ * @deprecated
+ */
+ public static LogStream log (String name)
+ {
+ throw new Error ("Not implemented");
+ }
+
+ /**
+ * @deprecated
+ */
+ public static PrintStream getDefaultStream ()
+ {
+ return defStream;
+ }
+
+ /**
+ * @deprecated
+ */
+ public static void setDefaultStream (PrintStream s)
+ {
+ defStream = s;
+ }
+
+ /**
+ * @deprecated
+ */
+ public OutputStream getOutputStream ()
+ {
+ return out;
+ }
+
+ /**
+ * @deprecated
+ */
+ public void setOutputStream (OutputStream s)
+ {
+ out = s;
+ }
+
+ /**
+ * @deprecated
+ */
+ public void write (int buffer)
+ {
+ super.write (buffer);
+ }
+
+ /**
+ * @deprecated
+ */
+ public void write (byte[] buffer, int offset, int len)
+ {
+ super.write (buffer, offset, len);
+ }
+
+ /**
+ * @deprecated
+ */
+ public String toString ()
+ {
+ throw new Error ("Not implemented");
+ }
+
+ /**
+ * @deprecated
+ */
+ public static int parseLevel (String s)
+ {
+ if (s.equalsIgnoreCase ("silent"))
+ {
+ return SILENT;
+ }
+
+ if (s.equalsIgnoreCase ("brief"))
+ {
+ return BRIEF;
+ }
+
+ if (s.equalsIgnoreCase ("verbose"))
+ {
+ return VERBOSE;
+ }
+
+ return SILENT;
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/ObjID.java b/libjava/classpath/java/rmi/server/ObjID.java
new file mode 100644
index 00000000000..07cbbde3a62
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/ObjID.java
@@ -0,0 +1,103 @@
+/* ObjID.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+
+public final class ObjID implements Serializable
+{
+static final long serialVersionUID = -6386392263968365220L;
+
+private static long next = 0x8000000000000000L;
+private static final Object lock = ObjID.class;
+
+public static final int REGISTRY_ID = 0;
+public static final int ACTIVATOR_ID = 1;
+public static final int DGC_ID = 2;
+
+private long objNum;
+private UID space;
+
+public ObjID() {
+ synchronized (lock) {
+ objNum = next++;
+ }
+ space = new UID();
+}
+
+public ObjID(int num) {
+ objNum = (long)num;
+ space = new UID((short)0);
+}
+
+public void write(ObjectOutput out) throws IOException {
+ DataOutput dout = (DataOutput)out;
+ dout.writeLong(objNum);
+ space.write(dout);
+}
+
+public static ObjID read(ObjectInput in) throws IOException {
+ DataInput din = (DataInput)in;
+ ObjID id = new ObjID();
+ id.objNum = din.readLong();
+ id.space = UID.read(din);
+ return (id);
+}
+
+public int hashCode() {
+ return ((int)objNum);
+}
+
+public boolean equals(Object obj) {
+ if (obj instanceof ObjID && this.objNum == ((ObjID)obj).objNum) {
+ return (true);
+ }
+ return (false);
+}
+
+public String toString() {
+ return ("[objNum: " + objNum + ", " + space + "]");
+}
+
+}
diff --git a/libjava/classpath/java/rmi/server/Operation.java b/libjava/classpath/java/rmi/server/Operation.java
new file mode 100644
index 00000000000..64faf66e2f8
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/Operation.java
@@ -0,0 +1,70 @@
+/* Operation.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.server;
+
+/**
+ * @deprecated
+ */
+public class Operation
+{
+ private String operation;
+
+ /**
+ * @deprecated
+ */
+ public Operation (String op)
+ {
+ operation = op;
+ }
+
+ /**
+ * @deprecated
+ */
+ public String getOperation ()
+ {
+ return operation;
+ }
+
+ /**
+ * @deprecated
+ */
+ public String toString ()
+ {
+ return operation;
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/RMIClassLoader.java b/libjava/classpath/java/rmi/server/RMIClassLoader.java
new file mode 100644
index 00000000000..1a2e2837dd8
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RMIClassLoader.java
@@ -0,0 +1,339 @@
+/* RMIClassLoader.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.rmi.server;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+
+/**
+ * This class provides a set of public static utility methods for supporting
+ * network-based class loading in RMI. These methods are called by RMI's
+ * internal marshal streams to implement the dynamic class loading of types for
+ * RMI parameters and return values.
+ */
+public class RMIClassLoader
+{
+ /**
+ * This class isn't intended to be instantiated.
+ */
+ private RMIClassLoader() {}
+
+ private static class MyClassLoader extends URLClassLoader
+ {
+ // Package-private to avoid a trampoline constructor.
+ MyClassLoader (URL[] urls, ClassLoader parent, String annotation)
+ {
+ super (urls, parent);
+ this.annotation = annotation;
+ }
+
+ private MyClassLoader (URL[] urls, ClassLoader parent)
+ {
+ super (urls, parent);
+ this.annotation = urlToAnnotation (urls);
+ }
+
+ public static String urlToAnnotation (URL[] urls)
+ {
+ if (urls.length == 0)
+ return null;
+
+ StringBuffer annotation = new StringBuffer (64 * urls.length);
+
+ for (int i = 0; i < urls.length; i++)
+ {
+ annotation.append (urls [i].toExternalForm());
+ annotation.append (' ');
+ }
+
+ return annotation.toString();
+ }
+
+ public final String getClassAnnotation()
+ {
+ return annotation;
+ }
+
+ private final String annotation;
+ }
+
+ /**
+ * This class is used to identify a cached classloader by its codebase and
+ * the context classloader that is its parent.
+ */
+ private static class CacheKey
+ {
+ private String mCodeBase;
+ private ClassLoader mContextClassLoader;
+
+ public CacheKey (String theCodebase, ClassLoader theContextClassLoader)
+ {
+ mCodeBase = theCodebase;
+ mContextClassLoader = theContextClassLoader;
+ }
+
+ /**
+ * @return true if the codebase and the context classloader are equal
+ */
+ public boolean equals (Object theOther)
+ {
+ if (theOther instanceof CacheKey)
+ {
+ CacheKey key = (CacheKey) theOther;
+
+ return (equals (this.mCodeBase,key.mCodeBase)
+ && equals (this.mContextClassLoader, key.mContextClassLoader));
+ }
+ return false;
+ }
+
+ /**
+ * Test if the two objects are equal or both null.
+ * @param theOne
+ * @param theOther
+ * @return
+ */
+ private boolean equals (Object theOne, Object theOther)
+ {
+ return theOne != null ? theOne.equals (theOther) : theOther == null;
+ }
+
+ /**
+ * @return hashCode
+ */
+ public int hashCode()
+ {
+ return ((mCodeBase != null ? mCodeBase.hashCode() : 0)
+ ^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1));
+ }
+
+ public String toString()
+ {
+ return "[" + mCodeBase + "," + mContextClassLoader + "]";
+ }
+
+ }
+
+ private static Map cacheLoaders; //map annotations to loaders
+ private static Map cacheAnnotations; //map loaders to annotations
+
+ //defaultAnnotation is got from system property
+ // "java.rmi.server.defaultAnnotation"
+ private static String defaultAnnotation;
+
+ //URL object for defaultAnnotation
+ private static URL defaultCodebase;
+
+ //class loader for defaultAnnotation
+ private static MyClassLoader defaultLoader;
+
+ static
+ {
+ // 89 is a nice prime number for Hashtable initial capacity
+ cacheLoaders = new Hashtable (89);
+ cacheAnnotations = new Hashtable (89);
+
+ defaultAnnotation = System.getProperty ("java.rmi.server.defaultAnnotation");
+
+ try
+ {
+ if (defaultAnnotation != null)
+ defaultCodebase = new URL (defaultAnnotation);
+ }
+ catch (Exception _)
+ {
+ defaultCodebase = null;
+ }
+
+ if (defaultCodebase != null)
+ {
+ defaultLoader = new MyClassLoader (new URL[] { defaultCodebase }, null,
+ defaultAnnotation);
+ cacheLoaders.put (new CacheKey (defaultAnnotation,
+ Thread.currentThread().getContextClassLoader()),
+ defaultLoader);
+ }
+ }
+
+ /**
+ * @deprecated
+ */
+ public static Class loadClass (String name)
+ throws MalformedURLException, ClassNotFoundException
+ {
+ return loadClass ("", name);
+ }
+
+ public static Class loadClass (String codebases, String name)
+ throws MalformedURLException, ClassNotFoundException
+ {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+ //try context class loader first
+ try
+ {
+ return loader.loadClass (name);
+ }
+ catch (ClassNotFoundException e)
+ {
+ // class not found in the local classpath
+ }
+
+ if (codebases.length() == 0) //==""
+ {
+ loader = defaultLoader;
+ }
+ else
+ {
+ loader = getClassLoader(codebases);
+ }
+
+ if (loader == null)
+ {
+ //do not throw NullPointerException
+ throw new ClassNotFoundException ("Could not find class (" + name +
+ ") at codebase (" + codebases + ")");
+ }
+
+ return loader.loadClass (name);
+ }
+
+ /**
+ * Gets a classloader for the given codebase and with the current
+ * context classloader as parent.
+ *
+ * @param codebases
+ *
+ * @return a classloader for the given codebase
+ *
+ * @throws MalformedURLException if the codebase contains a malformed URL
+ */
+ public static ClassLoader getClassLoader (String codebases)
+ throws MalformedURLException
+ {
+ ClassLoader loader;
+ CacheKey loaderKey = new CacheKey
+ (codebases, Thread.currentThread().getContextClassLoader());
+ loader = (ClassLoader) cacheLoaders.get (loaderKey);
+
+ if (loader == null)
+ {
+ //create an entry in cacheLoaders mapping a loader to codebases.
+ // codebases are separated by " "
+ StringTokenizer tok = new StringTokenizer (codebases, " ");
+ ArrayList urls = new ArrayList();
+
+ while (tok.hasMoreTokens())
+ urls.add (new URL (tok.nextToken()));
+
+ loader = new MyClassLoader ((URL[]) urls.toArray (new URL [urls.size()]),
+ Thread.currentThread().getContextClassLoader(),
+ codebases);
+ cacheLoaders.put (loaderKey, loader);
+ }
+
+ return loader;
+ }
+
+ /**
+ * Returns a string representation of the network location where a remote
+ * endpoint can get the class-definition of the given class.
+ *
+ * @param cl
+ *
+ * @return a space seperated list of URLs where the class-definition
+ * of cl may be found
+ */
+ public static String getClassAnnotation (Class cl)
+ {
+ ClassLoader loader = cl.getClassLoader();
+
+ if (loader == null
+ || loader == ClassLoader.getSystemClassLoader())
+ {
+ return System.getProperty ("java.rmi.server.codebase");
+ }
+
+ if (loader instanceof MyClassLoader)
+ {
+ return ((MyClassLoader) loader).getClassAnnotation();
+ }
+
+ String s = (String) cacheAnnotations.get (loader);
+
+ if (s != null)
+ return s;
+
+ if (loader instanceof URLClassLoader)
+ {
+ URL[] urls = ((URLClassLoader) loader).getURLs();
+
+ if (urls.length == 0)
+ return null;
+
+ StringBuffer annotation = new StringBuffer (64 * urls.length);
+
+ for (int i = 0; i < urls.length; i++)
+ {
+ annotation.append (urls [i].toExternalForm());
+ annotation.append (' ');
+ }
+
+ s = annotation.toString();
+ cacheAnnotations.put (loader, s);
+ return s;
+ }
+
+ return System.getProperty ("java.rmi.server.codebase");
+ }
+
+ /**
+ * @deprecated
+ */
+ public static Object getSecurityContext (ClassLoader loader)
+ {
+ throw new Error ("Not implemented");
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/RMIClassLoaderSpi.java b/libjava/classpath/java/rmi/server/RMIClassLoaderSpi.java
new file mode 100644
index 00000000000..372d81879f9
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RMIClassLoaderSpi.java
@@ -0,0 +1,64 @@
+/* RMIClassLoaderSpi.java --
+ Copyright (c) 2002 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.rmi.server;
+
+import java.net.MalformedURLException;
+
+/**
+ * @author Michael Koch
+ * @since 1.4
+ */
+public abstract class RMIClassLoaderSpi
+{
+ public RMIClassLoaderSpi()
+ {
+ }
+
+ public abstract Class loadClass (String codeBase, String name,
+ ClassLoader defaultLoader)
+ throws MalformedURLException, ClassNotFoundException;
+
+ public abstract Class loadProxyClass (String codeBase, String[] interfaces,
+ ClassLoader defaultLoader)
+ throws MalformedURLException, ClassNotFoundException;
+
+ public abstract ClassLoader getClassLoader (String codebase)
+ throws MalformedURLException;
+
+ public abstract String getClassAnnotation (Class cl);
+}
diff --git a/libjava/classpath/java/rmi/server/RMIClientSocketFactory.java b/libjava/classpath/java/rmi/server/RMIClientSocketFactory.java
new file mode 100644
index 00000000000..a54d11175e0
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RMIClientSocketFactory.java
@@ -0,0 +1,47 @@
+/* RMIClientSocketFactory.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import java.io.IOException;
+import java.net.Socket;
+
+public interface RMIClientSocketFactory
+{
+ Socket createSocket (String host, int port) throws IOException;
+}
diff --git a/libjava/classpath/java/rmi/server/RMIFailureHandler.java b/libjava/classpath/java/rmi/server/RMIFailureHandler.java
new file mode 100644
index 00000000000..3496cd6a073
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RMIFailureHandler.java
@@ -0,0 +1,46 @@
+/* RMIFailureHandler.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.server;
+
+public interface RMIFailureHandler
+{
+ /**
+ * @exception IOException If an error occurs
+ */
+ boolean failure (Exception ex);
+}
diff --git a/libjava/classpath/java/rmi/server/RMIServerSocketFactory.java b/libjava/classpath/java/rmi/server/RMIServerSocketFactory.java
new file mode 100644
index 00000000000..88eaff32dbc
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RMIServerSocketFactory.java
@@ -0,0 +1,47 @@
+/* RMIServerSocketFactory.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+
+public interface RMIServerSocketFactory
+{
+ ServerSocket createServerSocket(int port) throws IOException;
+}
diff --git a/libjava/classpath/java/rmi/server/RMISocketFactory.java b/libjava/classpath/java/rmi/server/RMISocketFactory.java
new file mode 100644
index 00000000000..953f1ef33ce
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RMISocketFactory.java
@@ -0,0 +1,108 @@
+/* RMISocketFactory.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import gnu.java.rmi.server.RMIDefaultSocketFactory;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+public abstract class RMISocketFactory
+ implements RMIClientSocketFactory, RMIServerSocketFactory
+{
+ private static RMISocketFactory defaultFactory;
+ private static RMISocketFactory currentFactory;
+ private static RMIFailureHandler currentHandler;
+
+ static
+ {
+ defaultFactory = new RMIDefaultSocketFactory();
+ currentFactory = defaultFactory;
+ }
+
+ public RMISocketFactory ()
+ {
+ }
+
+ /**
+ * @exception IOException If an error occurs
+ */
+ public abstract Socket createSocket (String host, int port)
+ throws IOException;
+
+ /**
+ * @exception IOException If an error occurs
+ */
+ public abstract ServerSocket createServerSocket (int port)
+ throws IOException;
+
+ /**
+ * @exception IOException If an error occurs
+ * @exception SecurityException FIXME
+ */
+ public static void setSocketFactory (RMISocketFactory fac)
+ throws IOException
+ {
+ currentFactory = fac;
+ }
+
+ public static RMISocketFactory getSocketFactory ()
+ {
+ return currentFactory;
+ }
+
+ public static RMISocketFactory getDefaultSocketFactory ()
+ {
+ return defaultFactory;
+ }
+
+ /**
+ * @exception SecurityException FIXME
+ */
+ public static void setFailureHandler (RMIFailureHandler fh)
+ {
+ currentHandler = fh;
+ }
+
+ public static RMIFailureHandler getFailureHandler ()
+ {
+ return currentHandler;
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/RemoteCall.java b/libjava/classpath/java/rmi/server/RemoteCall.java
new file mode 100644
index 00000000000..35f3bf1a655
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RemoteCall.java
@@ -0,0 +1,86 @@
+/* RemoteCall.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.StreamCorruptedException;
+
+/**
+ * @deprecated
+ */
+public interface RemoteCall
+{
+ /**
+ * @deprecated
+ */
+ ObjectOutput getOutputStream () throws IOException;
+
+ /**
+ * @deprecated
+ */
+ void releaseOutputStream () throws IOException;
+
+ /**
+ * @deprecated
+ */
+ ObjectInput getInputStream () throws IOException;
+
+ /**
+ * @deprecated
+ */
+ void releaseInputStream () throws IOException;
+
+ /**
+ * @deprecated
+ */
+ ObjectOutput getResultStream (boolean success)
+ throws IOException, StreamCorruptedException;
+
+ /**
+ * @deprecated
+ */
+ void executeCall () throws Exception;
+
+ /**
+ * @deprecated
+ */
+ void done () throws IOException;
+}
diff --git a/libjava/classpath/java/rmi/server/RemoteObject.java b/libjava/classpath/java/rmi/server/RemoteObject.java
new file mode 100644
index 00000000000..0b3c229c9d9
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RemoteObject.java
@@ -0,0 +1,160 @@
+/* RemoteObject.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.rmi.server;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.UnmarshalException;
+import java.util.WeakHashMap;
+
+public abstract class RemoteObject
+ implements Remote, Serializable {
+
+private static final long serialVersionUID = -3215090123894869218l;
+
+protected transient RemoteRef ref;
+
+private static final WeakHashMap stubs = new WeakHashMap();
+
+protected RemoteObject() {
+ this(null);
+}
+
+protected RemoteObject(RemoteRef newref) {
+ ref = newref;
+}
+
+public RemoteRef getRef() {
+ return (ref);
+}
+
+synchronized static void addStub(Remote obj, Remote stub)
+{
+ stubs.put(obj, stub);
+}
+
+synchronized static void deleteStub(Remote obj)
+{
+ stubs.remove(obj);
+}
+
+ public static Remote toStub(Remote obj) throws NoSuchObjectException
+ {
+ Remote stub = (Remote)stubs.get(obj);
+
+ if (stub == null)
+ throw new NoSuchObjectException(obj.getClass().getName());
+
+ return stub;
+ }
+
+public int hashCode() {
+ if (ref == null) {
+ return (0);
+ }
+ else {
+ return (ref.hashCode());
+ }
+}
+
+public boolean equals(Object obj) {
+ // We only compare references.
+ return (this == obj);
+}
+
+ public String toString()
+ {
+ if (ref == null)
+ return getClass ().toString ();
+ return (ref.toString ());
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+ {
+ String cname = in.readUTF();
+ if (!cname.equals(""))
+ {
+ if (cname.equals ("UnicastRef2"))
+ {
+ // hack for interoperating with JDK
+ cname = "UnicastRef";
+ in.read (); //some unknown UnicastRef2 field
+ }
+
+ cname = RemoteRef.packagePrefix + '.' + cname;
+ try
+ {
+ Class cls = Class.forName(cname);
+ ref = (RemoteRef)cls.newInstance();
+ }
+ catch (InstantiationException e1)
+ {
+ throw new UnmarshalException("failed to create ref", e1);
+ }
+ catch (IllegalAccessException e2)
+ {
+ throw new UnmarshalException("failed to create ref", e2);
+ }
+ ref.readExternal(in);
+ }
+ else
+ {
+ ref = (RemoteRef)in.readObject();
+ }
+ }
+
+private void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException {
+ if (ref == null) {
+ throw new UnmarshalException("no ref to serialize");
+ }
+ String cname = ref.getRefClass(out);
+ if (cname != null && cname.length() > 0) {
+ out.writeUTF(cname);
+ ref.writeExternal(out);
+ }
+ else {
+ out.writeUTF("");
+ out.writeObject(ref);
+ }
+}
+
+}
diff --git a/libjava/classpath/java/rmi/server/RemoteRef.java b/libjava/classpath/java/rmi/server/RemoteRef.java
new file mode 100644
index 00000000000..7e34db39e89
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RemoteRef.java
@@ -0,0 +1,79 @@
+/* RemoteRef.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import java.io.Externalizable;
+import java.io.ObjectOutput;
+import java.lang.reflect.Method;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface RemoteRef extends Externalizable
+{
+ long serialVersionUID = 3632638527362204081L;
+
+ String packagePrefix = "gnu.java.rmi.server";
+
+ /**
+ * @deprecated
+ */
+ void invoke (RemoteCall call) throws Exception;
+
+ Object invoke (Remote obj, Method method, Object[] params, long opnum)
+ throws Exception;
+
+ /**
+ * @deprecated
+ */
+ RemoteCall newCall (RemoteObject obj, Operation[] op, int opnum, long hash)
+ throws RemoteException;
+
+ /**
+ * @deprecated
+ */
+ void done (RemoteCall call) throws RemoteException;
+
+ boolean remoteEquals (RemoteRef ref);
+
+ int remoteHashCode();
+
+ String getRefClass (ObjectOutput out);
+
+ String remoteToString();
+}
diff --git a/libjava/classpath/java/rmi/server/RemoteServer.java b/libjava/classpath/java/rmi/server/RemoteServer.java
new file mode 100644
index 00000000000..9efb12a782d
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RemoteServer.java
@@ -0,0 +1,76 @@
+/* RemoteServer.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.rmi.server;
+
+import gnu.java.rmi.server.RMIIncomingThread;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+public abstract class RemoteServer extends RemoteObject
+{
+private static final long serialVersionUID = -4100238210092549637L;
+
+protected RemoteServer() {
+ super();
+}
+
+protected RemoteServer(RemoteRef ref) {
+ super(ref);
+}
+
+public static String getClientHost() throws ServerNotActiveException {
+ Thread currThread = Thread.currentThread();
+ if (currThread instanceof RMIIncomingThread) {
+ RMIIncomingThread incomingThread = (RMIIncomingThread) currThread;
+ return incomingThread.getClientHost();
+ } else {
+ throw new ServerNotActiveException(
+ "Unknown client host - current thread not instance of 'RMIIncomingThread'");
+ }
+}
+
+public static void setLog(OutputStream out) {
+ throw new Error("Not implemented");
+}
+
+public static PrintStream getLog() {
+ throw new Error("Not implemented");
+}
+
+}
diff --git a/libjava/classpath/java/rmi/server/RemoteStub.java b/libjava/classpath/java/rmi/server/RemoteStub.java
new file mode 100644
index 00000000000..18c614b54a8
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/RemoteStub.java
@@ -0,0 +1,61 @@
+/* RemoteStub.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.server;
+
+public abstract class RemoteStub extends RemoteObject
+{
+ static final long serialVersionUID = -1585587260594494182l;
+
+ protected RemoteStub ()
+ {
+ super ();
+ }
+
+ protected RemoteStub (RemoteRef ref)
+ {
+ super (ref);
+ }
+
+ /**
+ * @deprecated
+ */
+ protected static void setRef (RemoteStub stub, RemoteRef ref)
+ {
+ stub.ref = ref;
+ }
+} // class RemoteSub
diff --git a/libjava/classpath/java/rmi/server/ServerCloneException.java b/libjava/classpath/java/rmi/server/ServerCloneException.java
new file mode 100644
index 00000000000..bda41b3ce91
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/ServerCloneException.java
@@ -0,0 +1,117 @@
+/* ServerCloneException.java -- a UnicastRemoteObject could not be cloned
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.server;
+
+/**
+ * Thrown if a remote exception occurs during the cloning process of a
+ * <code>UnicastRemoteObject</code>.
+ *
+ * @author unknown
+ * @see UnicastRemoteObject#clone()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ServerCloneException extends CloneNotSupportedException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 6617456357664815945L;
+
+ /**
+ * The cause of this exception. This pre-dates the exception chaining
+ * of Throwable; and although you can change this field, you are wiser
+ * to leave it alone.
+ *
+ * @serial the exception cause
+ */
+ public Exception detail;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ServerCloneException(String s)
+ {
+ this(s, null);
+ }
+
+ /**
+ * Create an exception with a message and a cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public ServerCloneException(String s, Exception e)
+ {
+ super(s);
+ initCause(e);
+ detail = e;
+ }
+
+ /**
+ * This method returns a message indicating what went wrong, in this
+ * format:
+ * <code>super.getMessage() + (detail == null ? ""
+ * : "; nested exception is:\n\t" + detail)</code>.
+ *
+ * @return the chained message
+ */
+ public String getMessage()
+ {
+ if (detail == this || detail == null)
+ return super.getMessage();
+ return super.getMessage() + "; nested exception is:\n\t" + detail;
+ }
+
+ /**
+ * Returns the cause of this exception. Note that this may not be the
+ * original cause, thanks to the <code>detail</code> field being public
+ * and non-final (yuck). However, to avoid violating the contract of
+ * Throwable.getCause(), this returns null if <code>detail == this</code>,
+ * as no exception can be its own cause.
+ *
+ * @return the cause
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return detail == this ? null : detail;
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/ServerNotActiveException.java b/libjava/classpath/java/rmi/server/ServerNotActiveException.java
new file mode 100644
index 00000000000..0581b63bc82
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/ServerNotActiveException.java
@@ -0,0 +1,72 @@
+/* ServerNotActiveException.java -- the method is not servicing a remote call
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.server;
+
+/**
+ * Thrown during <code>RemoteServer.getClientHost</code> if the host is
+ * not servicing a remote method call.
+ *
+ * @author unknown
+ * @see RemoteServer#getClientHost()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ServerNotActiveException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4687940720827538231L;
+
+ /**
+ * Create an exception with no message.
+ */
+ public ServerNotActiveException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public ServerNotActiveException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/ServerRef.java b/libjava/classpath/java/rmi/server/ServerRef.java
new file mode 100644
index 00000000000..cf1013cf02b
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/ServerRef.java
@@ -0,0 +1,51 @@
+/* ServerRef.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface ServerRef extends RemoteRef
+{
+ long serialVersionUID = -4557750989390278438L;
+
+ RemoteStub exportObject(Remote obj, Object data) throws RemoteException;
+
+ String getClientHost() throws ServerNotActiveException;
+}
diff --git a/libjava/classpath/java/rmi/server/Skeleton.java b/libjava/classpath/java/rmi/server/Skeleton.java
new file mode 100644
index 00000000000..82f5d3837f4
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/Skeleton.java
@@ -0,0 +1,57 @@
+/* Skeleton.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.server;
+
+import java.rmi.Remote;
+
+/**
+ * @deprecated
+ */
+public interface Skeleton
+{
+ /**
+ * @deprecated
+ */
+ void dispatch (Remote obj, RemoteCall theCall, int opnum, long hash)
+ throws Exception;
+
+ /**
+ * @deprecated
+ */
+ Operation[] getOperations();
+}
diff --git a/libjava/classpath/java/rmi/server/SkeletonMismatchException.java b/libjava/classpath/java/rmi/server/SkeletonMismatchException.java
new file mode 100644
index 00000000000..9c0206ab3bc
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/SkeletonMismatchException.java
@@ -0,0 +1,68 @@
+/* SkeletonMismatchException.java -- thrown when stub class versions mismatch
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.server;
+
+import java.rmi.RemoteException;
+
+/**
+ * Thrown if a call is received that does not match a Skeleton. Note that
+ * Skeletons are no longer required.
+ *
+ * @author unknown
+ * @since 1.1
+ * @deprecated no replacement. Skeletons are no longer required.
+ * @status updated to 1.4
+ */
+public class SkeletonMismatchException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1.
+ */
+ private static final long serialVersionUID = -7780460454818859281l;
+
+ /**
+ * Create an exception with the specified message.
+ *
+ * @param s the message
+ * @deprecated no longer needed
+ */
+ public SkeletonMismatchException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/SkeletonNotFoundException.java b/libjava/classpath/java/rmi/server/SkeletonNotFoundException.java
new file mode 100644
index 00000000000..596aae15417
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/SkeletonNotFoundException.java
@@ -0,0 +1,79 @@
+/* SkeletonNotFoundException.java -- thrown if a Skeleton is not found
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.server;
+
+import java.rmi.RemoteException;
+
+/**
+ * Thrown if a Skeleton corresponding to the remote object is not found.
+ * Note that Skeletons are no longer required.
+ *
+ * @author unknown
+ * @since 1.1
+ * @deprecated no replacement. Skeletons are no longer required.
+ * @status updated to 1.4
+ */
+public class SkeletonNotFoundException extends RemoteException
+{
+ /**
+ * Compatible with JDK 1.1.
+ */
+ private static final long serialVersionUID = -7860299673822761231L;
+
+ /**
+ * Create an exception with the specified message.
+ *
+ * @param s the message
+ */
+ public SkeletonNotFoundException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with the specified message and cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public SkeletonNotFoundException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/SocketSecurityException.java b/libjava/classpath/java/rmi/server/SocketSecurityException.java
new file mode 100644
index 00000000000..aaf7698f4bc
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/SocketSecurityException.java
@@ -0,0 +1,75 @@
+/* SocketSecurityException.java -- the socket could not be created
+ Copyright (c) 1996, 1997, 1998, 1999, 2002 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.rmi.server;
+
+/**
+ * Thrown during remote object export if the code does not have permission
+ * to create a <code>java.net.ServerSocket</code> on the specified port.
+ *
+ * @author unknown
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class SocketSecurityException extends ExportException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -7622072999407781979L;
+
+ /**
+ * Create an exception with the specified message.
+ *
+ * @param s the message
+ */
+ public SocketSecurityException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Create an exception with the specified message and cause.
+ *
+ * @param s the message
+ * @param e the cause
+ */
+ public SocketSecurityException(String s, Exception e)
+ {
+ super(s, e);
+ }
+}
diff --git a/libjava/classpath/java/rmi/server/UID.java b/libjava/classpath/java/rmi/server/UID.java
new file mode 100644
index 00000000000..0f492bae77a
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/UID.java
@@ -0,0 +1,127 @@
+/* UID.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.rmi.server;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+
+public final class UID implements Serializable
+{
+private static final long serialVersionUID = 1086053664494604050L;
+
+private static final Object lock = UID.class;
+private static long baseTime = System.currentTimeMillis();
+private static short nextCount = Short.MIN_VALUE;
+// This is sun's algorithm - don't ask me why ...
+private static final int uniqueNr = (new Object()).hashCode();
+
+private int unique;
+private long time;
+private short count;
+
+/**
+ * This is sun's algorithm - don't ask me why ...
+ */
+public UID() {
+ synchronized (lock) {
+ if (nextCount == Short.MAX_VALUE) {
+ long newtime;
+ for (;;) {
+ newtime = System.currentTimeMillis();
+ if (newtime - baseTime > 1000) {
+ break;
+ }
+ try {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException _) {
+ }
+ }
+ baseTime = newtime;
+ nextCount = Short.MIN_VALUE;
+ }
+ count = nextCount++;
+ unique = uniqueNr;
+ time = baseTime;
+ }
+}
+
+public UID(short num) {
+ unique = (int)num;
+ time = 0;
+ count = 0;
+}
+
+public int hashCode() {
+ return (unique);
+}
+
+public boolean equals(Object obj) {
+ if (obj instanceof UID) {
+ UID uid = (UID)obj;
+ if (this.unique == uid.unique &&
+ this.time == uid.time &&
+ this.count == uid.count) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+public String toString() {
+ return ("[UID: " + unique + "," + time + "," + count + "]");
+}
+
+public void write(DataOutput out) throws IOException {
+ out.writeInt(unique);
+ out.writeLong(time);
+ out.writeShort(count);
+}
+
+public static UID read(DataInput in) throws IOException {
+ UID id = new UID();
+ id.unique = in.readInt();
+ id.time = in.readLong();
+ id.count = in.readShort();
+ return (id);
+}
+
+}
diff --git a/libjava/classpath/java/rmi/server/UnicastRemoteObject.java b/libjava/classpath/java/rmi/server/UnicastRemoteObject.java
new file mode 100644
index 00000000000..dbe25bda3fd
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/UnicastRemoteObject.java
@@ -0,0 +1,133 @@
+/* UnicastRemoteObject.java --
+ Copyright (c) 1996, 1997, 1998, 1999, 2002, 2003 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.rmi.server;
+
+import gnu.java.rmi.server.UnicastServerRef;
+
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public class UnicastRemoteObject extends RemoteServer
+{
+private static final long serialVersionUID = 4974527148936298033L;
+//The following serialized fields are from Java API Documentation "Serialized form"
+private int port = 0;
+private RMIClientSocketFactory csf = null;
+private RMIServerSocketFactory ssf = null;
+
+protected UnicastRemoteObject() throws RemoteException {
+ this(0);
+}
+
+protected UnicastRemoteObject(int port) throws RemoteException {
+ this(port, RMISocketFactory.getSocketFactory(), RMISocketFactory.getSocketFactory());
+}
+
+protected UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException {
+ this.port = port;
+ //Is RMIXXXSocketFactory serializable
+ //this.csf = csf;
+ //this.ssf = ssf;
+ this.ref = new UnicastServerRef(new ObjID(), port, ssf);
+ exportObject(this);
+}
+
+protected UnicastRemoteObject(RemoteRef ref) throws RemoteException {
+ super((UnicastServerRef)ref);
+ exportObject(this);
+}
+
+public Object clone() throws CloneNotSupportedException {
+ throw new Error("Not implemented");
+}
+
+public static RemoteStub exportObject(Remote obj) throws RemoteException {
+ UnicastServerRef sref = (UnicastServerRef)((RemoteObject)obj).getRef();
+ return (sref.exportObject(obj));
+}
+
+ public static Remote exportObject(Remote obj, int port) throws RemoteException
+ {
+ return exportObject(obj, port, null);
+ }
+
+ static Remote exportObject(Remote obj, int port, RMIServerSocketFactory ssf)
+ throws RemoteException
+ {
+ UnicastServerRef sref = null;
+ if (obj instanceof RemoteObject)
+ sref = (UnicastServerRef)((RemoteObject)obj).getRef ();
+ if(sref == null)
+ {
+ sref = new UnicastServerRef(new ObjID (), port, ssf);
+ }
+ Remote stub = sref.exportObject (obj);
+ addStub(obj, stub);
+ return stub;
+ }
+
+ /**
+ * FIXME
+ */
+ public static Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf)
+ throws RemoteException
+ {
+ return (exportObject(obj, port, ssf));
+ }
+
+ public static boolean unexportObject(Remote obj, boolean force)
+ throws NoSuchObjectException
+ {
+ if (obj instanceof RemoteObject)
+ {
+ deleteStub(obj);
+ UnicastServerRef sref = (UnicastServerRef)((RemoteObject)obj).getRef();
+ return sref.unexportObject(obj, force);
+ }
+ else
+ {
+ //FIX ME
+ ;
+ }
+ return true;
+ }
+
+}
diff --git a/libjava/classpath/java/rmi/server/Unreferenced.java b/libjava/classpath/java/rmi/server/Unreferenced.java
new file mode 100644
index 00000000000..982aa64458f
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/Unreferenced.java
@@ -0,0 +1,43 @@
+/* Unreferenced.java --
+ Copyright (c) 1996, 1997, 1998, 1999 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.rmi.server;
+
+public interface Unreferenced
+{
+ void unreferenced();
+}
diff --git a/libjava/classpath/java/rmi/server/package.html b/libjava/classpath/java/rmi/server/package.html
new file mode 100644
index 00000000000..54055a72158
--- /dev/null
+++ b/libjava/classpath/java/rmi/server/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.rmi.server package.
+ Copyright (C) 2002 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 - java.rmi.server</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/security/AccessControlContext.java b/libjava/classpath/java/security/AccessControlContext.java
new file mode 100644
index 00000000000..9a6ad208144
--- /dev/null
+++ b/libjava/classpath/java/security/AccessControlContext.java
@@ -0,0 +1,176 @@
+/* AccessControlContext.java --- Access Control Context Class
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+import java.util.HashSet;
+
+/**
+ * AccessControlContext makes system resource access decsion
+ * based on permission rights.
+ *
+ * It is used for a specific context and has only one method
+ * checkPermission. It is similar to AccessController except
+ * that it makes decsions based on the current context instead
+ * of the the current thread.
+ *
+ * It is created by call AccessController.getContext method.
+ *
+ * @author Mark Benvenuto
+ * @since 1.2
+ */
+public final class AccessControlContext
+{
+ private final ProtectionDomain[] protectionDomains;
+ private final DomainCombiner combiner;
+
+ /**
+ * Construct a new AccessControlContext with the specified
+ * ProtectionDomains. <code>context</code> must not be
+ * null and duplicates will be removed.
+ *
+ * @param context The ProtectionDomains to use
+ */
+ public AccessControlContext(ProtectionDomain[] context)
+ {
+ HashSet domains = new HashSet (context.length);
+ for (int i = 0; i < context.length; i++)
+ domains.add (context[i]);
+ protectionDomains = (ProtectionDomain[])
+ domains.toArray (new ProtectionDomain[domains.size()]);
+ combiner = null;
+ }
+
+ /**
+ * Construct a new AccessControlContext with the specified
+ * ProtectionDomains and DomainCombiner
+ *
+ * @since 1.3
+ */
+ public AccessControlContext(AccessControlContext acc,
+ DomainCombiner combiner)
+ {
+ // XXX check permission to call this.
+ AccessControlContext acc2 = AccessController.getContext();
+ protectionDomains = combiner.combine (acc2.protectionDomains,
+ acc.protectionDomains);
+ this.combiner = combiner;
+ }
+
+ AccessControlContext (ProtectionDomain[] domains, AccessControlContext acc,
+ DomainCombiner combiner)
+ {
+ protectionDomains = combiner.combine (domains, acc.protectionDomains);
+ this.combiner = combiner;
+ }
+
+ /**
+ * Returns the Domain Combiner associated with the AccessControlContext
+ *
+ * @return the DomainCombiner
+ */
+ public DomainCombiner getDomainCombiner()
+ {
+ return combiner;
+ }
+
+ /**
+ * Determines whether or not the specific permission is granted
+ * depending on the context it is within.
+ *
+ * @param perm a permission to check
+ *
+ * @throws AccessControlException if the permssion is not permitted
+ */
+ public void checkPermission(Permission perm) throws AccessControlException
+ {
+ if (protectionDomains.length == 0)
+ throw new AccessControlException ("permission not granted");
+ for (int i = 0; i < protectionDomains.length; i++)
+ if (!protectionDomains[i].implies(perm))
+ throw new AccessControlException ("permission not granted");
+ }
+
+ /**
+ * Checks if two AccessControlContexts are equal.
+ *
+ * It first checks if obj is an AccessControlContext class, and
+ * then checks if each ProtectionDomain matches.
+ *
+ * @param obj The object to compare this class to
+ *
+ * @return true if equal, false otherwise
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof AccessControlContext)
+ {
+ AccessControlContext acc = (AccessControlContext) obj;
+
+ if (acc.protectionDomains.length != protectionDomains.length)
+ return false;
+
+ int i, j;
+ for (i = 0; i < protectionDomains.length; i++)
+ {
+ for (j = 0; j < acc.protectionDomains.length; j++)
+ {
+ if (acc.protectionDomains[j].equals (protectionDomains[i]))
+ break;
+ }
+ if (j == acc.protectionDomains.length)
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Computes a hash code of this class
+ *
+ * @return a hash code representing this class
+ */
+ public int hashCode()
+ {
+ int h = 0;
+ for (int i = 0; i < protectionDomains.length; i++)
+ h ^= protectionDomains[i].hashCode();
+
+ return h;
+ }
+}
diff --git a/libjava/classpath/java/security/AccessControlException.java b/libjava/classpath/java/security/AccessControlException.java
new file mode 100644
index 00000000000..27aee7c869a
--- /dev/null
+++ b/libjava/classpath/java/security/AccessControlException.java
@@ -0,0 +1,97 @@
+/* AccessControlException.java -- Permission is denied
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception is thrown when the <code>AccessController</code> denies
+ * an attempt to perform an operation. This often keeps track of the
+ * permission that was not granted.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see AccessController
+ * @status updated to 1.4
+ */
+public class AccessControlException extends SecurityException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5138225684096988535L;
+
+ /**
+ * The <code>Permission</code> associated with this exception.
+ *
+ * @serial the permission
+ */
+ private final Permission perm;
+
+ /**
+ * Create a new instance with a descriptive error message, and a null
+ * <code>Permission</code> object.
+ *
+ * @param msg the descriptive error message
+ */
+ public AccessControlException(String msg)
+ {
+ this(msg, null);
+ }
+
+ /**
+ * Create a new instance with a descriptive error message and an associated
+ * <code>Permission</code> object.
+ *
+ * @param msg the descriptive error message
+ * @param perm the permission that caused this
+ */
+ public AccessControlException(String msg, Permission perm)
+ {
+ super(msg);
+ this.perm = perm;
+ }
+
+ /**
+ * This method returns the <code>Permission</code> object that caused
+ * this exception to be thrown.
+ *
+ * @return the denied permission, or null
+ */
+ public Permission getPermission()
+ {
+ return perm;
+ }
+}
diff --git a/libjava/classpath/java/security/AccessController.java b/libjava/classpath/java/security/AccessController.java
new file mode 100644
index 00000000000..bc9c2deefbb
--- /dev/null
+++ b/libjava/classpath/java/security/AccessController.java
@@ -0,0 +1,221 @@
+/* AccessController.java --- Access control context and permission checker
+ Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * Access control context and permission checker.
+ * Can check permissions in the access control context of the current thread
+ * through the <code>checkPermission()</code> method.
+ * Manipulates the access control context for code that needs to be executed
+ * the protection domain of the calling class (by explicitly ignoring the
+ * context of the calling code) in the <code>doPrivileged()</code> methods.
+ * And provides a <code>getContext()</code> method which gives the access
+ * control context of the current thread that can be used for checking
+ * permissions at a later time and/or in another thread.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @since 1.2
+ */
+public final class AccessController
+{
+ /**
+ * This class only has static methods so there is no public contructor.
+ */
+ private AccessController()
+ {
+ }
+
+ /**
+ * Checks wether the access control context of the current thread allows
+ * the given Permission. Throws an <code>AccessControlException</code>
+ * when the permission is not allowed in the current context. Otherwise
+ * returns silently without throwing an exception.
+ *
+ * @param perm the permission to be checked.
+ * @exception AccessControlException thrown if the current context does not
+ * allow the given permission.
+ */
+ public static void checkPermission(Permission perm)
+ throws AccessControlException
+ {
+ getContext().checkPermission(perm);
+ }
+
+ /**
+ * Calls the <code>run()</code> method of the given action with as
+ * (initial) access control context only the protection domain of the
+ * calling class. Calls to <code>checkPermission()</code> in the
+ * <code>run()</code> method ignore all earlier protection domains of
+ * classes in the call chain. Note that the protection domains of classes
+ * called by the code in the <code>run()</code> method are not ignored.
+ *
+ * @param action the <code>PrivilegedAction</code> whose <code>run()</code>
+ * should be be called.
+ * @return the result of the <code>action.run()</code> method.
+ */
+ public static Object doPrivileged(PrivilegedAction action)
+ {
+ VMAccessController.pushContext(null);
+ try
+ {
+ return action.run();
+ }
+ finally
+ {
+ VMAccessController.popContext();
+ }
+ }
+
+ /**
+ * Calls the <code>run()</code> method of the given action with as
+ * (initial) access control context the given context combined with the
+ * protection domain of the calling class. Calls to
+ * <code>checkPermission()</code> in the <code>run()</code> method ignore
+ * all earlier protection domains of classes in the call chain, but add
+ * checks for the protection domains given in the supplied context.
+ *
+ * @param action the <code>PrivilegedAction</code> whose <code>run()</code>
+ * should be be called.
+ * @param context the <code>AccessControlContext</code> whose protection
+ * domains should be added to the protection domain of the calling class.
+ * @return the result of the <code>action.run()</code> method.
+ */
+ public static Object doPrivileged(PrivilegedAction action,
+ AccessControlContext context)
+ {
+ VMAccessController.pushContext(context);
+ try
+ {
+ return action.run();
+ }
+ finally
+ {
+ VMAccessController.popContext();
+ }
+ }
+
+ /**
+ * Calls the <code>run()</code> method of the given action with as
+ * (initial) access control context only the protection domain of the
+ * calling class. Calls to <code>checkPermission()</code> in the
+ * <code>run()</code> method ignore all earlier protection domains of
+ * classes in the call chain. Note that the protection domains of classes
+ * called by the code in the <code>run()</code> method are not ignored.
+ * If the <code>run()</code> method throws an exception then this method
+ * will wrap that exception in an <code>PrivilegedActionException</code>.
+ *
+ * @param action the <code>PrivilegedExceptionAction</code> whose
+ * <code>run()</code> should be be called.
+ * @return the result of the <code>action.run()</code> method.
+ * @exception PrivilegedActionException wrapped around any exception that
+ * is thrown in the <code>run()</code> method.
+ */
+ public static Object doPrivileged(PrivilegedExceptionAction action)
+ throws PrivilegedActionException
+ {
+ VMAccessController.pushContext(null);
+ try
+ {
+ return action.run();
+ }
+ catch (Exception e)
+ {
+ throw new PrivilegedActionException(e);
+ }
+ finally
+ {
+ VMAccessController.popContext();
+ }
+ }
+
+ /**
+ * Calls the <code>run()</code> method of the given action with as
+ * (initial) access control context the given context combined with the
+ * protection domain of the calling class. Calls to
+ * <code>checkPermission()</code> in the <code>run()</code> method ignore
+ * all earlier protection domains of classes in the call chain, but add
+ * checks for the protection domains given in the supplied context.
+ * If the <code>run()</code> method throws an exception then this method
+ * will wrap that exception in an <code>PrivilegedActionException</code>.
+ *
+ * @param action the <code>PrivilegedExceptionAction</code> whose
+ * <code>run()</code> should be be called.
+ * @param context the <code>AccessControlContext</code> whose protection
+ * domains should be added to the protection domain of the calling class.
+ * @return the result of the <code>action.run()</code> method.
+ * @exception PrivilegedActionException wrapped around any exception that
+ * is thrown in the <code>run()</code> method.
+ */
+ public static Object doPrivileged(PrivilegedExceptionAction action,
+ AccessControlContext context)
+ throws PrivilegedActionException
+ {
+ VMAccessController.pushContext(context);
+ try
+ {
+ return action.run();
+ }
+ catch (Exception e)
+ {
+ throw new PrivilegedActionException(e);
+ }
+ finally
+ {
+ VMAccessController.popContext();
+ }
+ }
+
+ /**
+ * Returns the complete access control context of the current thread.
+ * The returned object encompasses all {@link ProtectionDomain} objects
+ * for all classes in the current call stack, or the set of protection
+ * domains until the last call to {@link
+ * #doPrivileged(java.security.PrivilegedAction)}.
+ *
+ * <p>Additionally, if a call was made to {@link
+ * #doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}
+ * that supplied an {@link AccessControlContext}, then that context
+ * will be intersected with the calculated one.
+ *
+ * @return The context.
+ */
+ public static AccessControlContext getContext()
+ {
+ return VMAccessController.getContext();
+ }
+}
diff --git a/libjava/classpath/java/security/AlgorithmParameterGenerator.java b/libjava/classpath/java/security/AlgorithmParameterGenerator.java
new file mode 100644
index 00000000000..5dc9e3bb274
--- /dev/null
+++ b/libjava/classpath/java/security/AlgorithmParameterGenerator.java
@@ -0,0 +1,302 @@
+/* AlgorithmParameterGenerator.java --- Algorithm Parameter Generator
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import gnu.java.security.Engine;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * <p>The <code>AlgorithmParameterGenerator</code> class is used to generate a
+ * set of parameters to be used with a certain algorithm. Parameter generators
+ * are constructed using the <code>getInstance()</code> factory methods (static
+ * methods that return instances of a given class).</p>
+ *
+ * <p>The object that will generate the parameters can be initialized in two
+ * different ways: in an algorithm-independent manner, or in an
+ * algorithm-specific manner:</p>
+ *
+ * <ul>
+ * <li>The algorithm-independent approach uses the fact that all parameter
+ * generators share the concept of a <i>"size"</i> and a <i>source of
+ * randomness</i>. The measure of <i>size</i> is universally shared by all
+ * algorithm parameters, though it is interpreted differently for different
+ * algorithms. For example, in the case of parameters for the <i>DSA</i>
+ * algorithm, <i>"size"</i> corresponds to the size of the prime modulus (in
+ * bits). When using this approach, algorithm-specific parameter generation
+ * values - if any - default to some standard values, unless they can be
+ * derived from the specified size.</li>
+ * <li>The other approach initializes a parameter generator object using
+ * algorithm-specific semantics, which are represented by a set of
+ * algorithm-specific parameter generation values. To generate Diffie-Hellman
+ * system parameters, for example, the parameter generation values usually
+ * consist of the size of the prime modulus and the size of the random
+ * exponent, both specified in number of bits.</li>
+ * </ul>
+ *
+ * <p>In case the client does not explicitly initialize the
+ * <code>AlgorithmParameterGenerator</code> (via a call to an <code>init()</code>
+ * method), each provider must supply (and document) a default initialization.
+ * For example, the <b>GNU</b> provider uses a default modulus prime size of
+ * <code>1024</code> bits for the generation of <i>DSA</i> parameters.
+ *
+ * @author Mark Benvenuto
+ * @since 1.2
+ * @see AlgorithmParameters
+ * @see AlgorithmParameterSpec
+ */
+public class AlgorithmParameterGenerator
+{
+ /** Service name for algorithm parameter generators. */
+ private static final String ALGORITHM_PARAMETER_GENERATOR =
+ "AlgorithmParameterGenerator";
+
+ private AlgorithmParameterGeneratorSpi paramGenSpi;
+ private Provider provider;
+ private String algorithm;
+
+ /**
+ * Creates an <code>AlgorithmParameterGenerator</code> object.
+ *
+ * @param paramGenSpi the delegate.
+ * @param provider the provider.
+ * @param algorithm the algorithm.
+ */
+ protected AlgorithmParameterGenerator(AlgorithmParameterGeneratorSpi
+ paramGenSpi, Provider provider,
+ String algorithm)
+ {
+ this.paramGenSpi = paramGenSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the standard name of the algorithm this parameter generator is
+ * associated with.
+ *
+ * @return the string name of the algorithm.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Generates an <code>AlgorithmParameterGenerator</code> object that
+ * implements the specified digest algorithm. If the default provider package
+ * provides an implementation of the requested digest algorithm, an instance
+ * of <code>AlgorithmParameterGenerator</code> containing that implementation
+ * is returned. If the algorithm is not available in the default package,
+ * other packages are searched.
+ *
+ * @param algorithm the string name of the algorithm this parameter generator
+ * is associated with.
+ * @return the new <code>AlgorithmParameterGenerator</code> object.
+ * @throws NoSuchAlgorithmException if the algorithm is not available in the
+ * environment.
+ */
+ public static AlgorithmParameterGenerator getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore.
+ }
+
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * Generates an <code>AlgorithmParameterGenerator</code> object for the
+ * requested algorithm, as supplied from the specified provider, if such a
+ * parameter generator is available from the provider.
+ *
+ * @param algorithm the string name of the algorithm.
+ * @param provider the string name of the provider.
+ * @return the new <code>AlgorithmParameterGenerator</code> object.
+ * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
+ * available from the <code>provider</code>.
+ * @throws NoSuchProviderException if the <code>provider</code> is not
+ * available in the environment.
+ * @throws IllegalArgumentException if the <code>provider</code> name is
+ * <code>null</code> or empty.
+ * @see Provider
+ */
+ public static AlgorithmParameterGenerator getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("Illegal provider");
+
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ throw new NoSuchProviderException(provider);
+
+ return getInstance(algorithm, p);
+ }
+
+ /**
+ * Generates an AlgorithmParameterGenerator object for the requested
+ * algorithm, as supplied from the specified provider, if such a parameter
+ * generator is available from the provider. Note: the <code>provider</code>
+ * doesn't have to be registered.
+ *
+ * @param algorithm the string name of the algorithm.
+ * @param provider the provider.
+ * @return the new AlgorithmParameterGenerator object.
+ * @throws NoSuchAlgorithmException if the algorithm is not available from
+ * the provider.
+ * @throws IllegalArgumentException if the provider is null.
+ * @since 1.4
+ * @see Provider
+ */
+ public static AlgorithmParameterGenerator getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("Illegal provider");
+
+ try
+ {
+ return new AlgorithmParameterGenerator(
+ (AlgorithmParameterGeneratorSpi) Engine.getInstance(
+ ALGORITHM_PARAMETER_GENERATOR, algorithm, provider),
+ provider, algorithm);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ }
+
+ /**
+ * Returns the provider of this algorithm parameter generator object.
+ *
+ * @return the provider of this algorithm parameter generator object.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Initializes this parameter generator for a certain <i>size</i>. To create
+ * the parameters, the {@link SecureRandom} implementation of the
+ * highest-priority installed provider is used as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * {@link SecureRandom}, a system-provided source of randomness is used.)
+ *
+ * @param size the size (number of bits).
+ */
+ public final void init(int size)
+ {
+ init(size, new SecureRandom());
+ }
+
+ /**
+ * Initializes this parameter generator for a certain size and source of
+ * randomness.
+ *
+ * @param size the size (number of bits).
+ * @param random the source of randomness.
+ */
+ public final void init(int size, SecureRandom random)
+ {
+ paramGenSpi.engineInit(size, random);
+ }
+
+ /**
+ * Initializes this parameter generator with a set of algorithm-specific
+ * parameter generation values. To generate the parameters, the {@link
+ * SecureRandom} implementation of the highest-priority installed provider is
+ * used as the source of randomness. (If none of the installed providers
+ * supply an implementation of {@link SecureRandom}, a system-provided source
+ * of randomness is used.)
+ *
+ * @param genParamSpec the set of algorithm-specific parameter generation
+ * values.
+ * @throws InvalidAlgorithmParameterException if the given parameter
+ * generation values are inappropriate for this parameter generator.
+ */
+ public final void init(AlgorithmParameterSpec genParamSpec)
+ throws InvalidAlgorithmParameterException
+ {
+ init(genParamSpec, new SecureRandom());
+ }
+
+ /**
+ * Initializes this parameter generator with a set of algorithm-specific
+ * parameter generation values.
+ *
+ * @param genParamSpec the set of algorithm-specific parameter generation
+ * values.
+ * @param random the source of randomness.
+ * @throws InvalidAlgorithmParameterException if the given parameter
+ * generation values are inappropriate for this parameter generator.
+ */
+ public final void init(AlgorithmParameterSpec genParamSpec,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ paramGenSpi.engineInit(genParamSpec, random);
+ }
+
+ /**
+ * Generates the parameters.
+ *
+ * @return the new {@link AlgorithmParameters} object.
+ */
+ public final AlgorithmParameters generateParameters()
+ {
+ return paramGenSpi.engineGenerateParameters();
+ }
+}
diff --git a/libjava/classpath/java/security/AlgorithmParameterGeneratorSpi.java b/libjava/classpath/java/security/AlgorithmParameterGeneratorSpi.java
new file mode 100644
index 00000000000..3143ea76b8b
--- /dev/null
+++ b/libjava/classpath/java/security/AlgorithmParameterGeneratorSpi.java
@@ -0,0 +1,94 @@
+/* AlgorithmParameterGeneratorSpi.java --- Algorithm Parameter Generator SPI
+ Copyright (C) 1999 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.security;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ AlgorithmParameterGeneratorSpi is the Service Provider
+ Interface for the AlgorithmParameterGenerator class.
+ This class is used to generate the algorithm parameters
+ for a specific algorithm.
+
+ @since JDK 1.2
+ @author Mark Benvenuto
+ */
+public abstract class AlgorithmParameterGeneratorSpi
+{
+
+ /**
+ Constructs a new AlgorithmParameterGeneratorSpi
+ */
+ public AlgorithmParameterGeneratorSpi()
+ {
+ }
+
+ /**
+ Initializes the parameter generator with the specified size
+ and SecureRandom
+
+ @param size the size( in number of bits)
+ @param random the SecureRandom class to use for randomness
+ */
+ protected abstract void engineInit(int size, SecureRandom random);
+
+ /**
+ Initializes the parameter generator with the specified
+ AlgorithmParameterSpec and SecureRandom classes.
+
+ If genParamSpec is an invalid AlgorithmParameterSpec for this
+ AlgorithmParameterGeneratorSpi then it throws
+ InvalidAlgorithmParameterException
+
+ @param genParamSpec the AlgorithmParameterSpec class to use
+ @param random the SecureRandom class to use for randomness
+
+ @throws InvalidAlgorithmParameterException genParamSpec is invalid
+ */
+ protected abstract void engineInit(AlgorithmParameterSpec genParamSpec,
+ SecureRandom random) throws
+ InvalidAlgorithmParameterException;
+
+
+ /**
+ Generate a new set of AlgorithmParameters.
+
+ @returns a new set of algorithm parameters
+ */
+ protected abstract AlgorithmParameters engineGenerateParameters();
+
+}
diff --git a/libjava/classpath/java/security/AlgorithmParameters.java b/libjava/classpath/java/security/AlgorithmParameters.java
new file mode 100644
index 00000000000..038fbb4bd64
--- /dev/null
+++ b/libjava/classpath/java/security/AlgorithmParameters.java
@@ -0,0 +1,340 @@
+/* AlgorithmParameters.java --- Algorithm Parameters Implementation Class
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import gnu.java.security.Engine;
+
+import java.io.IOException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+/**
+ * <p>This class is used as an opaque representation of cryptographic
+ * parameters.</p>
+ *
+ * <p>An <code>AlgorithmParameters</code> object for managing the parameters
+ * for a particular algorithm can be obtained by calling one of the
+ * <code>getInstance()</code> factory methods (static methods that return
+ * instances of a given class).</p>
+ *
+ * <p>There are two ways to request such an implementation: by specifying
+ * either just an algorithm name, or both an algorithm name and a package
+ * provider.</p>
+ *
+ * <ul>
+ * <li>If just an algorithm name is specified, the system will determine if
+ * there is an AlgorithmParameters implementation for the algorithm requested
+ * available in the environment, and if there is more than one, if there is
+ * a preferred one.</li>
+ * <li>If both an algorithm name and a package provider are specified, the
+ * system will determine if there is an implementation in the package
+ * requested, and throw an exception if there is not.</li>
+ * </ul>
+ *
+ * <p>Once an <code>AlgorithmParameters</code> object is returned, it must be
+ * initialized via a call to <code>init()</code>, using an appropriate
+ * parameter specification or parameter encoding.</p>
+ *
+ * <p>A transparent parameter specification is obtained from an
+ * <code>AlgorithmParameters</code> object via a call to
+ * <code>getParameterSpec()</code>, and a byte encoding of the parameters is
+ * obtained via a call to <code>getEncoded()</code>.</p>
+ *
+ * @author Mark Benvenuto
+ * @since 1.2
+ * @see AlgorithmParameterSpec
+ * @see java.security.spec.DSAParameterSpec
+ * @see KeyPairGenerator
+ */
+public class AlgorithmParameters
+{
+ /** Service name for algorithm parameters. */
+ private static final String ALGORITHM_PARAMETERS = "AlgorithmParameters";
+
+ private AlgorithmParametersSpi paramSpi;
+ private Provider provider;
+ private String algorithm;
+
+ /**
+ * Creates an <code>AlgorithmParameters</code> object.
+ *
+ * @param paramSpi the delegate.
+ * @param provider the provider.
+ * @param algorithm the algorithm.
+ */
+ protected AlgorithmParameters(AlgorithmParametersSpi paramSpi,
+ Provider provider, String algorithm)
+ {
+ this.paramSpi = paramSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the name of the algorithm associated with this parameter object.
+ *
+ * @return the algorithm name.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * <p>Generates a parameter object for the specified algorithm.</p>
+ *
+ * <p>If the default provider package provides an implementation of the
+ * requested algorithm, an instance of <code>AlgorithmParameters</code>
+ * containing that implementation is returned. If the algorithm is not
+ * available in the default package, other packages are searched.</p>
+ *
+ * <p>The returned parameter object must be initialized via a call to
+ * <code>init()</code>, using an appropriate parameter specification or
+ * parameter encoding.</p>
+ *
+ * @param algorithm the name of the algorithm requested.
+ * @return the new parameter object.
+ * @throws NoSuchAlgorithmException if the algorithm is not available in the
+ * environment.
+ */
+ public static AlgorithmParameters getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore this.
+ }
+
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * <p>Generates a parameter object for the specified algorithm, as supplied
+ * by the specified provider, if such an algorithm is available from the
+ * provider.</p>
+ *
+ * <p>The returned parameter object must be initialized via a call to
+ * <code>init()</code>, using an appropriate parameter specification or
+ * parameter encoding.</p>
+ *
+ * @param algorithm the name of the algorithm requested.
+ * @param provider the name of the provider.
+ * @return the new parameter object.
+ * @throws NoSuchAlgorithmException if the algorithm is not available in the
+ * package supplied by the requested provider.
+ * @throws NoSuchProviderException if the provider is not available in the
+ * environment.
+ * @throws IllegalArgumentException if the provider name is null or empty.
+ * @see Provider
+ */
+ public static AlgorithmParameters getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("Illegal provider");
+
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ throw new NoSuchProviderException(provider);
+
+ return getInstance(algorithm, p);
+ }
+
+ /**
+ * Generates an <code>AlgorithmParameterGenerator</code> object for the
+ * requested algorithm, as supplied from the specified provider, if such a
+ * parameter generator is available from the provider. Note: the
+ * <code>provider</code> doesn't have to be registered.
+ *
+ * @param algorithm the string name of the algorithm.
+ * @param provider the provider.
+ * @return the new <code>AlgorithmParameterGenerator</code> object.
+ * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
+ * available from the <code>provider</code>.
+ * @throws IllegalArgumentException if the <code>provider</code> is
+ * <code>null</code>.
+ * @since 1.4
+ */
+ public static AlgorithmParameters getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("Illegal provider");
+
+ try
+ {
+ return new AlgorithmParameters((AlgorithmParametersSpi)
+ Engine.getInstance(ALGORITHM_PARAMETERS, algorithm, provider),
+ provider, algorithm);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ }
+
+ /**
+ * Returns the provider of this parameter object.
+ *
+ * @return the provider of this parameter object.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Initializes this parameter object using the parameters specified in
+ * <code>paramSpec</code>.
+ *
+ * @param paramSpec the parameter specification.
+ * @throws InvalidParameterSpecException if the given parameter specification
+ * is inappropriate for the initialization of this parameter object, or if
+ * this parameter object has already been initialized.
+ */
+ public final void init(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException
+ {
+ paramSpi.engineInit(paramSpec);
+ }
+
+ /**
+ * Imports the specified parameters and decodes them according to the primary
+ * decoding format for parameters. The primary decoding format for parameters
+ * is ASN.1, if an ASN.1 specification for this type of parameters exists.
+ *
+ * @param params the encoded parameters.
+ * @throws IOException on decoding errors, or if this parameter object has
+ * already been initialized.
+ */
+ public final void init(byte[]params) throws IOException
+ {
+ paramSpi.engineInit(params);
+ }
+
+ /**
+ * Imports the parameters from params and decodes them according to the
+ * specified decoding scheme. If <code>format</code> is <code>null</code>,
+ * the primary decoding format for parameters is used. The primary decoding
+ * format is ASN.1, if an ASN.1 specification for these parameters exists.
+ *
+ * @param params the encoded parameters.
+ * @param format the name of the decoding scheme.
+ * @throws IOException on decoding errors, or if this parameter object has
+ * already been initialized.
+ */
+ public final void init(byte[]params, String format) throws IOException
+ {
+ paramSpi.engineInit(params, format);
+ }
+
+ /**
+ * Returns a (transparent) specification of this parameter object.
+ * <code>paramSpec</code> identifies the specification class in which the
+ * parameters should be returned. It could, for example, be
+ * <code>DSAParameterSpec.class</code>, to indicate that the parameters should
+ * be returned in an instance of the {@link java.security.spec.DSAParameterSpec}
+ * class.
+ *
+ * @param paramSpec the specification class in which the parameters should be
+ * returned.
+ * @return the parameter specification.
+ * @throws InvalidParameterSpecException if the requested parameter
+ * specification is inappropriate for this parameter object, or if this
+ * parameter object has not been initialized.
+ */
+ public final AlgorithmParameterSpec getParameterSpec(Class paramSpec)
+ throws InvalidParameterSpecException
+ {
+ return paramSpi.engineGetParameterSpec(paramSpec);
+ }
+
+ /**
+ * Returns the parameters in their primary encoding format. The primary
+ * encoding format for parameters is ASN.1, if an ASN.1 specification for
+ * this type of parameters exists.
+ *
+ * @return the parameters encoded using their primary encoding format.
+ * @throws IOException on encoding errors, or if this parameter object has not
+ * been initialized.
+ */
+ public final byte[] getEncoded() throws IOException
+ {
+ return paramSpi.engineGetEncoded();
+ }
+
+ /**
+ * Returns the parameters encoded in the specified scheme. If format is
+ * <code>null</code>, the primary encoding format for parameters is used. The
+ * primary encoding format is ASN.1, if an ASN.1 specification for these
+ * parameters exists.
+ *
+ * @param format the name of the encoding format.
+ * @return the parameters encoded using the specified encoding scheme.
+ * @throws IOException on encoding errors, or if this parameter object has
+ * not been initialized.
+ */
+ public final byte[] getEncoded(String format) throws IOException
+ {
+ return paramSpi.engineGetEncoded(format);
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters, or <code>null</code>
+ * if this parameter object has not been initialized.
+ */
+ public final String toString()
+ {
+ return paramSpi.engineToString();
+ }
+}
diff --git a/libjava/classpath/java/security/AlgorithmParametersSpi.java b/libjava/classpath/java/security/AlgorithmParametersSpi.java
new file mode 100644
index 00000000000..a9faa154374
--- /dev/null
+++ b/libjava/classpath/java/security/AlgorithmParametersSpi.java
@@ -0,0 +1,149 @@
+/* AlgorithmParametersSpi.java --- Algorithm Parameters SPI
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.IOException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+/**
+ * AlgorithmParametersSpi is the Service Provider Interface
+ * for the Algorithm Parameters class. This class is used
+ * to manage the algorithm parameters.
+ *
+ * @since 1.2
+ * @author Mark Benvenuto
+ */
+public abstract class AlgorithmParametersSpi
+{
+ /**
+ * Creates a new instance of AlgorithmParametersSpi
+ */
+ public AlgorithmParametersSpi()
+ {
+ }
+
+ /**
+ * Initializes the engine with the specified
+ * AlgorithmParameterSpec class.
+ *
+ * @param paramSpec A AlgorithmParameterSpec to initialize with
+ *
+ * @throws InvalidParameterSpecException For an inapporiate
+ * ParameterSpec class
+ */
+ protected abstract void engineInit(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException;
+
+ /**
+ * Initializes the engine with the specified
+ * parameters stored in the byte array and decodes them
+ * according to the ASN.1 specification. If the ASN.1
+ * specification exists then it succeeds or else it throws
+ * IOException.
+ *
+ * @param params Parameters to initialize with
+ *
+ * @throws IOException Decoding Error
+ */
+ protected abstract void engineInit(byte[]params) throws IOException;
+
+ /**
+ * Initializes the engine with the specified
+ * parameters stored in the byte array and decodes them
+ * according to the specified decoding specification.
+ * If format is null, then it is decoded using the ASN.1
+ * specification if it exists or else it throws
+ * IOException.
+ *
+ * @param params Parameters to initialize with
+ * @param format Name of decoding format to use
+ *
+ * @throws IOException Decoding Error
+ */
+ protected abstract void engineInit(byte[]params, String format)
+ throws IOException;
+
+
+ /**
+ * Returns a specification of this AlgorithmParameters object.
+ * paramSpec identifies the class to return the AlgortihmParameters
+ * in.
+ *
+ * @param paramSpec Class to return AlgorithmParameters in
+ *
+ * @return the parameter specification
+ *
+ * @throws InvalidParameterSpecException if the paramSpec is an
+ * invalid parameter class
+ */
+ protected abstract AlgorithmParameterSpec engineGetParameterSpec(Class
+ paramSpec)
+ throws InvalidParameterSpecException;
+
+
+ /**
+ * Returns the parameters in the default encoding format.
+ * The primary encoding format is ASN.1 format if it exists
+ * for the specified type.
+ *
+ * @return byte array representing the parameters
+ */
+ protected abstract byte[] engineGetEncoded() throws IOException;
+
+
+ /**
+ * Returns the parameters in the specified encoding format.
+ * If <code>format</code> is <code>null</code> then the
+ * primary encoding format is used, the ASN.1 format,
+ * if it exists for the specified type.
+ *
+ * @return byte array representing the parameters
+ */
+ protected abstract byte[] engineGetEncoded(String format)
+ throws IOException;
+
+ /**
+ * Returns a string describing the parameters in the
+ * AlgorithmParametersSpi class.
+ *
+ * @return A string representing the format of the parameters.
+ */
+ protected abstract String engineToString();
+}
diff --git a/libjava/classpath/java/security/AllPermission.java b/libjava/classpath/java/security/AllPermission.java
new file mode 100644
index 00000000000..6adcd8c9c96
--- /dev/null
+++ b/libjava/classpath/java/security/AllPermission.java
@@ -0,0 +1,198 @@
+/* AllPermission.java -- Permission to do anything
+ Copyright (C) 1998, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import gnu.java.util.EmptyEnumeration;
+
+import java.util.Collections;
+import java.util.Enumeration;
+
+/**
+ * This class is a permission that implies all other permissions. Granting
+ * this permission effectively grants all others. Extreme caution should
+ * be exercised in granting this permission.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see AccessController
+ * @see Permissions
+ * @see SecurityManager
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class AllPermission extends Permission
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -2916474571451318075L;
+
+ /**
+ * Create a new AllPermission object.
+ */
+ public AllPermission()
+ {
+ super("*");
+ }
+
+ /**
+ * Create a new AllPermission object. The parameters are ignored, as all
+ * permission implies ALL PERMISSION.
+ *
+ * @param name ignored
+ * @param actions ignored
+ */
+ public AllPermission(String name, String actions)
+ {
+ super("*");
+ }
+
+ /**
+ * This method always returns <code>true</code> to indicate that this
+ * permission always implies that any other permission is also granted.
+ *
+ * @param perm ignored
+ * @return true, the permission is implied
+ */
+ public boolean implies(Permission perm)
+ {
+ return true;
+ }
+
+ /**
+ * Checks an object for equality. All AllPermissions are equal.
+ *
+ * @param obj the <code>Object</code> to test for equality
+ */
+ public boolean equals(Object obj)
+ {
+ return obj instanceof AllPermission;
+ }
+
+ /**
+ * This method returns a hash code for this object. This returns 1.
+ *
+ * @return a hash value for this object
+ */
+ public int hashCode()
+ {
+ return 1;
+ }
+
+ /**
+ * This method returns the list of actions associated with this object.
+ * This will always be the empty string ("") for this class.
+ *
+ * @return the action list
+ */
+ public String getActions()
+ {
+ return "";
+ }
+
+ /**
+ * Returns a PermissionCollection which can hold AllPermission.
+ *
+ * @return a permission collection
+ */
+ public PermissionCollection newPermissionCollection()
+ {
+ return new AllPermissionCollection();
+ }
+
+ /**
+ * Implements AllPermission.newPermissionCollection, and obeys serialization
+ * of JDK.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class AllPermissionCollection extends PermissionCollection
+ {
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -4023755556366636806L;
+
+ /**
+ * Whether an AllPermission has been added to the collection.
+ *
+ * @serial if all permission is in the collection yet
+ */
+ private boolean all_allowed;
+
+ /**
+ * Add an AllPermission.
+ *
+ * @param perm the permission to add
+ * @throws IllegalArgumentException if perm is not an AllPermission
+ * @throws SecurityException if the collection is read-only
+ */
+ public void add(Permission perm)
+ {
+ if (isReadOnly())
+ throw new SecurityException();
+ if (! (perm instanceof AllPermission))
+ throw new IllegalArgumentException();
+ all_allowed = true;
+ }
+
+ /**
+ * Returns true if this collection implies a permission.
+ *
+ * @param perm the permission to check
+ * @return true if this collection contains an AllPermission
+ */
+ public boolean implies(Permission perm)
+ {
+ return all_allowed;
+ }
+
+ /**
+ * Returns an enumeration of the elements in the collection.
+ *
+ * @return the elements in the collection
+ */
+ public Enumeration elements()
+ {
+ return all_allowed
+ ? Collections.enumeration(Collections.singleton(new AllPermission()))
+ : EmptyEnumeration.getInstance();
+ }
+ } // class AllPermissionCollection
+} // class AllPermission
diff --git a/libjava/classpath/java/security/BasicPermission.java b/libjava/classpath/java/security/BasicPermission.java
new file mode 100644
index 00000000000..267a6e292ab
--- /dev/null
+++ b/libjava/classpath/java/security/BasicPermission.java
@@ -0,0 +1,308 @@
+/* BasicPermission.java -- implements a simple named permission
+ Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * This class implements a simple model for named permissions without an
+ * associated action list. That is, either the named permission is granted
+ * or it is not.
+ *
+ * <p>It also supports trailing wildcards to allow the easy granting of
+ * permissions in a hierarchical fashion. (For example, the name "org.gnu.*"
+ * might grant all permissions under the "org.gnu" permissions hierarchy).
+ * The only valid wildcard character is a '*' which matches anything. It
+ * must be the rightmost element in the permission name and must follow a
+ * '.' or else the Permission name must consist of only a '*'. Any other
+ * occurrence of a '*' is not valid.
+ *
+ * <p>This class ignores the action list. Subclasses can choose to implement
+ * actions on top of this class if desired.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Permission
+ * @see Permissions
+ * @see PermissionCollection
+ * @see RuntimePermission
+ * @see SecurityPermission
+ * @see PropertyPermission
+ * @see AWTPermission
+ * @see NetPermission
+ * @see SecurityManager
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class BasicPermission extends java.security.Permission
+ implements Serializable
+ // FIXME extends with fully qualified classname as workaround for gcj 3.3.
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 6279438298436773498L;
+
+ /**
+ * Create a new instance with the specified permission name. If the
+ * name is empty an exception is thrown.
+ *
+ * @param name the name of this permission
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException if name is invalid
+ */
+ public BasicPermission(String name)
+ {
+ super(name);
+
+ // This routine used to check for illegal wildcards, but no such
+ // requirement exists in the specification and Sun's runtime
+ // doesn't appear to do it.
+
+ if ("".equals(name))
+ throw new IllegalArgumentException("Empty name");
+ }
+
+ /**
+ * Create a new instance with the specified permission name. If the name
+ * is empty, or contains an illegal wildcard character, an exception is
+ * thrown. The actions parameter is ignored.
+ *
+ * @param name the name of this permission
+ * @param actions ignored
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException if name is invalid
+ */
+ public BasicPermission(String name, String actions)
+ {
+ this(name);
+ }
+
+ /**
+ * This method tests to see if the specified permission is implied by this
+ * permission. This will be true if the following conditions are met:<ul>
+ * <li>The specified object is an instance of the same class as this
+ * object.</li>
+ * <li>The name of the specified permission is implied by this permission's
+ * name based on wildcard matching. For example, "a.*" implies "a.b".</li>
+ * </ul>
+ *
+ * @param perm the <code>Permission</code> object to test against
+ * @return true if the specified permission is implied
+ */
+ public boolean implies(Permission perm)
+ {
+ if (! getClass().isInstance(perm))
+ return false;
+
+ String otherName = perm.getName();
+ String name = getName();
+
+ if (name.equals(otherName))
+ return true;
+
+ int last = name.length() - 1;
+ return name.charAt(last) == '*'
+ && otherName.startsWith(name.substring(0, last));
+ }
+
+ /**
+ * This method tests to see if this object is equal to the specified
+ * <code>Object</code>. This will be true if and only if the specified
+ * object meets the following conditions:<ul>
+ * <li>It is an instance of the same class as this.</li>
+ * <li>It has the same name as this permission.</li>
+ * </ul>
+ *
+ * @param obj the <code>Object</code> to test for equality
+ * @return true if obj is semantically equal to this
+ */
+ public boolean equals(Object obj)
+ {
+ return getClass().isInstance(obj)
+ && getName().equals(((BasicPermission) obj).getName());
+ }
+
+ /**
+ * This method returns a hash code for this permission object. The hash
+ * code returned is the value returned by calling the <code>hashCode</code>
+ * method on the <code>String</code> that is the name of this permission.
+ *
+ * @return a hash value for this object
+ */
+ public int hashCode()
+ {
+ return getName().hashCode();
+ }
+
+ /**
+ * This method returns a list of the actions associated with this
+ * permission. This method always returns the empty string ("") since
+ * this class ignores actions.
+ *
+ * @return the action list
+ */
+ public String getActions()
+ {
+ return "";
+ }
+
+ /**
+ * This method returns an instance of <code>PermissionCollection</code>
+ * suitable for storing <code>BasicPermission</code> objects. The
+ * collection returned can only store objects of the same type as this.
+ * Subclasses which use actions must override this method; but a class with
+ * no actions will work fine with this.
+ *
+ * @return a new empty <code>PermissionCollection</code> object
+ */
+ public PermissionCollection newPermissionCollection()
+ {
+ return new BasicPermissionCollection(getClass());
+ }
+
+ /**
+ * Implements AllPermission.newPermissionCollection, and obeys serialization
+ * of JDK.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class BasicPermissionCollection extends PermissionCollection
+ {
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 739301742472979399L;
+
+ /**
+ * The permissions in the collection.
+ *
+ * @serial a hash mapping name to permissions, all of type permClass
+ */
+ private final Hashtable permissions = new Hashtable();
+
+ /**
+ * If "*" is in the collection.
+ *
+ * @serial true if a permission named "*" is in the collection
+ */
+ private boolean all_allowed;
+
+ /**
+ * The runtime class which all entries in the table must belong to.
+ *
+ * @serial the limiting subclass of this collection
+ */
+ private final Class permClass;
+
+ /**
+ * Construct a collection over the given runtime class.
+ *
+ * @param c the class
+ */
+ BasicPermissionCollection(Class c)
+ {
+ permClass = c;
+ }
+
+ /**
+ * Add a Permission. It must be of the same type as the permission which
+ * created this collection.
+ *
+ * @param perm the permission to add
+ * @throws IllegalArgumentException if perm is not the correct type
+ * @throws SecurityException if the collection is read-only
+ */
+ public void add(Permission perm)
+ {
+ if (isReadOnly())
+ throw new SecurityException("readonly");
+ if (! permClass.isInstance(perm))
+ throw new IllegalArgumentException("Expecting instance of " + permClass);
+ BasicPermission bp = (BasicPermission) perm;
+ String name = bp.getName();
+ if (name.equals("*"))
+ all_allowed = true;
+ permissions.put(name, bp);
+ }
+
+ /**
+ * Returns true if this collection implies the given permission.
+ *
+ * @param permission the permission to check
+ * @return true if it is implied by this
+ */
+ public boolean implies(Permission permission)
+ {
+ if (! permClass.isInstance(permission))
+ return false;
+ if (all_allowed)
+ return true;
+ BasicPermission toImply = (BasicPermission) permission;
+ String name = toImply.getName();
+ if (name.equals("*"))
+ return false;
+ int prefixLength = name.length();
+ if (name.endsWith("*"))
+ prefixLength -= 2;
+
+ while (true)
+ {
+ if (permissions.get(name) != null)
+ return true;
+ prefixLength = name.lastIndexOf('.', prefixLength);
+ if (prefixLength < 0)
+ return false;
+ name = name.substring(0, prefixLength + 1) + '*';
+ }
+ }
+
+ /**
+ * Enumerate over the collection.
+ *
+ * @return an enumeration of the collection contents
+ */
+ public Enumeration elements()
+ {
+ return permissions.elements();
+ }
+ } // class BasicPermissionCollection
+} // class BasicPermission
diff --git a/libjava/classpath/java/security/Certificate.java b/libjava/classpath/java/security/Certificate.java
new file mode 100644
index 00000000000..5cdba6e101b
--- /dev/null
+++ b/libjava/classpath/java/security/Certificate.java
@@ -0,0 +1,125 @@
+/* Certificate.java -- deprecated interface for modeling digital certificates
+ Copyright (C) 1998, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * This interface models a digital certificate which verifies the
+ * authenticity of a party. This class simply allows certificate
+ * information to be queried, it does not guarantee that the certificate
+ * is valid.
+ *
+ * <p>This class is deprecated in favor of the new java.security.cert package.
+ * It exists for backward compatibility only.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @deprecated use {@link java.security.cert} instead
+ * @status updated to 1.4
+ */
+public interface Certificate
+{
+ /**
+ * This method returns the <code>Principal</code> that is guaranteeing
+ * this certificate.
+ *
+ * @return the <code>Principal</code> guaranteeing the certificate
+ */
+ Principal getGuarantor();
+
+ /**
+ * This method returns the <code>Principal</code> being guaranteed by
+ * this certificate.
+ *
+ * @return the <code>Principal</code> guaranteed by this certificate
+ */
+ Principal getPrincipal();
+
+ /**
+ * This method returns the public key for the <code>Principal</code> that
+ * is being guaranteed.
+ *
+ * @return the <code>PublicKey</code> of the Principal being guaranteed
+ */
+ PublicKey getPublicKey();
+
+ /**
+ * This method writes the certificate to an <code>OutputStream</code> in
+ * a format that can be understood by the <code>decode</code> method.
+ *
+ * @param out the <code>OutputStream</code> to write to
+ * @throws KeyException if there is a problem with the certificate
+ * @throws IOException if an error occurs writing to the stream
+ * @see #decode(InputStream)
+ * @see #getFormat()
+ */
+ void encode(OutputStream out) throws KeyException, IOException;
+
+ /**
+ * This method reads an encoded certificate from an <code>InputStream</code>.
+ *
+ * @param in the <code>InputStream</code> to read from
+ * @throws KeyException if there is a problem with the certificate data
+ * @throws IOException if an error occurs reading from the stream
+ * @see #encode(OutputStream)
+ * @see #getFormat()
+ */
+ void decode(InputStream in) throws KeyException, IOException;
+
+ /**
+ * This method returns the encoding format of the certificate (e.g., "PGP",
+ * "X.509"). This format is used by the <code>encode</code> and
+ * <code>decode</code> methods.
+ *
+ * @return the encoding format being used
+ */
+ String getFormat();
+
+ /**
+ * This method returns a <code>String</code> representation of the contents
+ * of this certificate.
+ *
+ * @param detail true to provided more detailed information
+ * @return the string representation
+ */
+ String toString(boolean detail);
+} // interface Certificate
diff --git a/libjava/classpath/java/security/CodeSource.java b/libjava/classpath/java/security/CodeSource.java
new file mode 100644
index 00000000000..b516170281c
--- /dev/null
+++ b/libjava/classpath/java/security/CodeSource.java
@@ -0,0 +1,354 @@
+/* CodeSource.java -- Code location and certifcates
+ Copyright (C) 1998, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.net.SocketPermission;
+import java.net.URL;
+// Note that this overrides Certificate in this package.
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * This class represents a location from which code is loaded (as
+ * represented by a URL), and the list of certificates that are used to
+ * check the signatures of signed code loaded from this source.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class CodeSource implements Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4977541819976013951L;
+
+ /**
+ * This is the URL that represents the code base from which code will
+ * be loaded.
+ *
+ * @serial the code location
+ */
+ private final URL location;
+
+ /** The set of certificates for this code base. */
+ private transient HashSet certs;
+
+ /**
+ * This creates a new instance of <code>CodeSource</code> that loads code
+ * from the specified URL location and which uses the specified certificates
+ * for verifying signatures.
+ *
+ * @param location the location from which code will be loaded
+ * @param certs the list of certificates
+ */
+ public CodeSource(URL location, Certificate[] certs)
+ {
+ this.location = location;
+ if (certs != null)
+ this.certs = new HashSet(Arrays.asList(certs));
+ }
+
+ /**
+ * This method returns a hash value for this object.
+ *
+ * @return a hash value for this object
+ */
+ public int hashCode()
+ {
+ return (location == null ? 0 : location.hashCode())
+ ^ (certs == null ? 0 : certs.hashCode());
+ }
+
+ /**
+ * This method tests the specified <code>Object</code> for equality with
+ * this object. This will be true if and only if the locations are equal
+ * and the certificate sets are identical (ignoring order).
+ *
+ * @param obj the <code>Object</code> to test against
+ * @return true if the specified object is equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof CodeSource))
+ return false;
+ CodeSource cs = (CodeSource) obj;
+ return (certs == null ? cs.certs == null : certs.equals(cs.certs))
+ && (location == null ? cs.location == null
+ : location.equals(cs.location));
+ }
+
+ /**
+ * This method returns the URL specifying the location from which code
+ * will be loaded under this <code>CodeSource</code>.
+ *
+ * @return the code location for this <code>CodeSource</code>
+ */
+ public final URL getLocation()
+ {
+ return location;
+ }
+
+ /**
+ * This method returns the list of digital certificates that can be used
+ * to verify the signatures of code loaded under this
+ * <code>CodeSource</code>.
+ *
+ * @return the certifcate list for this <code>CodeSource</code>
+ */
+ public final Certificate[] getCertificates()
+ {
+ if (certs == null)
+ return null;
+ Certificate[] c = new Certificate[certs.size()];
+ certs.toArray(c);
+ return c;
+ }
+
+ /**
+ * This method tests to see if a specified <code>CodeSource</code> is
+ * implied by this object. Effectively, to meet this test, the specified
+ * object must have all the certifcates this object has (but may have more),
+ * and must have a location that is a subset of this object's. In order
+ * for this object to imply the specified object, the following must be
+ * true:
+ *
+ * <ol>
+ * <li><em>codesource</em> must not be <code>null</code>.</li>
+ * <li>If <em>codesource</em> has a certificate list, all of it's
+ * certificates must be present in the certificate list of this
+ * code source.</li>
+ * <li>If this object does not have a <code>null</code> location, then
+ * the following addtional tests must be passed.
+ *
+ * <ol>
+ * <li><em>codesource</em> must not have a <code>null</code>
+ * location.</li>
+ * <li><em>codesource</em>'s location must be equal to this object's
+ * location, or
+ * <ul>
+ * <li><em>codesource</em>'s location protocol, port, and ref (aka,
+ * anchor) must equal this objects</li>
+ * <li><em>codesource</em>'s location host must imply this object's
+ * location host, as determined by contructing
+ * <code>SocketPermission</code> objects from each with no
+ * action list and using that classes's <code>implies</code>
+ * method</li>
+ * <li>If this object's location file ends with a '/', then the
+ * specified object's location file must start with this
+ * object's location file. Otherwise, the specified object's
+ * location file must start with this object's location file
+ * with the '/' character appended to it.</li>
+ * </ul></li>
+ * </ol></li>
+ * </ol>
+ *
+ * <p>For example, each of these locations imply the location
+ * "http://java.sun.com/classes/foo.jar":</p>
+ *
+ * <pre>
+ * http:
+ * http://*.sun.com/classes/*
+ * http://java.sun.com/classes/-
+ * http://java.sun.com/classes/foo.jar
+ * </pre>
+ *
+ * <p>Note that the code source with null location and null certificates implies
+ * all other code sources.</p>
+ *
+ * @param cs the <code>CodeSource</code> to test against this object
+ * @return true if this specified <code>CodeSource</code> is implied
+ */
+ public boolean implies(CodeSource cs)
+ {
+ if (cs == null)
+ return false;
+ // First check the certificate list.
+ if (certs != null && (cs.certs == null || ! certs.containsAll(cs.certs)))
+ return false;
+ // Next check the location.
+ if (location == null)
+ return true;
+ if (cs.location == null
+ || ! location.getProtocol().equals(cs.location.getProtocol())
+ || (location.getPort() != -1
+ && location.getPort() != cs.location.getPort())
+ || (location.getRef() != null
+ && ! location.getRef().equals(cs.location.getRef())))
+ return false;
+ if (location.getHost() != null)
+ {
+ String their_host = cs.location.getHost();
+ if (their_host == null)
+ return false;
+ SocketPermission our_sockperm =
+ new SocketPermission(location.getHost(), "accept");
+ SocketPermission their_sockperm =
+ new SocketPermission(their_host, "accept");
+ if (! our_sockperm.implies(their_sockperm))
+ return false;
+ }
+ String our_file = location.getFile();
+ if (our_file != null)
+ {
+ if (! our_file.endsWith("/"))
+ our_file += "/";
+ String their_file = cs.location.getFile();
+ if (their_file == null
+ || ! their_file.startsWith(our_file))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This method returns a <code>String</code> that represents this object.
+ * The result is in the format <code>"(" + getLocation()</code> followed
+ * by a space separated list of certificates (or "&lt;no certificates&gt;"),
+ * followed by <code>")"</code>.
+ *
+ * @return a <code>String</code> for this object
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer("(").append(location);
+ if (certs == null || certs.isEmpty())
+ sb.append(" <no certificates>");
+ else
+ {
+ Iterator iter = certs.iterator();
+ for (int i = certs.size(); --i >= 0; )
+ sb.append(' ').append(iter.next());
+ }
+ return sb.append(")").toString();
+ }
+
+ /**
+ * Reads this object from a serialization stream.
+ *
+ * @param s the input stream
+ * @throws IOException if reading fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData this reads the location, then expects an int indicating the
+ * number of certificates. Each certificate is a String type
+ * followed by an int encoding length, then a byte[] encoding
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ int count = s.readInt();
+ certs = new HashSet();
+ while (--count >= 0)
+ {
+ String type = (String) s.readObject();
+ int bytes = s.readInt();
+ byte[] encoded = new byte[bytes];
+ for (int i = 0; i < bytes; i++)
+ encoded[i] = s.readByte();
+ ByteArrayInputStream stream = new ByteArrayInputStream(encoded);
+ try
+ {
+ CertificateFactory factory = CertificateFactory.getInstance(type);
+ certs.add(factory.generateCertificate(stream));
+ }
+ catch (CertificateException e)
+ {
+ // XXX Should we ignore this certificate?
+ }
+ }
+ }
+
+ /**
+ * Writes this object to a serialization stream.
+ *
+ * @param s the output stream
+ * @throws IOException if writing fails
+ * @serialData this writes the location, then writes an int indicating the
+ * number of certificates. Each certificate is a String type
+ * followed by an int encoding length, then a byte[] encoding
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ if (certs == null)
+ s.writeInt(0);
+ else
+ {
+ int count = certs.size();
+ s.writeInt(count);
+ Iterator iter = certs.iterator();
+ while (--count >= 0)
+ {
+ Certificate c = (Certificate) iter.next();
+ s.writeObject(c.getType());
+ byte[] encoded;
+ try
+ {
+ encoded = c.getEncoded();
+ }
+ catch (CertificateEncodingException e)
+ {
+ // XXX Should we ignore this certificate?
+ encoded = null;
+ }
+ if (encoded == null)
+ s.writeInt(0);
+ else
+ {
+ s.writeInt(encoded.length);
+ for (int i = 0; i < encoded.length; i++)
+ s.writeByte(encoded[i]);
+ }
+ }
+ }
+ }
+} // class CodeSource
diff --git a/libjava/classpath/java/security/DigestException.java b/libjava/classpath/java/security/DigestException.java
new file mode 100644
index 00000000000..6393e0cc834
--- /dev/null
+++ b/libjava/classpath/java/security/DigestException.java
@@ -0,0 +1,70 @@
+/* DigestException.java -- A generic message digest exception
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception indicates that a generic message digest exception has
+ * occurred.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class DigestException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5821450303093652515L;
+
+ /**
+ * Create a new instance with no descriptive message.
+ */
+ public DigestException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param msg the descriptive message
+ */
+ public DigestException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/DigestInputStream.java b/libjava/classpath/java/security/DigestInputStream.java
new file mode 100644
index 00000000000..0d4a9d05dc6
--- /dev/null
+++ b/libjava/classpath/java/security/DigestInputStream.java
@@ -0,0 +1,167 @@
+/* DigestInputStream.java --- An Input stream tied to a message digest
+ Copyright (C) 1999, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * DigestInputStream is a class that ties an InputStream with a
+ * MessageDigest. The Message Digest is used by the class to
+ * update it self as bytes are read from the InputStream.
+ *
+ * The updating to the digest depends on the on flag which is set
+ * to true by default to tell the class to update the data
+ * in the message digest.
+ *
+ * @version 0.0
+ * @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ */
+public class DigestInputStream extends FilterInputStream
+{
+ /**
+ * The message digest for the DigestInputStream
+ */
+ protected MessageDigest digest;
+
+ //Manages the on flag
+ private boolean state = true;
+
+ /**
+ * Constructs a new DigestInputStream.
+ * It associates a MessageDigest with the stream to
+ * compute the stream as data is written.
+ *
+ * @param stream An InputStream to associate this stream with
+ * @param digest A MessageDigest to hash the stream with
+ */
+ public DigestInputStream(InputStream stream, MessageDigest digest)
+ {
+ super(stream);
+ //this.in = stream;
+ this.digest = digest;
+ }
+
+ /**
+ * Returns the MessageDigest associated with this DigestInputStream
+ *
+ * @return The MessageDigest used to hash this stream
+ */
+ public MessageDigest getMessageDigest()
+ {
+ return digest;
+ }
+
+ /**
+ * Sets the current MessageDigest to current parameter
+ *
+ * @param digest A MessageDigest to associate with this stream
+ */
+ public void setMessageDigest(MessageDigest digest)
+ {
+ this.digest = digest;
+ }
+
+ /**
+ * Reads a byte from the input stream and updates the digest.
+ * This method reads the underlying input stream and if the
+ * on flag is true then updates the message digest.
+ *
+ * @return Returns a byte from the input stream, -1 is returned to indicate that
+ * the end of stream was reached before this read call
+ *
+ * @throws IOException if an IO error occurs in the underlying input stream,
+ * this error is thrown
+ */
+ public int read() throws IOException
+ {
+ int temp = in.read();
+
+ if (state == true && temp != -1)
+ digest.update((byte) temp);
+
+ return temp;
+ }
+
+ /**
+ * Reads bytes from the input stream and updates the digest.
+ * This method reads the underlying input stream and if the
+ * on flag is true then updates the message digest.
+ *
+ * @param b a byte array to store the data from the input stream
+ * @param off an offset to start at in the array
+ * @param len length of data to read
+ * @return Returns count of bytes read, -1 is returned to indicate that
+ * the end of stream was reached before this read call
+ *
+ * @throws IOException if an IO error occurs in the underlying input stream,
+ * this error is thrown
+ */
+ public int read(byte[]b, int off, int len) throws IOException
+ {
+ int temp = in.read(b, off, len);
+
+ if (state == true && temp != -1)
+ digest.update(b, off, temp);
+
+ return temp;
+ }
+
+ /**
+ * Sets the flag specifing if this DigestInputStream updates the
+ * digest in the write() methods. The default is on;
+ *
+ * @param on True means it digests stream, false means it does not
+ */
+ public void on(boolean on)
+ {
+ state = on;
+ }
+
+ /**
+ * Converts the input stream and underlying message digest to a string.
+ *
+ * @return A string representing the input stream and message digest.
+ */
+ public String toString()
+ {
+ return "[Digest Input Stream] " + digest.toString();
+ }
+}
diff --git a/libjava/classpath/java/security/DigestOutputStream.java b/libjava/classpath/java/security/DigestOutputStream.java
new file mode 100644
index 00000000000..037b39e789c
--- /dev/null
+++ b/libjava/classpath/java/security/DigestOutputStream.java
@@ -0,0 +1,158 @@
+/* DigestOutputStream.java --- An output stream tied to a message digest
+ Copyright (C) 1999, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * DigestOutputStream is a class that ties an OutputStream with a
+ * MessageDigest. The Message Digest is used by the class to update it
+ * self as bytes are written to the OutputStream.
+ *
+ * The updating to the digest depends on the on flag which is set to
+ * true by default that tells the class to update the data in the
+ * message digest.
+ *
+ * @version 0.0
+ * @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ */
+public class DigestOutputStream extends FilterOutputStream
+{
+ /**
+ * The message digest for the DigestOutputStream
+ */
+ protected MessageDigest digest;
+
+ //Manages the on flag
+ private boolean state = true;
+
+ /**
+ * Constructs a new DigestOutputStream. It associates a
+ * MessageDigest with the stream to compute the stream as data is
+ * written.
+ *
+ * @param stream An OutputStream to associate this stream with
+ * @param digest A MessageDigest to hash the stream with
+ */
+ public DigestOutputStream(OutputStream stream, MessageDigest digest)
+ {
+ super(stream);
+ this.digest = digest;
+ }
+
+ /**
+ * Returns the MessageDigest associated with this DigestOutputStream
+ *
+ * @return The MessageDigest used to hash this stream
+ */
+ public MessageDigest getMessageDigest()
+ {
+ return digest;
+ }
+
+ /**
+ * Sets the current MessageDigest to current parameter
+ *
+ * @param digest A MessageDigest to associate with this stream
+ */
+ public void setMessageDigest(MessageDigest digest)
+ {
+ this.digest = digest;
+ }
+
+
+ /**
+ * Updates the hash if the on flag is true and then writes a byte to
+ * the underlying output stream.
+ *
+ * @param b A byte to write to the output stream
+ *
+ * @exception IOException if the underlying output stream
+ * cannot write the byte, this is thrown.
+ */
+ public void write(int b) throws IOException
+ {
+ if (state)
+ digest.update((byte) b);
+
+ out.write(b);
+ }
+
+ /**
+ * Updates the hash if the on flag is true and then writes the bytes
+ * to the underlying output stream.
+ *
+ * @param b Bytes to write to the output stream
+ * @param off Offset to start to start at in array
+ * @param len Length of data to write
+ *
+ * @exception IOException if the underlying output stream
+ * cannot write the bytes, this is thrown.
+ */
+ public void write(byte[]b, int off, int len) throws IOException
+ {
+ if (state)
+ digest.update(b, off, len);
+
+ out.write(b, off, len);
+ }
+
+ /**
+ * Sets the flag specifying if this DigestOutputStream updates the
+ * digest in the write() methods. The default is on;
+ *
+ * @param on True means it digests stream, false means it does not
+ */
+ public void on(boolean on)
+ {
+ state = on;
+ }
+
+ /**
+ * Converts the output stream and underlying message digest to a string.
+ *
+ * @return A string representing the output stream and message digest.
+ */
+ public String toString()
+ {
+ return "[Digest Output Stream] " + digest.toString();
+ }
+}
diff --git a/libjava/classpath/java/security/DomainCombiner.java b/libjava/classpath/java/security/DomainCombiner.java
new file mode 100644
index 00000000000..9ec680c63af
--- /dev/null
+++ b/libjava/classpath/java/security/DomainCombiner.java
@@ -0,0 +1,67 @@
+/* DomainCombiner.java -- Combines ProtectionDomains
+ Copyright (C) 1999, 2002 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.security;
+
+/**
+ * A public interface used to combine two ProtectionDomains in a new
+ * ProtectionDomain and update the current Protection Domains
+ * associated with the current AccessControlContext.
+ *
+ * It can add, subtract, or update ProtectionDomains or possibly
+ * remove duplicates or any possible complex action but just not add
+ * ones that do not already exist in either array.
+ *
+ * @author Mark Benvenuto
+ * @see AccessControlContext
+ * @see AccessController
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface DomainCombiner
+{
+ /**
+ * Combines the current ProtectionDomains of the Thread with new
+ * ProtectionDomains.
+ *
+ * @param currentDomains - the ProtectionDomains for the current thread.
+ * @param assignedDomains - ProtectionsDomains to add
+ * @return a new array of all the ProtectionDomains
+ */
+ ProtectionDomain[] combine(ProtectionDomain[] currentDomains,
+ ProtectionDomain[] assignedDomains);
+} // interface DomainCombiner
diff --git a/libjava/classpath/java/security/DummyKeyPairGenerator.java b/libjava/classpath/java/security/DummyKeyPairGenerator.java
new file mode 100644
index 00000000000..da8c362eb71
--- /dev/null
+++ b/libjava/classpath/java/security/DummyKeyPairGenerator.java
@@ -0,0 +1,75 @@
+/* DummyKeyPairGenerator.java - Wrapper for KeyPairGeneratorSpi
+ Copyright (C) 1999, 2002 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.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+final class DummyKeyPairGenerator extends KeyPairGenerator
+{
+ private KeyPairGeneratorSpi kpgSpi = null;
+
+ public DummyKeyPairGenerator(KeyPairGeneratorSpi kpgSpi, String algorithm)
+ {
+ super(algorithm);
+ this.kpgSpi = kpgSpi;
+ }
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ KeyPairGenerator result = new DummyKeyPairGenerator
+ ((KeyPairGeneratorSpi) kpgSpi.clone(), this.getAlgorithm());
+ result.provider = this.getProvider();
+ return result;
+ }
+
+ public void initialize(int keysize, SecureRandom random)
+ {
+ kpgSpi.initialize(keysize, random);
+ }
+
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ kpgSpi.initialize(params, random);
+ }
+
+ public KeyPair generateKeyPair()
+ {
+ return kpgSpi.generateKeyPair();
+ }
+}
diff --git a/libjava/classpath/java/security/DummyMessageDigest.java b/libjava/classpath/java/security/DummyMessageDigest.java
new file mode 100644
index 00000000000..6cecdcf6801
--- /dev/null
+++ b/libjava/classpath/java/security/DummyMessageDigest.java
@@ -0,0 +1,90 @@
+/* DummyMessageDigest.java - Wrapper for MessageDigestSpi
+ Copyright (C) 1999, 2002 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.security;
+
+final class DummyMessageDigest extends MessageDigest
+{
+ private MessageDigestSpi mdSpi = null;
+
+ public DummyMessageDigest(MessageDigestSpi mdSpi, String algorithm)
+ {
+ super(algorithm);
+ this.mdSpi = mdSpi;
+ }
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ MessageDigest result = new DummyMessageDigest
+ ((MessageDigestSpi) mdSpi.clone(), this.getAlgorithm());
+ result.provider = this.getProvider();
+ return result;
+ }
+
+ // java.security.MessageDigestSpi abstract methods implementation ---------
+
+ public byte[] engineDigest()
+ {
+ return mdSpi.engineDigest();
+ }
+
+ public int engineDigest(byte[] buf, int offset, int len)
+ throws DigestException
+ {
+ return mdSpi.engineDigest(buf, offset, len);
+ }
+
+ public int engineGetDigestLength()
+ {
+ return mdSpi.engineGetDigestLength();
+ }
+
+ public void engineReset()
+ {
+ mdSpi.engineReset();
+ }
+
+ public void engineUpdate(byte input)
+ {
+ mdSpi.engineUpdate(input);
+ }
+
+ public void engineUpdate(byte[] input, int offset, int len)
+ {
+ mdSpi.engineUpdate(input, offset, len);
+ }
+}
diff --git a/libjava/classpath/java/security/DummySignature.java b/libjava/classpath/java/security/DummySignature.java
new file mode 100644
index 00000000000..b74885c9973
--- /dev/null
+++ b/libjava/classpath/java/security/DummySignature.java
@@ -0,0 +1,102 @@
+/* DummySignature.java - Signature wrapper for SignatureSpi.
+ Copyright (C) 1999, 2002 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.security;
+
+final class DummySignature extends Signature
+{
+ private SignatureSpi sigSpi = null;
+
+ public DummySignature(SignatureSpi sigSpi, String algorithm)
+ {
+ super(algorithm);
+ this.sigSpi = sigSpi;
+ }
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ Signature result = new DummySignature
+ ((SignatureSpi) sigSpi.clone(), this.getAlgorithm());
+ result.provider = this.getProvider();
+ return result;
+ }
+
+ protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException
+ {
+ sigSpi.engineInitVerify(publicKey);
+ }
+
+ protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException
+ {
+ sigSpi.engineInitSign(privateKey);
+ }
+
+ protected void engineUpdate(byte b) throws SignatureException
+ {
+ sigSpi.engineUpdate(b);
+ }
+
+ protected void engineUpdate(byte[]b, int off, int len)
+ throws SignatureException
+ {
+ sigSpi.engineUpdate(b, off, len);
+ }
+
+ protected byte[] engineSign() throws SignatureException
+ {
+ return sigSpi.engineSign();
+ }
+
+ protected boolean engineVerify(byte[]sigBytes) throws SignatureException
+ {
+ return sigSpi.engineVerify(sigBytes);
+ }
+
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException
+ {
+ sigSpi.engineSetParameter(param, value);
+ }
+
+ protected Object engineGetParameter(String param)
+ throws InvalidParameterException
+ {
+ return sigSpi.engineGetParameter(param);
+ }
+}
diff --git a/libjava/classpath/java/security/GeneralSecurityException.java b/libjava/classpath/java/security/GeneralSecurityException.java
new file mode 100644
index 00000000000..72453ee8cbf
--- /dev/null
+++ b/libjava/classpath/java/security/GeneralSecurityException.java
@@ -0,0 +1,75 @@
+/* GeneralSecurityException.java -- Common superclass of security exceptions
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This class is the common superclass of all security exceptions. All
+ * exceptions in java.security extend this class with the exception (no
+ * pun intended) of <code>AccessControlException</code> and
+ * <code>CertificateException</code> (which extend
+ * <code>SecurityException</code>), <code>ProviderException</code>
+ * (<code>RuntimeException</code>), and <code>InvalidParamterException</code>
+ * (<code>IllegalArgumentException</code>).
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class GeneralSecurityException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 894798122053539237L;
+
+ /**
+ * Create a new instance with no descriptive error message.
+ */
+ public GeneralSecurityException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param msg the descriptive error message
+ */
+ public GeneralSecurityException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/Guard.java b/libjava/classpath/java/security/Guard.java
new file mode 100644
index 00000000000..4f22360a424
--- /dev/null
+++ b/libjava/classpath/java/security/Guard.java
@@ -0,0 +1,60 @@
+/* Guard.java -- Check access to a guarded object
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This interface specifies a mechanism for querying whether or not
+ * access is allowed to a guarded object.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see GuardedObject
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Guard
+{
+ /**
+ * This method tests whether or not access is allowed to the specified
+ * guarded object. Access is allowed if this method returns silently. If
+ * access is denied, an exception is generated.
+ *
+ * @param obj the <code>Object</code> to test
+ * @throws SecurityException if access to the object is denied
+ */
+ void checkGuard(Object obj);
+} // interface Guard
diff --git a/libjava/classpath/java/security/GuardedObject.java b/libjava/classpath/java/security/GuardedObject.java
new file mode 100644
index 00000000000..5ca08835dc5
--- /dev/null
+++ b/libjava/classpath/java/security/GuardedObject.java
@@ -0,0 +1,121 @@
+/* GuardedObject.java -- An object protected by a Guard
+ Copyright (C) 1998, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * This class is an object that is guarded by a <code>Guard</code> object.
+ * The object that is being guarded is retrieved by a call to the only
+ * method in this class - <code>getObject</code>. That method returns the
+ * guarded <code>Object</code> after first checking with the
+ * <code>Guard</code>. If the <code>Guard</code> disallows access, an
+ * exception will be thrown.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class GuardedObject implements Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5240450096227834308L;
+
+ /**
+ * This is the Guard that is protecting the object.
+ *
+ * @serial the guard
+ */
+ private final Guard guard;
+
+ /**
+ * This is the object that is being guarded.
+ *
+ * @serial the protected object
+ */
+ private final Object object;
+
+ /**
+ * This method initializes a new instance of <code>GuardedObject</code>
+ * that protects the specified <code>Object</code> using the specified
+ * <code>Guard</code>. A null guard means there are no restrictions on
+ * accessing the object.
+ *
+ * @param object the <code>Object</code> to guard
+ * @param guard the <code>Guard</code> that is protecting the object
+ */
+ public GuardedObject(Object object, Guard guard)
+ {
+ this.object = object;
+ this.guard = guard;
+ }
+
+ /**
+ * This method first call the <code>checkGuard</code> method on the
+ * <code>Guard</code> object protecting the guarded object. If the
+ * <code>Guard</code> disallows access, an exception is thrown, otherwise
+ * the <code>Object</code> is returned.
+ *
+ * @return The object being guarded
+ * @throws SecurityException if access is denied
+ */
+ public Object getObject()
+ {
+ if (guard != null)
+ guard.checkGuard(object);
+ return object;
+ }
+
+ /**
+ * Ensures that serialization is legal, by checking the guard.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ if (guard != null)
+ guard.checkGuard(object);
+ s.defaultWriteObject();
+ }
+} // class GuardedObject
diff --git a/libjava/classpath/java/security/Identity.java b/libjava/classpath/java/security/Identity.java
new file mode 100644
index 00000000000..26b01a50a6b
--- /dev/null
+++ b/libjava/classpath/java/security/Identity.java
@@ -0,0 +1,407 @@
+/* Identity.java --- Identity Class
+ Copyright (C) 1999, 2003, 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.security;
+
+import java.io.Serializable;
+import java.util.Vector;
+
+/**
+ * <p>This class represents identities: real-world objects such as people,
+ * companies or organizations whose identities can be authenticated using their
+ * public keys. Identities may also be more abstract (or concrete) constructs,
+ * such as daemon threads or smart cards.</p>
+ *
+ * <p>All Identity objects have a <i>name</i> and a <i>public key</i>. Names
+ * are immutable. <i>Identities</i> may also be <b>scoped</b>. That is, if an
+ * <i>Identity</i> is specified to have a particular <i>scope</i>, then the
+ * <i>name</i> and <i>public key</i> of the <i>Identity</i> are unique within
+ * that <i>scope</i>.</p>
+ *
+ * <p>An <i>Identity</i> also has a <i>set of certificates</i> (all certifying
+ * its own <i>public key</i>). The <i>Principal</i> names specified in these
+ * certificates need not be the same, only the key.</p>
+ *
+ * <p>An <i>Identity</i> can be subclassed, to include postal and email
+ * addresses, telephone numbers, images of faces and logos, and so on.</p>
+ *
+ * @author Mark Benvenuto
+ * @see IdentityScope
+ * @see Signer
+ * @see Principal
+ * @deprecated This class is no longer used. Its functionality has been replaced
+ * by <code>java.security.KeyStore</code>, the <code>java.security.cert</code>
+ * package, and <code>java.security.Principal</code>.
+ */
+public abstract class Identity implements Principal, Serializable
+{
+ private static final long serialVersionUID = 3609922007826600659L;
+
+ private String name;
+ private IdentityScope scope;
+ private PublicKey publicKey;
+ private String info;
+ private Vector certificates;
+
+ /** Constructor for serialization only. */
+ protected Identity()
+ {
+ }
+
+ /**
+ * Constructs an identity with the specified name and scope.
+ *
+ * @param name the identity name.
+ * @param scope the scope of the identity.
+ * @throws KeyManagementException if there is already an identity with the
+ * same name in the scope.
+ */
+ public Identity(String name, IdentityScope scope)
+ throws KeyManagementException
+ {
+ this.name = name;
+ this.scope = scope;
+ }
+
+ /**
+ * Constructs an identity with the specified name and no scope.
+ *
+ * @param name the identity name.
+ */
+ public Identity(String name)
+ {
+ this.name = name;
+ this.scope = null;
+ }
+
+ /**
+ * Returns this identity's name.
+ *
+ * @return the name of this identity.
+ */
+ public final String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns this identity's scope.
+ *
+ * @return the scope of this identity.
+ */
+ public final IdentityScope getScope()
+ {
+ return scope;
+ }
+
+ /**
+ * Returns this identity's public key.
+ *
+ * @return the public key for this identity.
+ * @see #setPublicKey(java.security.PublicKey)
+ */
+ public PublicKey getPublicKey()
+ {
+ return publicKey;
+ }
+
+ /**
+ * <p>Sets this identity's public key. The old key and all of this identity's
+ * certificates are removed by this operation.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"setIdentityPublicKey"</code> as its
+ * argument to see if it's ok to set the public key.</p>
+ *
+ * @param key the public key for this identity.
+ * @throws KeyManagementException if another identity in the identity's scope
+ * has the same public key, or if another exception occurs.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow setting the public
+ * key.
+ * @see #getPublicKey()
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public void setPublicKey(PublicKey key) throws KeyManagementException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("setIdentityPublicKey");
+
+ this.publicKey = key;
+ }
+
+ /**
+ * <p>Specifies a general information string for this identity.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"setIdentityInfo"</code> as its
+ * argument to see if it's ok to specify the information string.</p>
+ *
+ * @param info the information string.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow setting the
+ * information string.
+ * @see #getInfo()
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public void setInfo(String info)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("setIdentityInfo");
+
+ this.info = info;
+ }
+
+ /**
+ * Returns general information previously specified for this identity.
+ *
+ * @return general information about this identity.
+ * @see #setInfo(String)
+ */
+ public String getInfo()
+ {
+ return info;
+ }
+
+ /**
+ * <p>Adds a certificate for this identity. If the identity has a public key,
+ * the public key in the certificate must be the same, and if the identity
+ * does not have a public key, the identity's public key is set to be that
+ * specified in the certificate.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"addIdentityCertificate"</code> as its
+ * argument to see if it's ok to add a certificate.</p>
+ *
+ * @param certificate the certificate to be added.
+ * @throws KeyManagementException if the certificate is not valid, if the
+ * public key in the certificate being added conflicts with this identity's
+ * public key, or if another exception occurs.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow adding a
+ * certificate.
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public void addCertificate(Certificate certificate)
+ throws KeyManagementException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("addIdentityCertificate");
+
+ // Check public key of this certificate against the first one in the vector
+ if (certificates.size() > 0)
+ {
+ if (((Certificate) certificates.firstElement()).getPublicKey() != publicKey)
+ throw new KeyManagementException("Public key does not match");
+ }
+ certificates.addElement(certificate);
+ }
+
+ /**
+ * <p>Removes a certificate from this identity.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"removeIdentityCertificate"</code> as
+ * its argument to see if it's ok to remove a certificate.</p>
+ *
+ * @param certificate the certificate to be removed.
+ * @throws KeyManagementException if the certificate is missing, or if
+ * another exception occurs.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow removing a
+ * certificate.
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public void removeCertificate(Certificate certificate)
+ throws KeyManagementException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("removeIdentityCertificate");
+
+ if (certificates.contains(certificate) == false)
+ throw new KeyManagementException("Certificate not found");
+
+ certificates.removeElement(certificate);
+ }
+
+ /**
+ * Returns a copy of all the certificates for this identity.
+ *
+ * @return a copy of all the certificates for this identity.
+ */
+ public Certificate[] certificates()
+ {
+ Certificate[] certs = new Certificate[certificates.size()];
+ int max = certificates.size();
+ for (int i = 0; i < max; i++)
+ certs[i] = (Certificate) certificates.elementAt(i);
+
+ return certs;
+ }
+
+ /**
+ * Tests for equality between the specified object and this identity. This
+ * first tests to see if the entities actually refer to the same object, in
+ * which case it returns <code>true</code>. Next, it checks to see if the
+ * entities have the same <i>name</i> and the same <i>scope</i>. If they do,
+ * the method returns <code>true</code>. Otherwise, it calls
+ * <code>identityEquals()</code>, which subclasses should override.
+ *
+ * @param identity the object to test for equality with this identity.
+ * @return <code>true</code> if the objects are considered equal, <code>false
+ * </code>otherwise.
+ * @see #identityEquals(Identity)
+ */
+ public final boolean equals(Object identity)
+ {
+ if (identity instanceof Identity)
+ {
+ if (identity == this)
+ return true;
+
+ if ((((Identity) identity).getName() == this.name) &&
+ (((Identity) identity).getScope() == this.scope))
+ return true;
+
+ return identityEquals((Identity) identity);
+ }
+ return false;
+ }
+
+ /**
+ * Tests for equality between the specified <code>identity</code> and this
+ * <i>identity</i>. This method should be overriden by subclasses to test for
+ * equality. The default behavior is to return <code>true</code> if the names
+ * and public keys are equal.
+ *
+ * @param identity the identity to test for equality with this identity.
+ * @return <code>true</code> if the identities are considered equal,
+ * <code>false</code> otherwise.
+ * @see #equals(Object)
+ */
+ protected boolean identityEquals(Identity identity)
+ {
+ return ((identity.getName() == this.name) &&
+ (identity.getPublicKey() == this.publicKey));
+ }
+
+ /**
+ * <p>Returns a short string describing this identity, telling its name and
+ * its scope (if any).</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"printIdentity"</code> as its argument
+ * to see if it's ok to return the string.</p>
+ *
+ * @return information about this identity, such as its name and the name of
+ * its scope (if any).
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow returning a string
+ * describing this identity.
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public String toString()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("printIdentity");
+
+ /* TODO: Insert proper format here */
+ return (name + ":@" + scope + " Public Key: " + publicKey);
+ }
+
+ /**
+ * <p>Returns a string representation of this identity, with optionally more
+ * details than that provided by the <code>toString()</code> method without
+ * any arguments.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"printIdentity"</code> as its argument
+ * to see if it's ok to return the string.</p>
+ *
+ * @param detailed whether or not to provide detailed information.
+ * @return information about this identity. If detailed is <code>true</code>,
+ * then this method returns more information than that provided by the
+ * <code>toString()</code> method without any arguments.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow returning a string
+ * describing this identity.
+ * @see #toString()
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public String toString(boolean detailed)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("printIdentity");
+
+ if (detailed)
+ {
+ /* TODO: Insert proper detailed format here */
+ return (name + ":@" + scope + " Public Key: " + publicKey);
+ }
+ else
+ {
+ /* TODO: Insert proper format here */
+ return (name + ":@" + scope + " Public Key: " + publicKey);
+ }
+ }
+
+ /**
+ * Returns a hashcode for this identity.
+ *
+ * @return a hashcode for this identity.
+ */
+ public int hashCode()
+ {
+ int ret = name.hashCode();
+ if (publicKey != null)
+ ret |= publicKey.hashCode();
+ if (scope != null)
+ ret |= scope.hashCode();
+ if (info != null)
+ ret |= info.hashCode();
+ if (certificates != null)
+ ret |= certificates.hashCode();
+
+ return ret;
+ }
+}
diff --git a/libjava/classpath/java/security/IdentityScope.java b/libjava/classpath/java/security/IdentityScope.java
new file mode 100644
index 00000000000..34dd011e280
--- /dev/null
+++ b/libjava/classpath/java/security/IdentityScope.java
@@ -0,0 +1,226 @@
+/* IdentityScope.java --- IdentityScope Class
+ Copyright (C) 1999, 2003, 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.security;
+
+import java.util.Enumeration;
+
+/**
+ * <p>This class represents a scope for identities. It is an Identity itself,
+ * and therefore has a name and can have a scope. It can also optionally have a
+ * public key and associated certificates.</p>
+ *
+ * <p>An <code>IdentityScope</code> can contain {@link Identity} objects of all
+ * kinds, including {@link Signer}s. All types of <code>Identity</code> objects
+ * can be retrieved, added, and removed using the same methods. Note that it is
+ * possible, and in fact expected, that different types of identity scopes will
+ * apply different policies for their various operations on the various types of
+ * Identities.</p>
+ *
+ * <p>There is a one-to-one mapping between keys and identities, and there can
+ * only be one copy of one key per scope. For example, suppose Acme Software,
+ * Inc is a software publisher known to a user. Suppose it is an <i>Identity</i>,
+ * that is, it has a public key, and a set of associated certificates. It is
+ * named in the scope using the name "Acme Software". No other named <i>Identity
+ * </i> in the scope has the same public key. Of course, none has the same name
+ * as well.</p>
+ *
+ * @author Mark Benvenuto
+ * @see Identity
+ * @see Signer
+ * @see Principal
+ * @see Key
+ * @deprecated This class is no longer used. Its functionality has been replaced
+ * by <code>java.security.KeyStore</code>, the <code>java.security.cert</code>
+ * package, and <code>java.security.Principal</code>.
+ */
+public abstract class IdentityScope extends Identity
+{
+ private static final long serialVersionUID = -2337346281189773310L;
+ private static IdentityScope systemScope;
+
+ /**
+ * This constructor is used for serialization only and should not be used by
+ * subclasses.
+ */
+ protected IdentityScope()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new identity scope with the specified name.
+ *
+ * @param name the scope name.
+ */
+ public IdentityScope(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Constructs a new identity scope with the specified name and scope.
+ *
+ * @param name the scope name.
+ * @param scope the scope for the new identity scope.
+ * @throws KeyManagementException if there is already an identity with the
+ * same name in the scope.
+ */
+ public IdentityScope(String name, IdentityScope scope)
+ throws KeyManagementException
+ {
+ super(name, scope);
+ }
+
+ /**
+ * Returns the system's identity scope.
+ *
+ * @return the system's identity scope.
+ * @see #setSystemScope(IdentityScope)
+ */
+ public static IdentityScope getSystemScope()
+ {
+ if (systemScope == null)
+ {
+ //Load it
+ //systemScope;
+ }
+ return systemScope;
+ }
+
+ /**
+ * Sets the system's identity scope.
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"setSystemScope"</code> as its argument
+ * to see if it's ok to set the identity scope.</p>
+ *
+ * @param scope the scope to set.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow setting the
+ * identity scope.
+ * @see #getSystemScope()
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ protected static void setSystemScope(IdentityScope scope)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("setSystemScope");
+
+ systemScope = scope;
+ }
+
+ /**
+ * Returns the number of identities within this identity scope.
+ *
+ * @return the number of identities within this identity scope.
+ */
+ public abstract int size();
+
+ /**
+ * Returns the identity in this scope with the specified name (if any).
+ *
+ * @param name the name of the identity to be retrieved.
+ * @return the identity named name, or <code>null</code> if there are no
+ * identities named name in this scope.
+ */
+ public abstract Identity getIdentity(String name);
+
+ /**
+ * Retrieves the identity whose name is the same as that of the specified
+ * principal. (Note: <code>Identity</code> implements <code>Principal</code>.)
+ *
+ * @param principal the principal corresponding to the identity to be
+ * retrieved.
+ * @return the identity whose name is the same as that of the principal, or
+ * <code>null</code> if there are no identities of the same name in this scope.
+ */
+ public Identity getIdentity(Principal principal)
+ {
+ return getIdentity(principal.getName());
+ }
+
+ /**
+ * Retrieves the identity with the specified public key.
+ *
+ * @param key the public key for the identity to be returned.
+ * @return the identity with the given key, or <code>null</code> if there are
+ * no identities in this scope with that key.
+ */
+ public abstract Identity getIdentity(PublicKey key);
+
+ /**
+ * Adds an identity to this identity scope.
+ *
+ * @param identity the identity to be added.
+ * @throws KeyManagementException if the identity is not valid, a name
+ * conflict occurs, another identity has the same public key as the identity
+ * being added, or another exception occurs.
+ */
+ public abstract void addIdentity(Identity identity)
+ throws KeyManagementException;
+
+ /**
+ * Removes an identity from this identity scope.
+ *
+ * @param identity the identity to be removed.
+ * @throws KeyManagementException if the identity is missing, or another
+ * exception occurs.
+ */
+ public abstract void removeIdentity(Identity identity)
+ throws KeyManagementException;
+
+ /**
+ * Returns an enumeration of all identities in this identity scope.
+ *
+ * @return an enumeration of all identities in this identity scope.
+ */
+ public abstract Enumeration identities();
+
+ /**
+ * Returns a string representation of this identity scope, including its name,
+ * its scope name, and the number of identities in this identity scope.
+ *
+ * @return a string representation of this identity scope.
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public String toString()
+ {
+ return (super.getName() + " " + super.getScope().getName() + " " + size());
+ }
+}
diff --git a/libjava/classpath/java/security/IntersectingDomainCombiner.java b/libjava/classpath/java/security/IntersectingDomainCombiner.java
new file mode 100644
index 00000000000..2bfcfb44233
--- /dev/null
+++ b/libjava/classpath/java/security/IntersectingDomainCombiner.java
@@ -0,0 +1,82 @@
+/* IntersectingDomainCombiner.java --
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.util.HashSet;
+
+/**
+ * A trivial implementation of {@link DomainCombiner} that produces the
+ * intersection of the supplied {@link ProtectionDomain} objects.
+ */
+final class IntersectingDomainCombiner implements DomainCombiner
+{
+
+ // Contstant.
+ // -------------------------------------------------------------------------
+
+ static final IntersectingDomainCombiner SINGLETON = new IntersectingDomainCombiner();
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ private IntersectingDomainCombiner()
+ {
+ }
+
+ // Methods.
+ // -------------------------------------------------------------------------
+
+ public ProtectionDomain[] combine (ProtectionDomain[] currentDomains,
+ ProtectionDomain[] assignedDomains)
+ {
+ HashSet newDomains = new HashSet ();
+ for (int i = 0; i < currentDomains.length; i++)
+ {
+ if (currentDomains[i] == null)
+ continue;
+ for (int j = 0; j < assignedDomains.length; j++)
+ {
+ if (currentDomains[i].equals (assignedDomains[j]))
+ newDomains.add (currentDomains[i]);
+ }
+ }
+ return (ProtectionDomain[])
+ newDomains.toArray(new ProtectionDomain[newDomains.size()]);
+ }
+}
diff --git a/libjava/classpath/java/security/InvalidAlgorithmParameterException.java b/libjava/classpath/java/security/InvalidAlgorithmParameterException.java
new file mode 100644
index 00000000000..9b726199521
--- /dev/null
+++ b/libjava/classpath/java/security/InvalidAlgorithmParameterException.java
@@ -0,0 +1,73 @@
+/* InvalidAlgorithmParameterException.java -- an invalid parameter to a
+ security algorithm
+ Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * Thrown for an invalid security algorithm parameter.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InvalidAlgorithmParameterException
+ extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 2864672297499471472L;
+
+ /**
+ * Construct an exception with no message.
+ */
+ public InvalidAlgorithmParameterException()
+ {
+ super();
+ }
+
+ /**
+ * Construct an exception with a message.
+ *
+ * @param msg the message
+ */
+ public InvalidAlgorithmParameterException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/InvalidKeyException.java b/libjava/classpath/java/security/InvalidKeyException.java
new file mode 100644
index 00000000000..cd5845a6181
--- /dev/null
+++ b/libjava/classpath/java/security/InvalidKeyException.java
@@ -0,0 +1,69 @@
+/* InvalidKeyException -- thrown for an invalid key
+ Copyright (C) 2000, 2002 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.security;
+
+/**
+ * Thrown for an invalid key.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class InvalidKeyException extends KeyException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5698479920593359816L;
+
+ /**
+ * Construct an exception with no message.
+ */
+ public InvalidKeyException()
+ {
+ }
+
+ /**
+ * Construct an exception with a message.
+ *
+ * @param msg the message
+ */
+ public InvalidKeyException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/InvalidParameterException.java b/libjava/classpath/java/security/InvalidParameterException.java
new file mode 100644
index 00000000000..c5218a04917
--- /dev/null
+++ b/libjava/classpath/java/security/InvalidParameterException.java
@@ -0,0 +1,70 @@
+/* InvalidParameterException.java -- an invalid parameter in the JCA/JCE engine
+ Copyright (C) 2000, 2002 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.security;
+
+/**
+ * Thrown when an invalid parameter is passed to a method of the JCA/JCE
+ * engine classes.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @status updated to 1.4
+ */
+public class InvalidParameterException extends IllegalArgumentException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -857968536935667808L;
+
+ /**
+ * Construct an exception with no message.
+ */
+ public InvalidParameterException()
+ {
+ }
+
+ /**
+ * Construct an exception with a message.
+ *
+ * @param msg the message
+ */
+ public InvalidParameterException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/Key.java b/libjava/classpath/java/security/Key.java
new file mode 100644
index 00000000000..23652b6e7c4
--- /dev/null
+++ b/libjava/classpath/java/security/Key.java
@@ -0,0 +1,94 @@
+/* Key.java -- A abstract representation of a digital key
+ Copyright (C) 1998, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+import java.io.Serializable;
+
+/**
+ * This interfaces models the base characteristics that all keys must
+ * have. These are: a key algorithm, an encoded form, and a format used
+ * to encode the key. Specific key types inherit from this interface.
+ * Note that since this interface extends <code>Serializable</code>, all
+ * keys may be serialized. Keys are generally obtained through key generators,
+ * including {@link KeyFactory}.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see PublicKey
+ * @see PrivateKey
+ * @see KeyPair
+ * @see KeyPairGenerator
+ * @see KeyFactory
+ * @see KeySpec
+ * @see Identity
+ * @see Signer
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Key extends Serializable
+{
+ /**
+ * The version identifier used for serialization.
+ */
+ long serialVersionUID = 6603384152749567654L;
+
+ /**
+ * This method returns the name of the algorithm for this key. This is a
+ * <code>String</code> such as "RSA".
+ *
+ * @return the name of the algorithm in use
+ */
+ String getAlgorithm();
+
+ /**
+ * This method returns the name of the encoding format for this key. This
+ * is the name of the ASN.1 data format used for this key, such as
+ * "X.509" or "PKCS#8". This method returns <code>null</code> if this key
+ * does not have an encoding format.
+ *
+ * @return the name of the encoding format for this key, or null
+ */
+ String getFormat();
+
+ /**
+ * This method returns the encoded form of the key. If this key does not
+ * support encoding, this method returns <code>null</code>.
+ *
+ * @return the encoded form of the key, or null
+ */
+ byte[] getEncoded();
+} // interface Key
diff --git a/libjava/classpath/java/security/KeyException.java b/libjava/classpath/java/security/KeyException.java
new file mode 100644
index 00000000000..feaf0249a95
--- /dev/null
+++ b/libjava/classpath/java/security/KeyException.java
@@ -0,0 +1,72 @@
+/* KeyException.java -- Thrown when there is a problem with a key
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception is thrown when there is a problem with a key.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Key
+ * @status updated to 1.4
+ */
+public class KeyException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -7483676942812432108L;
+
+ /**
+ * This method initializes a new instance of <code>KeyException</code>
+ * with no descriptive message.
+ */
+ public KeyException()
+ {
+ }
+
+ /**
+ * This method initializes a new instance of <code>KeyException</code>
+ * with a descriptive message.
+ *
+ * @param msg the descriptive message
+ */
+ public KeyException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/KeyFactory.java b/libjava/classpath/java/security/KeyFactory.java
new file mode 100644
index 00000000000..64ce841fae8
--- /dev/null
+++ b/libjava/classpath/java/security/KeyFactory.java
@@ -0,0 +1,297 @@
+/* KeyFactory.java --- Key Factory Class
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import gnu.java.security.Engine;
+
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+/**
+ * <p>Key factories are used to convert keys (opaque cryptographic keys of type
+ * {@link Key}) into key specifications (transparent representations of the
+ * underlying key material), and vice versa.</p>
+ *
+ * <p>Key factories are bi-directional. That is, they allow you to build an
+ * opaque key object from a given key specification (key material), or to
+ * retrieve the underlying key material of a key object in a suitable format.</p>
+ *
+ * <p>Multiple compatible key specifications may exist for the same key. For
+ * example, a <i>DSA</i> public key may be specified using {@link
+ * java.security.spec.DSAPublicKeySpec} or {@link
+ * java.security.spec.X509EncodedKeySpec}. A key factory can be used to
+ * translate between compatible key specifications.</p>
+ *
+ * <p>The following is an example of how to use a key factory in order to
+ * instantiate a <i>DSA</i> public key from its encoding. Assume Alice has
+ * received a digital signature from Bob. Bob also sent her his public key (in
+ * encoded format) to verify his signature. Alice then performs the following
+ * actions:
+ *
+ * <pre>
+ * X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
+ * KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+ * PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
+ * Signature sig = Signature.getInstance("DSA");
+ * sig.initVerify(bobPubKey);
+ * sig.update(data);
+ * sig.verify(signature);
+ * </pre>
+ *
+ * @since 1.2
+ * @see Key
+ * @see PublicKey
+ * @see PrivateKey
+ * @see KeySpec
+ * @see java.security.spec.DSAPublicKeySpec
+ * @see java.security.spec.X509EncodedKeySpec
+ @author Mark Benvenuto
+ */
+public class KeyFactory
+{
+ /** The service name for key factories. */
+ private static final String KEY_FACTORY = "KeyFactory";
+
+ private KeyFactorySpi keyFacSpi;
+ private Provider provider;
+ private String algorithm;
+
+ /**
+ * Creates a <code>KeyFactory</code> object.
+ *
+ * @param keyFacSpi the delegate.
+ * @param provider the provider.
+ * @param algorithm the name of the algorithm to associate with this
+ * <code>KeyFactory</code>.
+ */
+ protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider,
+ String algorithm)
+ {
+ this.keyFacSpi = keyFacSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Generates a <code>KeyFactory</code> object that implements the specified
+ * algorithm. If the default provider package provides an implementation of
+ * the requested algorithm, an instance of <code>KeyFactory</code> containing
+ * that implementation is returned. If the algorithm is not available in the
+ * default package, other packages are searched.
+ *
+ * @param algorithm the name of the requested key algorithm. See Appendix A
+ * in the Java Cryptography Architecture API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @return a <code>KeyFactory</code> object for the specified algorithm.
+ * @throws NoSuchAlgorithmException if the requested algorithm is not
+ * available in the default provider package or any of the other provider
+ * packages that were searched.
+ */
+ public static KeyFactory getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore.
+ }
+
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * Generates a <code>KeyFactory</code> object for the specified algorithm
+ * from the specified provider.
+ *
+ * @param algorithm the name of the requested key algorithm. See Appendix A
+ * in the Java Cryptography Architecture API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @param provider the name of the provider.
+ * @return a <code>KeyFactory</code> object for the specified algorithm.
+ * @throws NoSuchAlgorithmException if the algorithm is not available from
+ * the specified provider.
+ * @throws NoSuchProviderException if the provider has not been configured.
+ * @throws IllegalArgumentException if the provider name is null or empty.
+ * @see Provider
+ */
+ public static KeyFactory getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("Illegal provider");
+
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ throw new NoSuchProviderException(provider);
+
+ return getInstance(algorithm, p);
+ }
+
+ /**
+ * Generates a <code>KeyFactory</code> object for the specified algorithm from
+ * the specified provider. Note: the <code>provider</code> doesn't have to be
+ * registered.
+ *
+ * @param algorithm the name of the requested key algorithm. See Appendix A
+ * in the Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ * @param provider the provider.
+ * @return a <code>KeyFactory</code> object for the specified algorithm.
+ * @throws NoSuchAlgorithmException if the algorithm is not available from
+ * the specified provider.
+ * @throws IllegalArgumentException if the <code>provider</code> is
+ * <code>null</code>.
+ * @since 1.4
+ * @see Provider
+ */
+ public static KeyFactory getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("Illegal provider");
+
+ try
+ {
+ return new KeyFactory((KeyFactorySpi)
+ Engine.getInstance(KEY_FACTORY, algorithm, provider),
+ provider, algorithm);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ }
+
+ /**
+ * Returns the provider of this key factory object.
+ *
+ * @return the provider of this key factory object.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Gets the name of the algorithm associated with this <code>KeyFactory</code>.
+ *
+ * @return the name of the algorithm associated with this
+ * <code>KeyFactory</code>.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Generates a public key object from the provided key specification (key
+ * material).
+ *
+ * @param keySpec the specification (key material) of the public key.
+ * @return the public key.
+ * @throws InvalidKeySpecException if the given key specification is
+ * inappropriate for this key factory to produce a public key.
+ */
+ public final PublicKey generatePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return keyFacSpi.engineGeneratePublic(keySpec);
+ }
+
+ /**
+ * Generates a private key object from the provided key specification (key
+ * material).
+ *
+ * @param keySpec the specification (key material) of the private key.
+ * @return the private key.
+ * @throws InvalidKeySpecException if the given key specification is
+ * inappropriate for this key factory to produce a private key.
+ */
+ public final PrivateKey generatePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return keyFacSpi.engineGeneratePrivate(keySpec);
+ }
+
+ /**
+ * Returns a specification (key material) of the given key object.
+ * <code>keySpec</code> identifies the specification class in which the key
+ * material should be returned. It could, for example, be
+ * <code>DSAPublicKeySpec.class</code>, to indicate that the key material
+ * should be returned in an instance of the {@link
+ * java.security.spec.DSAPublicKeySpec} class.
+ *
+ * @param key the key.
+ * @param keySpec the specification class in which the key material should be
+ * returned.
+ * @return the underlying key specification (key material) in an instance of
+ * the requested specification class.
+ * @throws InvalidKeySpecException if the requested key specification is
+ * inappropriate for the given key, or the given key cannot be processed
+ * (e.g., the given key has an unrecognized algorithm or format).
+ */
+ public final KeySpec getKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException
+ {
+ return keyFacSpi.engineGetKeySpec(key, keySpec);
+ }
+
+ /**
+ * Translates a key object, whose provider may be unknown or potentially
+ * untrusted, into a corresponding key object of this key factory.
+ *
+ * @param key the key whose provider is unknown or untrusted.
+ * @return the translated key.
+ * @throws InvalidKeyException if the given key cannot be processed by this
+ * key factory.
+ */
+ public final Key translateKey(Key key) throws InvalidKeyException
+ {
+ return keyFacSpi.engineTranslateKey(key);
+ }
+}
diff --git a/libjava/classpath/java/security/KeyFactorySpi.java b/libjava/classpath/java/security/KeyFactorySpi.java
new file mode 100644
index 00000000000..1894fad08df
--- /dev/null
+++ b/libjava/classpath/java/security/KeyFactorySpi.java
@@ -0,0 +1,133 @@
+/* KeyFactorySpi.java --- Key Factory Service Provider Interface
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+/**
+ * KeyFactorySpi is the Service Provider Interface (SPI) for the
+ * KeyFactory class. This is the interface for providers to
+ * supply to implement a key factory for an algorithm.
+ *
+ * Key factories are used to convert keys (opaque cryptographic
+ * keys of type Key) into key specifications (transparent
+ * representations of the underlying key material).
+ *
+ * Key factories are bi-directional. They allow a key class
+ * to be converted into a key specification (key material) and
+ * back again.
+ *
+ * For example DSA public keys can be specified as
+ * DSAPublicKeySpec or X509EncodedKeySpec. The key factory
+ * translate these key specifications.
+ *
+ * @since JDK 1.2
+ * @author Mark Benvenuto
+ */
+public abstract class KeyFactorySpi
+{
+ /**
+ * Constucts a new KeyFactorySpi.
+ */
+ public KeyFactorySpi()
+ {
+ }
+
+ /**
+ * Generates a public key from the provided key specification.
+ *
+ * @param keySpec key specification
+ *
+ * @return the public key
+ *
+ * @throws InvalidKeySpecException invalid key specification for
+ * this key factory to produce a public key
+ */
+ protected abstract PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException;
+
+
+ /**
+ * Generates a private key from the provided key specification.
+ *
+ * @param keySpec key specification
+ *
+ * @return the private key
+ *
+ * @throws InvalidKeySpecException invalid key specification for
+ * this key factory to produce a private key
+ */
+ protected abstract PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException;
+
+ /**
+ * Returns a key specification for the given key. keySpec
+ * identifies the specification class to return the key
+ * material in.
+ *
+ * @param key the key
+ * @param keySpec the specification class to return the
+ * key material in.
+ *
+ * @return the key specification in an instance of the requested
+ * specification class
+ *
+ * @throws InvalidKeySpecException the requested key specification
+ * is inappropriate for this key or the key is
+ * unrecognized.
+ */
+ protected abstract KeySpec engineGetKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException;
+
+
+ /**
+ * Translates the key from an unknown or untrusted provider
+ * into a key for this key factory.
+ *
+ * @param the key from an unknown or untrusted provider
+ *
+ * @return the translated key
+ *
+ * @throws InvalidKeySpecException if the key cannot be
+ * processed by this key factory
+ */
+ protected abstract Key engineTranslateKey(Key key)
+ throws InvalidKeyException;
+}
diff --git a/libjava/classpath/java/security/KeyManagementException.java b/libjava/classpath/java/security/KeyManagementException.java
new file mode 100644
index 00000000000..694b4c242b6
--- /dev/null
+++ b/libjava/classpath/java/security/KeyManagementException.java
@@ -0,0 +1,71 @@
+/* KeyManagementException.java -- an exception in key management
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception is thrown whenever a problem related to the management of
+ * security keys is encountered.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Key
+ * @status updated to 1.4
+ */
+public class KeyManagementException extends KeyException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 947674216157062695L;
+
+ /**
+ * Create a new instance with no descriptive error message.
+ */
+ public KeyManagementException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param msg the descriptive error message
+ */
+ public KeyManagementException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/KeyPair.java b/libjava/classpath/java/security/KeyPair.java
new file mode 100644
index 00000000000..bf1a40a23ab
--- /dev/null
+++ b/libjava/classpath/java/security/KeyPair.java
@@ -0,0 +1,87 @@
+/* KeyPair.java --- Key Pair Class
+ Copyright (C) 1999 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.security;
+import java.io.Serializable;
+
+/**
+ KeyPair serves as a simple container for public and private keys.
+ If properly initialized, this class should be treated like the
+ private key since it contains it and take approriate security
+ measures.
+
+ @author Mark Benvenuto
+ */
+public final class KeyPair implements Serializable
+{
+ private static final long serialVersionUID = -7565189502268009837L;
+
+ private PublicKey publicKey;
+ private PrivateKey privateKey;
+
+ /**
+ Initializes the KeyPair with a pubilc and private key.
+
+ @param publicKey Public Key to store
+ @param privateKey Private Key to store
+ */
+ public KeyPair(PublicKey publicKey, PrivateKey privateKey)
+ {
+ this.publicKey = publicKey;
+ this.privateKey = privateKey;
+ }
+
+ /**
+ Returns the public key stored in the KeyPair
+
+ @return The public key
+ */
+ public PublicKey getPublic()
+ {
+ return publicKey;
+ }
+
+ /**
+ Returns the private key stored in the KeyPair
+
+ @return The private key
+ */
+ public PrivateKey getPrivate()
+ {
+ return privateKey;
+ }
+}
diff --git a/libjava/classpath/java/security/KeyPairGenerator.java b/libjava/classpath/java/security/KeyPairGenerator.java
new file mode 100644
index 00000000000..e6f926e2bf0
--- /dev/null
+++ b/libjava/classpath/java/security/KeyPairGenerator.java
@@ -0,0 +1,401 @@
+/* KeyPairGenerator.java --- Key Pair Generator Class
+ Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import gnu.java.security.Engine;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * <p>The <code>KeyPairGenerator</code> class is used to generate pairs of
+ * public and private keys. Key pair generators are constructed using the
+ * <code>getInstance()</code> factory methods (static methods that return
+ * instances of a given class).</p>
+ *
+ * <p>A Key pair generator for a particular algorithm creates a public/private
+ * key pair that can be used with this algorithm. It also associates
+ * algorithm-specific parameters with each of the generated keys.</p>
+ *
+ * <p>There are two ways to generate a key pair: in an algorithm-independent
+ * manner, and in an algorithm-specific manner. The only difference between the
+ * two is the initialization of the object:</p>
+ *
+ * <ul>
+ * <li><b>Algorithm-Independent Initialization</b><br/>
+ * All key pair generators share the concepts of a <i>keysize</i> and a
+ * <i>source of randomness</i>. The <i>keysize</i> is interpreted differently
+ * for different algorithms (e.g., in the case of the <i>DSA</i> algorithm,
+ * the <i>keysize</i> corresponds to the length of the modulus). There is an
+ * <code>initialize()</code> method in this <code>KeyPairGenerator</code>
+ * class that takes these two universally shared types of arguments. There
+ * is also one that takes just a <i>keysize</i> argument, and uses the
+ * {@link SecureRandom} implementation of the highest-priority installed
+ * provider as the <i>source of randomness</i>. (If none of the installed
+ * providers supply an implementation of {@link SecureRandom}, a
+ * system-provided source of randomness is used.)
+ *
+ * <p>Since no other parameters are specified when you call the above
+ * algorithm-independent initialize methods, it is up to the provider what
+ * to do about the algorithm-specific parameters (if any) to be associated
+ * with each of the keys.</p>
+ *
+ * <p>If the algorithm is the <i>DSA</i> algorithm, and the <i>keysize</i>
+ * (modulus size) is <code>512</code>, <code>768</code>, or <code>1024</code>,
+ * then the <b>GNU</b> provider uses a set of precomputed values for the
+ * <code>p</code>, <code>q</code>, and <code>g</code> parameters. If the
+ * <i>modulus size</i> is not one of the above values, the <b>GNU</b>
+ * provider creates a new set of parameters. Other providers might have
+ * precomputed parameter sets for more than just the three modulus sizes
+ * mentioned above. Still others might not have a list of precomputed
+ * parameters at all and instead always create new parameter sets.</p></li>
+ * <li><b>Algorithm-Specific Initialization</b><br/>
+ * For situations where a set of algorithm-specific parameters already
+ * exists (e.g., so-called <i>community parameters</i> in <i>DSA</i>), there
+ * are two initialize methods that have an {@link AlgorithmParameterSpec}
+ * argument. One also has a {@link SecureRandom} argument, while the the
+ * other uses the {@link SecureRandom} implementation of the highest-priority
+ * installed provider as the source of randomness. (If none of the installed
+ * providers supply an implementation of {@link SecureRandom}, a
+ * system-provided source of randomness is used.)</li>
+ * </ul>
+ *
+ * <p>In case the client does not explicitly initialize the
+ * <code>KeyPairGenerator</code> (via a call to an initialize method), each
+ * provider must supply (and document) a default initialization. For example,
+ * the <b>GNU</b> provider uses a default modulus size (keysize) of
+ * <code>1024</code> bits.</p>
+ *
+ * <p>Note that this class is abstract and extends from {@link
+ * KeyPairGeneratorSpi} for historical reasons. Application developers should
+ * only take notice of the methods defined in this <code>KeyPairGenerator</code>
+ * class; all the methods in the superclass are intended for cryptographic
+ * service providers who wish to supply their own implementations of key pair
+ * generators.</p>
+ *
+ * @see Signature
+ * @see KeyPair
+ * @see AlgorithmParameterSpec
+ * @author Mark Benvenuto
+ * @author Casey Marshall
+ */
+public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
+{
+ /** The service name for key pair generators. */
+ private static final String KEY_PAIR_GENERATOR = "KeyPairGenerator";
+
+ Provider provider;
+ private String algorithm;
+
+ /**
+ * Creates a <code>KeyPairGenerator</code> object for the specified
+ * algorithm.
+ *
+ * @param algorithm the standard string name of the algorithm.
+ * See Appendix A in the Java Cryptography Architecture API
+ * Specification &amp; Reference for information about standard
+ * algorithm names.
+ */
+ protected KeyPairGenerator(String algorithm)
+ {
+ this.algorithm = algorithm;
+ this.provider = null;
+ }
+
+ /**
+ * Returns the standard name of the algorithm for this key pair generator.
+ * See Appendix A in the Java Cryptography Architecture API Specification
+ * &amp; Reference for information about standard algorithm names.
+ *
+ * @return the standard string name of the algorithm.
+ */
+ public String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Generates a <code>KeyPairGenerator</code> object that implements the
+ * specified digest algorithm. If the default provider package provides an
+ * implementation of the requested digest algorithm, an instance of
+ * <code>KeyPairGenerator</code> containing that implementation is returned.
+ * If the algorithm is not available in the default package, other packages
+ * are searched.
+ *
+ * @param algorithm the standard string name of the algorithm. See Appendix A
+ * in the Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ * @return the new <code>KeyPairGenerator</code> object.
+ * @throws NoSuchAlgorithmException if the algorithm is not available in the
+ * environment.
+ */
+ public static KeyPairGenerator getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignored.
+ }
+ }
+
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * Generates a <code>KeyPairGenerator</code> object implementing the
+ * specified algorithm, as supplied from the specified provider, if
+ * such an algorithm is available from the provider.
+ *
+ * @param algorithm the standard string name of the algorithm. See
+ * Appendix A in the Java Cryptography Architecture API Specification
+ * &amp; Reference for information about standard algorithm names.
+ * @param provider the string name of the provider.
+ * @return the new <code>KeyPairGenerator</code> object.
+ * @throws NoSuchAlgorithmException if the algorithm is not available
+ * from the provider.
+ * @throws NoSuchProviderException if the provider is not available in the
+ * environment.
+ * @throws IllegalArgumentException if the provider name is <code>null</code>
+ * or empty.
+ * @see Provider
+ */
+ public static KeyPairGenerator getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ throw new NoSuchProviderException(provider);
+
+ return getInstance(algorithm, p);
+ }
+
+ /**
+ * Generates a <code>KeyPairGenerator</code> object implementing the specified
+ * algorithm, as supplied from the specified provider, if such an algorithm is
+ * available from the provider. Note: the provider doesn't have to be
+ * registered.
+ *
+ * @param algorithm the standard string name of the algorithm. See Appendix A
+ * in the Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ * @param provider the provider.
+ * @return the new <code>KeyPairGenerator</code> object.
+ * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
+ * available from the <code>provider</code>.
+ * @throws IllegalArgumentException if the <code>provider</code> is
+ * <code>null</code>.
+ * @since 1.4
+ * @see Provider
+ */
+ public static KeyPairGenerator getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("Illegal provider");
+
+ Object o = null;
+ try
+ {
+ o = Engine.getInstance(KEY_PAIR_GENERATOR, algorithm, provider);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ KeyPairGenerator result = null;
+ if (o instanceof KeyPairGeneratorSpi)
+ {
+ result = new DummyKeyPairGenerator((KeyPairGeneratorSpi) o, algorithm);
+ }
+ else if (o instanceof KeyPairGenerator)
+ {
+ result = (KeyPairGenerator) o;
+ result.algorithm = algorithm;
+ }
+ result.provider = provider;
+ return result;
+ }
+
+ /**
+ * Returns the provider of this key pair generator object.
+ *
+ * @return the provider of this key pair generator object.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Initializes the key pair generator for a certain keysize using a default
+ * parameter set and the {@link SecureRandom} implementation of the
+ * highest-priority installed provider as the source of randomness. (If none
+ * of the installed providers supply an implementation of {@link SecureRandom},
+ * a system-provided source of randomness is used.)
+ *
+ * @param keysize the keysize. This is an algorithm-specific metric, such as
+ * modulus length, specified in number of bits.
+ * @throws InvalidParameterException if the keysize is not supported by this
+ * <code>KeyPairGenerator</code> object.
+ */
+ public void initialize(int keysize)
+ {
+ initialize(keysize, new SecureRandom());
+ }
+
+ /**
+ * Initializes the key pair generator for a certain keysize with the given
+ * source of randomness (and a default parameter set).
+ *
+ * @param keysize the keysize. This is an algorithm-specific metric, such as
+ * modulus length, specified in number of bits.
+ * @param random the source of randomness.
+ * @throws InvalidParameterException if the <code>keysize</code> is not
+ * supported by this <code>KeyPairGenerator</code> object.
+ * @since 1.2
+ */
+ public void initialize(int keysize, SecureRandom random)
+ {
+ initialize(keysize, random);
+ }
+
+ /**
+ * <p>Initializes the key pair generator using the specified parameter set and
+ * the {@link SecureRandom} implementation of the highest-priority installed
+ * provider as the source of randomness. (If none of the installed providers
+ * supply an implementation of {@link SecureRandom}, a system-provided source
+ * of randomness is used.)</p>
+ *
+ * <p>This concrete method has been added to this previously-defined abstract
+ * class. This method calls the
+ * {@link KeyPairGeneratorSpi#initialize(AlgorithmParameterSpec, SecureRandom)}
+ * initialize method, passing it <code>params</code> and a source of
+ * randomness (obtained from the highest-priority installed provider or
+ * system-provided if none of the installed providers supply one). That
+ * initialize method always throws an {@link UnsupportedOperationException}
+ * if it is not overridden by the provider.</p>
+ *
+ * @param params the parameter set used to generate the keys.
+ * @throws InvalidAlgorithmParameterException if the given parameters are
+ * inappropriate for this key pair generator.
+ * @since 1.2
+ */
+ public void initialize(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ initialize(params, new SecureRandom());
+ }
+
+ /**
+ * <p>Initializes the key pair generator with the given parameter set and
+ * source of randomness.</p>
+ *
+ * <p>This concrete method has been added to this previously-defined abstract
+ * class. This method calls the
+ * {@link KeyPairGeneratorSpi#initialize(AlgorithmParameterSpec, SecureRandom)}
+ * initialize method, passing it <code>params</code> and <code>random</code>.
+ * That initialize method always throws an {@link UnsupportedOperationException}
+ * if it is not overridden by the provider.</p>
+ *
+ * @param params the parameter set used to generate the keys.
+ * @param random the source of randomness.
+ * @throws InvalidAlgorithmParameterException if the given parameters are
+ * inappropriate for this key pair generator.
+ * @since 1.2
+ */
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ super.initialize(params, random);
+ }
+
+ /**
+ * <p>Generates a key pair.</p>
+ *
+ * <p>If this <code>KeyPairGenerator</code> has not been initialized
+ * explicitly, provider-specific defaults will be used for the size and other
+ * (algorithm-specific) values of the generated keys.</p>
+ *
+ * <p>This will generate a new key pair every time it is called.</p>
+ *
+ * <p>This method is functionally equivalent to {@link #generateKeyPair()}.</p>
+ *
+ * @return the generated key pair.
+ * @since 1.2
+ */
+ public final KeyPair genKeyPair()
+ {
+ try
+ {
+ return getInstance("DSA", "GNU").generateKeyPair();
+ }
+ catch (Exception e)
+ {
+ System.err.println("genKeyPair failed: " + e);
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * <p>Generates a key pair.</p>
+ *
+ * <p>If this <code>KeyPairGenerator</code> has not been initialized
+ * explicitly, provider-specific defaults will be used for the size and other
+ * (algorithm-specific) values of the generated keys.</p>
+ *
+ * <p>This will generate a new key pair every time it is called.</p>
+ *
+ * <p>This method is functionally equivalent to {@link #genKeyPair()}.</p>
+ *
+ * @return the generated key pair.
+ */
+ public KeyPair generateKeyPair()
+ {
+ return genKeyPair();
+ }
+}
diff --git a/libjava/classpath/java/security/KeyPairGeneratorSpi.java b/libjava/classpath/java/security/KeyPairGeneratorSpi.java
new file mode 100644
index 00000000000..689fbec128e
--- /dev/null
+++ b/libjava/classpath/java/security/KeyPairGeneratorSpi.java
@@ -0,0 +1,102 @@
+/* KeyPairGeneratorSpi.java --- Key Pair Generator SPI Class
+ Copyright (C) 1999, 2002 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.security;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ KeyPairGeneratorSpi is the interface used to generate key pairs
+ for security algorithms.
+
+ @author Mark Benvenuto
+ */
+public abstract class KeyPairGeneratorSpi
+{
+ /**
+ Constructs a new KeyPairGeneratorSpi
+ */
+ public KeyPairGeneratorSpi()
+ {
+ }
+
+ /**
+ Initialize the KeyPairGeneratorSpi with the specified
+ key size and source of randomness
+
+ @param keysize size of the key to generate
+ @param random A SecureRandom source of randomness
+ */
+ public abstract void initialize(int keysize, SecureRandom random);
+
+ /**
+ Initialize the KeyPairGeneratorSpi with the specified
+ AlgorithmParameterSpec and source of randomness
+
+ This is a concrete method. It may be overridden by the provider
+ and if the AlgorithmParameterSpec class is invalid
+ throw InvalidAlgorithmParameterException. By default this
+ method just throws UnsupportedOperationException.
+
+ @param params A AlgorithmParameterSpec to intialize with
+ @param random A SecureRandom source of randomness
+
+ @throws InvalidAlgorithmParameterException
+ */
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ throw new java.lang.UnsupportedOperationException();
+ }
+
+ /**
+ Generates a KeyPair according the rules for the algorithm.
+ Unless intialized, algorithm defaults will be used. It
+ creates a unique key pair each time.
+
+ @return a key pair
+ */
+ public abstract KeyPair generateKeyPair();
+
+ /**
+ * We override clone here to make it accessible for use by
+ * DummyKeyPairGenerator.
+ */
+ protected Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+}
diff --git a/libjava/classpath/java/security/KeyStore.java b/libjava/classpath/java/security/KeyStore.java
new file mode 100644
index 00000000000..696448728ff
--- /dev/null
+++ b/libjava/classpath/java/security/KeyStore.java
@@ -0,0 +1,507 @@
+/* KeyStore.java --- Key Store Class
+ Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import gnu.java.security.Engine;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+
+/**
+ * Keystore represents an in-memory collection of keys and
+ * certificates. There are two types of entries:
+ *
+ * <dl>
+ * <dt>Key Entry</dt>
+ *
+ * <dd><p>This type of keystore entry store sensitive crytographic key
+ * information in a protected format.Typically this is a secret
+ * key or a private key with a certificate chain.</p></dd>
+ *
+ * <dt>Trusted Ceritificate Entry</dt>
+ *
+ * <dd><p>This type of keystore entry contains a single public key
+ * certificate belonging to annother entity. It is called trusted
+ * because the keystore owner trusts that the certificates
+ * belongs to the subject (owner) of the certificate.</p></dd>
+ * </dl>
+ *
+ * <p>Entries in a key store are referred to by their "alias": a simple
+ * unique string.
+ *
+ * <p>The structure and persistentence of the key store is not
+ * specified. Any method could be used to protect sensitive
+ * (private or secret) keys. Smart cards or integrated
+ * cryptographic engines could be used or the keystore could
+ * be simply stored in a file.</p>
+ *
+ * @see java.security.cert.Certificate
+ * @see Key
+ */
+public class KeyStore
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ /** Service name for key stores. */
+ private static final String KEY_STORE = "KeyStore";
+
+ private KeyStoreSpi keyStoreSpi;
+ private Provider provider;
+ private String type;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ Creates an instance of KeyStore
+
+ @param keyStoreSpi A KeyStore engine to use
+ @param provider A provider to use
+ @param type The type of KeyStore
+ */
+ protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
+ {
+ this.keyStoreSpi = keyStoreSpi;
+ this.provider = provider;
+ 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.
+ */
+ public static KeyStore getInstance(String type) throws KeyStoreException
+ {
+ Provider[] p = Security.getProviders();
+
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(type, p[i]);
+ }
+ catch (KeyStoreException e)
+ {
+ // Ignore.
+ }
+ }
+
+ 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
+ */
+ public static KeyStore getInstance(String type, String provider)
+ throws KeyStoreException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("Illegal provider");
+
+ 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
+ * @since 1.4
+ */
+ public static KeyStore getInstance(String type, Provider provider)
+ throws KeyStoreException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("Illegal provider");
+ try
+ {
+ return new KeyStore(
+ (KeyStoreSpi) Engine.getInstance(KEY_STORE, type, provider),
+ provider, type);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new KeyStoreException(type);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new KeyStoreException(type);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new KeyStoreException(type);
+ }
+ }
+
+ /**
+ * Returns the default KeyStore type. This method looks up the
+ * type in &lt;JAVA_HOME&gt;/lib/security/java.security with the
+ * property "keystore.type" or if that fails then "jks" .
+ */
+ public static final String getDefaultType()
+ {
+ // Security reads every property in java.security so it
+ // will return this property if it exists.
+ String tmp = Security.getProperty("keystore.type");
+
+ if (tmp == null)
+ tmp = "jks";
+
+ return tmp;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ Gets the provider that the class is from.
+
+ @return the provider of this class
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ Returns the type of the KeyStore supported
+
+ @return A string with the type of KeyStore
+ */
+ public final String getType()
+ {
+ return type;
+ }
+
+ /**
+ Returns the key associated with given alias using the
+ supplied password.
+
+ @param alias an alias for the key to get
+ @param password password to access key with
+
+ @return the requested key, or null otherwise
+
+ @throws NoSuchAlgorithmException if there is no algorithm
+ for recovering the key
+ @throws UnrecoverableKeyException key cannot be reocovered
+ (wrong password).
+ */
+ public final Key getKey(String alias, char[]password)
+ throws KeyStoreException, NoSuchAlgorithmException,
+ UnrecoverableKeyException
+ {
+ return keyStoreSpi.engineGetKey(alias, password);
+ }
+
+ /**
+ Gets a Certificate chain for the specified alias.
+
+ @param alias the alias name
+
+ @return a chain of Certificates ( ordered from the user's
+ certificate to the Certificate Authority's ) or
+ null if the alias does not exist or there is no
+ certificate chain for the alias ( the alias refers
+ to a trusted certificate entry or there is no entry).
+ */
+ public final java.security.cert.
+ Certificate[] getCertificateChain(String alias) throws KeyStoreException
+ {
+ return keyStoreSpi.engineGetCertificateChain(alias);
+ }
+
+ /**
+ Gets a Certificate for the specified alias.
+
+ If there is a trusted certificate entry then that is returned.
+ it there is a key entry with a certificate chain then the
+ first certificate is return or else null.
+
+ @param alias the alias name
+
+ @return a Certificate or null if the alias does not exist
+ or there is no certificate for the alias
+ */
+ public final java.security.cert.Certificate getCertificate(String alias)
+ throws KeyStoreException
+ {
+ return keyStoreSpi.engineGetCertificate(alias);
+ }
+
+ /**
+ Gets entry creation date for the specified alias.
+
+ @param alias the alias name
+
+ @returns the entry creation date or null
+ */
+ public final Date getCreationDate(String alias) throws KeyStoreException
+ {
+ return keyStoreSpi.engineGetCreationDate(alias);
+ }
+
+ /**
+ Assign the key to the alias in the keystore, protecting it
+ with the given password. It will overwrite an existing
+ entry and if the key is a PrivateKey, also add the
+ certificate chain representing the corresponding public key.
+
+ @param alias the alias name
+ @param key the key to add
+ @password the password to protect with
+ @param chain the certificate chain for the corresponding
+ public key
+
+ @throws KeyStoreException if it fails
+ */
+ public final void setKeyEntry(String alias, Key key, char[]password,
+ java.security.cert.
+ Certificate[]chain) throws KeyStoreException
+ {
+ keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
+ }
+
+ /**
+ Assign the key to the alias in the keystore. It will overwrite
+ an existing entry and if the key is a PrivateKey, also
+ add the certificate chain representing the corresponding
+ public key.
+
+ @param alias the alias name
+ @param key the key to add
+ @param chain the certificate chain for the corresponding
+ public key
+
+ @throws KeyStoreException if it fails
+ */
+ public final void setKeyEntry(String alias, byte[]key,
+ java.security.cert.
+ Certificate[]chain) throws KeyStoreException
+ {
+ keyStoreSpi.engineSetKeyEntry(alias, key, chain);
+ }
+
+ /**
+ Assign the certificate to the alias in the keystore. It
+ will overwrite an existing entry.
+
+ @param alias the alias name
+ @param cert the certificate to add
+
+ @throws KeyStoreException if it fails
+ */
+ public final void setCertificateEntry(String alias,
+ java.security.cert.
+ Certificate cert) throws
+ KeyStoreException
+ {
+ keyStoreSpi.engineSetCertificateEntry(alias, cert);
+ }
+
+ /**
+ Deletes the entry for the specified entry.
+
+ @param alias the alias name
+
+ @throws KeyStoreException if it fails
+ */
+ public final void deleteEntry(String alias) throws KeyStoreException
+ {
+ keyStoreSpi.engineDeleteEntry(alias);
+ }
+
+ /**
+ Generates a list of all the aliases in the keystore.
+
+ @return an Enumeration of the aliases
+ */
+ public final Enumeration aliases() throws KeyStoreException
+ {
+ return keyStoreSpi.engineAliases();
+ }
+
+ /**
+ Determines if the keystore contains the specified alias.
+
+ @param alias the alias name
+
+ @return true if it contains the alias, false otherwise
+ */
+ public final boolean containsAlias(String alias) throws KeyStoreException
+ {
+ return keyStoreSpi.engineContainsAlias(alias);
+ }
+
+ /**
+ Returns the number of entries in the keystore.
+
+ @returns the number of keystore entries.
+ */
+ public final int size() throws KeyStoreException
+ {
+ return keyStoreSpi.engineSize();
+ }
+
+ /**
+ Determines if the keystore contains a key entry for
+ the specified alias.
+
+ @param alias the alias name
+
+ @return true if it is a key entry, false otherwise
+ */
+ public final boolean isKeyEntry(String alias) throws KeyStoreException
+ {
+ return keyStoreSpi.engineIsKeyEntry(alias);
+ }
+
+
+ /**
+ Determines if the keystore contains a certificate entry for
+ the specified alias.
+
+ @param alias the alias name
+
+ @return true if it is a certificate entry, false otherwise
+ */
+ public final boolean isCertificateEntry(String alias)
+ throws KeyStoreException
+ {
+ return keyStoreSpi.engineIsCertificateEntry(alias);
+ }
+
+ /**
+ Determines if the keystore contains the specified certificate
+ entry and returns the alias.
+
+ It checks every entry and for a key entry checks only the
+ first certificate in the chain.
+
+ @param cert Certificate to look for
+
+ @return alias of first matching certificate, null if it
+ does not exist.
+ */
+ public final String getCertificateAlias(java.security.cert.Certificate cert)
+ throws KeyStoreException
+ {
+ return keyStoreSpi.engineGetCertificateAlias(cert);
+ }
+
+ /**
+ Stores the keystore in the specified output stream and it
+ uses the specified key it keep it secure.
+
+ @param stream the output stream to save the keystore to
+ @param password the password to protect the keystore integrity with
+
+ @throws IOException if an I/O error occurs.
+ @throws NoSuchAlgorithmException the data integrity algorithm
+ used cannot be found.
+ @throws CertificateException if any certificates could not be
+ stored in the output stream.
+ */
+ public final void store(OutputStream stream, char[]password)
+ throws KeyStoreException, IOException, NoSuchAlgorithmException,
+ CertificateException
+ {
+ keyStoreSpi.engineStore(stream, password);
+ }
+
+ /**
+ Loads the keystore from the specified input stream and it
+ uses the specified password to check for integrity if supplied.
+
+ @param stream the input stream to load the keystore from
+ @param password the password to check the keystore integrity with
+
+ @throws IOException if an I/O error occurs.
+ @throws NoSuchAlgorithmException the data integrity algorithm
+ used cannot be found.
+ @throws CertificateException if any certificates could not be
+ stored in the output stream.
+ */
+ public final void load(InputStream stream, char[]password)
+ throws IOException, NoSuchAlgorithmException, CertificateException
+ {
+ keyStoreSpi.engineLoad(stream, password);
+ }
+
+}
diff --git a/libjava/classpath/java/security/KeyStoreException.java b/libjava/classpath/java/security/KeyStoreException.java
new file mode 100644
index 00000000000..9a0a5354d2c
--- /dev/null
+++ b/libjava/classpath/java/security/KeyStoreException.java
@@ -0,0 +1,70 @@
+/* KeyStoreException.java -- Indicates a problem with the key store
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * Indicates a problem with the key store.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class KeyStoreException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -1119353179322377262L;
+
+ /**
+ * Create a new instance detailed error message.
+ */
+ public KeyStoreException()
+ {
+ }
+
+ /**
+ * Create a new instance with a detailed error message.
+ *
+ * @param msg the descriptive error message
+ */
+ public KeyStoreException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/KeyStoreSpi.java b/libjava/classpath/java/security/KeyStoreSpi.java
new file mode 100644
index 00000000000..a16008f9960
--- /dev/null
+++ b/libjava/classpath/java/security/KeyStoreSpi.java
@@ -0,0 +1,275 @@
+/* KeyStoreSpi.java --- Key Store Service Provider Interface
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.CertificateException;
+import java.util.Date;
+import java.util.Enumeration;
+
+/**
+ * KeyStoreSpi is the Service Provider Interface (SPI) for the
+ * KeyStore class. This is the interface for providers to
+ * supply to implement a keystore for a particular keystore
+ * type.
+ *
+ * @since 1.2
+ * @author Mark Benvenuto
+ */
+public abstract class KeyStoreSpi
+{
+ /**
+ * Constructs a new KeyStoreSpi
+ */
+ public KeyStoreSpi()
+ {
+ }
+
+ /**
+ * Returns the key associated with given alias using the
+ * supplied password.
+ *
+ * @param alias an alias for the key to get
+ * @param password password to access key with
+ *
+ * @return the requested key, or null otherwise
+ *
+ * @throws NoSuchAlgorithmException if there is no algorithm
+ * for recovering the key
+ * @throws UnrecoverableKeyException key cannot be reocovered
+ * (wrong password).
+ */
+ public abstract Key engineGetKey(String alias, char[]password)
+ throws NoSuchAlgorithmException, UnrecoverableKeyException;
+
+ /**
+ * Gets a Certificate chain for the specified alias.
+ *
+ * @param alias the alias name
+ *
+ * @return a chain of Certificates ( ordered from the user's
+ * certificate to the Certificate Authority's ) or
+ * null if the alias does not exist or there is no
+ * certificate chain for the alias ( the alias refers
+ * to a trusted certificate entry or there is no entry).
+ */
+ public abstract java.security.cert.
+ Certificate[] engineGetCertificateChain(String alias);
+
+
+ /**
+ * Gets a Certificate for the specified alias.
+ *
+ * If there is a trusted certificate entry then that is returned.
+ * it there is a key entry with a certificate chain then the
+ * first certificate is return or else null.
+ *
+ * @param alias the alias name
+ *
+ * @return a Certificate or null if the alias does not exist
+ * or there is no certificate for the alias
+ */
+ public abstract java.security.cert.
+ Certificate engineGetCertificate(String alias);
+
+ /**
+ * Gets entry creation date for the specified alias.
+ *
+ * @param alias the alias name
+ *
+ * @returns the entry creation date or null
+ */
+ public abstract Date engineGetCreationDate(String alias);
+
+ /**
+ * Assign the key to the alias in the keystore, protecting it
+ * with the given password. It will overwrite an existing
+ * entry and if the key is a PrivateKey, also add the
+ * certificate chain representing the corresponding public key.
+ *
+ * @param alias the alias name
+ * @param key the key to add
+ * @password the password to protect with
+ * @param chain the certificate chain for the corresponding
+ * public key
+ *
+ * @throws KeyStoreException if it fails
+ */
+ public abstract void engineSetKeyEntry(String alias, Key key,
+ char[]password,
+ java.security.cert.
+ Certificate[]chain) throws
+ KeyStoreException;
+
+ /**
+ * Assign the key to the alias in the keystore. It will overwrite
+ * an existing entry and if the key is a PrivateKey, also
+ * add the certificate chain representing the corresponding
+ * public key.
+ *
+ * @param alias the alias name
+ * @param key the key to add
+ * @param chain the certificate chain for the corresponding
+ * public key
+ *
+ * @throws KeyStoreException if it fails
+ */
+ public abstract void engineSetKeyEntry(String alias, byte[]key,
+ java.security.cert.
+ Certificate[]chain) throws
+ KeyStoreException;
+
+
+ /**
+ * Assign the certificate to the alias in the keystore. It
+ * will overwrite an existing entry.
+ *
+ * @param alias the alias name
+ * @param cert the certificate to add
+ *
+ * @throws KeyStoreException if it fails
+ */
+ public abstract void engineSetCertificateEntry(String alias,
+ java.security.cert.
+ Certificate cert) throws
+ KeyStoreException;
+
+ /**
+ * Deletes the entry for the specified entry.
+ *
+ * @param alias the alias name
+ *
+ * @throws KeyStoreException if it fails
+ */
+ public abstract void engineDeleteEntry(String alias)
+ throws KeyStoreException;
+
+ /**
+ * Generates a list of all the aliases in the keystore.
+ *
+ * @return an Enumeration of the aliases
+ */
+ public abstract Enumeration engineAliases();
+
+ /**
+ * Determines if the keystore contains the specified alias.
+ *
+ * @param alias the alias name
+ *
+ * @return true if it contains the alias, false otherwise
+ */
+ public abstract boolean engineContainsAlias(String alias);
+
+ /**
+ * Returns the number of entries in the keystore.
+ *
+ * @returns the number of keystore entries.
+ */
+ public abstract int engineSize();
+
+ /**
+ * Determines if the keystore contains a key entry for
+ * the specified alias.
+ *
+ * @param alias the alias name
+ *
+ * @return true if it is a key entry, false otherwise
+ */
+ public abstract boolean engineIsKeyEntry(String alias);
+
+ /**
+ * Determines if the keystore contains a certificate entry for
+ * the specified alias.
+ *
+ * @param alias the alias name
+ *
+ * @return true if it is a certificate entry, false otherwise
+ */
+ public abstract boolean engineIsCertificateEntry(String alias);
+
+ /**
+ * Determines if the keystore contains the specified certificate
+ * entry and returns the alias.
+ *
+ * It checks every entry and for a key entry checks only the
+ * first certificate in the chain.
+ *
+ * @param cert Certificate to look for
+ *
+ * @return alias of first matching certificate, null if it
+ * does not exist.
+ */
+ public abstract String engineGetCertificateAlias(java.security.cert.
+ Certificate cert);
+
+ /**
+ * Stores the keystore in the specified output stream and it
+ * uses the specified key it keep it secure.
+ *
+ * @param stream the output stream to save the keystore to
+ * @param password the password to protect the keystore integrity with
+ *
+ * @throws IOException if an I/O error occurs.
+ * @throws NoSuchAlgorithmException the data integrity algorithm
+ * used cannot be found.
+ * @throws CertificateException if any certificates could not be
+ * stored in the output stream.
+ */
+ public abstract void engineStore(OutputStream stream, char[]password)
+ throws IOException, NoSuchAlgorithmException, CertificateException;
+
+
+ /**
+ * Loads the keystore from the specified input stream and it
+ * uses the specified password to check for integrity if supplied.
+ *
+ * @param stream the input stream to load the keystore from
+ * @param password the password to check the keystore integrity with
+ *
+ * @throws IOException if an I/O error occurs.
+ * @throws NoSuchAlgorithmException the data integrity algorithm
+ * used cannot be found.
+ * @throws CertificateException if any certificates could not be
+ * stored in the output stream.
+ */
+ public abstract void engineLoad(InputStream stream, char[]password)
+ throws IOException, NoSuchAlgorithmException, CertificateException;
+}
diff --git a/libjava/classpath/java/security/MessageDigest.java b/libjava/classpath/java/security/MessageDigest.java
new file mode 100644
index 00000000000..8684f2083b1
--- /dev/null
+++ b/libjava/classpath/java/security/MessageDigest.java
@@ -0,0 +1,413 @@
+/* MessageDigest.java --- The message digest interface.
+ Copyright (C) 1999, 2002, 2003 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.security;
+
+import gnu.java.security.Engine;
+
+/**
+ * <p>This <code>MessageDigest</code> class provides applications the
+ * functionality of a message digest algorithm, such as <i>MD5</i> or <i>SHA</i>.
+ * Message digests are secure one-way hash functions that take arbitrary-sized
+ * data and output a fixed-length hash value.</p>
+ *
+ * <p>A <code>MessageDigest</code> object starts out initialized. The data is
+ * processed through it using the <code>update()</code> methods. At any point
+ * <code>reset()</code> can be called to reset the digest. Once all the data to
+ * be updated has been updated, one of the <code>digest()</code> methods should
+ * be called to complete the hash computation.</p>
+ *
+ * <p>The <code>digest()</code> method can be called <b>once</b> for a given
+ * number of updates. After <code>digest()</code> has been called, the
+ * <code>MessageDigest</code> object is <b>reset</b> to its initialized state.
+ * </p>
+ *
+ * <p>Implementations are free to implement the {@link Cloneable} interface.
+ * Client applications can test cloneability by attempting cloning and catching
+ * the {@link CloneNotSupportedException}:
+ *
+ * <pre>
+ * MessageDigest md = MessageDigest.getInstance("SHA");
+ * try
+ * {
+ * md.update(toChapter1);
+ * MessageDigest tc1 = md.clone();
+ * byte[] toChapter1Digest = tc1.digest();
+ * md.update(toChapter2);
+ * // ...
+ * }
+ * catch (CloneNotSupportedException x)
+ * {
+ * throw new DigestException("couldn't make digest of partial content");
+ * }
+ * </pre>
+ *
+ * <p>Note that if a given implementation is not cloneable, it is still possible
+ * to compute intermediate digests by instantiating several instances, if the
+ * number of digests is known in advance.</p>
+ *
+ * <p>Note that this class is abstract and extends from {@link MessageDigestSpi}
+ * for historical reasons. Application developers should only take notice of the
+ * methods defined in this <code>MessageDigest</code> class; all the methods in
+ * the superclass are intended for cryptographic service providers who wish to
+ * supply their own implementations of message digest algorithms.</p>
+ *
+ * @see MessageDigestSpi
+ * @see Provider
+ * @since JDK 1.1
+ */
+public abstract class MessageDigest extends MessageDigestSpi
+{
+ /** The service name for message digests. */
+ private static final String MESSAGE_DIGEST = "MessageDigest";
+
+ private String algorithm;
+ Provider provider;
+ private byte[] lastDigest;
+
+ /**
+ * Creates a message digest with the specified algorithm name.
+ *
+ * @param algorithm the standard name of the digest algorithm.
+ * See Appendix A in the Java Cryptography Architecture API
+ * Specification &amp; Reference for information about standard
+ * algorithm names.
+ */
+ protected MessageDigest(String algorithm)
+ {
+ this.algorithm = algorithm;
+ provider = null;
+ }
+
+ /**
+ * Generates a <code>MessageDigest</code> object that implements the specified
+ * digest algorithm. If the default provider package provides an
+ * implementation of the requested digest algorithm, an instance of
+ * <code>MessageDigest</code> containing that implementation is returned. If
+ * the algorithm is not available in the default package, other packages are
+ * searched.
+ *
+ * @param algorithm the name of the algorithm requested. See Appendix A in the
+ * Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ * @return a Message Digest object implementing the specified algorithm.
+ * @throws NoSuchAlgorithmException if the algorithm is not available in the
+ * caller's environment.
+ */
+ public static MessageDigest getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException ignored)
+ {
+ // Ignore.
+ }
+ }
+
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * Generates a <code>MessageDigest</code> object implementing the specified
+ * algorithm, as supplied from the specified provider, if such an algorithm is
+ * available from the provider.
+ *
+ * @param algorithm the name of the algorithm requested. See Appendix A in the
+ * Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ * @param provider the name of the provider.
+ * @return a Message Digest object implementing the specified algorithm.
+ * @throws NoSuchAlgorithmException if the algorithm is not available in the
+ * package supplied by the requested provider.
+ * @throws NoSuchProviderException if the provider is not available in the
+ * environment.
+ * @throws IllegalArgumentException if the provider name is null or empty.
+ * @see Provider
+ */
+ public static MessageDigest getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("Illegal provider");
+
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ throw new NoSuchProviderException(provider);
+
+ return getInstance(algorithm, p);
+ }
+
+ /**
+ * Generates a <code>MessageDigest</code> object implementing the specified
+ * algorithm, as supplied from the specified provider, if such an algorithm
+ * is available from the provider. Note: the provider doesn't have to be
+ * registered.
+ *
+ * @param algorithm the name of the algorithm requested. See Appendix A in
+ * the Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ * @param provider the provider.
+ * @return a Message Digest object implementing the specified algorithm.
+ * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
+ * available in the package supplied by the requested <code>provider</code>.
+ * @throws IllegalArgumentException if the <code>provider</code> is
+ * <code>null</code>.
+ * @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;
+ try
+ {
+ o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ if (o instanceof MessageDigestSpi)
+ {
+ result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
+ }
+ else if (o instanceof MessageDigest)
+ {
+ result = (MessageDigest) o;
+ result.algorithm = algorithm;
+ }
+ else
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ result.provider = provider;
+ return result;
+ }
+
+ /**
+ * Returns the provider of this message digest object.
+ *
+ * @return the provider of this message digest object.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Updates the digest using the specified byte.
+ *
+ * @param input the byte with which to update the digest.
+ */
+ public void update(byte input)
+ {
+ engineUpdate(input);
+ }
+
+ /**
+ * Updates the digest using the specified array of bytes, starting at the
+ * specified offset.
+ *
+ * @param input the array of bytes.
+ * @param offset the offset to start from in the array of bytes.
+ * @param len the number of bytes to use, starting at offset.
+ */
+ public void update(byte[] input, int offset, int len)
+ {
+ engineUpdate(input, offset, len);
+ }
+
+ /**
+ * Updates the digest using the specified array of bytes.
+ *
+ * @param input the array of bytes.
+ */
+ public void update(byte[] input)
+ {
+ engineUpdate(input, 0, input.length);
+ }
+
+ /**
+ * Completes the hash computation by performing final operations such as
+ * padding. The digest is reset after this call is made.
+ *
+ * @return the array of bytes for the resulting hash value.
+ */
+ public byte[] digest()
+ {
+ return lastDigest = engineDigest();
+ }
+
+ /**
+ * Completes the hash computation by performing final operations such as
+ * padding. The digest is reset after this call is made.
+ *
+ * @param buf An output buffer for the computed digest.
+ * @param offset The offset into the output buffer to begin storing the digest.
+ * @param len The number of bytes within buf allotted for the digest.
+ * @return The number of bytes placed into buf.
+ * @throws DigestException if an error occurs.
+ */
+ public int digest(byte[] buf, int offset, int len) throws DigestException
+ {
+ return engineDigest(buf, offset, len);
+ }
+
+ /**
+ * Performs a final update on the digest using the specified array of bytes,
+ * then completes the digest computation. That is, this method first calls
+ * <code>update(input)</code>, passing the input array to the <code>update()
+ * </code> method, then calls <code>digest()</code>.
+ *
+ * @param input the input to be updated before the digest is completed.
+ * @return the array of bytes for the resulting hash value.
+ */
+ public byte[] digest(byte[] input)
+ {
+ update(input);
+ return digest();
+ }
+
+ /**
+ * Returns a string representation of this message digest object.
+ *
+ * @return a string representation of the object.
+ */
+ public String toString()
+ {
+ return (getClass()).getName() + " Message Digest <" + digestToString() + ">";
+ }
+
+ /**
+ * Compares two digests for equality. Does a simple byte compare.
+ *
+ * @param digesta one of the digests to compare.
+ * @param digestb the other digest to compare.
+ * @return <code>true</code> if the digests are equal, <code>false</code>
+ * otherwise.
+ */
+ public static boolean isEqual(byte[] digesta, byte[] digestb)
+ {
+ if (digesta.length != digestb.length)
+ return false;
+
+ for (int i = digesta.length - 1; i >= 0; --i)
+ if (digesta[i] != digestb[i])
+ return false;
+
+ return true;
+ }
+
+ /** Resets the digest for further use. */
+ public void reset()
+ {
+ engineReset();
+ }
+
+ /**
+ * Returns a string that identifies the algorithm, independent of
+ * implementation details. The name should be a standard Java Security name
+ * (such as <code>"SHA"</code>, <code>"MD5"</code>, and so on). See Appendix
+ * A in the Java Cryptography Architecture API Specification &amp; Reference
+ * for information about standard algorithm names.
+ *
+ * @return the name of the algorithm.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Returns the length of the digest in bytes, or <code>0</code> if this
+ * operation is not supported by the provider and the implementation is not
+ * cloneable.
+ *
+ * @return the digest length in bytes, or <code>0</code> if this operation is
+ * not supported by the provider and the implementation is not cloneable.
+ * @since 1.2
+ */
+ public final int getDigestLength()
+ {
+ return engineGetDigestLength();
+ }
+
+ /**
+ * Returns a clone if the implementation is cloneable.
+ *
+ * @return a clone if the implementation is cloneable.
+ * @throws CloneNotSupportedException if this is called on an implementation
+ * that does not support {@link Cloneable}.
+ */
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+
+ private String digestToString()
+ {
+ byte[] digest = lastDigest;
+
+ if (digest == null)
+ return "incomplete";
+
+ StringBuffer buf = new StringBuffer();
+ int len = digest.length;
+ for (int i = 0; i < len; ++i)
+ {
+ byte b = digest[i];
+ byte high = (byte) ((b & 0xff) >>> 4);
+ byte low = (byte) (b & 0xf);
+
+ buf.append(high > 9 ? ('a' - 10) + high : '0' + high);
+ buf.append(low > 9 ? ('a' - 10) + low : '0' + low);
+ }
+
+ return buf.toString();
+ }
+}
diff --git a/libjava/classpath/java/security/MessageDigestSpi.java b/libjava/classpath/java/security/MessageDigestSpi.java
new file mode 100644
index 00000000000..df3bd3ead02
--- /dev/null
+++ b/libjava/classpath/java/security/MessageDigestSpi.java
@@ -0,0 +1,155 @@
+/* MessageDigestSpi.java --- The message digest service provider interface.
+ Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ This is the Service Provider Interface (SPI) for MessageDigest
+ class in java.security. It provides the back end functionality
+ for the MessageDigest class so that it can compute message
+ hashes. The default hashes are SHA-1 and MD5. A message hash
+ takes data of arbitrary length and produces a unique number
+ representing it.
+
+ Cryptography service providers who want to implement their
+ own message digest hashes need only to subclass this class.
+
+ The implementation of a Cloneable interface is left to up to
+ the programmer of a subclass.
+
+ @version 0.0
+
+ @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ */
+public abstract class MessageDigestSpi
+{
+ /**
+ Default constructor of the MessageDigestSpi class
+ */
+ public MessageDigestSpi()
+ {
+ }
+
+ /**
+ Returns the length of the digest. It may be overridden by the
+ provider to return the length of the digest. Default is to
+ return 0. It is concrete for backwards compatibility with JDK1.1
+ message digest classes.
+
+ @return Length of Digest in Bytes
+
+ @since 1.2
+ */
+ protected int engineGetDigestLength()
+ {
+ return 0;
+ }
+
+ /**
+ Updates the digest with the specified byte.
+
+ @param input the byte to update digest with
+ */
+ protected abstract void engineUpdate(byte input);
+
+
+ /**
+ Updates the digest with the specified bytes starting with the
+ offset and proceeding for the specified length.
+
+ @param input the byte array to update digest with
+ @param offset the offset of the byte to start with
+ @param len the number of the bytes to update with
+ */
+ protected abstract void engineUpdate(byte[]input, int offset, int len);
+
+ /**
+ Computes the final digest of the stored bytes and returns
+ them. It performs any necessary padding. The message digest
+ should reset sensitive data after performing the digest.
+
+ @return An array of bytes containing the digest
+ */
+ protected abstract byte[] engineDigest();
+
+ /**
+ Computes the final digest of the stored bytes and returns
+ them. It performs any necessary padding. The message digest
+ should reset sensitive data after performing the digest. This
+ method is left concrete for backwards compatibility with JDK1.1
+ message digest classes.
+
+ @param buf An array of bytes to store the digest
+ @param offset An offset to start storing the digest at
+ @param len The length of the buffer
+ @return Returns the length of the buffer
+
+ @since 1.2
+ */
+ protected int engineDigest(byte[]buf, int offset, int len)
+ throws DigestException
+ {
+ if (engineGetDigestLength() > len)
+ throw new DigestException("Buffer is too small.");
+
+ byte[] tmp = engineDigest();
+ if (tmp.length > len)
+ throw new DigestException("Buffer is too small");
+
+ System.arraycopy(tmp, 0, buf, offset, tmp.length);
+ return tmp.length;
+ }
+
+ /**
+ Resets the digest engine. Reinitializes internal variables
+ and clears sensitive data.
+ */
+ protected abstract void engineReset();
+
+ /**
+ Returns a clone of this class.
+
+ If cloning is not supported, then by default the class throws a
+ CloneNotSupportedException. The MessageDigestSpi provider
+ implementation has to overload this class in order to be
+ cloneable.
+ */
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+}
diff --git a/libjava/classpath/java/security/NoSuchAlgorithmException.java b/libjava/classpath/java/security/NoSuchAlgorithmException.java
new file mode 100644
index 00000000000..412d14a16d7
--- /dev/null
+++ b/libjava/classpath/java/security/NoSuchAlgorithmException.java
@@ -0,0 +1,70 @@
+/* NoSuchAlgorithmException.java -- an algorithm was not available
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception is thrown when the requested security algorithm is
+ * not available
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class NoSuchAlgorithmException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -7443947487218346562L;
+
+ /**
+ * Create a new instance with no descriptive error message.
+ */
+ public NoSuchAlgorithmException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param msg the descriptive error message
+ */
+ public NoSuchAlgorithmException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/NoSuchProviderException.java b/libjava/classpath/java/security/NoSuchProviderException.java
new file mode 100644
index 00000000000..bd26df5ef07
--- /dev/null
+++ b/libjava/classpath/java/security/NoSuchProviderException.java
@@ -0,0 +1,70 @@
+/* NoSuchProviderException.java -- thrown when a provider is not found
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception is thrown when the requested security provider is
+ * not available.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class NoSuchProviderException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 8488111756688534474L;
+
+ /**
+ * Create a new instance with no descriptive error message.
+ */
+ public NoSuchProviderException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param msg the descriptive error message
+ */
+ public NoSuchProviderException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/Permission.java b/libjava/classpath/java/security/Permission.java
new file mode 100644
index 00000000000..48f4d52a18c
--- /dev/null
+++ b/libjava/classpath/java/security/Permission.java
@@ -0,0 +1,187 @@
+/* Permission.java -- The superclass for all permission objects
+ Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+import java.io.Serializable;
+
+/**
+ * This class is the abstract superclass of all classes that implement
+ * the concept of a permission. A permission consists of a permission name
+ * and optionally a list of actions that relate to the permission. The
+ * actual meaning of the name of the permission is defined only in the
+ * context of a subclass. It may name a resource to which access permissions
+ * are granted (for example, the name of a file) or it might represent
+ * something else entirely. Similarly, the action list only has meaning
+ * within the context of a subclass. Some permission names may have no
+ * actions associated with them. That is, you either have the permission
+ * or you don't.
+ *
+ * <p>The most important method in this class is <code>implies</code>. This
+ * checks whether if one has this permission, then the specified
+ * permission is also implied. As a conceptual example, consider the
+ * permissions "Read All Files" and "Read File foo". The permission
+ * "Read All Files" implies that the caller has permission to read the
+ * file foo.
+ *
+ * <p><code>Permission</code>'s must be immutable - do not change their
+ * state after creation.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Permissions
+ * @see PermissionCollection
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class Permission implements Guard, Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5636570222231596674L;
+
+ /**
+ * This is the name assigned to this permission object.
+ *
+ * @serial the name of the permission
+ */
+ private String name;
+
+ /**
+ * Create an instance with the specified name.
+ *
+ * @param name the permission name
+ */
+ public Permission(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * This method implements the <code>Guard</code> interface for this class.
+ * It calls the <code>checkPermission</code> method in
+ * <code>SecurityManager</code> with this <code>Permission</code> as its
+ * argument. This method returns silently if the security check succeeds
+ * or throws an exception if it fails.
+ *
+ * @param obj the <code>Object</code> being guarded - ignored by this class
+ * @throws SecurityException if the security check fails
+ * @see GuardedObject
+ * @see SecurityManager#checkPermission(Permission)
+ */
+ public void checkGuard(Object obj)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(this);
+ }
+
+ /**
+ * This method tests whether this <code>Permission</code> implies that the
+ * specified <code>Permission</code> is also granted.
+ *
+ * @param perm the <code>Permission</code> to test against
+ * @return true if perm is implied by this
+ */
+ public abstract boolean implies(Permission perm);
+
+ /**
+ * Check to see if this object equals obj. Use <code>implies</code>, rather
+ * than <code>equals</code>, when making access control decisions.
+ *
+ * @param obj the object to compare to
+ */
+ public abstract boolean equals(Object obj);
+
+ /**
+ * This method returns a hash code for this <code>Permission</code>. It
+ * must satisfy the contract of <code>Object.hashCode</code>: it must be
+ * the same for all objects that equals considers to be the same.
+ *
+ * @return a hash value
+ */
+ public abstract int hashCode();
+
+ /**
+ * Get the name of this <code>Permission</code>.
+ *
+ * @return the name
+ */
+ public final String getName()
+ {
+ return name;
+ }
+
+ /**
+ * This method returns the list of actions for this <code>Permission</code>
+ * as a <code>String</code>. The string should be in canonical order, for
+ * example, both <code>new FilePermission(f, "write,read")</code> and
+ * <code>new FilePermission(f, "read,write")</code> have the action list
+ * "read,write".
+ *
+ * @return the action list for this <code>Permission</code>
+ */
+ public abstract String getActions();
+
+ /**
+ * This method returns an empty <code>PermissionCollection</code> object
+ * that can store permissions of this type, or <code>null</code> if no
+ * such collection is defined. Subclasses must override this to provide
+ * an appropriate collection when one is needed to accurately calculate
+ * <code>implies</code>.
+ *
+ * @return a new <code>PermissionCollection</code>
+ */
+ public PermissionCollection newPermissionCollection()
+ {
+ return null;
+ }
+
+ /**
+ * This method returns a <code>String</code> representation of this
+ * <code>Permission</code> object. This is in the format:
+ * <code>'(' + getClass().getName() + ' ' + getName() + ' ' + getActions
+ * + ')'</code>.
+ *
+ * @return this object as a <code>String</code>
+ */
+ public String toString()
+ {
+ return '(' + getClass().getName() + ' ' + getName() + ' '
+ + getActions() + ')';
+ }
+} // class Permission
diff --git a/libjava/classpath/java/security/PermissionCollection.java b/libjava/classpath/java/security/PermissionCollection.java
new file mode 100644
index 00000000000..4e8ffe57948
--- /dev/null
+++ b/libjava/classpath/java/security/PermissionCollection.java
@@ -0,0 +1,167 @@
+/* PermissionCollection.java -- A collection of permission objects
+ Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+
+/**
+ * This class models a group of Java permissions. It has convenient
+ * methods for determining whether or not a given permission is implied
+ * by any of the permissions in this collection.
+ *
+ * <p>Some care must be taken in storing permissions. First, a collection of
+ * the appropriate type must be created. This is done by calling the
+ * <code>newPermissionCollection</code> method on an object of the
+ * permission class you wish to add to the collection. If this method
+ * returns <code>null</code>, any type of <code>PermissionCollection</code>
+ * can be used to store permissions of that type. However, if a
+ * <code>PermissionCollection</code> collection object is returned, that
+ * type must be used.
+ *
+ * <p>A <code>PermissionCollection</code> returned by the
+ * <code>newPermissionCollection</code> method in a subclass of
+ * <code>Permission</code> is a homogeneous collection. It only will
+ * hold permissions of one specified type - instances of the class that
+ * created it. Not all <code>PermissionCollection</code> subclasses
+ * have to hold permissions of only one type however. For example,
+ * the <code>Permissions</code> class holds permissions of many types.
+ *
+ * <p>Since the <code>newPermissionCollection</code> in <code>Permission</code>
+ * itself returns <code>null</code>, by default a permission can be stored
+ * in any type of collection unless it overrides that method to create its
+ * own collection type.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Permission
+ * @see Permissions
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class PermissionCollection implements Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -6727011328946861783L;
+
+ /**
+ * Indicates whether or not this collection is read only.
+ *
+ * @serial if the collection is read-only
+ */
+ private boolean readOnly;
+
+ /**
+ * Create a new collection.
+ */
+ public PermissionCollection()
+ {
+ }
+
+ /**
+ * This method adds a new <code>Permission</code> object to the collection.
+ *
+ * @param perm the <code>Permission</code> to add
+ *
+ * @throws SecurityException if the collection is marked read only
+ * @throws IllegalArgumentException if perm is of the wrong type
+ */
+ public abstract void add(Permission perm);
+
+ /**
+ * This method tests whether the specified <code>Permission</code> object is
+ * implied by this collection of <code>Permission</code> objects.
+ *
+ * @param perm the <code>Permission</code> object to test
+ * @return true if the collection implies perm
+ */
+ public abstract boolean implies(Permission perm);
+
+ /**
+ * This method returns an <code>Enumeration</code> of all the objects in
+ * this collection.
+ *
+ * @return an <code>Enumeration</code> of this collection's objects
+ */
+ public abstract Enumeration elements();
+
+ /**
+ * This method sets this <code>PermissionCollection</code> object to be
+ * read only. No further permissions can be added to it after calling this
+ * method.
+ */
+ public void setReadOnly()
+ {
+ readOnly = true;
+ }
+
+ /**
+ * This method tests whether or not this <code>PermissionCollection</code>
+ * object is read only.
+ *
+ * @return true if this collection is read only
+ */
+ public boolean isReadOnly()
+ {
+ return readOnly;
+ }
+
+ /**
+ * This method returns a <code>String</code> representation of this
+ * collection. It is formed by:
+ * <pre>
+ * super.toString()" (\n"
+ * // enumerate all permissions, one per line
+ * ")\n"
+ * </pre>
+ *
+ * @return a <code>String</code> representing this object
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer(super.toString());
+
+ sb.append(" (\n");
+ Enumeration e = elements();
+ while (e.hasMoreElements())
+ sb.append(' ').append(e.nextElement()).append('\n');
+ return sb.append(")\n").toString();
+ }
+} // class PermissionCollection
diff --git a/libjava/classpath/java/security/Permissions.java b/libjava/classpath/java/security/Permissions.java
new file mode 100644
index 00000000000..e3fd06970ab
--- /dev/null
+++ b/libjava/classpath/java/security/Permissions.java
@@ -0,0 +1,254 @@
+/* Permissions.java -- a collection of permission collections
+ Copyright (C) 1998, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+
+/**
+ * This class is a heterogeneous collection of permissions. It is
+ * organized as a collection of <code>PermissionCollection</code>'s stored
+ * in a hashtable. Each individual <code>PermissionCollection</code>
+ * contains permissions of a single type. If a specific type of
+ * <code>Permission</code> does not provide a collection type to use
+ * via its <code>newPermissionCollection</code> method, then a default
+ * collection type which stores its permissions in a hash table will be
+ * used.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ */
+public final class Permissions extends PermissionCollection
+ implements Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4858622370623524688L;
+
+ /**
+ * Holds instances of <code>AllPermission</code>.
+ *
+ * @serial the permission collection for AllPermission
+ */
+ private PermissionCollection allPermission;
+
+ // Package-private to avoid a trampoline.
+ /**
+ * This is the <code>Hashtable</code> that contains our collections.
+ *
+ * @serial maps Class to PermissionCollection
+ */
+ final Hashtable perms = new Hashtable();
+
+ /**
+ * This method initializes a new instance of <code>Permissions</code>.
+ */
+ public Permissions()
+ {
+ }
+
+ /**
+ * This method adds a new <code>Permission</code> to this collection. It
+ * will be stored in a <code>PermissionCollection</code> of the appropriate
+ * type, as determined by calling <code>newPermissionCollection</code> on
+ * the specified permission (if an appropriate collection does not already
+ * exist). If this object does not specify a particular type of collection,
+ * a default collection, which stores in permissions in a hash table, will
+ * be used.
+ *
+ * @param perm the <code>Permission</code> to add
+ * @throws SecurityException if this collection is marked as read only
+ */
+ public void add(Permission perm)
+ {
+ if (isReadOnly())
+ throw new SecurityException("PermissionCollection is read only");
+ if (perm instanceof AllPermission)
+ {
+ if (allPermission == null)
+ {
+ allPermission = perm.newPermissionCollection();
+ allPermission.add(perm);
+ perms.put(perm.getClass(), allPermission);
+ }
+ }
+ else
+ {
+ PermissionCollection pc
+ = (PermissionCollection) perms.get(perm.getClass());
+ if (pc == null)
+ {
+ pc = perm.newPermissionCollection();
+ if (pc == null)
+ pc = new PermissionsHash();
+ perms.put(perm.getClass(), pc);
+ }
+ pc.add(perm);
+ }
+ }
+
+ /**
+ * This method tests whether or not the specified <code>Permission</code>
+ * is implied by this <code>PermissionCollection</code>.
+ *
+ * @param perm the <code>Permission</code> to test
+ * @return true if the specified permission is implied by this
+ */
+ public boolean implies(Permission perm)
+ {
+ if (allPermission != null)
+ return true;
+ PermissionCollection pc
+ = (PermissionCollection) perms.get(perm.getClass());
+ return pc == null ? false : pc.implies(perm);
+ }
+
+ /**
+ * This method returns an <code>Enumeration</code> which contains a
+ * list of all <code>Permission</code> objects contained in this
+ * collection.
+ *
+ * @return an <code>Enumeration</code> of this collection's elements
+ */
+ public Enumeration elements()
+ {
+ return new Enumeration()
+ {
+ Enumeration main_enum = perms.elements();
+ Enumeration sub_enum;
+
+ public boolean hasMoreElements()
+ {
+ if (sub_enum == null)
+ {
+ if (main_enum == null)
+ return false;
+ if (! main_enum.hasMoreElements())
+ {
+ main_enum = null;
+ return false;
+ }
+ PermissionCollection pc =
+ (PermissionCollection) main_enum.nextElement();
+ sub_enum = pc.elements();
+ }
+ if (! sub_enum.hasMoreElements())
+ {
+ sub_enum = null;
+ return hasMoreElements();
+ }
+ return true;
+ }
+
+ public Object nextElement()
+ {
+ if (! hasMoreElements())
+ throw new NoSuchElementException();
+ return sub_enum.nextElement();
+ }
+ };
+ }
+
+ /**
+ * Implements the permission collection for all permissions without one of
+ * their own, and obeys serialization of JDK.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class PermissionsHash extends PermissionCollection
+ {
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -8491988220802933440L;
+
+ /**
+ * Hashtable where we store permissions.
+ *
+ * @serial the stored permissions, both as key and value
+ */
+ private final Hashtable perms = new Hashtable();
+
+ /**
+ * Add a permission. We don't need to check for read-only, as this
+ * collection is never exposed outside of Permissions, which has already
+ * done that check.
+ *
+ * @param perm the permission to add
+ */
+ public void add(Permission perm)
+ {
+ perms.put(perm, perm);
+ }
+
+ /**
+ * Returns true if perm is in the collection.
+ *
+ * @param perm the permission to check
+ * @return true if it is implied
+ */
+ // FIXME: Should this method be synchronized?
+ public boolean implies(Permission perm)
+ {
+ Enumeration elements = elements();
+
+ while (elements.hasMoreElements())
+ {
+ Permission p = (Permission)elements.nextElement();
+ if (p.implies(perm))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return the elements.
+ *
+ * @return the elements
+ */
+ public Enumeration elements()
+ {
+ return perms.elements();
+ }
+ } // class PermissionsHash
+} // class Permissions
diff --git a/libjava/classpath/java/security/Policy.java b/libjava/classpath/java/security/Policy.java
new file mode 100644
index 00000000000..03d9bbb4ed6
--- /dev/null
+++ b/libjava/classpath/java/security/Policy.java
@@ -0,0 +1,310 @@
+/* Policy.java --- Policy Manager Class
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * <p>This is an abstract class for representing the system security policy for
+ * a Java application environment (specifying which permissions are available
+ * for code from various sources). That is, the security policy is represented
+ * by a <code>Policy</code> subclass providing an implementation of the abstract
+ * methods in this <code>Policy</code> class.</p>
+ *
+ * <p>There is only one <code>Policy</code> object in effect at any given time.
+ * </p>
+ *
+ * <p>The source location for the policy information utilized by the
+ * <code>Policy</code> object is up to the <code>Policy</code> implementation.
+ * The policy configuration may be stored, for example, as a flat ASCII file, as
+ * a serialized binary file of the <code>Policy</code> class, or as a database.
+ * </p>
+ *
+ * <p>The currently-installed <code>Policy</code> object can be obtained by
+ * calling the <code>getPolicy()</code> method, and it can be changed by a call
+ * to the <code>setPolicy()</code> method (by code with permission to reset the
+ * <code>Policy</code>).</p>
+ *
+ * <p>The <code>refresh()</code> method causes the policy object to refresh /
+ * reload its current configuration.</p>
+ *
+ * <p>This is implementation-dependent. For example, if the policy object stores
+ * its policy in configuration files, calling <code>refresh()</code> will cause
+ * it to re-read the configuration policy files. The refreshed policy may not
+ * have an effect on classes in a particular {@link ProtectionDomain}. This is
+ * dependent on the <code>Policy</code> provider's implementation of the
+ * <code>implies()</code> method and the {@link PermissionCollection} caching
+ * strategy.</p>
+ *
+ * <p>The default <code>Policy</code> implementation can be changed by setting
+ * the value of the <code>"policy.provider"</code> security property (in the
+ * Java security properties file) to the fully qualified name of the desired
+ * <code>Policy</code> implementation class. The Java security properties file
+ * is located in the file named <code>&lt;JAVA_HOME>/lib/security/java.security
+ * </code>, where <code>&lt;JAVA_HOME></code> refers to the directory where the
+ * SDK was installed.</p>
+ *
+ * <p><b>IMPLEMENTATION NOTE:</b> This implementation attempts to read the
+ * System property named <code>policy.provider</code> to find the concrete
+ * implementation of the <code>Policy</code>. If/when this fails, it falls back
+ * to a default implementation, which <b>allows everything</b>.
+ *
+ * @author Mark Benvenuto
+ * @see CodeSource
+ * @see PermissionCollection
+ * @see SecureClassLoader
+ * @since 1.2
+ */
+public abstract class Policy
+{
+ private static Policy currentPolicy;
+
+ /** Map of ProtectionDomains to PermissionCollections for this instance. */
+ private Map pd2pc = null;
+
+ /** Constructs a new <code>Policy</code> object. */
+ public Policy()
+ {
+ }
+
+ /**
+ * Returns the installed <code>Policy</code> object. This value should not be
+ * cached, as it may be changed by a call to <code>setPolicy()</code>. This
+ * method first calls {@link SecurityManager#checkPermission(Permission)} with
+ * a <code>SecurityPermission("getPolicy")</code> permission to ensure it's ok
+ * to get the <code>Policy</code> object.
+ *
+ * @return the installed <code>Policy</code>.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkPermission()</code> method doesn't allow getting the
+ * <code>Policy</code> object.
+ * @see SecurityManager#checkPermission(Permission)
+ * @see #setPolicy(Policy)
+ */
+ public static Policy getPolicy()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new SecurityPermission("getPolicy"));
+
+ return getCurrentPolicy();
+ }
+
+ /**
+ * Sets the system-wide <code>Policy</code> object. This method first calls
+ * {@link SecurityManager#checkPermission(Permission)} with a
+ * <code>SecurityPermission("setPolicy")</code> permission to ensure it's ok
+ * to set the <code>Policy</code>.
+ *
+ * @param policy the new system <code>Policy</code> object.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkPermission()</code> method doesn't allow setting the
+ * <code>Policy</code>.
+ * @see SecurityManager#checkPermission(Permission)
+ * @see #getPolicy()
+ */
+ public static void setPolicy(Policy policy)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new SecurityPermission("setPolicy"));
+
+ setup(policy);
+ currentPolicy = policy;
+ }
+
+ private static void setup(final Policy policy)
+ {
+ if (policy.pd2pc == null)
+ policy.pd2pc = Collections.synchronizedMap(new LinkedHashMap());
+
+ ProtectionDomain pd = policy.getClass().getProtectionDomain();
+ if (pd.getCodeSource() != null)
+ {
+ PermissionCollection pc = null;
+ if (currentPolicy != null)
+ pc = currentPolicy.getPermissions(pd);
+
+ if (pc == null) // assume it has all
+ {
+ pc = new Permissions();
+ pc.add(new AllPermission());
+ }
+
+ policy.pd2pc.put(pd, pc); // add the mapping pd -> pc
+ }
+ }
+
+ /**
+ * Ensures/forces loading of the configured policy provider, while bypassing
+ * the {@link SecurityManager} checks for <code>"getPolicy"</code> security
+ * permission. Needed by {@link ProtectionDomain}.
+ */
+ static Policy getCurrentPolicy()
+ {
+ // FIXME: The class name of the Policy provider should really be sourced
+ // from the "java.security" configuration file. For now, just hard-code
+ // a stub implementation.
+ if (currentPolicy == null)
+ {
+ String pp = System.getProperty ("policy.provider");
+ if (pp != null)
+ try
+ {
+ currentPolicy = (Policy) Class.forName(pp).newInstance();
+ }
+ catch (Exception e)
+ {
+ // Ignored.
+ }
+
+ if (currentPolicy == null)
+ currentPolicy = new gnu.java.security.provider.DefaultPolicy();
+ }
+ return currentPolicy;
+ }
+
+ /**
+ * Tests if <code>currentPolicy</code> is not <code>null</code>,
+ * thus allowing clients to not force loading of any policy
+ * provider; needed by {@link ProtectionDomain}.
+ */
+ static boolean isLoaded()
+ {
+ return currentPolicy != null;
+ }
+
+ /**
+ * Evaluates the global policy and returns a {@link PermissionCollection}
+ * object specifying the set of permissions allowed for code from the
+ * specified code source.
+ *
+ * @param codesource the {@link CodeSource} associated with the caller. This
+ * encapsulates the original location of the code (where the code came from)
+ * and the public key(s) of its signer.
+ * @return the set of permissions allowed for code from codesource according
+ * to the policy. The returned set of permissions must be a new mutable
+ * instance and it must support heterogeneous {@link Permission} types.
+ */
+ public abstract PermissionCollection getPermissions(CodeSource codesource);
+
+ /**
+ * Evaluates the global policy and returns a {@link PermissionCollection}
+ * object specifying the set of permissions allowed given the characteristics
+ * of the protection domain.
+ *
+ * @param domain the {@link ProtectionDomain} associated with the caller.
+ * @return the set of permissions allowed for the domain according to the
+ * policy. The returned set of permissions must be a new mutable instance and
+ * it must support heterogeneous {@link Permission} types.
+ * @since 1.4
+ * @see ProtectionDomain
+ * @see SecureClassLoader
+ */
+ public PermissionCollection getPermissions(ProtectionDomain domain)
+ {
+ if (domain == null)
+ return new Permissions();
+
+ if (pd2pc == null)
+ setup(this);
+
+ PermissionCollection result = (PermissionCollection) pd2pc.get(domain);
+ if (result != null)
+ {
+ Permissions realResult = new Permissions();
+ for (Enumeration e = result.elements(); e.hasMoreElements(); )
+ realResult.add((Permission) e.nextElement());
+
+ return realResult;
+ }
+
+ result = getPermissions(domain.getCodeSource());
+ if (result == null)
+ result = new Permissions();
+
+ PermissionCollection pc = domain.getPermissions();
+ if (pc != null)
+ for (Enumeration e = pc.elements(); e.hasMoreElements(); )
+ result.add((Permission) e.nextElement());
+
+ return result;
+ }
+
+ /**
+ * Evaluates the global policy for the permissions granted to the {@link
+ * ProtectionDomain} and tests whether the <code>permission</code> is granted.
+ *
+ * @param domain the {@link ProtectionDomain} to test.
+ * @param permission the {@link Permission} object to be tested for
+ * implication.
+ * @return <code>true</code> if <code>permission</code> is a proper subset of
+ * a permission granted to this {@link ProtectionDomain}.
+ * @since 1.4
+ * @see ProtectionDomain
+ */
+ public boolean implies(ProtectionDomain domain, Permission permission)
+ {
+ if (pd2pc == null)
+ setup(this);
+
+ PermissionCollection pc = (PermissionCollection) pd2pc.get(domain);
+ if (pc != null)
+ return pc.implies(permission);
+
+ boolean result = false;
+ pc = getPermissions(domain);
+ if (pc != null)
+ {
+ result = pc.implies(permission);
+ pd2pc.put(domain, pc);
+ }
+
+ return result;
+ }
+
+ /**
+ * Refreshes/reloads the policy configuration. The behavior of this method
+ * depends on the implementation. For example, calling refresh on a file-based
+ * policy will cause the file to be re-read.
+ */
+ public abstract void refresh();
+}
diff --git a/libjava/classpath/java/security/Principal.java b/libjava/classpath/java/security/Principal.java
new file mode 100644
index 00000000000..6d9de6ccd8a
--- /dev/null
+++ b/libjava/classpath/java/security/Principal.java
@@ -0,0 +1,85 @@
+/* Principal.java -- A security entity
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+/**
+ * This interface models an entity (such as a user or a certificate authority)
+ * for the purposes of applying the Java security model.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see X509Certificate
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Principal
+{
+ /**
+ * This method tests another <code>Principal</code> object for equality
+ * with this one.
+ *
+ * @param obj the Object to test for equality
+ * @return true if the specified <code>Principal</code> is equal
+ */
+ boolean equals(Object obj);
+
+ /**
+ * This method returns a <code>String</code> representation of this
+ * <code>Principal</code>.
+ *
+ * @return this <code>Principal</code> represented as a <code>String</code>
+ */
+ String toString();
+
+ /**
+ * This method returns a hash code value for this <code>Principal</code>.
+ * Remember the contract of hashCode - two objects which compare as
+ * equals() must have the same hashCode().
+ *
+ * @return a hash value
+ */
+ int hashCode();
+
+ /**
+ * This method returns a <code>String</code> that names this
+ * <code>Principal</code>.
+ *
+ * @return the name of this <code>Principal</code>
+ */
+ String getName();
+} // interface Principal
diff --git a/libjava/classpath/java/security/PrivateKey.java b/libjava/classpath/java/security/PrivateKey.java
new file mode 100644
index 00000000000..70607c13442
--- /dev/null
+++ b/libjava/classpath/java/security/PrivateKey.java
@@ -0,0 +1,62 @@
+/* PrivateKey.java -- tagging interface for all private keys
+ Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+/**
+ * This interface specified no methods. In simply provides a common
+ * super-interface for all algorithm specific private key values.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Key
+ * @see PublicKey
+ * @see Certificate
+ * @see Signature#initVerify(PublicKey)
+ * @see DSAPrivateKey
+ * @see RSAPrivateKey
+ * @see RSAPrivateCrtKey
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface PrivateKey extends Key
+{
+ /**
+ * The version identifier used for serialization.
+ */
+ long serialVersionUID = 6034044314589513430L;
+} // interface PrivateKey
diff --git a/libjava/classpath/java/security/PrivilegedAction.java b/libjava/classpath/java/security/PrivilegedAction.java
new file mode 100644
index 00000000000..c3a41346f9c
--- /dev/null
+++ b/libjava/classpath/java/security/PrivilegedAction.java
@@ -0,0 +1,64 @@
+/* PrivilegedAction.java -- Perform a privileged action
+ Copyright (C) 1998, 2002 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.security;
+
+/**
+ * This interface specifes a single <code>run</code> method that
+ * executes a privileged operation. This method is called by
+ * <code>AccessController.doPrivileged()</code> after that method
+ * activiates the required privileges.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see AccessController
+ * @see PrivilegedExceptionAction
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface PrivilegedAction
+{
+ /**
+ * This method performs an operation that requires higher privileges to
+ * perform. It is called when a section of code invokes
+ * <code>AccessController.doPrivileged()</code>.
+ *
+ * @return obj An implementation dependent return value
+ * @see AccessController#doPrivileged(PrivilegedAction)
+ * @see AccessController#doPrivileged(PrivilegedAction, AccessControlContext)
+ */
+ Object run();
+} // interface PrivilegedAction
diff --git a/libjava/classpath/java/security/PrivilegedActionException.java b/libjava/classpath/java/security/PrivilegedActionException.java
new file mode 100644
index 00000000000..3f08c813065
--- /dev/null
+++ b/libjava/classpath/java/security/PrivilegedActionException.java
@@ -0,0 +1,109 @@
+/* PrivilegedActionException.java -- wrap an exception in a privileged action
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception is thrown when an exception is thrown during a
+ * privileged action being performed with the
+ * <code>AccessController.doPrivileged()</code> method. It wraps the
+ * actual exception thrown in the privileged code.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see PrivilegedExceptionAction
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction)
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction, AccessControlContext)
+ * @status updated to 1.4
+ */
+public class PrivilegedActionException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4724086851538908602L;
+
+ /**
+ * This is the actual exception that occurred.
+ *
+ * @serial the wrapped exception
+ */
+ private Exception exception;
+
+ /**
+ * Create a new instance that wraps the specified <code>Exception</code>.
+ *
+ * @param e the <code>Exception</code> to wrap
+ */
+ public PrivilegedActionException(Exception e)
+ {
+ super(e);
+ exception = e;
+ }
+
+ /**
+ * Get the underlying <code>Exception</code> that caused this one. This
+ * is a legacy method, the preferred way is {@link #getCause()}.
+ *
+ * @return the cause
+ */
+ public Exception getException()
+ {
+ return exception;
+ }
+
+ /**
+ * Gets the cause of this exception.
+ *
+ * @return the cause
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return exception;
+ }
+
+ /**
+ * Convert this to a String.
+ *
+ * @return the string representation
+ */
+ public String toString()
+ {
+ return super.toString();
+ }
+}
diff --git a/libjava/classpath/java/security/PrivilegedExceptionAction.java b/libjava/classpath/java/security/PrivilegedExceptionAction.java
new file mode 100644
index 00000000000..d3d0478fd48
--- /dev/null
+++ b/libjava/classpath/java/security/PrivilegedExceptionAction.java
@@ -0,0 +1,65 @@
+/* PrivilegedExceptionAction.java -- Perform a privileged operation
+ Copyright (C) 1998, 2002 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.security;
+
+/**
+ * This interface defines a method that is called by
+ * <code>AccessController.doPrivileged()</code> in order to perform a
+ * privileged operation with higher privileges enabled. This interface
+ * differs from <code>PrivilegedAction</code> in that the <code>run</code>
+ * method in this interface may throw a checked exception.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface PrivilegedExceptionAction
+{
+ /**
+ * This method performs an operation that requires higher privileges to
+ * successfully complete. It is called when a section of code invokes
+ * <code>AccessController.doPrivileged()</code>.
+ *
+ * @return obj An implementation defined return value
+ * @throws Exception An implementation specific exception
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction)
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction,
+ * AccessControlContext)
+ */
+ Object run() throws Exception;
+} // interface PrivilegedExceptionAction
diff --git a/libjava/classpath/java/security/ProtectionDomain.java b/libjava/classpath/java/security/ProtectionDomain.java
new file mode 100644
index 00000000000..a5851b5adf4
--- /dev/null
+++ b/libjava/classpath/java/security/ProtectionDomain.java
@@ -0,0 +1,269 @@
+/* ProtectionDomain.java -- A security domain
+ Copyright (C) 1998, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * <p>This <code>ProtectionDomain</code> class encapsulates the characteristics
+ * of a domain, which encloses a set of classes whose instances are granted a
+ * set of permissions when being executed on behalf of a given set of
+ * <i>Principals</i>.
+ *
+ * <p>A static set of permissions can be bound to a <code>ProtectionDomain</code>
+ * when it is constructed; such permissions are granted to the domain regardless
+ * of the {@link Policy} in force. However, to support dynamic security
+ * policies, a <code>ProtectionDomain</code> can also be constructed such that
+ * it is dynamically mapped to a set of permissions by the current {@link
+ * Policy} whenever a permission is checked.</p>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @version 0.0
+ */
+public class ProtectionDomain
+{
+ /** This is the <code>CodeSource</code> for this protection domain. */
+ private CodeSource code_source;
+
+ /** This is the set of permissions granted to this domain. */
+ private PermissionCollection perms;
+
+ /** The {@link ClassLoader} associated with this domain. */
+ private ClassLoader classloader;
+
+ /** The array of Principals associated with this domain.. */
+ private Principal[] principals;
+
+ /** Post 1.4 the policy may be refreshed! use false for pre 1.4. */
+ private boolean staticBinding;
+
+ /**
+ * Creates a new <code>ProtectionDomain</code> with the given {@link
+ * CodeSource} and {@link Permissions}. If the permissions object is not
+ * <code>null</code>, then <code>setReadOnly()</code> will be called on the
+ * passed in {@link Permissions} object. The only permissions granted to this
+ * domain are the ones specified; the current {@link Policy} will not be
+ * consulted.
+ *
+ * @param codesource the codesource associated with this domain.
+ * @param permissions the permissions granted to this domain
+ */
+ public ProtectionDomain(CodeSource codesource, PermissionCollection permissions)
+ {
+ this(codesource, permissions, null, null, true);
+ }
+
+ /**
+ * <p>Creates a new ProtectionDomain qualified by the given CodeSource,
+ * Permissions, ClassLoader and array of Principals. If the permissions
+ * object is not null, then <code>setReadOnly()</code> will be called on the
+ * passed in Permissions object. The permissions granted to this domain are
+ * dynamic; they include both the static permissions passed to this
+ * constructor, and any permissions granted to this domain by the current
+ * Policy at the time a permission is checked.</p>
+ *
+ * <p>This constructor is typically used by {@link ClassLoader}s and {@link
+ * DomainCombiner}s which delegate to <code>Policy</code> to actively
+ * associate the permissions granted to this domain. This constructor affords
+ * the Policy provider the opportunity to augment the supplied
+ * PermissionCollection to reflect policy changes.</p>
+ *
+ * @param codesource the CodeSource associated with this domain.
+ * @param permissions the permissions granted to this domain.
+ * @param classloader the ClassLoader associated with this domain.
+ * @param principals the array of Principals associated with this domain.
+ * @since 1.4
+ * @see Policy#refresh()
+ * @see Policy#getPermissions(ProtectionDomain)
+ */
+ public ProtectionDomain(CodeSource codesource,
+ PermissionCollection permissions,
+ ClassLoader classloader, Principal[] principals)
+ {
+ this(codesource, permissions, classloader, principals, false);
+ }
+
+ private ProtectionDomain(CodeSource codesource,
+ PermissionCollection permissions,
+ ClassLoader classloader, Principal[] principals,
+ boolean staticBinding)
+ {
+ super();
+
+ code_source = codesource;
+ if (permissions != null)
+ {
+ perms = permissions;
+ perms.setReadOnly();
+ }
+
+ this.classloader = classloader;
+ this.principals =
+ (principals != null ? (Principal[]) principals.clone() : new Principal[0]);
+ this.staticBinding = staticBinding;
+ }
+
+ /**
+ * Returns the {@link CodeSource} of this domain.
+ *
+ * @return the {@link CodeSource} of this domain which may be <code>null</code>.
+ * @since 1.2
+ */
+ public final CodeSource getCodeSource()
+ {
+ return code_source;
+ }
+
+ /**
+ * Returns the {@link ClassLoader} of this domain.
+ *
+ * @return the {@link ClassLoader} of this domain which may be
+ * <code>null</code>.
+ * @since 1.4
+ */
+ public final ClassLoader getClassLoader()
+ {
+ return this.classloader;
+ }
+
+ /**
+ * Returns an array of principals for this domain.
+ *
+ * @return returns a non-null array of principals for this domain. Changes to
+ * this array will have no impact on the <code>ProtectionDomain</code>.
+ * @since 1.4
+ */
+ public final Principal[] getPrincipals()
+ {
+ return (Principal[]) principals.clone();
+ }
+
+ /**
+ * Returns the static permissions granted to this domain.
+ *
+ * @return the static set of permissions for this domain which may be
+ * <code>null</code>.
+ * @see Policy#refresh()
+ * @see Policy#getPermissions(ProtectionDomain)
+ */
+ public final PermissionCollection getPermissions()
+ {
+ return perms;
+ }
+
+ /**
+ * <p>Check and see if this <code>ProtectionDomain</code> implies the
+ * permissions expressed in the <code>Permission</code> object.</p>
+ *
+ * <p>The set of permissions evaluated is a function of whether the
+ * <code>ProtectionDomain</code> was constructed with a static set of
+ * permissions or it was bound to a dynamically mapped set of permissions.</p>
+ *
+ * <p>If the <code>ProtectionDomain</code> was constructed to a statically
+ * bound {@link PermissionCollection} then the permission will only be checked
+ * against the {@link PermissionCollection} supplied at construction.</p>
+ *
+ * <p>However, if the <code>ProtectionDomain</code> was constructed with the
+ * constructor variant which supports dynamically binding permissions, then
+ * the permission will be checked against the combination of the
+ * {@link PermissionCollection} supplied at construction and the current
+ * {@link Policy} binding.
+ *
+ * @param permission the {@link Permission} object to check.
+ * @return <code>true</code> if <code>permission</code> is implicit to this
+ * <code>ProtectionDomain</code>.
+ */
+ public boolean implies(Permission permission)
+ {
+ if (staticBinding)
+ return (perms == null ? false : perms.implies(permission));
+ // Else dynamically bound. Do we have it?
+ // NOTE: this will force loading of Policy.currentPolicy
+ return Policy.getCurrentPolicy().implies(this, permission);
+ }
+
+ /**
+ * Convert a <code>ProtectionDomain</code> to a String.
+ *
+ * @return a string representation of the object.
+ */
+ public String toString()
+ {
+ String linesep = System.getProperty("line.separator");
+ StringBuffer sb = new StringBuffer("ProtectionDomain (").append(linesep);
+
+ if (code_source == null)
+ sb.append("CodeSource:null");
+ else
+ sb.append(code_source);
+
+ sb.append(linesep);
+ if (classloader == null)
+ sb.append("ClassLoader:null");
+ else
+ sb.append(classloader);
+
+ sb.append(linesep);
+ sb.append("Principals:");
+ if (principals != null && principals.length > 0)
+ {
+ sb.append("[");
+ Principal pal;
+ for (int i = 0; i < principals.length; i++)
+ {
+ pal = principals[i];
+ sb.append("'").append(pal.getName())
+ .append("' of type ").append(pal.getClass().getName());
+ if (i < principals.length-1)
+ sb.append(", ");
+ }
+ sb.append("]");
+ }
+ else
+ sb.append("none");
+
+ sb.append(linesep);
+ if (!staticBinding) // include all but dont force loading Policy.currentPolicy
+ if (Policy.isLoaded())
+ sb.append(Policy.getCurrentPolicy().getPermissions(this));
+ else // fallback on this one's permissions
+ sb.append(perms);
+ else
+ sb.append(perms);
+
+ return sb.append(linesep).append(")").append(linesep).toString();
+ }
+}
diff --git a/libjava/classpath/java/security/Provider.java b/libjava/classpath/java/security/Provider.java
new file mode 100644
index 00000000000..4ffaa55bcb1
--- /dev/null
+++ b/libjava/classpath/java/security/Provider.java
@@ -0,0 +1,202 @@
+/* Provider.java -- Security provider information
+ Copyright (C) 1998, 1999, 2000, 2002 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.security;
+
+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.
+ * <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
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class Provider extends Properties implements Serializable
+{
+ private static final long serialVersionUID = -4298000515446427739L;
+
+ /**
+ * This is a textual description of the provider
+ */
+ private String info;
+
+ /**
+ * This is the name of the provider
+ */
+ private String name;
+
+ /**
+ * This is the version number of the provider
+ */
+ private double version;
+
+ /**
+ * This method initializes a new instance of <code>Provider</code> to have
+ * the specified name, version, and description information.
+ *
+ * @param name The name to assign to this <code>Provider</code>.
+ * @param version The version number for this <code>Provider</code>.
+ * @param info A textual description of this provider.
+ */
+ protected Provider(String name, double version, String info)
+ {
+ this.name = name;
+ this.version = version;
+ this.info = info;
+ }
+
+ /**
+ * This method returns the name assigned to this <code>Provider</code>.
+ *
+ * @return The <code>Provider</code>'s name.
+ */
+ public String getName()
+ {
+ return (name);
+ }
+
+ /**
+ * This method retunrs the version number of this <code>Provider</code>.
+ *
+ * @return The <code>Provider</code>'s version number.
+ */
+ public double getVersion()
+ {
+ return (version);
+ }
+
+ /**
+ * This method returns a textual description of the <code>Provider</code>.
+ *
+ * @return A description of the <code>Provider</code>.
+ */
+ public String getInfo()
+ {
+ return (info);
+ }
+
+ /**
+ * Sets the key property to have the specified 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>]
+ *
+ * @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.
+ * @since Classpath 0.4+cvs, JDK 1.2
+ * @see java.lang.Object.equals(Object)
+ * @see java.util.Hashtable.get(Object)
+ */
+ public Object put(Object key, Object value)
+ {
+ return super.put(toCanonicalKey(key), value);
+ }
+
+ // overrides same in java.util.Hashtable
+ public Object get(Object key)
+ {
+ return super.get(toCanonicalKey(key));
+ }
+
+ /**
+ * This method removes the specified key entry (and its associated value)
+ * from the property mapping list.
+ *
+ * @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)
+ {
+ return super.remove(toCanonicalKey(key));
+ }
+
+ /**
+ * This method clears the entire property list such that it no longer
+ * contains the properties used to look up the services provided by
+ * the <code>Provider</code>.
+ */
+ public void clear()
+ {
+ super.clear();
+ }
+
+ /**
+ * This method returns a <code>String</code> representation of this
+ * object. This will include the <code>Provider</code> name and
+ * version number.
+ *
+ * @return A <code>String</code> representation of this object.
+ */
+ public String toString()
+ {
+ 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;
+ }
+}
diff --git a/libjava/classpath/java/security/ProviderException.java b/libjava/classpath/java/security/ProviderException.java
new file mode 100644
index 00000000000..2dafcec3495
--- /dev/null
+++ b/libjava/classpath/java/security/ProviderException.java
@@ -0,0 +1,70 @@
+/* ProviderException.java -- Generic security provider runtime exception
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception indicates that a runtime problem was encounterd with
+ * a security provider.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class ProviderException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5256023526693665674L;
+
+ /**
+ * Create an instance with no descriptive error message.
+ */
+ public ProviderException()
+ {
+ }
+
+ /**
+ * Create an instance with a descriptive error message.
+ *
+ * @param msg the descriptive error message
+ */
+ public ProviderException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/PublicKey.java b/libjava/classpath/java/security/PublicKey.java
new file mode 100644
index 00000000000..9bf14584089
--- /dev/null
+++ b/libjava/classpath/java/security/PublicKey.java
@@ -0,0 +1,60 @@
+/* PublicKey.java -- tagging interface for all public keys
+ Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This interface specified no methods. In simply provides a common
+ * super-interface for all algorithm specific public key values.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Key
+ * @see PrivateKey
+ * @see Certificate
+ * @see Signature#initVerify(PublicKey)
+ * @see DSAPublicKey
+ * @see RSAPublicKey
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface PublicKey extends Key
+{
+ /**
+ * The version identifier used for serialization.
+ */
+ long serialVersionUID = 7187392471159151072L;
+} // interface PublicKey
diff --git a/libjava/classpath/java/security/SecureClassLoader.java b/libjava/classpath/java/security/SecureClassLoader.java
new file mode 100644
index 00000000000..9d1fac79749
--- /dev/null
+++ b/libjava/classpath/java/security/SecureClassLoader.java
@@ -0,0 +1,128 @@
+/* SecureClassLoader.java --- A Secure Class Loader
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * A Secure Class Loader for loading classes with additional
+ * support for specifying code source and permissions when
+ * they are retrieved by the system policy handler.
+ *
+ * @since 1.2
+ *
+ * @author Mark Benvenuto
+ */
+public class SecureClassLoader extends ClassLoader
+{
+ java.util.WeakHashMap protectionDomainCache = new java.util.WeakHashMap();
+
+ protected SecureClassLoader(ClassLoader parent)
+ {
+ super(parent);
+ SecurityManager sm = System.getSecurityManager();
+ if(sm != null)
+ sm.checkCreateClassLoader();
+ }
+
+ protected SecureClassLoader()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if(sm != null)
+ sm.checkCreateClassLoader();
+ }
+
+ /**
+ * Creates a class using an array of bytes and a
+ * CodeSource.
+ *
+ * @param name the name to give the class. null if unknown.
+ * @param b the data representing the classfile, in classfile format.
+ * @param off the offset into the data where the classfile starts.
+ * @param len the length of the classfile data in the array.
+ * @param cs the CodeSource for the class or null when unknown.
+ *
+ * @return the class that was defined and optional CodeSource.
+ *
+ * @exception ClassFormatError if the byte array is not in proper classfile format.
+ */
+ protected final Class defineClass(String name, byte[] b, int off, int len,
+ CodeSource cs)
+ {
+ if (cs != null)
+ {
+ ProtectionDomain protectionDomain;
+
+ synchronized (protectionDomainCache)
+ {
+ protectionDomain = (ProtectionDomain)protectionDomainCache.get(cs);
+ }
+
+ if (protectionDomain == null)
+ {
+ protectionDomain
+ = new ProtectionDomain(cs, getPermissions(cs), this, null);
+ synchronized (protectionDomainCache)
+ {
+ ProtectionDomain domain
+ = (ProtectionDomain)protectionDomainCache.get(cs);
+ if (domain == null)
+ protectionDomainCache.put(cs, protectionDomain);
+ else
+ protectionDomain = domain;
+ }
+ }
+ return super.defineClass(name, b, off, len, protectionDomain);
+ }
+ else
+ return super.defineClass(name, b, off, len);
+ }
+
+ /**
+ * Returns a PermissionCollection for the specified CodeSource.
+ * The default implementation invokes
+ * java.security.Policy.getPermissions.
+ *
+ * This method is called by defineClass that takes a CodeSource
+ * arguement to build a proper ProtectionDomain for the class
+ * being defined.
+ */
+ protected PermissionCollection getPermissions(CodeSource cs)
+ {
+ Policy policy = Policy.getCurrentPolicy();
+ return policy.getPermissions(cs);
+ }
+}
diff --git a/libjava/classpath/java/security/SecureRandom.java b/libjava/classpath/java/security/SecureRandom.java
new file mode 100644
index 00000000000..3ee3a841d26
--- /dev/null
+++ b/libjava/classpath/java/security/SecureRandom.java
@@ -0,0 +1,380 @@
+/* SecureRandom.java --- Secure Random class implementation
+ Copyright (C) 1999, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+import gnu.java.security.Engine;
+
+import java.util.Enumeration;
+import java.util.Random;
+
+/**
+ * An interface to a cryptographically secure pseudo-random number
+ * generator (PRNG). Random (or at least unguessable) numbers are used
+ * in all areas of security and cryptography, from the generation of
+ * keys and initialization vectors to the generation of random padding
+ * bytes.
+ *
+ * @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ * @author Casey Marshall
+ */
+public class SecureRandom extends Random
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ /** Service name for PRNGs. */
+ private static final String SECURE_RANDOM = "SecureRandom";
+
+ private static final long serialVersionUID = 4940670005562187L;
+
+ //Serialized Field
+ long counter = 0; //Serialized
+ Provider provider = null;
+ byte[] randomBytes = null; //Always null
+ int randomBytesUsed = 0;
+ SecureRandomSpi secureRandomSpi = null;
+ byte[] state = null;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ Default constructor for SecureRandom. It constructs a
+ new SecureRandom by instantating the first SecureRandom
+ algorithm in the default security provier.
+
+ It is not seeded and should be seeded using setSeed or else
+ on the first call to getnextBytes it will force a seed.
+
+ It is maintained for backwards compatibility and programs
+ should use {@link #getInstance(java.lang.String)}.
+ */
+ public SecureRandom()
+ {
+ Provider[] p = Security.getProviders();
+
+ //Format of Key: SecureRandom.algname
+ String key;
+
+ String classname = null;
+ int i;
+ Enumeration e;
+ for (i = 0; i < p.length; i++)
+ {
+ e = p[i].propertyNames();
+ while (e.hasMoreElements())
+ {
+ key = (String) e.nextElement();
+ if (key.startsWith("SECURERANDOM."))
+ {
+ if ((classname = p[i].getProperty(key)) != null)
+ {
+ try
+ {
+ secureRandomSpi = (SecureRandomSpi) Class.
+ forName(classname).newInstance();
+ provider = p[i];
+ return;
+ }
+ catch (ThreadDeath death)
+ {
+ throw death;
+ }
+ catch (Throwable t)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+ }
+
+ // Nothing found. Fall back to SHA1PRNG
+ secureRandomSpi = new gnu.java.security.provider.SHA1PRNG();
+ }
+
+ /**
+ A constructor for SecureRandom. It constructs a new
+ SecureRandom by instantating the first SecureRandom algorithm
+ in the default security provier.
+
+ It is seeded with the passed function and is useful if the user
+ has access to hardware random device (like a radiation detector).
+
+ It is maintained for backwards compatibility and programs
+ should use getInstance.
+
+ @param seed Seed bytes for class
+ */
+ public SecureRandom(byte[] seed)
+ {
+ this();
+ setSeed(seed);
+ }
+
+ /**
+ A constructor for SecureRandom. It constructs a new
+ SecureRandom using the specified SecureRandomSpi from
+ the specified security provier.
+
+ @param secureRandomSpi A SecureRandomSpi class
+ @param provider A Provider class
+ */
+ protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider)
+ {
+ this.secureRandomSpi = secureRandomSpi;
+ this.provider = provider;
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns an instance of a SecureRandom. It creates the class 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.
+ */
+ public static SecureRandom getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore.
+ }
+ }
+
+ // None found.
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * Returns an instance of a SecureRandom. It creates the class
+ * 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.
+ * @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.
+ */
+ public static SecureRandom getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("Illegal provider");
+
+ 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.
+ */
+ public static SecureRandom getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("Illegal provider");
+ try
+ {
+ return new SecureRandom((SecureRandomSpi)
+ Engine.getInstance(SECURE_RANDOM, algorithm, provider),
+ provider);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ Returns the provider being used by the current SecureRandom class.
+
+ @return The provider from which this SecureRandom was attained
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ Seeds the SecureRandom. The class is re-seeded for each call and
+ each seed builds on the previous seed so as not to weaken security.
+
+ @param seed seed bytes to seed with
+ */
+ public void setSeed(byte[] seed)
+ {
+ secureRandomSpi.engineSetSeed(seed);
+ }
+
+ /**
+ Seeds the SecureRandom. The class is re-seeded for each call and
+ each seed builds on the previous seed so as not to weaken security.
+
+ @param seed 8 seed bytes to seed with
+ */
+ public void setSeed(long seed)
+ {
+ // This particular setSeed will be called by Random.Random(), via
+ // our own constructor, before secureRandomSpi is initialized. In
+ // this case we can't call a method on secureRandomSpi, and we
+ // definitely don't want to throw a NullPointerException.
+ // Therefore we test.
+ if (secureRandomSpi != null)
+ {
+ byte[] tmp = { (byte) (0xff & (seed >> 56)),
+ (byte) (0xff & (seed >> 48)),
+ (byte) (0xff & (seed >> 40)),
+ (byte) (0xff & (seed >> 32)),
+ (byte) (0xff & (seed >> 24)),
+ (byte) (0xff & (seed >> 16)),
+ (byte) (0xff & (seed >> 8)),
+ (byte) (0xff & seed)
+ };
+ secureRandomSpi.engineSetSeed(tmp);
+ }
+ }
+
+ /**
+ Generates a user specified number of bytes. This function
+ is the basis for all the random functions.
+
+ @param bytes array to store generated bytes in
+ */
+ public void nextBytes(byte[] bytes)
+ {
+ randomBytesUsed += bytes.length;
+ counter++;
+ secureRandomSpi.engineNextBytes(bytes);
+ }
+
+ /**
+ Generates an integer containing the user specified
+ number of random bits. It is right justified and padded
+ with zeros.
+
+ @param numBits number of random bits to get, 0 <= numBits <= 32;
+
+ @return the random bits
+ */
+ protected final int next(int numBits)
+ {
+ if (numBits == 0)
+ return 0;
+
+ byte[] tmp = new byte[numBits / 8 + (1 * (numBits % 8))];
+
+ secureRandomSpi.engineNextBytes(tmp);
+ randomBytesUsed += tmp.length;
+ counter++;
+
+ int ret = 0;
+
+ for (int i = 0; i < tmp.length; i++)
+ ret |= (tmp[i] & 0xFF) << (8 * i);
+
+ long mask = (1L << numBits) - 1;
+ return (int) (ret & mask);
+ }
+
+ /**
+ Returns the given number of seed bytes. This method is
+ maintained only for backwards capability.
+
+ @param numBytes number of seed bytes to get
+
+ @return an array containing the seed bytes
+ */
+ public static byte[] getSeed(int numBytes)
+ {
+ byte[] tmp = new byte[numBytes];
+
+ new Random().nextBytes(tmp);
+ return tmp;
+ //return secureRandomSpi.engineGenerateSeed( numBytes );
+ }
+
+ /**
+ Returns the specified number of seed bytes.
+
+ @param numBytes number of seed bytes to get
+
+ @return an array containing the seed bytes
+ */
+ public byte[] generateSeed(int numBytes)
+ {
+ return secureRandomSpi.engineGenerateSeed(numBytes);
+ }
+
+}
diff --git a/libjava/classpath/java/security/SecureRandomSpi.java b/libjava/classpath/java/security/SecureRandomSpi.java
new file mode 100644
index 00000000000..7759097a456
--- /dev/null
+++ b/libjava/classpath/java/security/SecureRandomSpi.java
@@ -0,0 +1,85 @@
+/* SecureRandomSpi.java --- Secure Random Service Provider Interface
+ Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+import java.io.Serializable;
+
+/**
+ SecureRandomSpi is the Service Provider Interface for SecureRandom
+ providers. It provides an interface for providers to the
+ SecureRandom engine to write their own pseudo-random number
+ generator.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ */
+public abstract class SecureRandomSpi implements Serializable
+{
+ private static final long serialVersionUID = -2991854161009191830L;
+
+ /**
+ Default Constructor for SecureRandomSpi
+ */
+ public SecureRandomSpi()
+ {
+ }
+
+ /**
+ Updates the seed for SecureRandomSpi but does not reset seed.
+ It does to this so repeated called never decrease randomness.
+ */
+ protected abstract void engineSetSeed(byte[] seed);
+
+ /**
+ Gets a user specified number of bytes depending on the length
+ of the array?
+
+ @param bytes array to fill with random bytes
+ */
+ protected abstract void engineNextBytes(byte[] bytes);
+
+ /**
+ Gets a user specified number of bytes specified by the
+ parameter.
+
+ @param numBytes number of random bytes to generate
+
+ @return an array full of random bytes
+ */
+ protected abstract byte[] engineGenerateSeed(int numBytes);
+}
diff --git a/libjava/classpath/java/security/Security.java b/libjava/classpath/java/security/Security.java
new file mode 100644
index 00000000000..54b97923efd
--- /dev/null
+++ b/libjava/classpath/java/security/Security.java
@@ -0,0 +1,740 @@
+/* Security.java --- Java base security class implementation
+ Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import gnu.classpath.SystemProperties;
+
+import gnu.classpath.Configuration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ * This class centralizes all security properties and common security methods.
+ * One of its primary uses is to manage providers.
+ *
+ * @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ */
+public final class Security
+{
+ private static final String ALG_ALIAS = "Alg.Alias.";
+
+ private static Vector providers = new Vector();
+ private static Properties secprops = new Properties();
+
+ static
+ {
+ String base = SystemProperties.getProperty("gnu.classpath.home.url");
+ String vendor = SystemProperties.getProperty("gnu.classpath.vm.shortname");
+
+ // Try VM specific security file
+ boolean loaded = loadProviders (base, vendor);
+
+ // Append classpath standard provider if possible
+ if (!loadProviders (base, "classpath")
+ && !loaded
+ && providers.size() == 0)
+ {
+ if (Configuration.DEBUG)
+ {
+ /* No providers found and both security files failed to
+ * load properly. Give a warning in case of DEBUG is
+ * enabled. Could be done with java.util.logging later.
+ */
+ System.err.println
+ ("WARNING: could not properly read security provider files:");
+ System.err.println
+ (" " + base + "/security/" + vendor
+ + ".security");
+ System.err.println
+ (" " + base + "/security/" + "classpath"
+ + ".security");
+ System.err.println
+ (" Falling back to standard GNU security provider");
+ }
+ providers.addElement (new gnu.java.security.provider.Gnu());
+ }
+ }
+ // This class can't be instantiated.
+ private Security()
+ {
+ }
+
+ /**
+ * Tries to load the vender specific security providers from the given
+ * base URL. Returns true if the resource could be read and completely
+ * parsed successfully, false otherwise.
+ */
+ private static boolean loadProviders(String baseUrl, String vendor)
+ {
+ if (baseUrl == null || vendor == null)
+ return false;
+
+ boolean result = true;
+ String secfilestr = baseUrl + "/security/" + vendor + ".security";
+ try
+ {
+ InputStream fin = new URL(secfilestr).openStream();
+ secprops.load(fin);
+
+ int i = 1;
+ String name;
+ while ((name = secprops.getProperty("security.provider." + i)) != null)
+ {
+ Exception exception = null;
+ try
+ {
+ providers.addElement(Class.forName(name).newInstance());
+ }
+ catch (ClassNotFoundException x)
+ {
+ exception = x;
+ }
+ catch (InstantiationException x)
+ {
+ exception = x;
+ }
+ catch (IllegalAccessException x)
+ {
+ exception = x;
+ }
+
+ if (exception != null)
+ {
+ System.err.println ("WARNING: Error loading security provider "
+ + name + ": " + exception);
+ result = false;
+ }
+ i++;
+ }
+ }
+ catch (IOException ignored)
+ {
+ result = false;
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets a specified property for an algorithm. The algorithm name should be a
+ * standard name. See Appendix A in the Java Cryptography Architecture API
+ * Specification &amp; Reference for information about standard algorithm
+ * names. One possible use is by specialized algorithm parsers, which may map
+ * classes to algorithms which they understand (much like {@link Key} parsers
+ * do).
+ *
+ * @param algName the algorithm name.
+ * @param propName the name of the property to get.
+ * @return the value of the specified property.
+ * @deprecated This method used to return the value of a proprietary property
+ * in the master file of the "SUN" Cryptographic Service Provider in order to
+ * determine how to parse algorithm-specific parameters. Use the new
+ * provider-based and algorithm-independent {@link AlgorithmParameters} and
+ * {@link KeyFactory} engine classes (introduced in the Java 2 platform)
+ * instead.
+ */
+ public static String getAlgorithmProperty(String algName, String propName)
+ {
+ if (algName == null || propName == null)
+ return null;
+
+ String property = String.valueOf(propName) + "." + String.valueOf(algName);
+ Provider p;
+ for (Iterator i = providers.iterator(); i.hasNext(); )
+ {
+ p = (Provider) i.next();
+ for (Iterator j = p.keySet().iterator(); j.hasNext(); )
+ {
+ String key = (String) j.next();
+ if (key.equalsIgnoreCase(property))
+ return p.getProperty(key);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * <p>Adds a new provider, at a specified position. The position is the
+ * preference order in which providers are searched for requested algorithms.
+ * Note that it is not guaranteed that this preference will be respected. The
+ * position is 1-based, that is, <code>1</code> is most preferred, followed by
+ * <code>2</code>, and so on.</p>
+ *
+ * <p>If the given provider is installed at the requested position, the
+ * provider that used to be at that position, and all providers with a
+ * position greater than position, are shifted up one position (towards the
+ * end of the list of installed providers).</p>
+ *
+ * <p>A provider cannot be added if it is already installed.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with the string <code>"insertProvider."+provider.
+ * getName()</code> to see if it's ok to add a new provider. If the default
+ * implementation of <code>checkSecurityAccess()</code> is used (i.e., that
+ * method is not overriden), then this will result in a call to the security
+ * manager's <code>checkPermission()</code> method with a
+ * <code>SecurityPermission("insertProvider."+provider.getName())</code>
+ * permission.</p>
+ *
+ * @param provider the provider to be added.
+ * @param position the preference position that the caller would like for
+ * this provider.
+ * @return the actual preference position in which the provider was added, or
+ * <code>-1</code> if the provider was not added because it is already
+ * installed.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkSecurityAccess(String)} method denies access
+ * to add a new provider.
+ * @see #getProvider(String)
+ * @see #removeProvider(String)
+ * @see SecurityPermission
+ */
+ public static int insertProviderAt(Provider provider, int position)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("insertProvider." + provider.getName());
+
+ position--;
+ int max = providers.size ();
+ for (int i = 0; i < max; i++)
+ {
+ if (((Provider) providers.elementAt(i)).getName().equals(provider.getName()))
+ return -1;
+ }
+
+ if (position < 0)
+ position = 0;
+ if (position > max)
+ position = max;
+
+ providers.insertElementAt(provider, position);
+
+ return position + 1;
+ }
+
+ /**
+ * <p>Adds a provider to the next position available.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with the string <code>"insertProvider."+provider.
+ * getName()</code> to see if it's ok to add a new provider. If the default
+ * implementation of <code>checkSecurityAccess()</code> is used (i.e., that
+ * method is not overriden), then this will result in a call to the security
+ * manager's <code>checkPermission()</code> method with a
+ * <code>SecurityPermission("insertProvider."+provider.getName())</code>
+ * permission.</p>
+ *
+ * @param provider the provider to be added.
+ * @return the preference position in which the provider was added, or
+ * <code>-1</code> if the provider was not added because it is already
+ * installed.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkSecurityAccess(String)} method denies access
+ * to add a new provider.
+ * @see #getProvider(String)
+ * @see #removeProvider(String)
+ * @see SecurityPermission
+ */
+ public static int addProvider(Provider provider)
+ {
+ return insertProviderAt (provider, providers.size () + 1);
+ }
+
+ /**
+ * <p>Removes the provider with the specified name.</p>
+ *
+ * <p>When the specified provider is removed, all providers located at a
+ * position greater than where the specified provider was are shifted down
+ * one position (towards the head of the list of installed providers).</p>
+ *
+ * <p>This method returns silently if the provider is not installed.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with the string <code>"removeProvider."+name</code>
+ * to see if it's ok to remove the provider. If the default implementation of
+ * <code>checkSecurityAccess()</code> is used (i.e., that method is not
+ * overriden), then this will result in a call to the security manager's
+ * <code>checkPermission()</code> method with a <code>SecurityPermission(
+ * "removeProvider."+name)</code> permission.</p>
+ *
+ * @param name the name of the provider to remove.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkSecurityAccess(String)} method denies access
+ * to remove the provider.
+ * @see #getProvider(String)
+ * @see #addProvider(Provider)
+ */
+ public static void removeProvider(String name)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("removeProvider." + name);
+
+ int max = providers.size ();
+ for (int i = 0; i < max; i++)
+ {
+ if (((Provider) providers.elementAt(i)).getName().equals(name))
+ {
+ providers.remove(i);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns an array containing all the installed providers. The order of the
+ * providers in the array is their preference order.
+ *
+ * @return an array of all the installed providers.
+ */
+ public static Provider[] getProviders()
+ {
+ Provider[] array = new Provider[providers.size ()];
+ providers.copyInto (array);
+ return array;
+ }
+
+ /**
+ * Returns the provider installed with the specified name, if any. Returns
+ * <code>null</code> if no provider with the specified name is installed.
+ *
+ * @param name the name of the provider to get.
+ * @return the provider of the specified name.
+ * @see #removeProvider(String)
+ * @see #addProvider(Provider)
+ */
+ public static Provider getProvider(String name)
+ {
+ Provider p;
+ int max = providers.size ();
+ for (int i = 0; i < max; i++)
+ {
+ p = (Provider) providers.elementAt(i);
+ if (p.getName().equals(name))
+ return p;
+ }
+ return null;
+ }
+
+ /**
+ * <p>Gets a security property value.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkPermission()</code>
+ * method is called with a <code>SecurityPermission("getProperty."+key)</code>
+ * permission to see if it's ok to retrieve the specified security property
+ * value.</p>
+ *
+ * @param key the key of the property being retrieved.
+ * @return the value of the security property corresponding to key.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkPermission(Permission)} method denies access
+ * to retrieve the specified security property value.
+ * @see #setProperty(String, String)
+ * @see SecurityPermission
+ */
+ public static String getProperty(String key)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("getProperty." + key);
+
+ return secprops.getProperty(key);
+ }
+
+ /**
+ * <p>Sets a security property value.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkPermission()</code>
+ * method is called with a <code>SecurityPermission("setProperty."+key)</code>
+ * permission to see if it's ok to set the specified security property value.
+ * </p>
+ *
+ * @param key the name of the property to be set.
+ * @param datnum the value of the property to be set.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkPermission(Permission)} method denies access
+ * to set the specified security property value.
+ * @see #getProperty(String)
+ * @see SecurityPermission
+ */
+ public static void setProperty(String key, String datnum)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("setProperty." + key);
+
+ secprops.put(key, datnum);
+ }
+
+ /**
+ * Returns a Set of Strings containing the names of all available algorithms
+ * or types for the specified Java cryptographic service (e.g., Signature,
+ * MessageDigest, Cipher, Mac, KeyStore). Returns an empty Set if there is no
+ * provider that supports the specified service. For a complete list of Java
+ * cryptographic services, please see the Java Cryptography Architecture API
+ * Specification &amp; Reference. Note: the returned set is immutable.
+ *
+ * @param serviceName the name of the Java cryptographic service (e.g.,
+ * Signature, MessageDigest, Cipher, Mac, KeyStore). Note: this parameter is
+ * case-insensitive.
+ * @return a Set of Strings containing the names of all available algorithms
+ * or types for the specified Java cryptographic service or an empty set if
+ * no provider supports the specified service.
+ * @since 1.4
+ */
+ public static Set getAlgorithms(String serviceName)
+ {
+ HashSet result = new HashSet();
+ if (serviceName == null || serviceName.length() == 0)
+ return result;
+
+ serviceName = serviceName.trim();
+ if (serviceName.length() == 0)
+ return result;
+
+ serviceName = serviceName.toUpperCase()+".";
+ Provider[] providers = getProviders();
+ int ndx;
+ for (int i = 0; i < providers.length; i++)
+ for (Enumeration e = providers[i].propertyNames(); e.hasMoreElements(); )
+ {
+ String service = ((String) e.nextElement()).trim();
+ if (service.toUpperCase().startsWith(serviceName))
+ {
+ service = service.substring(serviceName.length()).trim();
+ ndx = service.indexOf(' '); // get rid of attributes
+ if (ndx != -1)
+ service = service.substring(0, ndx);
+ result.add(service);
+ }
+ }
+ return Collections.unmodifiableSet(result);
+ }
+
+ /**
+ * <p>Returns an array containing all installed providers that satisfy the
+ * specified selection criterion, or <code>null</code> if no such providers
+ * have been installed. The returned providers are ordered according to their
+ * preference order.</p>
+ *
+ * <p>A cryptographic service is always associated with a particular
+ * algorithm or type. For example, a digital signature service is always
+ * associated with a particular algorithm (e.g., <i>DSA</i>), and a
+ * CertificateFactory service is always associated with a particular
+ * certificate type (e.g., <i>X.509</i>).</p>
+ *
+ * <p>The selection criterion must be specified in one of the following two
+ * formats:</p>
+ *
+ * <ul>
+ * <li><p>&lt;crypto_service&gt;.&lt;algorithm_or_type&gt;</p>
+ * <p>The cryptographic service name must not contain any dots.</p>
+ * <p>A provider satisfies the specified selection criterion iff the
+ * provider implements the specified algorithm or type for the specified
+ * cryptographic service.</p>
+ * <p>For example, "CertificateFactory.X.509" would be satisfied by any
+ * provider that supplied a CertificateFactory implementation for X.509
+ * certificates.</p></li>
+ *
+ * <li><p>&lt;crypto_service&gt;.&lt;algorithm_or_type&gt; &lt;attribute_name&gt;:&lt;attribute_value&gt;</p>
+ * <p>The cryptographic service name must not contain any dots. There must
+ * be one or more space charaters between the the &lt;algorithm_or_type&gt;
+ * and the &lt;attribute_name&gt;.</p>
+ * <p>A provider satisfies this selection criterion iff the provider
+ * implements the specified algorithm or type for the specified
+ * cryptographic service and its implementation meets the constraint
+ * expressed by the specified attribute name/value pair.</p>
+ * <p>For example, "Signature.SHA1withDSA KeySize:1024" would be satisfied
+ * by any provider that implemented the SHA1withDSA signature algorithm
+ * with a keysize of 1024 (or larger).</p></li>
+ * </ul>
+ *
+ * <p>See Appendix A in the Java Cryptogaphy Architecture API Specification
+ * &amp; Reference for information about standard cryptographic service names,
+ * standard algorithm names and standard attribute names.</p>
+ *
+ * @param filter the criterion for selecting providers. The filter is case-
+ * insensitive.
+ * @return all the installed providers that satisfy the selection criterion,
+ * or null if no such providers have been installed.
+ * @throws InvalidParameterException if the filter is not in the required
+ * format.
+ * @see #getProviders(Map)
+ */
+ public static Provider[] getProviders(String filter)
+ {
+ if (providers == null || providers.isEmpty())
+ return null;
+
+ if (filter == null || filter.length() == 0)
+ return getProviders();
+
+ HashMap map = new HashMap(1);
+ int i = filter.indexOf(':');
+ if (i == -1) // <service>.<algorithm>
+ map.put(filter, "");
+ else // <service>.<algorithm> <attribute>:<value>
+ map.put(filter.substring(0, i), filter.substring(i+1));
+
+ return getProviders(map);
+ }
+
+ /**
+ * <p>Returns an array containing all installed providers that satisfy the
+ * specified selection criteria, or <code>null</code> if no such providers
+ * have been installed. The returned providers are ordered according to their
+ * preference order.</p>
+ *
+ * <p>The selection criteria are represented by a map. Each map entry
+ * represents a selection criterion. A provider is selected iff it satisfies
+ * all selection criteria. The key for any entry in such a map must be in one
+ * of the following two formats:</p>
+ *
+ * <ul>
+ * <li><p>&lt;crypto_service&gt;.&lt;algorithm_or_type&gt;</p>
+ * <p>The cryptographic service name must not contain any dots.</p>
+ * <p>The value associated with the key must be an empty string.</p>
+ * <p>A provider satisfies this selection criterion iff the provider
+ * implements the specified algorithm or type for the specified
+ * cryptographic service.</p></li>
+ *
+ * <li><p>&lt;crypto_service&gt;.&lt;algorithm_or_type&gt; &lt;attribute_name&gt;</p>
+ * <p>The cryptographic service name must not contain any dots. There must
+ * be one or more space charaters between the &lt;algorithm_or_type&gt; and
+ * the &lt;attribute_name&gt;.</p>
+ * <p>The value associated with the key must be a non-empty string. A
+ * provider satisfies this selection criterion iff the provider implements
+ * the specified algorithm or type for the specified cryptographic service
+ * and its implementation meets the constraint expressed by the specified
+ * attribute name/value pair.</p></li>
+ * </ul>
+ *
+ * <p>See Appendix A in the Java Cryptogaphy Architecture API Specification
+ * &amp; Reference for information about standard cryptographic service names,
+ * standard algorithm names and standard attribute names.</p>
+ *
+ * @param filter the criteria for selecting providers. The filter is case-
+ * insensitive.
+ * @return all the installed providers that satisfy the selection criteria,
+ * or <code>null</code> if no such providers have been installed.
+ * @throws InvalidParameterException if the filter is not in the required
+ * format.
+ * @see #getProviders(String)
+ */
+ public static Provider[] getProviders(Map filter)
+ {
+ if (providers == null || providers.isEmpty())
+ return null;
+
+ if (filter == null)
+ return getProviders();
+
+ Set querries = filter.keySet();
+ if (querries == null || querries.isEmpty())
+ return getProviders();
+
+ LinkedHashSet result = new LinkedHashSet(providers); // assume all
+ int dot, ws;
+ String querry, service, algorithm, attribute, value;
+ LinkedHashSet serviceProviders = new LinkedHashSet(); // preserve insertion order
+ for (Iterator i = querries.iterator(); i.hasNext(); )
+ {
+ querry = (String) i.next();
+ if (querry == null) // all providers
+ continue;
+
+ querry = querry.trim();
+ if (querry.length() == 0) // all providers
+ continue;
+
+ dot = querry.indexOf('.');
+ if (dot == -1) // syntax error
+ throw new InvalidParameterException(
+ "missing dot in '" + String.valueOf(querry)+"'");
+
+ value = (String) filter.get(querry);
+ // deconstruct querry into [service, algorithm, attribute]
+ if (value == null || value.trim().length() == 0) // <service>.<algorithm>
+ {
+ value = null;
+ attribute = null;
+ service = querry.substring(0, dot).trim();
+ algorithm = querry.substring(dot+1).trim();
+ }
+ else // <service>.<algorithm> <attribute>
+ {
+ ws = querry.indexOf(' ');
+ if (ws == -1)
+ throw new InvalidParameterException(
+ "value (" + String.valueOf(value) +
+ ") is not empty, but querry (" + String.valueOf(querry) +
+ ") is missing at least one space character");
+ value = value.trim();
+ attribute = querry.substring(ws+1).trim();
+ // was the dot in the attribute?
+ if (attribute.indexOf('.') != -1)
+ throw new InvalidParameterException(
+ "attribute_name (" + String.valueOf(attribute) +
+ ") in querry (" + String.valueOf(querry) + ") contains a dot");
+
+ querry = querry.substring(0, ws).trim();
+ service = querry.substring(0, dot).trim();
+ algorithm = querry.substring(dot+1).trim();
+ }
+
+ // service and algorithm must not be empty
+ if (service.length() == 0)
+ throw new InvalidParameterException(
+ "<crypto_service> in querry (" + String.valueOf(querry) +
+ ") is empty");
+
+ if (algorithm.length() == 0)
+ throw new InvalidParameterException(
+ "<algorithm_or_type> in querry (" + String.valueOf(querry) +
+ ") is empty");
+
+ selectProviders(service, algorithm, attribute, value, result, serviceProviders);
+ result.retainAll(serviceProviders); // eval next retaining found providers
+ if (result.isEmpty()) // no point continuing
+ break;
+ }
+
+ if (result.isEmpty())
+ return null;
+
+ return (Provider[]) result.toArray(new Provider[0]);
+ }
+
+ private static void selectProviders(String svc, String algo, String attr,
+ String val, LinkedHashSet providerSet,
+ LinkedHashSet result)
+ {
+ result.clear(); // ensure we start with an empty result set
+ for (Iterator i = providerSet.iterator(); i.hasNext(); )
+ {
+ Provider p = (Provider) i.next();
+ if (provides(p, svc, algo, attr, val))
+ result.add(p);
+ }
+ }
+
+ private static boolean provides(Provider p, String svc, String algo,
+ String attr, String val)
+ {
+ Iterator it;
+ String serviceDotAlgorithm = null;
+ String key = null;
+ String realVal;
+ boolean found = false;
+ // if <svc>.<algo> <attr> is in the set then so is <svc>.<algo>
+ // but it may be stored under an alias <algo>. resolve
+ outer: for (int r = 0; r < 3; r++) // guard against circularity
+ {
+ serviceDotAlgorithm = (svc+"."+String.valueOf(algo)).trim();
+ for (it = p.keySet().iterator(); it.hasNext(); )
+ {
+ key = (String) it.next();
+ if (key.equalsIgnoreCase(serviceDotAlgorithm)) // eureka
+ {
+ found = true;
+ break outer;
+ }
+ // it may be there but as an alias
+ if (key.equalsIgnoreCase(ALG_ALIAS + serviceDotAlgorithm))
+ {
+ algo = p.getProperty(key);
+ continue outer;
+ }
+ // else continue inner
+ }
+ }
+
+ if (!found)
+ return false;
+
+ // found a candidate for the querry. do we have an attr to match?
+ if (val == null) // <service>.<algorithm> querry
+ return true;
+
+ // <service>.<algorithm> <attribute>; find the key entry that match
+ String realAttr;
+ int limit = serviceDotAlgorithm.length() + 1;
+ for (it = p.keySet().iterator(); it.hasNext(); )
+ {
+ key = (String) it.next();
+ if (key.length() <= limit)
+ continue;
+
+ if (key.substring(0, limit).equalsIgnoreCase(serviceDotAlgorithm+" "))
+ {
+ realAttr = key.substring(limit).trim();
+ if (! realAttr.equalsIgnoreCase(attr))
+ continue;
+
+ // eveything matches so far. do the value
+ realVal = p.getProperty(key);
+ if (realVal == null)
+ return false;
+
+ realVal = realVal.trim();
+ // is it a string value?
+ if (val.equalsIgnoreCase(realVal))
+ return true;
+
+ // assume value is a number. cehck for greater-than-or-equal
+ return (new Integer(val).intValue() >= new Integer(realVal).intValue());
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/libjava/classpath/java/security/SecurityPermission.java b/libjava/classpath/java/security/SecurityPermission.java
new file mode 100644
index 00000000000..6aba18f346e
--- /dev/null
+++ b/libjava/classpath/java/security/SecurityPermission.java
@@ -0,0 +1,178 @@
+/* SecurityPermission.java -- Class for named security permissions
+ Copyright (C) 1998, 2002 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.security;
+
+/**
+ * This class provides a mechanism for specified named permissions
+ * related to the Java security framework. These permissions have no
+ * associated actions list. They are either granted or not granted.
+ *
+ * <p>The list of valid permission names is:<br>
+ * <table border=1>
+ * <tr><th>Permission Name</th><th>Permission Allows</th><th>Risks</th</tr>
+ * <tr>
+ * <td><code>createAccessControlContext</code></td>
+ * <td>Allows creation of an AccessControlContext</td>
+ * <td>The new control context can have a rogue DomainCombiner, leading
+ * to a privacy leak</td></tr>
+ * <tr>
+ * <td><code>getDomainCombiner</code></td>
+ * <td>Get a DomainCombiner from an AccessControlContext</td>
+ * <td>Access to a DomainCombiner can lead to a privacy leak</td></tr>
+ * <tr>
+ * <td><code>getPolicy</code></td>
+ * <td>Allows retrieval of the system security policy</td>
+ * <td>Malicious code can use information from the policy to better plan
+ * an attack</td></tr>
+ * <tr>
+ * <td><code>setPolicy</code></td>
+ * <td>Allows the security policy to be changed</td>
+ * <td>Malicious code can give itself any permission it wants</td></tr>
+ * <tr>
+ * <td><code>getProperty.</code><em>key</em></td>
+ * <td>Retrieve the property specified by the key</td>
+ * <td>Malicious code can use information from the property to better plan
+ * an attack</td></tr>
+ * <tr>
+ * <td><code>setProperty.</code><em>key</em></td>
+ * <td>Allows changing of the value of all properties implied by key</td>
+ * <td>Malicious code can insert rogue classes to steal keys or recreate
+ * the security policy with whatever permissions it desires</td></tr>
+ * <tr>
+ * <td><code>insertProvider.</code><em>key</em></td>
+ * <td>Allows the named provider to be added</td>
+ * <td>Malicious code can insert rogue providers that steal data</td></tr>
+ * <tr>
+ * <td><code>removeProvider.</code><em>key</em></td>
+ * <td>Allows the named provider to be removed</td>
+ * <td>A missing provider can cripple code that relies on it</td></tr>
+ * <tr>
+ * <td><code>setSystemScope</code></td>
+ * <td>Allows the system identity scope to be set</td>
+ * <td>Malicious code can add certificates not available in the original
+ * identity scope, to gain more permissions</td></tr>
+ * <tr>
+ * <td><code>setIdentityPublicKey</code></td>
+ * <td>Allows the public key of an Identity to be set</td>
+ * <td>Malicious code can install its own key to gain permissions not
+ * allowed by the original identity scope</td></tr>
+ * <tr>
+ * <td><code>SetIdentityInfo</code></td>
+ * <td>Allows the description of an Identity to be set</td>
+ * <td>Malicious code can spoof users into trusting a fake identity</td></tr>
+ * <tr>
+ * <td><code>addIdentityCertificate</code></td>
+ * <td>Allows a certificate to be set for the public key of an identity</td>
+ * <td>The public key can become trusted to a wider audience than originally
+ * intended</td></tr>
+ * <tr>
+ * <td><code>removeIdentityCertificate</code></td>
+ * <td>Allows removal of a certificate from an identity's public key</td>
+ * <td>The public key can become less trusted than it should be</td></tr>
+ * <tr>
+ * <td><code>printIdentity</code></td>
+ * <td>View the name of the identity and scope, and whether they are
+ * trusted</td>
+ * <td>The scope may include a filename, which provides an entry point for
+ * further security breaches</td></tr>
+ * <tr>
+ * <td><code>clearProviderProperties.</code><em>key</em></td>
+ * <td>Allows the properties of the named provider to be cleared</td>
+ * <td>This can disable parts of the program which depend on finding the
+ * provider</td></tr>
+ * <tr>
+ * <td><code>putProviderProperty.</code><em>key</em></td>
+ * <td>Allows the properties of the named provider to be changed</td>
+ * <td>Malicious code can replace the implementation of a provider</td></tr>
+ * <tr>
+ * <td><code>removeProviderProperty.</code><em>key</em></td>
+ * <td>Allows the properties of the named provider to be deleted</td>
+ * <td>This can disable parts of the program which depend on finding the
+ * provider</td></tr>
+ * <tr>
+ * <td><code>getSignerPrivateKey</code></td>
+ * <td>Allows the retrieval of the private key for a signer</td>
+ * <td>Anyone that can access the private key can claim to be the
+ * Signer</td></tr>
+ * <tr>
+ * <td><code>setSignerKeyPair</code></td>
+ * <td>Allows the public and private key of a Signer to be changed</td>
+ * <td>The replacement might be a weaker encryption, or the attacker
+ * can use knowledge of the replaced key to decrypt an entire
+ * communication session</td></tr>
+ * </table>
+ *
+ * <p>There is some degree of security risk in granting any of these
+ * permissions. Some of them can completely compromise system security.
+ * Please exercise extreme caution in granting these permissions.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Permission
+ * @see SecurityManager
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class SecurityPermission extends BasicPermission
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5236109936224050470L;
+
+ /**
+ * Create a new instance with the specified name.
+ *
+ * @param name the name to assign to this permission
+ */
+ public SecurityPermission(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Create a new instance with the specified name. As SecurityPermission
+ * carries no actions, the second parameter is ignored.
+ *
+ * @param name the name to assign to this permission
+ * @param actions ignored
+ */
+ public SecurityPermission(String name, String actions)
+ {
+ super(name);
+ }
+} // class SecurityPermission
diff --git a/libjava/classpath/java/security/Signature.java b/libjava/classpath/java/security/Signature.java
new file mode 100644
index 00000000000..852c959220f
--- /dev/null
+++ b/libjava/classpath/java/security/Signature.java
@@ -0,0 +1,636 @@
+/* Signature.java --- Signature Class
+ Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import gnu.java.security.Engine;
+
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * <p>This <code>Signature</code> class is used to provide applications the
+ * functionality of a digital signature algorithm. Digital signatures are used
+ * for authentication and integrity assurance of digital data.</p>
+ *
+ * <p>The signature algorithm can be, among others, the NIST standard <i>DSS</i>,
+ * using <i>DSA</i> and <i>SHA-1</i>. The <i>DSA</i> algorithm using the
+ * <i>SHA-1</i> message digest algorithm can be specified as <code>SHA1withDSA
+ * </code>. In the case of <i>RSA</i>, there are multiple choices for the
+ * message digest algorithm, so the signing algorithm could be specified as, for
+ * example, <code>MD2withRSA</code>, <code>MD5withRSA</code>, or
+ * <code>SHA1withRSA</code>. The algorithm name must be specified, as there is
+ * no default.</p>
+ *
+ * <p>Like other algorithm-based classes in Java Security, <code>Signature</code>
+ * provides implementation-independent algorithms, whereby a caller (application
+ * code) requests a particular signature algorithm and is handed back a properly
+ * initialized <code>Signature</code> object. It is also possible, if desired,
+ * to request a particular algorithm from a particular provider. See the
+ * <code>getInstance()</code> methods.</p>
+ *
+ * <p>Thus, there are two ways to request a <code>Signature</code> algorithm
+ * object: by specifying either just an algorithm name, or both an algorithm
+ * name and a package provider.</p>
+ *
+ * <p>If just an algorithm name is specified, the system will determine if there
+ * is an implementation of the algorithm requested available in the environment,
+ * and if there is more than one, if there is a preferred one.</p>
+ *
+ * <p>If both an algorithm name and a package provider are specified, the system
+ * will determine if there is an implementation of the algorithm in the package
+ * requested, and throw an exception if there is not.</p>
+ *
+ * <p>A <code>Signature</code> object can be used to generate and verify digital
+ * signatures.</p>
+ *
+ * <p>There are three phases to the use of a <code>Signature</code> object for
+ * either signing data or verifying a signature:</p>
+ *
+ * <ol>
+ * <li>Initialization, with either
+ * <ul>
+ * <li>a public key, which initializes the signature for verification
+ * (see <code>initVerify()</code>), or</li>
+ * <li>a private key (and optionally a Secure Random Number Generator),
+ * which initializes the signature for signing (see
+ * {@link #initSign(PrivateKey)} and {@link #initSign(PrivateKey, SecureRandom)}
+ * ).</li>
+ * </ul></li>
+ * <li>Updating<br/>
+ * Depending on the type of initialization, this will update the bytes to
+ * be signed or verified. See the update methods.<br/></li>
+ * <li>Signing or Verifying a signature on all updated bytes. See the
+ * <code>sign()</code> methods and the <code>verify()</code> method.</li>
+ * </ol>
+ *
+ * <p>Note that this class is abstract and extends from {@link SignatureSpi} for
+ * historical reasons. Application developers should only take notice of the
+ * methods defined in this <code>Signature</code> class; all the methods in the
+ * superclass are intended for cryptographic service providers who wish to
+ * supply their own implementations of digital signature algorithms.
+ *
+ * @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ */
+public abstract class Signature extends SignatureSpi
+{
+ /** Service name for signatures. */
+ private static final String SIGNATURE = "Signature";
+
+ /**
+ * Possible <code>state</code> value, signifying that this signature object
+ * has not yet been initialized.
+ */
+ protected static final int UNINITIALIZED = 0;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Possible <code>state</code> value, signifying that this signature object
+ * has been initialized for signing.
+ */
+ protected static final int SIGN = 2;
+
+ /**
+ * Possible <code>state</code> value, signifying that this signature object
+ * has been initialized for verification.
+ */
+ protected static final int VERIFY = 3;
+
+ /** Current state of this signature object. */
+ protected int state = UNINITIALIZED;
+
+ private String algorithm;
+ Provider provider;
+
+ /**
+ * Creates a <code>Signature</code> object for the specified algorithm.
+ *
+ * @param algorithm the standard string name of the algorithm. See Appendix A
+ * in the Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ */
+ protected Signature(String algorithm)
+ {
+ this.algorithm = algorithm;
+ state = UNINITIALIZED;
+ }
+
+ /**
+ * Generates a <code>Signature</code> object that implements the specified
+ * digest algorithm. If the default provider package provides an
+ * implementation of the requested digest algorithm, an instance of
+ * <code>Signature</code> containing that implementation is returned. If the
+ * algorithm is not available in the default package, other packages are
+ * searched.
+ *
+ * @param algorithm the standard name of the algorithm requested. See Appendix
+ * A in the Java Cryptography Architecture API Specification &amp; Reference
+ * for information about standard algorithm names.
+ * @return the new Signature object.
+ * @throws NoSuchAlgorithmException if the algorithm is not available in the
+ * environment.
+ */
+ public static Signature getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignored.
+ }
+ }
+
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * Generates a <code>Signature</code> object implementing the specified
+ * algorithm, as supplied from the specified provider, if such an algorithm
+ * is available from the provider.
+ *
+ * @param algorithm the name of the algorithm requested. See Appendix A in
+ * the Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ * @param provider the name of the provider.
+ * @return the new <code>Signature</code> object.
+ * @throws NoSuchAlgorithmException if the algorithm is not available in the
+ * package supplied by the requested provider.
+ * @throws NoSuchProviderException if the provider is not available in the
+ * environment.
+ * @throws IllegalArgumentException if the provider name is <code>null</code>
+ * or empty.
+ * @see Provider
+ */
+ public static Signature getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("Illegal provider");
+
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ throw new NoSuchProviderException(provider);
+
+ return getInstance(algorithm, p);
+ }
+
+ /**
+ * Generates a <code>Signature</code> object implementing the specified
+ * algorithm, as supplied from the specified provider, if such an algorithm
+ * is available from the provider. Note: the provider doesn't have to be
+ * registered.
+ *
+ * @param algorithm the name of the algorithm requested. See Appendix A in
+ * the Java Cryptography Architecture API Specification &amp; Reference for
+ * information about standard algorithm names.
+ * @param provider the provider.
+ * @return the new <code>Signature</code> object.
+ * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
+ * available in the package supplied by the requested <code>provider</code>.
+ * @throws IllegalArgumentException if the <code>provider</code> is
+ * <code>null</code>.
+ * @since 1.4
+ * @see Provider
+ */
+ public static Signature getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("Illegal provider");
+
+ Signature result = null;
+ Object o = null;
+ try
+ {
+ o = Engine.getInstance(SIGNATURE, algorithm, provider);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ if (o instanceof SignatureSpi)
+ {
+ result = new DummySignature((SignatureSpi) o, algorithm);
+ }
+ else if (o instanceof Signature)
+ {
+ result = (Signature) o;
+ result.algorithm = algorithm;
+ }
+ else
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ result.provider = provider;
+ return result;
+ }
+
+ /**
+ * Returns the provider of this signature object.
+ *
+ * @return the provider of this signature object.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Initializes this object for verification. If this method is called again
+ * with a different argument, it negates the effect of this call.
+ *
+ * @param publicKey the public key of the identity whose signature is going
+ * to be verified.
+ * @throws InvalidKeyException if the key is invalid.
+ */
+ public final void initVerify(PublicKey publicKey) throws InvalidKeyException
+ {
+ state = VERIFY;
+ engineInitVerify(publicKey);
+ }
+
+ /**
+ * <p>Initializes this object for verification, using the public key from the
+ * given certificate.</p>
+ *
+ * <p>If the certificate is of type <i>X.509</i> and has a <i>key usage</i>
+ * extension field marked as <i>critical</i>, and the value of the <i>key
+ * usage</i> extension field implies that the public key in the certificate
+ * and its corresponding private key are not supposed to be used for digital
+ * signatures, an {@link InvalidKeyException} is thrown.</p>
+ *
+ * @param certificate the certificate of the identity whose signature is
+ * going to be verified.
+ * @throws InvalidKeyException if the public key in the certificate is not
+ * encoded properly or does not include required parameter information or
+ * cannot be used for digital signature purposes.
+ */
+ public final void initVerify(Certificate certificate)
+ throws InvalidKeyException
+ {
+ state = VERIFY;
+ if (certificate.getType().equals("X509"))
+ {
+ X509Certificate cert = (X509Certificate) certificate;
+ boolean[]array = cert.getKeyUsage();
+ if (array != null && array[0] == false)
+ throw new InvalidKeyException(
+ "KeyUsage of this Certificate indicates it cannot be used for digital signing");
+ }
+ this.initVerify(certificate.getPublicKey());
+ }
+
+ /**
+ * Initialize this object for signing. If this method is called again with a
+ * different argument, it negates the effect of this call.
+ *
+ * @param privateKey the private key of the identity whose signature is going
+ * to be generated.
+ * @throws InvalidKeyException if the key is invalid.
+ */
+ public final void initSign(PrivateKey privateKey) throws InvalidKeyException
+ {
+ state = SIGN;
+ engineInitSign(privateKey);
+ }
+
+ /**
+ * Initialize this object for signing. If this method is called again with a
+ * different argument, it negates the effect of this call.
+ *
+ * @param privateKey the private key of the identity whose signature is going
+ * to be generated.
+ * @param random the source of randomness for this signature.
+ * @throws InvalidKeyException if the key is invalid.
+ */
+ public final void initSign(PrivateKey privateKey, SecureRandom random)
+ throws InvalidKeyException
+ {
+ state = SIGN;
+ engineInitSign(privateKey, random);
+ }
+
+ /**
+ * <p>Returns the signature bytes of all the data updated. The format of the
+ * signature depends on the underlying signature scheme.</p>
+ *
+ * <p>A call to this method resets this signature object to the state it was
+ * in when previously initialized for signing via a call to
+ * <code>initSign(PrivateKey)</code>. That is, the object is reset and
+ * available to generate another signature from the same signer, if desired,
+ * via new calls to <code>update()</code> and <code>sign()</code>.</p>
+ *
+ * @return the signature bytes of the signing operation's result.
+ * @throws SignatureException if this signature object is not initialized
+ * properly.
+ */
+ public final byte[] sign() throws SignatureException
+ {
+ if (state == SIGN)
+ return engineSign();
+ else
+ throw new SignatureException();
+ }
+
+ /**
+ * <p>Finishes the signature operation and stores the resulting signature
+ * bytes in the provided buffer <code>outbuf</code>, starting at <code>offset
+ * </code>. The format of the signature depends on the underlying signature
+ * scheme.</p>
+ *
+ * <p>This signature object is reset to its initial state (the state it was
+ * in after a call to one of the <code>initSign()</code> methods) and can be
+ * reused to generate further signatures with the same private key.</p>
+ *
+ * @param outbuf buffer for the signature result.
+ * @param offset offset into outbuf where the signature is stored.
+ * @param len number of bytes within outbuf allotted for the signature.
+ * @return the number of bytes placed into outbuf.
+ * @throws SignatureException if an error occurs or len is less than the
+ * actual signature length.
+ * @since 1.2
+ */
+ public final int sign(byte[] outbuf, int offset, int len)
+ throws SignatureException
+ {
+ if (state == SIGN)
+ return engineSign(outbuf, offset, len);
+ else
+ throw new SignatureException();
+ }
+
+ /**
+ * <p>Verifies the passed-in signature.</p>
+ *
+ * <p>A call to this method resets this signature object to the state it was
+ * in when previously initialized for verification via a call to
+ * <code>initVerify(PublicKey)</code>. That is, the object is reset and
+ * available to verify another signature from the identity whose public key
+ * was specified in the call to <code>initVerify()</code>.</p>
+ *
+ * @param signature the signature bytes to be verified.
+ * @return <code>true</code> if the signature was verified, <code>false</code>
+ * if not.
+ * @throws SignatureException if this signature object is not initialized
+ * properly, or the passed-in signature is improperly encoded or of the wrong
+ * type, etc.
+ */
+ public final boolean verify(byte[]signature) throws SignatureException
+ {
+ if (state == VERIFY)
+ return engineVerify(signature);
+ else
+ throw new SignatureException();
+ }
+
+ /**
+ * <p>Verifies the passed-in <code>signature</code> in the specified array of
+ * bytes, starting at the specified <code>offset</code>.</p>
+ *
+ * <p>A call to this method resets this signature object to the state it was
+ * in when previously initialized for verification via a call to
+ * <code>initVerify(PublicKey)</code>. That is, the object is reset and
+ * available to verify another signature from the identity whose public key
+ * was specified in the call to <code>initVerify()</code>.</p>
+ *
+ * @param signature the signature bytes to be verified.
+ * @param offset the offset to start from in the array of bytes.
+ * @param length the number of bytes to use, starting at offset.
+ * @return <code>true</code> if the signature was verified, <code>false</code>
+ * if not.
+ * @throws SignatureException if this signature object is not initialized
+ * properly, or the passed-in <code>signature</code> is improperly encoded or
+ * of the wrong type, etc.
+ * @throws IllegalArgumentException if the <code>signature</code> byte array
+ * is <code>null</code>, or the <code>offset</code> or <code>length</code> is
+ * less than <code>0</code>, or the sum of the <code>offset</code> and
+ * <code>length</code> is greater than the length of the <code>signature</code>
+ * byte array.
+ */
+ public final boolean verify(byte[] signature, int offset, int length)
+ throws SignatureException
+ {
+ if (state != VERIFY)
+ throw new SignatureException("illegal state");
+
+ if (signature == null)
+ throw new IllegalArgumentException("signature is null");
+ if (offset < 0)
+ throw new IllegalArgumentException("offset is less than 0");
+ if (length < 0)
+ throw new IllegalArgumentException("length is less than 0");
+ if (offset + length < signature.length)
+ throw new IllegalArgumentException("range is out of bounds");
+
+ return engineVerify(signature, offset, length);
+ }
+
+ /**
+ * Updates the data to be signed or verified by a byte.
+ *
+ * @param b the byte to use for the update.
+ * @throws SignatureException if this signature object is not initialized
+ * properly.
+ */
+ public final void update(byte b) throws SignatureException
+ {
+ if (state != UNINITIALIZED)
+ engineUpdate(b);
+ else
+ throw new SignatureException();
+ }
+
+ /**
+ * Updates the data to be signed or verified, using the specified array of
+ * bytes.
+ *
+ * @param data the byte array to use for the update.
+ * @throws SignatureException if this signature object is not initialized
+ * properly.
+ */
+ public final void update(byte[]data) throws SignatureException
+ {
+ if (state != UNINITIALIZED)
+ engineUpdate(data, 0, data.length);
+ else
+ throw new SignatureException();
+ }
+
+ /**
+ * Updates the data to be signed or verified, using the specified array of
+ * bytes, starting at the specified offset.
+ *
+ * @param data the array of bytes.
+ * @param off the offset to start from in the array of bytes.
+ * @param len the number of bytes to use, starting at offset.
+ * @throws SignatureException if this signature object is not initialized
+ * properly.
+ */
+ public final void update(byte[]data, int off, int len)
+ throws SignatureException
+ {
+ if (state != UNINITIALIZED)
+ engineUpdate(data, off, len);
+ else
+ throw new SignatureException();
+ }
+
+ /**
+ * Returns the name of the algorithm for this signature object.
+ *
+ * @return the name of the algorithm for this signature object.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Returns a string representation of this signature object, providing
+ * information that includes the state of the object and the name of the
+ * algorithm used.
+ *
+ * @return a string representation of this signature object.
+ */
+ public String toString()
+ {
+ return (algorithm + " Signature");
+ }
+
+ /**
+ * Sets the specified algorithm parameter to the specified value. This method
+ * supplies a general-purpose mechanism through which it is possible to set
+ * the various parameters of this object. A parameter may be any settable
+ * parameter for the algorithm, such as a parameter size, or a source of
+ * random bits for signature generation (if appropriate), or an indication of
+ * whether or not to perform a specific but optional computation. A uniform
+ * algorithm-specific naming scheme for each parameter is desirable but left
+ * unspecified at this time.
+ *
+ * @param param the string identifier of the parameter.
+ * @param value the parameter value.
+ * @throws InvalidParameterException if param is an invalid parameter for this
+ * signature algorithm engine, the parameter is already set and cannot be set
+ * again, a security exception occurs, and so on.
+ * @see #getParameter(String)
+ * @deprecated Use setParameter(AlgorithmParameterSpec).
+ */
+ public final void setParameter(String param, Object value)
+ throws InvalidParameterException
+ {
+ engineSetParameter(param, value);
+ }
+
+ /**
+ * Initializes this signature engine with the specified parameter set.
+ *
+ * @param params the parameters.
+ * @throws InvalidAlgorithmParameterException if the given parameters are
+ * inappropriate for this signature engine.
+ * @see #getParameters()
+ */
+ public final void setParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ engineSetParameter(params);
+ }
+
+ /**
+ * <p>Returns the parameters used with this signature object.</p>
+ *
+ * <p>The returned parameters may be the same that were used to initialize
+ * this signature, or may contain a combination of default and randomly
+ * generated parameter values used by the underlying signature implementation
+ * if this signature requires algorithm parameters but was not initialized
+ * with any.
+ *
+ * @return the parameters used with this signature, or <code>null</code> if
+ * this signature does not use any parameters.
+ * @see #setParameter(AlgorithmParameterSpec)
+ */
+ public final AlgorithmParameters getParameters()
+ {
+ return engineGetParameters();
+ }
+
+ /**
+ * Gets the value of the specified algorithm parameter. This method supplies
+ * a general-purpose mechanism through which it is possible to get the various
+ * parameters of this object. A parameter may be any settable parameter for
+ * the algorithm, such as a parameter size, or a source of random bits for
+ * signature generation (if appropriate), or an indication of whether or not
+ * to perform a specific but optional computation. A uniform
+ * algorithm-specific naming scheme for each parameter is desirable but left
+ * unspecified at this time.
+ *
+ * @param param the string name of the parameter.
+ * @return the object that represents the parameter value, or null if there
+ * is none.
+ * @throws InvalidParameterException if param is an invalid parameter for this
+ * engine, or another exception occurs while trying to get this parameter.
+ * @see #setParameter(String, Object)
+ * @deprecated
+ */
+ public final Object getParameter(String param)
+ throws InvalidParameterException
+ {
+ return engineGetParameter(param);
+ }
+
+ /**
+ * Returns a clone if the implementation is cloneable.
+ *
+ * @return a clone if the implementation is cloneable.
+ * @throws CloneNotSupportedException if this is called on an implementation
+ * that does not support {@link Cloneable}.
+ */
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+}
diff --git a/libjava/classpath/java/security/SignatureException.java b/libjava/classpath/java/security/SignatureException.java
new file mode 100644
index 00000000000..e294c16c3f6
--- /dev/null
+++ b/libjava/classpath/java/security/SignatureException.java
@@ -0,0 +1,70 @@
+/* SignatureException.java -- Generic error in signature
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception is thrown when a problem is encountered with a
+ * digital signature.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class SignatureException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 7509989324975124438L;
+
+ /**
+ * Create an instance with no descriptive error message.
+ */
+ public SignatureException()
+ {
+ }
+
+ /**
+ * Create an instance with a descriptive error message.
+ *
+ * @param msg the message
+ */
+ public SignatureException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/SignatureSpi.java b/libjava/classpath/java/security/SignatureSpi.java
new file mode 100644
index 00000000000..471a73d17cd
--- /dev/null
+++ b/libjava/classpath/java/security/SignatureSpi.java
@@ -0,0 +1,302 @@
+/* SignatureSpi.java --- Signature Service Provider Interface
+ Copyright (C) 1999, 2003, 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.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * <p>This class defines the <i>Service Provider Interface (SPI)</i> for the
+ * {@link Signature} class, which is used to provide the functionality of a
+ * digital signature algorithm. Digital signatures are used for authentication
+ * and integrity assurance of digital data.</p>
+ *
+ * <p>All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation of a
+ * particular signature algorithm.
+ *
+ * @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ * @since 1.2
+ * @see Signature
+ */
+public abstract class SignatureSpi
+{
+ /** Application-specified source of randomness. */
+ protected SecureRandom appRandom;
+
+ public SignatureSpi()
+ {
+ appRandom = null;
+ }
+
+ /**
+ * Initializes this signature object with the specified public key for
+ * verification operations.
+ *
+ * @param publicKey the public key of the identity whose signature is going
+ * to be verified.
+ * @throws InvalidKeyException if the key is improperly encoded, parameters
+ * are missing, and so on.
+ */
+ protected abstract void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException;
+
+ /**
+ * Initializes this signature object with the specified private key for
+ * signing operations.
+ *
+ * @param privateKey the private key of the identity whose signature will be
+ * generated.
+ * @throws InvalidKeyException if the key is improperly encoded, parameters
+ * are missing, and so on.
+ */
+ protected abstract void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException;
+
+ /**
+ * <p>Initializes this signature object with the specified private key and
+ * source of randomness for signing operations.</p>
+ *
+ * <p>This concrete method has been added to this previously-defined abstract
+ * class. (For backwards compatibility, it cannot be abstract.)</p>
+ *
+ * @param privateKey the private key of the identity whose signature will be
+ * generated.
+ * @param random the source of randomness.
+ * @throws InvalidKeyException if the key is improperly encoded, parameters
+ * are missing, and so on.
+ * @since 1.2
+ */
+ protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
+ throws InvalidKeyException
+ {
+ appRandom = random;
+ engineInitSign(privateKey);
+ }
+
+ /**
+ * Updates the data to be signed or verified using the specified byte.
+ *
+ * @param b the byte to use for the update.
+ * @throws SignatureException if the engine is not initialized properly.
+ */
+ protected abstract void engineUpdate(byte b) throws SignatureException;
+
+ /**
+ * Updates the data to be signed or verified, using the specified array of
+ * bytes, starting at the specified offset.
+ *
+ * @param b the array of bytes.
+ * @param off the offset to start from in the array of bytes.
+ * @param len the number of bytes to use, starting at offset.
+ * @throws SignatureException if the engine is not initialized properly.
+ */
+ protected abstract void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException;
+
+ /**
+ * Returns the signature bytes of all the data updated so far. The format of
+ * the signature depends on the underlying signature scheme.
+ *
+ * @return the signature bytes of the signing operation's result.
+ * @throws SignatureException if the engine is not initialized properly.
+ */
+ protected abstract byte[] engineSign() throws SignatureException;
+
+ /**
+ * <p>Finishes this signature operation and stores the resulting signature
+ * bytes in the provided buffer <code>outbuf</code>, starting at <code>offset
+ * </code>. The format of the signature depends on the underlying signature
+ * scheme.</p>
+ *
+ * <p>The signature implementation is reset to its initial state (the state it
+ * was in after a call to one of the <code>engineInitSign()</code> methods)
+ * and can be reused to generate further signatures with the same private key.
+ * This method should be abstract, but we leave it concrete for binary
+ * compatibility. Knowledgeable providers should override this method.</p>
+ *
+ * @param outbuf buffer for the signature result.
+ * @param offset offset into outbuf where the signature is stored.
+ * @param len number of bytes within outbuf allotted for the signature. Both
+ * this default implementation and the <b>GNU</b> provider do not return
+ * partial digests. If the value of this parameter is less than the actual
+ * signature length, this method will throw a {@link SignatureException}. This
+ * parameter is ignored if its value is greater than or equal to the actual
+ * signature length.
+ * @return the number of bytes placed into <code>outbuf</code>.
+ * @throws SignatureException if an error occurs or len is less than the
+ * actual signature length.
+ * @since 1.2
+ */
+ protected int engineSign(byte[] outbuf, int offset, int len)
+ throws SignatureException
+ {
+ byte[] tmp = engineSign();
+ if (tmp.length > len)
+ throw new SignatureException("Invalid Length");
+
+ System.arraycopy(outbuf, offset, tmp, 0, tmp.length);
+ return tmp.length;
+ }
+
+ /**
+ * Verifies the passed-in signature.
+ *
+ * @param sigBytes the signature bytes to be verified.
+ * @return <code>true</code> if the signature was verified, <code>false</code>
+ * if not.
+ * @throws SignatureException if the engine is not initialized properly, or
+ * the passed-in signature is improperly encoded or of the wrong type, etc.
+ */
+ protected abstract boolean engineVerify(byte[] sigBytes)
+ throws SignatureException;
+
+ /**
+ * <p>Verifies the passed-in <code>signature</code> in the specified array of
+ * bytes, starting at the specified <code>offset</code>.</p>
+ *
+ * <p>Note: Subclasses should overwrite the default implementation.</p>
+ *
+ * @param sigBytes the signature bytes to be verified.
+ * @param offset the offset to start from in the array of bytes.
+ * @param length the number of bytes to use, starting at offset.
+ * @return <code>true</code> if the signature was verified, <code>false</code>
+ * if not.
+ * @throws SignatureException if the engine is not initialized properly, or
+ * the passed-in <code>signature</code> is improperly encoded or of the wrong
+ * type, etc.
+ */
+ protected boolean engineVerify(byte[] sigBytes, int offset, int length)
+ throws SignatureException
+ {
+ byte[] tmp = new byte[length];
+ System.arraycopy(sigBytes, offset, tmp, 0, length);
+ return engineVerify(tmp);
+ }
+
+ /**
+ * Sets the specified algorithm parameter to the specified value. This method
+ * supplies a general-purpose mechanism through which it is possible to set
+ * the various parameters of this object. A parameter may be any settable
+ * parameter for the algorithm, such as a parameter size, or a source of
+ * random bits for signature generation (if appropriate), or an indication of
+ * whether or not to perform a specific but optional computation. A uniform
+ * algorithm-specific naming scheme for each parameter is desirable but left
+ * unspecified at this time.
+ *
+ * @param param the string identifier of the parameter.
+ * @param value the parameter value.
+ * @throws InvalidParameterException if <code>param</code> is an invalid
+ * parameter for this signature algorithm engine, the parameter is already set
+ * and cannot be set again, a security exception occurs, and so on.
+ * @deprecated Replaced by engineSetParameter(AlgorithmParameterSpec).
+ */
+ protected abstract void engineSetParameter(String param, Object value)
+ throws InvalidParameterException;
+
+ /**
+ * This method is overridden by providers to initialize this signature engine
+ * with the specified parameter set.
+ *
+ * @param params the parameters.
+ * @throws UnsupportedOperationException if this method is not overridden by
+ * a provider.
+ * @throws InvalidAlgorithmParameterException if this method is overridden by
+ * a provider and the the given parameters are inappropriate for this
+ * signature engine.
+ */
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * <p>This method is overridden by providers to return the parameters used
+ * with this signature engine, or <code>null</code> if this signature engine
+ * does not use any parameters.</p>
+ *
+ * <p>The returned parameters may be the same that were used to initialize
+ * this signature engine, or may contain a combination of default and randomly
+ * generated parameter values used by the underlying signature implementation
+ * if this signature engine requires algorithm parameters but was not
+ * initialized with any.</p>
+ *
+ * @return the parameters used with this signature engine, or <code>null</code>
+ * if this signature engine does not use any parameters.
+ * @throws UnsupportedOperationException if this method is not overridden by
+ * a provider.
+ */
+ protected AlgorithmParameters engineGetParameters()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Gets the value of the specified algorithm parameter. This method supplies
+ * a general-purpose mechanism through which it is possible to get the various
+ * parameters of this object. A parameter may be any settable parameter for
+ * the algorithm, such as a parameter size, or a source of random bits for
+ * signature generation (if appropriate), or an indication of whether or not
+ * to perform a specific but optional computation. A uniform algorithm-specific
+ * naming scheme for each parameter is desirable but left unspecified at this
+ * time.
+ *
+ * @param param the string name of the parameter.
+ * @return the object that represents the parameter value, or <code>null</code>
+ * if there is none.
+ * @throws InvalidParameterException if <code>param</code> is an invalid
+ * parameter for this engine, or another exception occurs while trying to get
+ * this parameter.
+ * @deprecated
+ */
+ protected abstract Object engineGetParameter(String param)
+ throws InvalidParameterException;
+
+ /**
+ * Returns a clone if the implementation is cloneable.
+ *
+ * @return a clone if the implementation is cloneable.
+ * @throws CloneNotSupportedException if this is called on an implementation
+ * that does not support {@link Cloneable}.
+ * @see Cloneable
+ */
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+}
diff --git a/libjava/classpath/java/security/SignedObject.java b/libjava/classpath/java/security/SignedObject.java
new file mode 100644
index 00000000000..d565b2ea3b4
--- /dev/null
+++ b/libjava/classpath/java/security/SignedObject.java
@@ -0,0 +1,240 @@
+/* SignedObject.java --- Signed Object Class
+ Copyright (C) 1999, 2003, 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.security;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * <p><code>SignedObject</code> is a class for the purpose of creating authentic
+ * runtime objects whose integrity cannot be compromised without being detected.
+ * </p>
+ *
+ * <p>More specifically, a <code>SignedObject</code> contains another
+ * {@link Serializable} object, the (to-be-)signed object and its signature.</p>
+ *
+ * <p>The signed object is a <i>"deep copy"</i> (in serialized form) of an
+ * original object. Once the copy is made, further manipulation of the original
+ * object has no side effect on the copy.</p>
+ *
+ * <p>The underlying signing algorithm is designated by the {@link Signature}
+ * object passed to the constructor and the <code>verify()</code> method. A
+ * typical usage for signing is the following:</p>
+ *
+ * <pre>
+ * Signature signingEngine = Signature.getInstance(algorithm, provider);
+ * SignedObject so = new SignedObject(myobject, signingKey, signingEngine);
+ * </pre>
+ *
+ * <p>A typical usage for verification is the following (having received
+ * <code>SignedObject</code> so):</p>
+ *
+ * <pre>
+ * Signature verificationEngine = Signature.getInstance(algorithm, provider);
+ * if (so.verify(publickey, verificationEngine))
+ * try
+ * {
+ * Object myobj = so.getObject();
+ * }
+ * catch (ClassNotFoundException ignored) {};
+ * </pre>
+ *
+ * <p>Several points are worth noting. First, there is no need to initialize the
+ * signing or verification engine, as it will be re-initialized inside the
+ * constructor and the <code>verify()</code> method. Secondly, for verification
+ * to succeed, the specified public key must be the public key corresponding to
+ * the private key used to generate the <code>SignedObject</code>.</p>
+ *
+ * <p>More importantly, for flexibility reasons, the <code>constructor</code>
+ * and <code>verify()</code> method allow for customized signature engines,
+ * which can implement signature algorithms that are not installed formally as
+ * part of a crypto provider. However, it is crucial that the programmer writing
+ * the verifier code be aware what {@link Signature} engine is being used, as
+ * its own implementation of the <code>verify()</code> method is invoked to
+ * verify a signature. In other words, a malicious {@link Signature} may choose
+ * to always return <code>true</code> on verification in an attempt to bypass a
+ * security check.</p>
+ *
+ * <p>The signature algorithm can be, among others, the NIST standard <i>DSS</i>,
+ * using <i>DSA</i> and <i>SHA-1</i>. The algorithm is specified using the same
+ * convention as that for signatures. The <i>DSA</i> algorithm using the
+ * <i>SHA-1</i> message digest algorithm can be specified, for example, as
+ * <code>"SHA/DSA"</code> or <code>"SHA-1/DSA"</code> (they are equivalent). In
+ * the case of <i>RSA</i>, there are multiple choices for the message digest
+ * algorithm, so the signing algorithm could be specified as, for example,
+ * <code>"MD2/RSA"</code>, <code>"MD5/RSA"</code> or <code>"SHA-1/RSA"</code>.
+ * The algorithm name must be specified, as there is no default.</p>
+ *
+ * <p>The name of the Cryptography Package Provider is designated also by the
+ * {@link Signature} parameter to the <code>constructor</code> and the <code>
+ * verify()</code> method. If the provider is not specified, the default
+ * provider is used. Each installation can be configured to use a particular
+ * provider as default.</p>
+ *
+ * <p>Potential applications of <code>SignedObject</code> include:</p>
+ *
+ * <ul>
+ * <li>It can be used internally to any Java runtime as an unforgeable
+ * authorization token -- one that can be passed around without the fear that
+ * the token can be maliciously modified without being detected.</li>
+ * <li>It can be used to sign and serialize data/object for storage outside the
+ * Java runtime (e.g., storing critical access control data on disk).</li>
+ * <li>Nested <i>SignedObjects</i> can be used to construct a logical sequence
+ * of signatures, resembling a chain of authorization and delegation.</li>
+ * </ul>
+ *
+ * @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ * @since 1.2
+ * @see Signature
+ */
+public final class SignedObject implements Serializable
+{
+ private static final long serialVersionUID = 720502720485447167L;
+
+ /** @serial */
+ private byte[] content;
+ /** @serial */
+ private byte[] signature;
+ /** @serial */
+ private String thealgorithm;
+
+ /**
+ * Constructs a <code>SignedObject</code> from any {@link Serializable}
+ * object. The given object is signed with the given signing key, using the
+ * designated signature engine.
+ *
+ * @param object the object to be signed.
+ * @param signingKey the private key for signing.
+ * @param signingEngine the signature signing engine.
+ * @throws IOException if an error occurs during serialization.
+ * @throws InvalidKeyException if the key is invalid.
+ * @throws SignatureException if signing fails.
+ */
+ public SignedObject(Serializable object, PrivateKey signingKey,
+ Signature signingEngine)
+ throws IOException, InvalidKeyException, SignatureException
+ {
+ thealgorithm = signingEngine.getAlgorithm();
+
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+ ObjectOutputStream p = new ObjectOutputStream(ostream);
+ p.writeObject(object);
+ p.flush();
+ p.close();
+
+ content = ostream.toByteArray();
+
+ signingEngine.initSign(signingKey);
+ signingEngine.update(content);
+ signature = signingEngine.sign();
+ }
+
+ /**
+ * Retrieves the encapsulated object. The encapsulated object is de-serialized
+ * before it is returned.
+ *
+ * @return the encapsulated object.
+ * @throws IOException if an error occurs during de-serialization.
+ * @throws ClassNotFoundException if an error occurs during de-serialization.
+ */
+ public Object getObject() throws IOException, ClassNotFoundException
+ {
+ ByteArrayInputStream bais = new ByteArrayInputStream(content);
+ ObjectInput oi = new ObjectInputStream(bais);
+ Object obj = oi.readObject();
+ oi.close();
+ bais.close();
+
+ return obj;
+ }
+
+ /**
+ * Retrieves the signature on the signed object, in the form of a byte array.
+ *
+ * @return a copy of the signature.
+ */
+ public byte[] getSignature()
+ {
+ return (byte[]) signature.clone();
+
+ }
+
+ /**
+ * Retrieves the name of the signature algorithm.
+ *
+ * @return the signature algorithm name.
+ */
+ public String getAlgorithm()
+ {
+ return thealgorithm;
+ }
+
+ /**
+ * Verifies that the signature in this <code>SignedObject</code> is the valid
+ * signature for the object stored inside, with the given verification key,
+ * using the designated verification engine.
+ *
+ * @param verificationKey the public key for verification.
+ * @param verificationEngine the signature verification engine.
+ * @return <code>true</code> if the signature is valid, <code>false</code>
+ * otherwise.
+ * @throws SignatureException if signature verification failed.
+ * @throws InvalidKeyException if the verification key is invalid.
+ */
+ public boolean verify(PublicKey verificationKey, Signature verificationEngine)
+ throws InvalidKeyException, SignatureException
+ {
+ verificationEngine.initVerify(verificationKey);
+ verificationEngine.update(content);
+ return verificationEngine.verify(signature);
+ }
+
+ /** Called to restore the state of the SignedObject from a stream. */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ content = (byte[]) content.clone();
+ signature = (byte[]) signature.clone();
+ }
+}
diff --git a/libjava/classpath/java/security/Signer.java b/libjava/classpath/java/security/Signer.java
new file mode 100644
index 00000000000..ae1463db84c
--- /dev/null
+++ b/libjava/classpath/java/security/Signer.java
@@ -0,0 +1,164 @@
+/* Signer.java --- Signer Class
+ Copyright (C) 1999, 2003, 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.security;
+
+/**
+ * <p>This class is used to represent an {@link Identity} that can also
+ * digitally sign data.</p>
+ *
+ * <p>The management of a signer's private keys is an important and sensitive
+ * issue that should be handled by subclasses as appropriate to their intended
+ * use.</p>
+ *
+ * @author Mark Benvenuto (ivymccough@worldnet.att.net)
+ * @deprecated This class is no longer used. Its functionality has been replaced
+ * by <code>java.security.KeyStore</code>, the <code>java.security.cert</code>
+ * package, and <code>java.security.Principal</code>.
+ */
+public abstract class Signer extends Identity
+{
+ private static final long serialVersionUID = -1763464102261361480L;
+ private PrivateKey privateKey = null;
+
+ /**
+ * Creates a <code>Signer</code>. This constructor should only be used for
+ * serialization.
+ */
+ protected Signer()
+ {
+ }
+
+ /**
+ * Creates a <code>Signer</code> with the specified identity name.
+ *
+ * @param name the identity name.
+ */
+ public Signer(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Creates a <code>Signer</code> with the specified identity name and scope.
+ *
+ * @param name the identity name.
+ * @param scope the scope of the identity.
+ * @throws KeyManagementException if there is already an identity with the
+ * same name in the scope.
+ */
+ public Signer(String name, IdentityScope scope) throws KeyManagementException
+ {
+ super(name, scope);
+ }
+
+ /**
+ * <p>Returns this signer's private key.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"getSignerPrivateKey"</code> as its
+ * argument to see if it's ok to return the private key.</p>
+ *
+ * @return this signer's private key, or <code>null</code> if the private key
+ * has not yet been set.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow returning the
+ * private key.
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public PrivateKey getPrivateKey()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("getSignerPrivateKey");
+
+ return privateKey;
+ }
+
+ /**
+ * <p>Sets the key pair (public key and private key) for this signer.</p>
+ *
+ * <p>First, if there is a security manager, its <code>checkSecurityAccess()
+ * </code> method is called with <code>"setSignerKeyPair"</code> as its
+ * argument to see if it's ok to set the key pair.</p>
+ *
+ * @param pair an initialized key pair.
+ * @throws InvalidParameterException if the key pair is not properly
+ * initialized.
+ * @throws KeyException if the key pair cannot be set for any other reason.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkSecurityAccess()</code> method doesn't allow setting the key
+ * pair.
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public final void setKeyPair(KeyPair pair)
+ throws InvalidParameterException, KeyException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("setSignerKeyPair");
+
+ try
+ {
+ if (pair.getPublic() != null)
+ setPublicKey(pair.getPublic());
+ else
+ throw new InvalidParameterException();
+
+ }
+ catch (KeyManagementException kme)
+ {
+ throw new KeyException();
+ }
+
+ if (pair.getPrivate() != null)
+ privateKey = pair.getPrivate();
+ else
+ throw new InvalidParameterException();
+ }
+
+ /**
+ * Returns a string of information about the signer.
+ *
+ * @return a string of information about the signer.
+ * @see SecurityManager#checkSecurityAccess(String)
+ */
+ public String toString()
+ {
+ return (getName() + ": " + privateKey);
+ }
+}
diff --git a/libjava/classpath/java/security/UnrecoverableKeyException.java b/libjava/classpath/java/security/UnrecoverableKeyException.java
new file mode 100644
index 00000000000..6759c3c7b91
--- /dev/null
+++ b/libjava/classpath/java/security/UnrecoverableKeyException.java
@@ -0,0 +1,71 @@
+/* UnrecoverableKeyException.java -- Cannot recover a key from the key store
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+/**
+ * This exception is thrown when a key cannot be recovered from the key
+ * store.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class UnrecoverableKeyException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 7275063078190151277L;
+
+ /**
+ * Create an instance with no descriptive error message.
+ */
+ public UnrecoverableKeyException()
+ {
+ }
+
+ /**
+ * Create an instance with a descriptive error message.
+ *
+ * @param msg the descriptive error message
+ */
+ public UnrecoverableKeyException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/UnresolvedPermission.java b/libjava/classpath/java/security/UnresolvedPermission.java
new file mode 100644
index 00000000000..d3f671a9c06
--- /dev/null
+++ b/libjava/classpath/java/security/UnresolvedPermission.java
@@ -0,0 +1,304 @@
+/* UnresolvedPermission.java -- Placeholder for unresolved permissions
+ Copyright (C) 1998, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+// All uses of Certificate in this file refer to the one in the listed
+// package, not this one.
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+import java.util.Vector;
+
+/**
+ * This class is used to hold instances of all permissions that cannot
+ * be resolved to available permission classes when the security
+ * <code>Policy</code> object is instantiated. This may happen when the
+ * necessary security class has not yet been downloaded from the network.
+ *
+ * <p>Instances of this class are re-resolved when
+ * <code>AccessController</code> check is done. At that time, a scan is
+ * made of all existing <code>UnresolvedPermission</code> objects and they
+ * are converted to objects of the appropriate permission type if the class
+ * for that type is then available.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Permission
+ * @see Permissions
+ * @see PermissionCollection
+ * @see Policy
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class UnresolvedPermission extends Permission
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -4821973115467008846L;
+
+ /**
+ * The list of actions associated with this permission object.
+ *
+ * @serial the permission actions
+ */
+ private final String actions;
+
+ /**
+ * The list of <code>Certificates</code> associated with this object.
+ */
+ private final transient Certificate[] certs;
+
+ /**
+ * The name of the class this object should be resolved to.
+ *
+ * @serial the fully-qualified classname of the resolved type
+ */
+ // Package visible for use by UnresolvedPermissionCollection.
+ final String type;
+
+ /**
+ * The name of the permission.
+ *
+ * @serial the permission name
+ */
+ private final String name;
+
+ /**
+ * Create a new instance with all the information necessary to resolve it
+ * to an instance of the proper class at a future time.
+ *
+ * @param type the fully-qualified name of the class of this permission
+ * @param name the name of this permission
+ * @param actions the action list for this permission
+ * @param certs the list of certificates that sign this permission
+ */
+ public UnresolvedPermission(String type, String name, String actions,
+ Certificate[] certs)
+ {
+ super(name);
+ this.name = name;
+ this.type = type;
+ this.actions = actions;
+ this.certs = certs;
+ }
+
+ /**
+ * This method returns <code>false</code> always to indicate that this
+ * permission does not imply the specified permission. An
+ * <code>UnresolvedPermission</code> never grants any permissions.
+ *
+ * @param perm the <code>Permission</code> object to test
+ * @return false; until a permission is resolved, it implies nothing
+ */
+ public boolean implies(Permission perm)
+ {
+ return false;
+ }
+
+ /**
+ * This method tests this permission for equality against the specified
+ * <code>Object</code>. This will be true if and only if the following
+ * conditions are met:<ul>
+ * <li>The specified <code>Object</code> is an UnresolvedPermission</li>
+ * <li>The specified permission has the same type (i.e., desired class name)
+ * as this permission.</li>
+ * <li>The specified permission has the same name as this one.</li>
+ * <li>The specified permissoin has the same action list as this one.</li>
+ * <li>The specified permission has the same certificate list as this
+ * one.</li>
+ * </ul>
+ *
+ * @param obj the <code>Object</code> to test for equality
+ * @return true if the specified object is equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof UnresolvedPermission))
+ return (false);
+ UnresolvedPermission up = (UnresolvedPermission) obj;
+ return up.name.equals(name) && up.actions.equals(actions)
+ && up.type.equals(type) && Arrays.equals(up.certs, certs);
+ }
+
+ /**
+ * Returns a hash code value for this object. Following the lead of
+ * Permission, this returns the hashcode of the permission name.
+ *
+ * @return A hash value
+ */
+ public int hashCode()
+ {
+ return name.hashCode();
+ }
+
+ /**
+ * This method returns the list of actions associated with this
+ * permission.
+ *
+ * @return the action list
+ */
+ public String getActions()
+ {
+ return actions;
+ }
+
+ /**
+ * This method returns a <code>String</code> representation of this
+ * class. The format is: '(unresolved "ClassName "name" "actions")'
+ *
+ * @return <code>String</code> representation of this object
+ */
+ public String toString()
+ {
+ return "(unresolved " + type + ' ' + name + ' ' + actions + ')';
+ }
+
+ /**
+ * This class returns a <code>PermissionCollection</code> object that can
+ * be used to store instances of <code>UnresolvedPermission</code>.
+ *
+ * @return a new <code>PermissionCollection</code>
+ */
+ public PermissionCollection newPermissionCollection()
+ {
+ return new UnresolvedPermissionCollection();
+ }
+} // class UnresolvedPermission
+
+/**
+ * Implements the permission collection for unresolved permissions, and
+ * obeys serialization of JDK.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+class UnresolvedPermissionCollection extends PermissionCollection
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -7176153071733132400L;
+
+ // Package-private to avoid a trampoline.
+ /**
+ * Hashtable where we store permissions.
+ *
+ * @serial map of typename to a Vector of permissions (you'd think Sun
+ * would document this better!)
+ */
+ final Hashtable permissions = new Hashtable();
+
+ /**
+ * Add a permission.
+ *
+ * @param perm the permission to add
+ * @throws IllegalArgumentException if perm is not an UnresolvedPermission
+ * @throws SecurityException if the collection is read-only
+ */
+ public void add(Permission perm)
+ {
+ if (isReadOnly())
+ throw new SecurityException();
+ if (! (perm instanceof UnresolvedPermission))
+ throw new IllegalArgumentException();
+ UnresolvedPermission up = (UnresolvedPermission) perm;
+ Vector v = (Vector) permissions.get(up.type);
+ if (v == null)
+ {
+ v = new Vector();
+ permissions.put(up.type, v);
+ }
+ v.add(up);
+ }
+
+ /**
+ * Returns true if perm is implied by the collection.
+ *
+ * @param perm the permission to check
+ * @return false; unresolved permissions imply nothing
+ */
+ public boolean implies(Permission perm)
+ {
+ return false;
+ }
+
+ /**
+ * Return the elements.
+ *
+ * @return the elements
+ */
+ public Enumeration elements()
+ {
+ return new Enumeration()
+ {
+ Enumeration main_enum = permissions.elements();
+ Enumeration sub_enum;
+
+ public boolean hasMoreElements()
+ {
+ if (sub_enum == null)
+ {
+ if (main_enum == null)
+ return false;
+ if (! main_enum.hasMoreElements())
+ {
+ main_enum = null;
+ return false;
+ }
+ Vector v = (Vector) main_enum.nextElement();
+ sub_enum = v.elements();
+ }
+ if (! sub_enum.hasMoreElements())
+ {
+ sub_enum = null;
+ return hasMoreElements();
+ }
+ return true;
+ }
+
+ public Object nextElement()
+ {
+ if (! hasMoreElements())
+ throw new NoSuchElementException();
+ return sub_enum.nextElement();
+ }
+ };
+ }
+} // class UnresolvedPermissionCollection
diff --git a/libjava/classpath/java/security/acl/Acl.java b/libjava/classpath/java/security/acl/Acl.java
new file mode 100644
index 00000000000..ff139afd6c0
--- /dev/null
+++ b/libjava/classpath/java/security/acl/Acl.java
@@ -0,0 +1,153 @@
+/* Acl.java -- An access control list
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.acl;
+
+import java.security.Principal;
+import java.util.Enumeration;
+
+/**
+ * A Java access control list (ACL) is a group of individual ACL entries.
+ * These entries consist of a <code>Principal</code> and a list of
+ * permissions this <code>Principal</code> is either granted or denied.
+ * A given <code>Principal</code> can have at most one positive ACL entry
+ * (i.e., one that grants permissions) and one negative ACL entry (i.e., one
+ * that denies permissions). If a given permission is both granted and
+ * denied, the ACL treats it as if it were never granted or denied. If
+ * both a <code>Principal</code> and a <code>Group</code> to which the
+ * <code>Principal</code> belongs have an ACL entry, the permissions for
+ * the individual <code>Principal</code> take precedence over the
+ * permissions of the <code>Group</code> if there is a conflict.
+ * <p>
+ * Additionally, the ACL interface extends the <code>Owner</code> interface
+ * and so an ACL has owners. Actions which modify the ACL are restricted
+ * to owners.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Acl extends Owner
+{
+
+ /**
+ * This method returns the name of this ACL.
+ *
+ * @return The name of this ACL
+ */
+ String getName();
+
+ /**
+ * This method sets the name of the ACL
+ *
+ * @param caller The <code>Principal</code> requesting the action.
+ * @param name The new name for this ACL.
+ *
+ * @exception NotOwnerException If the caller is not an owner of this ACL.
+ */
+ void setName(Principal caller, String name)
+ throws NotOwnerException;
+
+ /**
+ * This method adds the specified entry to the ACL
+ *
+ * @param caller The <code>Principal</code> requesting the addition
+ * @param entry The ACL entry to add
+ *
+ * @return <code>true</code> if the entry was added, <code>false</code>
+ * if there is already an entry of the same type for the
+ * <code>Principal</code>.
+ *
+ * @exception NotOwnerException If the caller is not an owner of this ACL.
+ */
+ boolean addEntry(Principal caller, AclEntry entry)
+ throws NotOwnerException;
+
+ /**
+ * This method delets the specified entry from the ACL
+ *
+ * @param caller The <code>Principal</code> requesting the deletion.
+ * @param entry The ACL entry to delete
+ *
+ * @return <code>true</code> if the entry was deleted, or <code>false</code>
+ * if this entry was not part of the ACL to begin with
+ *
+ * @exception NotOwnerException If the caller is not an owner of this ACL.
+ */
+ boolean removeEntry(Principal caller, AclEntry entry)
+ throws NotOwnerException;
+
+ /**
+ * This method returns a list of all the entries in the ACL as an
+ * <code>Enumeration</code>.
+ *
+ * @return An enumeration of the ACL entries
+ */
+ Enumeration entries();
+
+ /**
+ * This method tests whether or not the specified <code>Principal</code>
+ * has the specified <code>Permission</code>
+ *
+ * @param user The <code>Principal</code> to test
+ * @param perm The <code>Permission</code> to test for
+ *
+ * @return <code>true</code> if the user has been granted the permission,
+ * <code>false</code> otherwise
+ */
+ boolean checkPermission(Principal user, Permission perm);
+
+ /**
+ * This method returns a list of <code>Permission</code>'s that are granted
+ * to a particular <code>Principal</code>. This includes any permissions
+ * that are granted to <code>Group</code>'s to which the <code>Principal</code>
+ * belongs unless they are overridden by a negative ACL. This permission
+ * list is returned as an <code>Enumeration</code>.
+ *
+ * @param user The <code>Principal</code> to retrieve permissions for.
+ *
+ * @return A list of permissions for the <code>Principal</code>.
+ */
+ Enumeration getPermissions(Principal user);
+
+ /**
+ * This method returns the ACL as a <code>String</code>
+ *
+ * @return A <code>String</code> representation of this ACL
+ */
+ String toString();
+}
diff --git a/libjava/classpath/java/security/acl/AclEntry.java b/libjava/classpath/java/security/acl/AclEntry.java
new file mode 100644
index 00000000000..7b1bcf54db9
--- /dev/null
+++ b/libjava/classpath/java/security/acl/AclEntry.java
@@ -0,0 +1,143 @@
+/* AclEntry.java -- An entry in an ACL list.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.acl;
+
+import java.security.Principal;
+import java.util.Enumeration;
+
+/**
+ * This interface models an entry in an access control list (ACL). Java
+ * ACL's consist of a list of entries, where each consists of a
+ * <code>Principal</code> and a list of <code>Permission</code>'s which
+ * have been granted to that <code>Principal</code>. An ACL can also
+ * be <em>negative</em>, which indicates that the list of
+ * <code>Permission</code>'s is a list of permissions that are <em>not</em>
+ * granted to the <code>Principal</code>. A <code>Principal</code> can
+ * have at most one regular (or positive) ACL entry and one negative
+ * ACL entry.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface AclEntry extends Cloneable
+{
+ /**
+ * This method returns the <code>Principal</code> associated with this
+ * ACL entry.
+ *
+ * @return The <code>Principal</code> for this ACL entry
+ */
+ Principal getPrincipal();
+
+ /**
+ * This method sets ths <code>Principal</code> associated with this
+ * ACL entry. This operation will only succeed if there is not already
+ * a <code>Principal</code> assigned.
+ *
+ * @param user The <code>Principal</code> for this ACL entry
+ *
+ * @return <code>true</code> if the <code>Principal</code> was successfully set or <code>false</code> if this entry already has a <code>Principal</code>.
+ */
+ boolean setPrincipal(Principal user);
+
+ /**
+ * This method sets this ACL entry to be a <em>negative</em> entry, indicating
+ * that it contains a list of permissions that are <em>not</em> granted
+ * to the entry's <code>Principal</code>. Note that there is no way to
+ * undo this operation.
+ */
+ void setNegativePermissions();
+
+ /**
+ * This method tests whether or not this ACL entry is a negative entry or not.
+ *
+ * @return <code>true</code> if this ACL entry is negative, <code>false</code> otherwise
+ */
+ boolean isNegative();
+
+ /**
+ * This method adds the specified permission to this ACL entry.
+ *
+ * @param perm The <code>Permission</code> to add
+ *
+ * @return <code>true</code> if the permission was added or <code>false</code> if it was already set for this entry
+ */
+ boolean addPermission(Permission permission);
+
+ /**
+ * This method deletes the specified permission to this ACL entry.
+ *
+ * @param perm The <code>Permission</code> to delete from this ACL entry.
+ *
+ * @return <code>true</code> if the permission was successfully deleted or <code>false</code> if the permission was not part of this ACL to begin with
+ */
+ boolean removePermission(Permission perm);
+
+ /**
+ * This method tests whether or not the specified permission is associated
+ * with this ACL entry.
+ *
+ * @param perm The <code>Permission</code> to test
+ *
+ * @return <code>true</code> if this permission is associated with this entry or <code>false</code> otherwise
+ */
+ boolean checkPermission(Permission permission);
+
+ /**
+ * This method returns a list of all <code>Permission</code> objects
+ * associated with this ACL entry as an <code>Enumeration</code>.
+ *
+ * @return A list of permissions for this ACL entry
+ */
+ Enumeration permissions();
+
+ /**
+ * This method returns this object as a <code>String</code>.
+ *
+ * @return A <code>String</code> representation of this object
+ */
+ String toString();
+
+ /**
+ * This method returns a clone of this ACL entry
+ *
+ * @return A clone of this ACL entry
+ */
+ Object clone();
+}
diff --git a/libjava/classpath/java/security/acl/AclNotFoundException.java b/libjava/classpath/java/security/acl/AclNotFoundException.java
new file mode 100644
index 00000000000..9a16d9c50b0
--- /dev/null
+++ b/libjava/classpath/java/security/acl/AclNotFoundException.java
@@ -0,0 +1,60 @@
+/* AclNotFoundException.java -- thrown when an ACL is not found
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.acl;
+
+/**
+ * This exception is thrown when a requested access control list (ACL) is
+ * not found.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class AclNotFoundException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5684295034092681791L;
+
+ /**
+ * Initializes a new instance of this class with no descriptive message
+ */
+ public AclNotFoundException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/security/acl/Group.java b/libjava/classpath/java/security/acl/Group.java
new file mode 100644
index 00000000000..3ffdf15a4ce
--- /dev/null
+++ b/libjava/classpath/java/security/acl/Group.java
@@ -0,0 +1,90 @@
+/* Group.java -- Represents a group of Principals
+ Copyright (C) 1998, 2001 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.security.acl;
+
+import java.security.Principal;
+import java.util.Enumeration;
+
+/**
+ * This interface represents a group of <code>Principals</code>. Note that
+ * since this interface extends <code>Principal</code>, a <code>Group</code>
+ * can be used where ever a <code>Principal</code> is requested. This
+ * includes arguments to the methods in this interface.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Group extends Principal
+{
+ /**
+ * This method adds a new <code>Principal</code> to this group.
+ *
+ * @param user The new <code>Principal</code> to add
+ *
+ * @return <code>true</code> if the user was successfully added or <code>false</code> if the user is already a member
+ */
+ boolean addMember(Principal user);
+
+ /**
+ * This method deletes a member from the group.
+ *
+ * @param user The <code>Principal</code> to delete
+ *
+ * @return <code>true</code> if the user was successfully deleted or <code>false</code> if the user is not a member of the group
+ */
+ boolean removeMember(Principal user);
+
+ /**
+ * This method tests whether or not a given <code>Principal</code> is a
+ * member of this group.
+ *
+ * @param user The <code>Principal</code> to test for membership
+ *
+ * @return <code>true</code> if the user is member, <code>false</code> otherwise
+ */
+ boolean isMember(Principal member);
+
+ /**
+ * This method returns a list of all members of the group as an
+ * <code>Enumeration</code>.
+ *
+ * @return The list of all members of the group
+ */
+ Enumeration members();
+}
diff --git a/libjava/classpath/java/security/acl/LastOwnerException.java b/libjava/classpath/java/security/acl/LastOwnerException.java
new file mode 100644
index 00000000000..95272445997
--- /dev/null
+++ b/libjava/classpath/java/security/acl/LastOwnerException.java
@@ -0,0 +1,62 @@
+/* LastOwnerException.java -- User attempted to delete last ACL owner
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.acl;
+
+/**
+ * This exception is thrown when an attempt is made to delete the last owner
+ * of an access control list (ACL)
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Owner#deleteOwner(java.security.Principal, java.security.Principal)
+ * @status updated to 1.4
+ */
+public class LastOwnerException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5141997548211140359L;
+
+ /**
+ * Initialize a new instance of <code>LastOwnerException</code> that does
+ * not have a log message.
+ */
+ public LastOwnerException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/security/acl/NotOwnerException.java b/libjava/classpath/java/security/acl/NotOwnerException.java
new file mode 100644
index 00000000000..bea94763e4b
--- /dev/null
+++ b/libjava/classpath/java/security/acl/NotOwnerException.java
@@ -0,0 +1,62 @@
+/* NotOwnerException.java -- Attempt to modify an unowned ACL
+ Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.acl;
+
+/**
+ * This exception is thrown whenever an operation is attempted that requires
+ * the caller to be the owner of the access control list (ACL) when the caller
+ * is in fact not the owner of the ACL.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class NotOwnerException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5555597911163362399L;
+
+ /**
+ * Initializes a new instance of <code>NotOwnerException</code> that does
+ * not have a descriptive message.
+ */
+ public NotOwnerException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/security/acl/Owner.java b/libjava/classpath/java/security/acl/Owner.java
new file mode 100644
index 00000000000..df1605b2e4f
--- /dev/null
+++ b/libjava/classpath/java/security/acl/Owner.java
@@ -0,0 +1,95 @@
+/* Owner.java -- ACL owner
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.acl;
+
+import java.security.Principal;
+
+/**
+ * This interface provides a mechanism for maintaining a list of owners
+ * of an access control list (ACL). Since a <code>Principal</code> must
+ * be an owner in order to modify the owner list, a mechanism must be
+ * provided to specify the initial owner of the ACL. The proper way to do
+ * this is for the implementing class to specify the initial owner in
+ * the contructor for that class.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Owner
+{
+ /**
+ * This method adds an owner to the access control list (ACL). Only a
+ * <code>Principal</code> who is already an owner can perform this operation.
+ *
+ * @param caller The <code>Principal</code> who is requesting that an owner be added
+ * @param owner The <code>Principal</code> to add as a new owner
+ *
+ * @param <code>true</code> if the new owner was successfully added or <code>false</code> if the specified new owner is already an owner
+ *
+ * @exception NotOwnerException If the caller is not already an owner of this ACL
+ */
+ boolean addOwner(Principal caller, Principal owner)
+ throws NotOwnerException;
+
+ /**
+ * This method delets an owner from the access control list (ACL). Only a
+ * <code>Principal</code> who is an owner can perform this operation. An
+ * owner can delete itself from the list. If there is only one
+ * owner remaining on this list, any attempt to delete it will throw an
+ * exception.
+ *
+ * @param caller The <code>Principal</code> who is requesting that an owner be deleted
+ * @param owner The <code>Principal</code> to delete as an owner
+ *
+ * @param <code>true</code> if the new owner was successfully deleted or <code>false</code> if the specified owner is not currently an owner
+ *
+ * @exception NotOwnerException If the caller is not already an owner of this ACL
+ * @exception LastOwnerException If completing the operation would delete the last ACL owner
+ */
+ boolean deleteOwner(Principal caller, Principal owner)
+ throws NotOwnerException, LastOwnerException;
+
+ /**
+ * This method tests whether or not a given <code>Principal</code> is an
+ * owner of this access control list (ACL).
+ *
+ * @return <code>true</code> if the <code>Principal</code> is an owner, <code>false</code> otherwise
+ */
+ boolean isOwner(Principal owner);
+}
diff --git a/libjava/classpath/java/security/acl/Permission.java b/libjava/classpath/java/security/acl/Permission.java
new file mode 100644
index 00000000000..e5ba2913890
--- /dev/null
+++ b/libjava/classpath/java/security/acl/Permission.java
@@ -0,0 +1,67 @@
+/* Permission.java -- Information about an ACL permission
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.acl;
+
+/**
+ * This interface provides information about a permission that can be
+ * granted. Note that this is <em>not</em> the same as the class
+ * <code>java.security.Permission</code>.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Permission
+{
+ /**
+ * This method tests whether or not a specified <code>Permission</code>
+ * (passed as an <code>Object</code>) is the same as this permission.
+ *
+ * @param perm The permission to check for equality
+ *
+ * @return <code>true</code> if the specified permission is the same as this one, <code>false</code> otherwise
+ */
+ boolean equals (Object perm);
+
+ /**
+ * This method returns this <code>Permission</code> as a <code>String</code>.
+ *
+ * @return A <code>String</code> representing this permission.
+ */
+ String toString();
+}
diff --git a/libjava/classpath/java/security/acl/package.html b/libjava/classpath/java/security/acl/package.html
new file mode 100644
index 00000000000..19facf190b2
--- /dev/null
+++ b/libjava/classpath/java/security/acl/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.security.acl package.
+ Copyright (C) 2002 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 - java.security.acl</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/security/cert/CRL.java b/libjava/classpath/java/security/cert/CRL.java
new file mode 100644
index 00000000000..e763663f52c
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CRL.java
@@ -0,0 +1,98 @@
+/* CRL.java --- Certificate Revocation List
+ Copyright (C) 1999 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.security.cert;
+
+/**
+ Certificate Revocation List class for managing CRLs that
+ have different formats but the same general use. They
+ all serve as lists of revoked certificates and can
+ be queried for a given certificate.
+
+ Specialized CRLs extend this class.
+
+ @author Mark Benvenuto
+
+ @since JDK 1.2
+*/
+public abstract class CRL
+{
+
+ private String type;
+
+ /**
+ Creates a new CRL for the specified type. An example
+ is "X.509".
+
+ @param type the standard name for the CRL type.
+ */
+ protected CRL(String type)
+ {
+ this.type = type;
+ }
+
+ /**
+ Returns the CRL type.
+
+ @return a string representing the CRL type
+ */
+ public final String getType()
+ {
+ return type;
+ }
+
+ /**
+ Returns a string representing the CRL.
+
+ @return a string representing the CRL.
+ */
+ public abstract String toString();
+
+ /**
+ Determines whether or not the specified Certificate
+ is revoked.
+
+ @param cert A certificate to check if it is revoked
+
+ @return true if the certificate is revoked,
+ false otherwise.
+ */
+ public abstract boolean isRevoked(Certificate cert);
+
+
+}
diff --git a/libjava/classpath/java/security/cert/CRLException.java b/libjava/classpath/java/security/cert/CRLException.java
new file mode 100644
index 00000000000..f3addfe9594
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CRLException.java
@@ -0,0 +1,73 @@
+/* CRLException.java -- Certificate Revocation List Exception
+ Copyright (C) 1999, 2002 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.security.cert;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Exception for a Certificate Revocation List.
+ *
+ * @author Mark Benvenuto
+ * @since 1.2
+ * @status updated to 1.4
+*/
+public class CRLException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -6694728944094197147L;
+
+ /**
+ * Constructs an CRLExceptionwithout a message string.
+ */
+ public CRLException()
+ {
+ }
+
+ /**
+ * Constructs an CRLException with a message string.
+ *
+ * @param msg a message to display with exception
+ */
+ public CRLException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CRLSelector.java b/libjava/classpath/java/security/cert/CRLSelector.java
new file mode 100644
index 00000000000..1fa5a207dfc
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CRLSelector.java
@@ -0,0 +1,69 @@
+/* CRLSelector.java -- matches CRLs against criteria.
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * A generic interface to classes that match certificate revocation
+ * lists (CRLs) to some given criteria. Implementations of this
+ * interface are useful for finding {@link CRL} objects in a {@link
+ * CertStore}.
+ *
+ * @see CertStore
+ * @see CertSelector
+ * @see X509CRLSelector
+ */
+public interface CRLSelector extends Cloneable
+{
+
+ /**
+ * Returns a clone of this instance.
+ *
+ * @return The clone.
+ */
+ Object clone();
+
+ /**
+ * Match a given certificate revocation list to this selector's
+ * criteria, returning true if it matches, false otherwise.
+ *
+ * @param crl The certificate revocation list to test.
+ * @return The boolean result of this test.
+ */
+ boolean match(CRL crl);
+}
diff --git a/libjava/classpath/java/security/cert/CertPath.java b/libjava/classpath/java/security/cert/CertPath.java
new file mode 100644
index 00000000000..e818763aab4
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPath.java
@@ -0,0 +1,252 @@
+/* CertPath.java -- a sequence of certificates
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.NotSerializableException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This class represents an immutable sequence, or path, of security
+ * certificates. The path type must match the type of each certificate in the
+ * path, or in other words, for all instances of cert in a certpath object,
+ * <code>cert.getType().equals(certpath.getType())</code> will return true.
+ *
+ * <p>Since this class is immutable, it is thread-safe. During serialization,
+ * the path is consolidated into a {@link CertPathRep}, which preserves the
+ * data regardless of the underlying implementation of the path.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class CertPath implements Serializable
+{
+ /**
+ * The serialized representation of a path.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ protected static class CertPathRep implements Serializable
+ {
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 3015633072427920915L;
+
+ /**
+ * The certificate type.
+ *
+ * @serial the type of the certificate path
+ */
+ private final String type;
+
+ /**
+ * The encoded form of the path.
+ *
+ * @serial the encoded form
+ */
+ private final byte[] data;
+
+ /**
+ * Create the new serial representation.
+ *
+ * @param type the path type
+ * @param data the encoded path data
+ */
+ protected CertPathRep(String type, byte[] data)
+ {
+ this.type = type;
+ this.data = data;
+ }
+
+ /**
+ * Decode the data into an actual {@link CertPath} upon deserialization.
+ *
+ * @return the replacement object
+ * @throws ObjectStreamException if replacement fails
+ */
+ protected Object readResolve() throws ObjectStreamException
+ {
+ try
+ {
+ return CertificateFactory.getInstance(type)
+ .generateCertPath(new ByteArrayInputStream(data));
+ }
+ catch (CertificateException e)
+ {
+ throw (ObjectStreamException)
+ new NotSerializableException("java.security.cert.CertPath: "
+ + type).initCause(e);
+ }
+ }
+ } // class CertPathRep
+
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 6068470306649138683L;
+
+ /**
+ * The path type.
+ *
+ * @serial the type of all certificates in this path
+ */
+ private final String type;
+
+ /**
+ * Create a certificate path with the given type. Most code should use
+ * {@link CertificateFactory} to create CertPaths.
+ *
+ * @param type the type of the path
+ */
+ protected CertPath(String type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Get the (non-null) type of all certificates in the path.
+ *
+ * @return the path certificate type
+ */
+ public String getType()
+ {
+ return type;
+ }
+
+ /**
+ * Get an immutable iterator over the path encodings (all String names),
+ * starting with the default encoding. The iterator will throw an
+ * <code>UnsupportedOperationException</code> if an attempt is made to
+ * remove items from the list.
+ *
+ * @return the iterator of supported encodings in the path
+ */
+ public abstract Iterator getEncodings();
+
+ /**
+ * Compares this path to another for semantic equality. To be equal, both
+ * must be instances of CertPath, with the same type, and identical
+ * certificate lists. Overriding classes must not change this behavior.
+ *
+ * @param o the object to compare to
+ * @return true if the two are equal
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof CertPath))
+ return false;
+ CertPath cp = (CertPath) o;
+ return type.equals(cp.type)
+ && getCertificates().equals(cp.getCertificates());
+ }
+
+ /**
+ * Returns the hashcode of this certificate path. This is defined as:<br>
+ * <code>31 * getType().hashCode() + getCertificates().hashCode()</code>.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ return 31 * type.hashCode() + getCertificates().hashCode();
+ }
+
+ public String toString()
+ {
+ List l = getCertificates();
+ int size = l.size();
+ int i = 0;
+ StringBuffer result = new StringBuffer(type);
+ result.append(" Cert Path: length = ").append(size).append(".\n[\n");
+ while (--size >= 0)
+ result.append(l.get(i++)).append('\n');
+ return result.append("\n]").toString();
+ }
+
+ /**
+ * Returns the encoded form of this path, via the default encoding.
+ *
+ * @return the encoded form
+ * @throws CertificateEncodingException if encoding fails
+ */
+ public abstract byte[] getEncoded() throws CertificateEncodingException;
+
+ /**
+ * Returns the encoded form of this path, via the specified encoding.
+ *
+ * @param encoding the encoding to use
+ * @return the encoded form
+ * @throws CertificateEncodingException if encoding fails or does not exist
+ */
+ public abstract byte[] getEncoded(String encoding)
+ throws CertificateEncodingException;
+
+ /**
+ * Returns the immutable, thread-safe list of certificates in this path.
+ *
+ * @return the list of certificates, non-null but possibly empty
+ */
+ public abstract List getCertificates();
+
+ /**
+ * Serializes the path in its encoded form, to ensure reserialization with
+ * the appropriate factory object without worrying about list implementation.
+ * The result will always be an instance of {@link CertPathRep}.
+ *
+ * @return the replacement object
+ * @throws ObjectStreamException if the replacement creation fails
+ */
+ protected Object writeReplace() throws ObjectStreamException
+ {
+ try
+ {
+ return new CertPathRep(type, getEncoded());
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw (ObjectStreamException)
+ new NotSerializableException("java.security.cert.CertPath: "
+ + type).initCause(e);
+ }
+ }
+} // class CertPath
diff --git a/libjava/classpath/java/security/cert/CertPathBuilder.java b/libjava/classpath/java/security/cert/CertPathBuilder.java
new file mode 100644
index 00000000000..f6965205f53
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathBuilder.java
@@ -0,0 +1,238 @@
+/* CertPathBuilder.java -- bulids CertPath objects from Certificates.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import gnu.java.security.Engine;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+
+/**
+ * This class builds certificate paths (also called certificate chains),
+ * which can be used to establish trust for a particular certificate by
+ * building a path from a trusted certificate (a trust anchor) to the
+ * untrusted certificate.
+ *
+ * @see CertPath
+ */
+public class CertPathBuilder
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ /** Service name for CertPathBuilder. */
+ private static final String CERT_PATH_BUILDER = "CertPathBuilder";
+
+ /** The underlying implementation. */
+ private CertPathBuilderSpi cpbSpi;
+
+ /** The provider of this implementation. */
+ private Provider provider;
+
+ /** The name of this implementation. */
+ private String algorithm;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new CertPathBuilder.
+ *
+ * @param cpbSpi The underlying implementation.
+ * @param provider The provider of the implementation.
+ * @param algorithm This implementation's name.
+ */
+ protected CertPathBuilder(CertPathBuilderSpi cpbSpi, Provider provider,
+ String algorithm)
+ {
+ this.cpbSpi = cpbSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get the default cert path builder type.
+ *
+ * <p>This value can be set at run-time by the security property
+ * <code>"certpathbuilder.type"</code>. If this property is not set,
+ * then the value returned is <code>"PKIX"</code>.
+ *
+ * @return The default CertPathBuilder algorithm.
+ */
+ public static final String getDefaultType()
+ {
+ String type = Security.getProperty("certpathbuilder.type");
+ if (type == null)
+ type = "PKIX";
+ return type;
+ }
+
+ /**
+ * Get an instance of a named CertPathBuilder, from the first provider
+ * that implements it.
+ *
+ * @param algorithm The name of the CertPathBuilder to create.
+ * @return The new instance.
+ * @throws NoSuchAlgorithmException If no installed provider
+ * implements the named algorithm.
+ */
+ public static CertPathBuilder getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignored.
+ }
+ }
+
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * Get an instance of a named CertPathBuilder from the named
+ * provider.
+ *
+ * @param algorithm The name of the CertPathBuilder to create.
+ * @param provider The name of the provider from which to get the
+ * implementation.
+ * @return The new instance.
+ * @throws NoSuchAlgorithmException If no installed provider
+ * implements the named algorithm.
+ * @throws NoSuchProviderException If the named provider does not
+ * exist.
+ */
+ public static CertPathBuilder getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ throw new NoSuchProviderException(provider);
+ return getInstance(algorithm, p);
+ }
+
+ /**
+ * 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.
+ * @return The new instance.
+ * @throws NoSuchAlgorithmException If no installed provider
+ * implements the named algorithm.
+ * @throws IllegalArgumentException If <i>provider</i> in
+ * <tt>null</tt>.
+ */
+ public static CertPathBuilder getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("null provider");
+ try
+ {
+ return new CertPathBuilder((CertPathBuilderSpi)
+ Engine.getInstance(CERT_PATH_BUILDER, algorithm, provider),
+ provider, algorithm);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Return the name of this CertPathBuilder algorithm.
+ *
+ * @return The algorithm name.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Return the provider of this instance's implementation.
+ *
+ * @return The provider.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Builds a certificate path. The {@link CertPathParameters} parameter
+ * passed to this method is implementation-specific, but in general
+ * should contain some number of certificates and some number of
+ * trusted certificates (or "trust anchors").
+ *
+ * @param params The parameters.
+ * @retrun The certificate path result.
+ * @throws CertPathBuilderException If the certificate path cannot be
+ * built.
+ * @throws InvalidAlgorithmParameterException If the implementation
+ * rejects the specified parameters.
+ */
+ public final CertPathBuilderResult build(CertPathParameters params)
+ throws CertPathBuilderException, InvalidAlgorithmParameterException
+ {
+ return cpbSpi.engineBuild(params);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertPathBuilderException.java b/libjava/classpath/java/security/cert/CertPathBuilderException.java
new file mode 100644
index 00000000000..98515101025
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathBuilderException.java
@@ -0,0 +1,159 @@
+/* CertPathBuilderException.java -- wraps an exception during certificate
+ path building
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.security.GeneralSecurityException;
+
+/**
+ * Indicates a problem while using a <code>CertPathBuilder</code>, wrapping
+ * the lower exception. This class is not thread-safe.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see CertPathBuilder
+ * @since 1.4
+ * @status updated to 1.4
+*/
+public class CertPathBuilderException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 5316471420178794402L;
+
+ /**
+ * Create an exception without a message. The cause may be initialized.
+ */
+ public CertPathBuilderException()
+ {
+ }
+
+ /**
+ * Create an exception with a message. The cause may be initialized.
+ *
+ * @param msg a message to display with exception
+ */
+ public CertPathBuilderException(String msg)
+ {
+ super(msg);
+ }
+
+ /**
+ * Create an exception with a cause. The message will be
+ * <code>cause == null ? null : cause.toString()</code>.
+ *
+ * @param cause the cause
+ */
+ public CertPathBuilderException(Throwable cause)
+ {
+ this(cause == null ? null : cause.toString(), cause);
+ }
+
+ /**
+ * Create an exception with a cause and a message.
+ *
+ * @param msg the message
+ * @param cause the cause
+ */
+ public CertPathBuilderException(String msg, Throwable cause)
+ {
+ super(msg);
+ initCause(cause);
+ }
+
+ /**
+ * Get the detail message.
+ *
+ * @return the detail message
+ */
+ public String getMessage()
+ {
+ return super.getMessage();
+ }
+
+ /**
+ * Get the cause, null if unknown.
+ *
+ * @return the cause
+ */
+ public Throwable getCause()
+ {
+ return super.getCause();
+ }
+
+ /**
+ * Convert this to a string, including its cause.
+ *
+ * @return the string conversion
+ */
+ public String toString()
+ {
+ return super.toString();
+ }
+
+ /**
+ * Print the stack trace to <code>System.err</code>.
+ */
+ public void printStackTrace()
+ {
+ super.printStackTrace();
+ }
+
+ /**
+ * Print the stack trace to a stream.
+ *
+ * @param stream the stream
+ */
+ public void printStackTrace(PrintStream stream)
+ {
+ super.printStackTrace(stream);
+ }
+
+ /**
+ * Print the stack trace to a stream.
+ *
+ * @param stream the stream
+ */
+ public void printStackTrace(PrintWriter stream)
+ {
+ super.printStackTrace(stream);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertPathBuilderResult.java b/libjava/classpath/java/security/cert/CertPathBuilderResult.java
new file mode 100644
index 00000000000..737ba9431b3
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathBuilderResult.java
@@ -0,0 +1,63 @@
+/* CertPathBuilderResult -- results from building cert paths.
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * A standard interface for the result of building a certificate path.
+ * All implementations of this class must provide a way to get the
+ * certificate path, but may also define additional methods for
+ * returning other result data generated by the certificate path
+ * builder.
+ */
+public interface CertPathBuilderResult extends Cloneable {
+
+ /**
+ * Creates a copy of this builder result.
+ *
+ * @return The copy.
+ */
+ Object clone();
+
+ /**
+ * Get the certificate path that was built.
+ *
+ * @retrn The certificate path.
+ */
+ CertPath getCertPath();
+}
diff --git a/libjava/classpath/java/security/cert/CertPathBuilderSpi.java b/libjava/classpath/java/security/cert/CertPathBuilderSpi.java
new file mode 100644
index 00000000000..afc7fc07366
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathBuilderSpi.java
@@ -0,0 +1,74 @@
+/* CertPathBuilderSpi -- CertPathBuilder service provider interface.
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * The {@link CertPathBuilder} <i>Service Provider Interface</i>
+ * (<b>SPI</b>).
+ *
+ * @see CertPathBuilder
+ */
+public abstract class CertPathBuilderSpi {
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new CertPathBuilderSpi.
+ */
+ public CertPathBuilderSpi() {
+ super();
+ }
+
+ // Abstract methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a certificate path from the specified parameters.
+ *
+ * @param params The parameters to use.
+ * @return The certificate path result.
+ * @throws CertPathBuilderException If the certificate path cannot be
+ * built.
+ * @throws java.security.InvalidAlgorithmParameterException If the
+ * implementation rejects the specified parameters.
+ */
+ public abstract CertPathBuilderResult engineBuild(CertPathParameters params)
+ throws CertPathBuilderException,
+ java.security.InvalidAlgorithmParameterException;
+}
diff --git a/libjava/classpath/java/security/cert/CertPathParameters.java b/libjava/classpath/java/security/cert/CertPathParameters.java
new file mode 100644
index 00000000000..62a5cb6a69e
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathParameters.java
@@ -0,0 +1,58 @@
+/* CertPathParameters.java -- parameters for CertPathBuilder.
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * Parameters for generating and validating certificate paths. This
+ * class does not define any methods (except a required cloneable
+ * interface) and is provided only to provide type safety for
+ * implementations. Concrete implementations implement this interface
+ * in accord with thier own needs.
+ *
+ * @see CertPathBuilder
+ * @see CertPathValidator
+ */
+public interface CertPathParameters extends Cloneable {
+
+ /**
+ * Makes a copy of this CertPathParameters instance.
+ *
+ * @return The copy.
+ */
+ Object clone();
+}
diff --git a/libjava/classpath/java/security/cert/CertPathValidator.java b/libjava/classpath/java/security/cert/CertPathValidator.java
new file mode 100644
index 00000000000..5fed19e9a78
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathValidator.java
@@ -0,0 +1,249 @@
+/* CertPathValidator -- validates certificate paths.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import gnu.java.security.Engine;
+
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.Security;
+
+/**
+ * Generic interface to classes that validate certificate paths.
+ *
+ * <p>Using this class is similar to all the provider-based security
+ * classes; the method of interest, {@link
+ * #validate(java.security.cert.CertPath,java.security.cert.CertPathParameters)},
+ * which takes provider-specific implementations of {@link
+ * CertPathParameters}, and return provider-specific implementations of
+ * {@link CertPathValidatorResult}.
+ *
+ * @since JDK 1.4
+ * @see CertPath
+ */
+public class CertPathValidator {
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ /** Service name for CertPathValidator. */
+ private static final String CERT_PATH_VALIDATOR = "CertPathValidator";
+
+ /** The underlying implementation. */
+ private final CertPathValidatorSpi validatorSpi;
+
+ /** The provider of this implementation. */
+ private final Provider provider;
+
+ /** The algorithm's name. */
+ private final String algorithm;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new CertPathValidator.
+ *
+ * @param validatorSpi The underlying implementation.
+ * @param provider The provider of the implementation.
+ * @param algorithm The algorithm name.
+ */
+ protected CertPathValidator(CertPathValidatorSpi validatorSpi,
+ Provider provider, String algorithm)
+ {
+ this.validatorSpi = validatorSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the default validator type.
+ *
+ * <p>This value may be set at run-time via the security property
+ * "certpathvalidator.type", or the value "PKIX" if this property is
+ * not set.
+ *
+ * @return The default validator type.
+ */
+ public static synchronized String getDefaultType() {
+ String type = (String) AccessController.doPrivileged(
+ new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return Security.getProperty("certpathvalidator.type");
+ }
+ }
+ );
+ if (type == null)
+ type = "PKIX";
+ return type;
+ }
+
+ /**
+ * Get 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.
+ */
+ public static CertPathValidator getInstance(String algorithm)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignored.
+ }
+ }
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+
+ /**
+ * Get 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.
+ * @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.
+ */
+ public static CertPathValidator getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ 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.
+ *
+ * @param algorithm The name of the algorithm to get.
+ * @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.
+ */
+ public static CertPathValidator getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("null provider");
+
+ try
+ {
+ return new CertPathValidator((CertPathValidatorSpi)
+ Engine.getInstance(CERT_PATH_VALIDATOR, algorithm, provider),
+ provider, algorithm);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new NoSuchAlgorithmException(algorithm);
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Return the name of this validator.
+ *
+ * @return This validator's name.
+ */
+ public final String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ /**
+ * Return the provider of this implementation.
+ *
+ * @return The provider.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Attempt to validate a certificate path.
+ *
+ * @param certPath The path to validate.
+ * @param params The algorithm-specific parameters.
+ * @return The result of this validation attempt.
+ * @throws CertPathValidatorException If the certificate path cannot
+ * be validated.
+ * @throws InvalidAlgorithmParameterException If this implementation
+ * rejects the specified parameters.
+ */
+ public final CertPathValidatorResult validate(CertPath certPath,
+ CertPathParameters params)
+ throws CertPathValidatorException, InvalidAlgorithmParameterException
+ {
+ return validatorSpi.engineValidate(certPath, params);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertPathValidatorException.java b/libjava/classpath/java/security/cert/CertPathValidatorException.java
new file mode 100644
index 00000000000..f3195be296f
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathValidatorException.java
@@ -0,0 +1,226 @@
+/* CertPathValidatorException.java -- wraps an exception during validation
+ of a CertPath
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.security.GeneralSecurityException;
+
+/**
+ * Indicates a problem while validating a certification path. In addition,
+ * it can store the path an index in that path that caused the problem. This
+ * class is not thread-safe.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see CertPathValidator
+ * @since 1.4
+ * @status updated to 1.4
+*/
+public class CertPathValidatorException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -3083180014971893139L;
+
+ /**
+ * The index of the certificate path that failed, or -1.
+ *
+ * @serial the failed index
+ */
+ private final int index;
+
+ /**
+ * The <code>CertPath</code> that failed.
+ *
+ * @serial the object being validated at time of failure
+ */
+ private final CertPath certPath;
+
+ /**
+ * Create an exception without a message. The cause may be initialized. The
+ * index is set to -1 and the failed CertPath object to null.
+ */
+ public CertPathValidatorException()
+ {
+ this((String) null);
+ }
+
+ /**
+ * Create an exception with a message. The cause may be initialized. The
+ * index is set to -1 and the failed CertPath object to null.
+ *
+ * @param msg a message to display with exception
+ */
+ public CertPathValidatorException(String msg)
+ {
+ super(msg);
+ index = -1;
+ certPath = null;
+ }
+
+ /**
+ * Create an exception with a cause. The message will be
+ * <code>cause == null ? null : cause.toString()</code>. The index is set
+ * to -1 and the failed CertPath object to null.
+ *
+ * @param cause the cause
+ */
+ public CertPathValidatorException(Throwable cause)
+ {
+ this(cause == null ? null : cause.toString(), cause, null, -1);
+ }
+
+ /**
+ * Create an exception with a cause and a message. The index is set to -1
+ * and the failed CertPath object to null.
+ *
+ * @param msg the message
+ * @param cause the cause
+ */
+ public CertPathValidatorException(String msg, Throwable cause)
+ {
+ this(msg, cause, null, -1);
+ }
+
+ /**
+ * Create an exception with a cause, message, failed object, and index of
+ * failure in that CertPath.
+ *
+ * @param msg the message
+ * @param cause the cause
+ * @param certPath the path that was being validated, or null
+ * @param index the index of the path, or -1
+ * @throws IndexOutOfBoundsException if index is &lt; -1 or
+ * &gt; certPath.getCertificates().size()
+ * @throws IllegalArgumentException if certPath is null but index != -1
+ */
+ public CertPathValidatorException(String msg, Throwable cause,
+ CertPath certPath, int index)
+ {
+ super(msg);
+ initCause(cause);
+ if (index < -1 || (certPath != null
+ && index >= certPath.getCertificates().size()))
+ throw new IndexOutOfBoundsException();
+ if ((certPath == null) != (index == -1))
+ throw new IllegalArgumentException();
+ this.certPath = certPath;
+ this.index = index;
+ }
+
+ /**
+ * Get the detail message.
+ *
+ * @return the detail message
+ */
+ public String getMessage()
+ {
+ return super.getMessage();
+ }
+
+ /**
+ * Get the certificate path that had the failure, or null.
+ *
+ * @return the culprit path
+ */
+ public CertPath getCertPath()
+ {
+ return certPath;
+ }
+
+ /**
+ * Get the index that failed, or -1.
+ *
+ * @return the colprit index
+ */
+ public int getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * Get the cause, null if unknown.
+ *
+ * @return the cause
+ */
+ public Throwable getCause()
+ {
+ return super.getCause();
+ }
+
+ /**
+ * Convert this to a string, including its cause.
+ *
+ * @return the string conversion
+ */
+ public String toString()
+ {
+ return super.toString();
+ }
+
+ /**
+ * Print the stack trace to <code>System.err</code>.
+ */
+ public void printStackTrace()
+ {
+ super.printStackTrace();
+ }
+
+ /**
+ * Print the stack trace to a stream.
+ *
+ * @param stream the stream
+ */
+ public void printStackTrace(PrintStream stream)
+ {
+ super.printStackTrace(stream);
+ }
+
+ /**
+ * Print the stack trace to a stream.
+ *
+ * @param stream the stream
+ */
+ public void printStackTrace(PrintWriter stream)
+ {
+ super.printStackTrace(stream);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertPathValidatorResult.java b/libjava/classpath/java/security/cert/CertPathValidatorResult.java
new file mode 100644
index 00000000000..71aaf89bc18
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathValidatorResult.java
@@ -0,0 +1,63 @@
+/* CertPathValidatorResult -- result of validating certificate paths
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * Interface to the result of calling {@link
+ * CertPathValidator#validate(java.security.cert.CertPath,java.security.cert.CertPathParameters)}.
+ *
+ * <p>This interface defines no methods other than the required
+ * {@link java.lang.Cloneable} interface, and is intended to group and
+ * provide type safety for validator results. Providers that implement
+ * a certificate path validator must also provide an implementation of
+ * this interface, possibly defining additional methods.
+ *
+ * @since JDK 1.4
+ * @see CertPathValidator
+ */
+public interface CertPathValidatorResult extends Cloneable
+{
+
+ /**
+ * Returns a copy of this validator result.
+ *
+ * @return The copy.
+ */
+ Object clone();
+}
diff --git a/libjava/classpath/java/security/cert/CertPathValidatorSpi.java b/libjava/classpath/java/security/cert/CertPathValidatorSpi.java
new file mode 100644
index 00000000000..8d18b49dac4
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertPathValidatorSpi.java
@@ -0,0 +1,79 @@
+/* CertPathValidatorSpi -- cert path validator service provider interface
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * The <i>service provider interface</i> (<b>SPI</b>) for the {@link
+ * CertPathValidator} class. Providers implementing certificate path
+ * validators must subclass this class and implement its abstract
+ * methods.
+ */
+public abstract class CertPathValidatorSpi
+{
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public CertPathValidatorSpi()
+ {
+ super();
+ }
+
+ // Abstract methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Attempt to validate a certificate path.
+ *
+ * @param certPath The path to validate.
+ * @param params The algorithm-specific parameters.
+ * @return The result of this validation attempt.
+ * @throws CertPathValidatorException If the certificate path cannot
+ * be validated.
+ * @throws InvalidAlgorithmParameterException If this implementation
+ * rejects the specified parameters.
+ */
+ public abstract CertPathValidatorResult
+ engineValidate(CertPath certPath, CertPathParameters params)
+ throws CertPathValidatorException,
+ java.security.InvalidAlgorithmParameterException;
+}
diff --git a/libjava/classpath/java/security/cert/CertSelector.java b/libjava/classpath/java/security/cert/CertSelector.java
new file mode 100644
index 00000000000..aea614ad95e
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertSelector.java
@@ -0,0 +1,58 @@
+/* CertSelector.java -- certificate selector interface.
+ Copyright (C) 2003 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.security.cert;
+
+public interface CertSelector extends Cloneable
+{
+
+ /**
+ * Returns a copy of this CertSelector.
+ *
+ * @return The copy.
+ */
+ Object clone();
+
+ /**
+ * Match a certificate according to this selector's criteria.
+ *
+ * @param cert The certificate to match.
+ * @return true if the certificate matches thin criteria.
+ */
+ boolean match(Certificate cert);
+}
diff --git a/libjava/classpath/java/security/cert/CertStore.java b/libjava/classpath/java/security/cert/CertStore.java
new file mode 100644
index 00000000000..864da868f19
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertStore.java
@@ -0,0 +1,294 @@
+/* CertStore -- stores and retrieves certificates.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import gnu.java.security.Engine;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Collection;
+
+/**
+ * A CertStore is a read-only repository for certificates and
+ * certificate revocation lists.
+ *
+ * @since JDK 1.4
+ */
+public class CertStore
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ /** Service name for CertStore. */
+ private static final String CERT_STORE = "CertStore";
+
+ /** The underlying implementation. */
+ private CertStoreSpi storeSpi;
+
+ /** This implementation's provider. */
+ private Provider provider;
+
+ /** The name of this key store type. */
+ private String type;
+
+ /** The parameters used to initialize this instance, if any. */
+ private CertStoreParameters params;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new CertStore.
+ *
+ * @param storeSpi The underlying implementation.
+ * @param provider The provider of this implementation.
+ * @param type The type of CertStore this class represents.
+ * @param params The parameters used to initialize this instance, if any.
+ */
+ protected CertStore(CertStoreSpi storeSpi, Provider provider, String type,
+ CertStoreParameters params)
+ {
+ this.storeSpi = storeSpi;
+ this.provider = provider;
+ this.type = type;
+ this.params = params;
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the default certificate store type.
+ *
+ * <p>This value can be set at run-time via the security property
+ * "certstore.type"; if not specified than the default type will be
+ * "LDAP".
+ *
+ * @return The default CertStore type.
+ */
+ public static final synchronized String getDefaultType()
+ {
+ String type = null;
+ type = (String) java.security.AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ return Security.getProperty("certstore.type");
+ }
+ }
+ );
+ if (type == null)
+ type = "LDAP";
+ return type;
+ }
+
+ /**
+ * Get an instance of the given certificate store from the first
+ * installed provider.
+ *
+ * @param type The type of CertStore 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.
+ */
+ public static CertStore getInstance(String type, CertStoreParameters params)
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(type, params, p[i]);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignored.
+ }
+ }
+
+ throw new NoSuchAlgorithmException(type);
+ }
+
+ /**
+ * Get an instance of the given certificate store from the 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.
+ * @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 NoSuchProviderException If no provider named
+ * <i>provider</i> is installed.
+ * @throws IllegalArgumentException If <i>provider</i> is null.
+ */
+ public static CertStore getInstance(String type, CertStoreParameters params,
+ String provider)
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
+ NoSuchProviderException
+ {
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ throw new NoSuchProviderException(provider);
+ return getInstance(type, params, p);
+ }
+
+ /**
+ * Get an instance of the given certificate store from the given
+ * provider.
+ *
+ * @param type The type of CertStore to create.
+ * @param params The parameters to initialize this cert store with.
+ * @param provider The provider from which to get the implementation.
+ * @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.
+ */
+ public static CertStore getInstance(String type, CertStoreParameters params,
+ Provider provider)
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("null provider");
+
+ try
+ {
+ return new CertStore((CertStoreSpi) Engine.getInstance(CERT_STORE,
+ type, provider, new Object[] { params }), provider, type, params);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new NoSuchAlgorithmException(type);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ Throwable cause = ite.getCause();
+ if (cause instanceof InvalidAlgorithmParameterException)
+ throw (InvalidAlgorithmParameterException) cause;
+ else
+ throw new NoSuchAlgorithmException(type);
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Return the type of certificate store this instance represents.
+ *
+ * @return The CertStore type.
+ */
+ public final String getType()
+ {
+ return type;
+ }
+
+ /**
+ * Return the provider of this implementation.
+ *
+ * @return The provider.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Get the parameters this instance was created with, if any. The
+ * parameters will be cloned before they are returned.
+ *
+ * @return The parameters, or null.
+ */
+ public final CertStoreParameters getCertStoreParameters()
+ {
+ return params != null ? (CertStoreParameters) params.clone() : null;
+ }
+
+ /**
+ * Get a collection of certificates from this CertStore, optionally
+ * filtered by the specified CertSelector. The Collection returned may
+ * be empty, but will never be null.
+ *
+ * <p>Implementations may not allow a null argument, even if no
+ * filtering is desired.
+ *
+ * @param selector The certificate selector.
+ * @return The collection of certificates.
+ * @throws CertStoreException If the certificates cannot be retrieved.
+ */
+ public final Collection getCertificates(CertSelector selector)
+ throws CertStoreException
+ {
+ return storeSpi.engineGetCertificates(selector);
+ }
+
+ /**
+ * Get a collection of certificate revocation lists from this CertStore,
+ * optionally filtered by the specified CRLSelector. The Collection
+ * returned may be empty, but will never be null.
+ *
+ * <p>Implementations may not allow a null argument, even if no
+ * filtering is desired.
+ *
+ * @param selector The certificate selector.
+ * @return The collection of certificate revocation lists.
+ * @throws CertStoreException If the CRLs cannot be retrieved.
+ */
+ public final Collection getCRLs(CRLSelector selector)
+ throws CertStoreException
+ {
+ return storeSpi.engineGetCRLs(selector);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertStoreException.java b/libjava/classpath/java/security/cert/CertStoreException.java
new file mode 100644
index 00000000000..a4d8b7a46e1
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertStoreException.java
@@ -0,0 +1,159 @@
+/* CertStoreException.java -- wraps an exception during certificate storage
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.security.GeneralSecurityException;
+
+/**
+ * Indicates a problem while retrieving certificates and CRLs from
+ * <code>CertStore</code>, wrapping the lower exception. This class is not
+ * thread-safe.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see CertStore
+ * @since 1.4
+ * @status updated to 1.4
+*/
+public class CertStoreException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 2395296107471573245L;
+
+ /**
+ * Create an exception without a message. The cause may be initialized.
+ */
+ public CertStoreException()
+ {
+ }
+
+ /**
+ * Create an exception with a message. The cause may be initialized.
+ *
+ * @param msg a message to display with exception
+ */
+ public CertStoreException(String msg)
+ {
+ super(msg);
+ }
+
+ /**
+ * Create an exception with a cause. The message will be
+ * <code>cause == null ? null : cause.toString()</code>.
+ *
+ * @param cause the cause
+ */
+ public CertStoreException(Throwable cause)
+ {
+ this(cause == null ? null : cause.toString(), cause);
+ }
+
+ /**
+ * Create an exception with a cause and a message.
+ *
+ * @param msg the message
+ * @param cause the cause
+ */
+ public CertStoreException(String msg, Throwable cause)
+ {
+ super(msg);
+ initCause(cause);
+ }
+
+ /**
+ * Get the detail message.
+ *
+ * @return the detail message
+ */
+ public String getMessage()
+ {
+ return super.getMessage();
+ }
+
+ /**
+ * Get the cause, null if unknown.
+ *
+ * @return the cause
+ */
+ public Throwable getCause()
+ {
+ return super.getCause();
+ }
+
+ /**
+ * Convert this to a string, including its cause.
+ *
+ * @return the string conversion
+ */
+ public String toString()
+ {
+ return super.toString();
+ }
+
+ /**
+ * Print the stack trace to <code>System.err</code>.
+ */
+ public void printStackTrace()
+ {
+ super.printStackTrace();
+ }
+
+ /**
+ * Print the stack trace to a stream.
+ *
+ * @param stream the stream
+ */
+ public void printStackTrace(PrintStream stream)
+ {
+ super.printStackTrace(stream);
+ }
+
+ /**
+ * Print the stack trace to a stream.
+ *
+ * @param stream the stream
+ */
+ public void printStackTrace(PrintWriter stream)
+ {
+ super.printStackTrace(stream);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertStoreParameters.java b/libjava/classpath/java/security/cert/CertStoreParameters.java
new file mode 100644
index 00000000000..aab22f01fda
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertStoreParameters.java
@@ -0,0 +1,60 @@
+/* CertStoreParameters -- interface to CertStore parameters.
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * Parameters used when creating instances of {@link CertStore}. This
+ * class does not define any methods (except a required cloneable
+ * interface) and is provided only to provide type safety for
+ * implementations. Concrete implementations implement this interface
+ * in accord with thier own needs.
+ *
+ * @see LDAPCertStoreParameters
+ * @see CollectionCertStoreParameters
+ */
+public interface CertStoreParameters extends Cloneable
+{
+
+ /**
+ * Create a copy of these parameters.
+ *
+ * @return The copy.
+ */
+ Object clone();
+}
diff --git a/libjava/classpath/java/security/cert/CertStoreSpi.java b/libjava/classpath/java/security/cert/CertStoreSpi.java
new file mode 100644
index 00000000000..eca0e866ca1
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertStoreSpi.java
@@ -0,0 +1,102 @@
+/* CertStoreSpi -- certificate store service provider interface.
+ Copyright (C) 2003 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.security.cert;
+
+import java.util.Collection;
+
+/**
+ * The <i>service provider interface</i> (<b>SPI</b>) for the {@link
+ * CertStore} class.
+ *
+ * <p>Providers wishing to implement a CertStore must subclass this
+ * class, implementing all the abstract methods. Providers may also
+ * implement the {@link CertStoreParameters} interface, if they require
+ * parameters.
+ *
+ * @since JDK 1.4
+ * @see CertStore
+ * @see CollectionCertStoreParameters
+ * @see LDAPCertStoreParameters
+ */
+public abstract class CertStoreSpi
+{
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new CertStoreSpi.
+ *
+ * @param params The parameters to initialize this instance with, or
+ * null if no parameters are required.
+ * @throws InvalidAlgorithmParameterException If the specified
+ * parameters are inappropriate for this class.
+ */
+ public CertStoreSpi(CertStoreParameters params)
+ throws java.security.InvalidAlgorithmParameterException
+ {
+ super();
+ }
+
+ // Abstract methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get the certificates from this store, filtering them through the
+ * specified CertSelector.
+ *
+ * @param selector The CertSelector to filter certificates.
+ * @return A (non-null) collection of certificates.
+ * @throws CertStoreException If the certificates cannot be retrieved.
+ */
+ public abstract Collection engineGetCertificates(CertSelector selector)
+ throws CertStoreException;
+
+ /**
+ * Get the certificate revocation list from this store, filtering them
+ * through the specified CRLSelector.
+ *
+ * @param selector The CRLSelector to filter certificate revocation
+ * lists.
+ * @return A (non-null) collection of certificate revocation list.
+ * @throws CertStoreException If the CRLs cannot be retrieved.
+ */
+ public abstract Collection engineGetCRLs(CRLSelector selector)
+ throws CertStoreException;
+}
diff --git a/libjava/classpath/java/security/cert/Certificate.java b/libjava/classpath/java/security/cert/Certificate.java
new file mode 100644
index 00000000000..f8456f97ae5
--- /dev/null
+++ b/libjava/classpath/java/security/cert/Certificate.java
@@ -0,0 +1,306 @@
+/* Certificate.java --- Certificate class
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
+import java.security.SignatureException;
+
+/**
+ * The Certificate class is an abstract class used to manage
+ * identity certificates. An identity certificate is a
+ * combination of a principal and a public key which is
+ * certified by another principal. This is the puprose of
+ * Certificate Authorities (CA).
+ *
+ * <p>This class is used to manage different types of certificates
+ * but have important common puposes. Different types of
+ * certificates like X.509 and OpenPGP share general certificate
+ * functions (like encoding and verifying) and information like
+ * public keys.
+ *
+ * <p>X.509, OpenPGP, and SDSI can be implemented by subclassing this
+ * class even though they differ in storage methods and information
+ * stored.
+ *
+ * @see CertificateFactory
+ * @see X509Certificate
+ * @since JDK 1.2
+ * @author Mark Benvenuto
+ * @author Casey Marshall
+ */
+public abstract class Certificate implements Serializable
+{
+ private static final long serialVersionUID = -6751606818319535583L;
+
+ private String type;
+
+ /**
+ Constructs a new certificate of the specified type. An example
+ is "X.509".
+
+ @param type a valid standard name for a certificate.
+ */
+ protected Certificate(String type)
+ {
+ this.type = type;
+ }
+
+ /**
+ Returns the Certificate type.
+
+ @return a string representing the Certificate type
+ */
+ public final String getType()
+ {
+ return type;
+ }
+
+ /**
+ Compares this Certificate to other. It checks if the
+ object if instanceOf Certificate and then checks if
+ the encoded form matches.
+
+ @param other An Object to test for equality
+
+ @return true if equal, false otherwise
+ */
+ public boolean equals(Object other)
+ {
+ if( other instanceof Certificate ) {
+ try {
+ Certificate x = (Certificate) other;
+ if( getEncoded().length != x.getEncoded().length )
+ return false;
+
+ byte[] b1 = getEncoded();
+ byte[] b2 = x.getEncoded();
+
+ for( int i = 0; i < b1.length; i++ )
+ if( b1[i] != b2[i] )
+ return false;
+
+ } catch( CertificateEncodingException cee ) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ Returns a hash code for this Certificate in its encoded
+ form.
+
+ @return A hash code of this class
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ Gets the DER ASN.1 encoded format for this Certificate.
+ It assumes each certificate has only one encoding format.
+ Ex: X.509 is encoded as ASN.1 DER
+
+ @return byte array containg encoded form
+
+ @throws CertificateEncodingException if an error occurs
+ */
+ public abstract byte[] getEncoded() throws CertificateEncodingException;
+
+ /**
+ Verifies that this Certificate was properly signed with the
+ PublicKey that corresponds to its private key.
+
+ @param key PublicKey to verify with
+
+ @throws CertificateException encoding error
+ @throws NoSuchAlgorithmException unsupported algorithm
+ @throws InvalidKeyException incorrect key
+ @throws NoSuchProviderException no provider
+ @throws SignatureException signature error
+ */
+ public abstract void verify(PublicKey key)
+ throws CertificateException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ NoSuchProviderException,
+ SignatureException;
+
+ /**
+ Verifies that this Certificate was properly signed with the
+ PublicKey that corresponds to its private key and uses
+ the signature engine provided by the provider.
+
+ @param key PublicKey to verify with
+ @param sigProvider Provider to use for signature algorithm
+
+ @throws CertificateException encoding error
+ @throws NoSuchAlgorithmException unsupported algorithm
+ @throws InvalidKeyException incorrect key
+ @throws NoSuchProviderException incorrect provider
+ @throws SignatureException signature error
+ */
+ public abstract void verify(PublicKey key,
+ String sigProvider)
+ throws CertificateException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ NoSuchProviderException,
+ SignatureException;
+
+ /**
+ Returns a string representing the Certificate.
+
+ @return a string representing the Certificate.
+ */
+ public abstract String toString();
+
+
+ /**
+ Returns the public key stored in the Certificate.
+
+ @return The public key
+ */
+ public abstract PublicKey getPublicKey();
+
+ // Protected methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns a replacement for this certificate to be serialized. This
+ * method returns the equivalent to the following for this class:
+ *
+ * <blockquote>
+ * <pre>new CertificateRep(getType(), getEncoded());</pre>
+ * </blockquote>
+ *
+ * <p>This thusly replaces the certificate with its name and its
+ * encoded form, which can be deserialized later with the {@link
+ * CertificateFactory} implementation for this certificate's type.
+ *
+ * @return The replacement object to be serialized.
+ * @throws ObjectStreamException If the replacement could not be
+ * created.
+ */
+ protected Object writeReplace() throws ObjectStreamException
+ {
+ try
+ {
+ return new CertificateRep(getType(), getEncoded());
+ }
+ catch (CertificateEncodingException cee)
+ {
+ throw new InvalidObjectException(cee.toString());
+ }
+ }
+
+ // Inner class.
+ // ------------------------------------------------------------------------
+
+ /**
+ Certificate.CertificateRep is an inner class used to provide an alternate
+ storage mechanism for serialized Certificates.
+ */
+ protected static class CertificateRep implements java.io.Serializable
+ {
+
+ /** From JDK1.4. */
+ private static final long serialVersionUID = -8563758940495660020L;
+
+ /** The certificate type, e.g. "X.509". */
+ private String type;
+
+ /** The encoded certificate data. */
+ private byte[] data;
+
+ /**
+ * Create an alternative representation of this certificate. The
+ * <code>(type, data)</code> pair is typically the certificate's
+ * type as returned by {@link Certificate#getType()} (i.e. the
+ * canonical name of the certificate type) and the encoded form as
+ * returned by {@link Certificate#getEncoded()}.
+ *
+ * <p>For example, X.509 certificates would create an instance of
+ * this class with the parameters "X.509" and the ASN.1
+ * representation of the certificate, encoded as DER bytes.
+ *
+ * @param type The certificate type.
+ * @param data The encoded certificate data.
+ */
+ protected CertificateRep(String type, byte[] data)
+ {
+ this.type = type;
+ this.data = data;
+ }
+
+ /**
+ * Deserialize this certificate replacement into the appropriate
+ * certificate object. That is, this method attempts to create a
+ * {@link CertificateFactory} for this certificate's type, then
+ * attempts to parse the encoded data with that factory, returning
+ * the resulting certificate.
+ *
+ * @return The deserialized certificate.
+ * @throws ObjectStreamException If there is no appropriate
+ * certificate factory for the given type, or if the encoded form
+ * cannot be parsed.
+ */
+ protected Object readResolve() throws ObjectStreamException
+ {
+ try
+ {
+ CertificateFactory fact = CertificateFactory.getInstance(type);
+ return fact.generateCertificate(new ByteArrayInputStream(data));
+ }
+ catch (Exception e)
+ {
+ throw new InvalidObjectException(e.toString());
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertificateEncodingException.java b/libjava/classpath/java/security/cert/CertificateEncodingException.java
new file mode 100644
index 00000000000..0bb0c26d358
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertificateEncodingException.java
@@ -0,0 +1,71 @@
+/* CertificateEncodingException.java -- Certificate Encoding Exception
+ Copyright (C) 1999, 2002 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.security.cert;
+
+/**
+ * Exception for a Certificate Encoding.
+ *
+ * @author Mark Benvenuto
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class CertificateEncodingException extends CertificateException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 6219492851589449162L;
+
+ /**
+ * Constructs an exception without a message string.
+ */
+ public CertificateEncodingException()
+ {
+ }
+
+ /**
+ * Constructs an exception with a message string.
+ *
+ * @param msg A message to display with exception
+ */
+ public CertificateEncodingException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertificateException.java b/libjava/classpath/java/security/cert/CertificateException.java
new file mode 100644
index 00000000000..3e075ddaf35
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertificateException.java
@@ -0,0 +1,74 @@
+/* CertificateException.java -- Certificate Exception
+ Copyright (C) 1999, 2002 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.security.cert;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Exception for a Certificate.
+ *
+ * @author Mark Benvenuto
+ * @see Certificate
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class CertificateException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 3192535253797119798L;
+
+ /**
+ * Constructs an exception without a message string.
+ */
+ public CertificateException()
+ {
+ }
+
+ /**
+ * Constructs an exception with a message string.
+ *
+ * @param msg a message to display with exception
+ */
+ public CertificateException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertificateExpiredException.java b/libjava/classpath/java/security/cert/CertificateExpiredException.java
new file mode 100644
index 00000000000..5b37142b5ec
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertificateExpiredException.java
@@ -0,0 +1,71 @@
+/* CertificateExpiredException.java --- Certificate Expired Exception
+ Copyright (C) 1999, 2002 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.security.cert;
+
+/**
+ * Exception for a Certificate Expiring.
+ *
+ * @author Mark Benvenuto
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class CertificateExpiredException extends CertificateException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 9071001339691533771L;
+
+ /**
+ * Constructs an exception without a message string.
+ */
+ public CertificateExpiredException()
+ {
+ }
+
+ /**
+ * Constructs an exception with a message string.
+ *
+ * @param msg a message to display with exception
+ */
+ public CertificateExpiredException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertificateFactory.java b/libjava/classpath/java/security/cert/CertificateFactory.java
new file mode 100644
index 00000000000..aedeff53573
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertificateFactory.java
@@ -0,0 +1,358 @@
+/* CertificateFactory.java -- Certificate Factory Class
+ Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import gnu.java.security.Engine;
+
+import java.io.InputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This class implements the CertificateFactory class interface used to
+ * generate certificates, certificate revocation lists (CRLs), and certificate
+ * paths objects from their encoded forms.
+ *
+ * @author Mark Benvenuto
+ * @author Casey Marshall
+ * @since JDK 1.2
+ * @status Fully compatible with JDK 1.4.
+ */
+public class CertificateFactory
+{
+
+ /** The service name for certificate factories. */
+ private static final String CERTIFICATE_FACTORY = "CertificateFactory";
+
+ private CertificateFactorySpi certFacSpi;
+ private Provider provider;
+ private String type;
+
+ /**
+ * Creates an instance of CertificateFactory.
+ *
+ * @param certFacSpi The underlying CertificateFactory engine.
+ * @param provider The provider of this implementation.
+ * @param type The type of Certificate this factory creates.
+ */
+ protected CertificateFactory(CertificateFactorySpi certFacSpi,
+ Provider provider, String type)
+ {
+ this.certFacSpi = certFacSpi;
+ this.provider = provider;
+ 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.
+ */
+ public static final CertificateFactory getInstance(String type)
+ throws CertificateException
+ {
+ Provider[] p = Security.getProviders();
+
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(type, p[i]);
+ }
+ catch (CertificateException e)
+ {
+ // Ignored.
+ }
+ }
+
+ 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.
+ * @throws NoSuchProviderException If the named provider is not installed.
+ */
+ public static final CertificateFactory getInstance(String type,
+ String provider)
+ throws CertificateException, NoSuchProviderException
+ {
+ Provider p = Security.getProvider(provider);
+ 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.
+ * @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.
+ */
+ public static final CertificateFactory getInstance(String type,
+ Provider provider)
+ throws CertificateException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("null provider");
+
+ try
+ {
+ return new CertificateFactory((CertificateFactorySpi)
+ Engine.getInstance(CERTIFICATE_FACTORY, type, provider),
+ provider, type);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new CertificateException(type);
+ }
+ catch (java.lang.reflect.InvocationTargetException ite)
+ {
+ throw new CertificateException(type);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new CertificateException(nsae.getMessage());
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Gets the provider of this implementation.
+ *
+ * @return The provider of this implementation.
+ */
+ public final Provider getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the type of the certificate this factory creates.
+ *
+ * @return A string with the type of certificate
+ */
+ public final String getType()
+ {
+ return type;
+ }
+
+ /**
+ * Generates a Certificate from the encoded data read
+ * from an InputStream.
+ *
+ * <p>The input stream must contain only one certificate.
+ *
+ * <p>If there exists a specialized certificate class for the
+ * certificate format handled by the certificate factory
+ * then the return Ceritificate should be a typecast of it.
+ * Ex: A X.509 CertificateFactory should return X509Certificate.
+ *
+ * <p>For X.509 certificates, the certificate in inStream must be
+ * DER encoded and supplied in binary or printable (Base64)
+ * encoding. If the certificate is in Base64 encoding, it must be
+ * bounded by -----BEGINCERTIFICATE-----, and
+ * -----END CERTIFICATE-----.
+ *
+ * @param inStream An input stream containing the certificate data.
+ * @return A certificate initialized from the decoded InputStream data.
+ * @throws CertificateException If an error occurs decoding the
+ * certificate.
+ */
+ public final Certificate generateCertificate(InputStream inStream)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertificate(inStream);
+ }
+
+ /**
+ * Returns a collection of certificates that were read from the
+ * input stream. It may be empty, have only one, or have
+ * multiple certificates.
+ *
+ * For a X.509 certificate factory, the stream may contain a
+ * single DER encoded certificate or a PKCS#7 certificate
+ * chain. This is a PKCS#7 <I>SignedData</I> object with the
+ * most significant field being <I>certificates</I>. If no
+ * CRLs are present, then an empty collection is returned.
+ *
+ * @param inStream An input stream containing the certificate data.
+ * @return A collection of certificates initialized from the decoded
+ * InputStream data.
+ * @throws CertificateException If an error occurs decoding the
+ * certificates.
+ */
+ public final Collection generateCertificates(InputStream inStream)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertificates(inStream);
+ }
+
+ /**
+ * Generates a CRL based on the encoded data read
+ * from the InputStream.
+ *
+ * <p>The input stream must contain only one CRL.
+ *
+ * <p>If there exists a specialized CRL class for the
+ * CRL format handled by the certificate factory
+ * then the return CRL should be a typecast of it.
+ * Ex: A X.509 CertificateFactory should return X509CRL.
+ *
+ * @param inStream An input stream containing the CRL data.
+ * @return A CRL initialized from the decoded InputStream data.
+ * @throws CRLException If an error occurs decoding the CRL.
+ */
+ public final CRL generateCRL(InputStream inStream)
+ throws CRLException
+ {
+ return certFacSpi.engineGenerateCRL(inStream);
+ }
+
+ /**
+ * <p>Generates CRLs based on the encoded data read
+ * from the InputStream.
+ *
+ * <p>For a X.509 certificate factory, the stream may contain a
+ * single DER encoded CRL or a PKCS#7 CRL set. This is a
+ * PKCS#7 <I>SignedData</I> object with the most significant
+ * field being <I>crls</I>. If no CRLs are present, then an
+ * empty collection is returned.
+ *
+ * @param inStream an input stream containing the CRLs.
+ * @return a collection of CRLs initialized from the decoded
+ * InputStream data.
+ * @throws CRLException If an error occurs decoding the CRLs.
+ */
+ public final Collection generateCRLs(InputStream inStream)
+ throws CRLException
+ {
+ return certFacSpi.engineGenerateCRLs( inStream );
+ }
+
+ /**
+ * Generate a {@link CertPath} and initialize it with data parsed from
+ * the input stream. The default encoding of this factory is used.
+ *
+ * @param inStream The InputStream containing the CertPath data.
+ * @return A CertPath initialized from the input stream data.
+ * @throws CertificateException If an error occurs decoding the
+ * CertPath.
+ */
+ public final CertPath generateCertPath(InputStream inStream)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertPath(inStream);
+ }
+
+ /**
+ * Generate a {@link CertPath} and initialize it with data parsed from
+ * the input stream, using the specified encoding.
+ *
+ * @param inStream The InputStream containing the CertPath data.
+ * @param encoding The encoding of the InputStream data.
+ * @return A CertPath initialized from the input stream data.
+ * @throws CertificateException If an error occurs decoding the
+ * CertPath.
+ */
+ public final CertPath generateCertPath(InputStream inStream, String encoding)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertPath(inStream, encoding);
+ }
+
+ /**
+ * Generate a {@link CertPath} and initialize it with the certificates
+ * in the {@link java.util.List} argument.
+ *
+ * @param certificates The list of certificates with which to create
+ * the CertPath.
+ * @return A CertPath initialized from the certificates.
+ * @throws CertificateException If an error occurs generating the
+ * CertPath.
+ */
+ public final CertPath generateCertPath(List certificates)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertPath(certificates);
+ }
+
+ /**
+ * Returns an Iterator of CertPath encodings supported by this
+ * factory, with the default encoding first. The returned Iterator
+ * cannot be modified.
+ *
+ * @return The Iterator of supported encodings.
+ */
+ public final Iterator getCertPathEncodings()
+ {
+ return certFacSpi.engineGetCertPathEncodings();
+ }
+} // class CertificateFactory
diff --git a/libjava/classpath/java/security/cert/CertificateFactorySpi.java b/libjava/classpath/java/security/cert/CertificateFactorySpi.java
new file mode 100644
index 00000000000..beea9646a67
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertificateFactorySpi.java
@@ -0,0 +1,225 @@
+/* CertificateFactorySpi.java --- Certificate Factory Class
+ Copyright (C) 1999,2003 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.security.cert;
+
+import java.io.InputStream;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ CertificateFactorySpi is the abstract class Service Provider
+ Interface (SPI) for the CertificateFactory class. A provider
+ must implement all the abstract methods if they wish to
+ supply a certificate factory for a particular certificate
+ type. Ex: X.509
+
+ Certificate factories are used to generate certificates and
+ certificate revocation lists (CRL) from their encoding.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+ */
+public abstract class CertificateFactorySpi
+{
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new CertificateFactorySpi
+ */
+ public CertificateFactorySpi()
+ {}
+
+ // Abstract methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ Generates a Certificate based on the encoded data read
+ from the InputStream.
+
+ The input stream must contain only one certificate.
+
+ If there exists a specialized certificate class for the
+ certificate format handled by the certificate factory
+ then the return Ceritificate should be a typecast of it.
+ Ex: A X.509 CertificateFactory should return X509Certificate.
+
+ For X.509 certificates, the certificate in inStream must be
+ DER encoded and supplied in binary or printable (Base64)
+ encoding. If the certificate is in Base64 encoding, it must be
+ bounded by -----BEGIN CERTIFICATE-----, and
+ -----END CERTIFICATE-----.
+
+ @param inStream an input stream containing the certificate data
+
+ @return a certificate initialized with InputStream data.
+
+ @throws CertificateException Certificate parsing error
+ */
+ public abstract Certificate engineGenerateCertificate(InputStream inStream)
+ throws CertificateException;
+
+ /**
+ Returns a collection of certificates that were read from the
+ input stream. It may be empty, have only one, or have
+ multiple certificates.
+
+ For a X.509 certificate factory, the stream may contain a
+ single DER encoded certificate or a PKCS#7 certificate
+ chain. This is a PKCS#7 <I>SignedData</I> object with the
+ most significant field being <I>certificates</I>. If no
+ CRLs are present, then an empty collection is returned.
+
+ @param inStream an input stream containing the certificates
+
+ @return a collection of certificates initialized with
+ the InputStream data.
+
+ @throws CertificateException Certificate parsing error
+ */
+ public abstract Collection engineGenerateCertificates(InputStream inStream)
+ throws CertificateException;
+
+ /**
+ Generates a CRL based on the encoded data read
+ from the InputStream.
+
+ The input stream must contain only one CRL.
+
+ If there exists a specialized CRL class for the
+ CRL format handled by the certificate factory
+ then the return CRL should be a typecast of it.
+ Ex: A X.509 CertificateFactory should return X509CRL.
+
+ @param inStream an input stream containing the CRL data
+
+ @return a CRL initialized with InputStream data.
+
+ @throws CRLException CRL parsing error
+ */
+ public abstract CRL engineGenerateCRL(InputStream inStream)
+ throws CRLException;
+
+ /**
+ Generates CRLs based on the encoded data read
+ from the InputStream.
+
+ For a X.509 certificate factory, the stream may contain a
+ single DER encoded CRL or a PKCS#7 CRL set. This is a
+ PKCS#7 <I>SignedData</I> object with the most significant
+ field being <I>crls</I>. If no CRLs are present, then an
+ empty collection is returned.
+
+ @param inStream an input stream containing the CRLs
+
+ @return a collection of CRLs initialized with
+ the InputStream data.
+
+ @throws CRLException CRL parsing error
+ */
+ public abstract Collection engineGenerateCRLs(InputStream inStream)
+ throws CRLException;
+
+ // 1.4 instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generate a {@link CertPath} and initialize it with data parsed from
+ * the input stream. The default encoding of this factory is used.
+ *
+ * @param inStream The InputStream containing the CertPath data.
+ * @return A CertPath initialized from the input stream data.
+ * @throws CertificateException If an error occurs decoding the
+ * CertPath.
+ */
+ public CertPath engineGenerateCertPath(InputStream inStream)
+ throws CertificateException
+ {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /**
+ * Generate a {@link CertPath} and initialize it with data parsed from
+ * the input stream, using the specified encoding.
+ *
+ * @param inStream The InputStream containing the CertPath data.
+ * @param encoding The encoding of the InputStream data.
+ * @return A CertPath initialized from the input stream data.
+ * @throws CertificateException If an error occurs decoding the
+ * CertPath.
+ */
+ public CertPath engineGenerateCertPath(InputStream inStream, String encoding)
+ throws CertificateException
+ {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /**
+ * Generate a {@link CertPath} and initialize it with the certificates
+ * in the {@link java.util.List} argument.
+ *
+ * @param certificates The list of certificates with which to create
+ * the CertPath.
+ * @return A CertPath initialized from the certificates.
+ * @throws CertificateException If an error occurs generating the
+ * CertPath.
+ */
+ public CertPath engineGenerateCertPath(List certificates)
+ throws CertificateException
+ {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /**
+ * Returns an Iterator of CertPath encodings supported by this
+ * factory, with the default encoding first. The returned Iterator
+ * cannot be modified.
+ *
+ * @return The Iterator of supported encodings.
+ */
+ public Iterator engineGetCertPathEncodings()
+ {
+ throw new UnsupportedOperationException("not implemented");
+ }
+}
+
diff --git a/libjava/classpath/java/security/cert/CertificateNotYetValidException.java b/libjava/classpath/java/security/cert/CertificateNotYetValidException.java
new file mode 100644
index 00000000000..dfb4b483785
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertificateNotYetValidException.java
@@ -0,0 +1,71 @@
+/* CertificateNotYetValidException.java -- Certificate Not Yet Valid Exception
+ Copyright (C) 1999, 2002 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.security.cert;
+
+/**
+ * Exception for a Certificate that is not yet valid.
+ *
+ * @author Mark Benvenuto
+ * @since 1.2
+ * @status updated to 1.4
+*/
+public class CertificateNotYetValidException extends CertificateException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 4355919900041064702L;
+
+ /**
+ * Constructs an exception without a message string.
+ */
+ public CertificateNotYetValidException()
+ {
+ }
+
+ /**
+ * Constructs an exception with a message string.
+ *
+ * @param msg A message to display with exception
+ */
+ public CertificateNotYetValidException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CertificateParsingException.java b/libjava/classpath/java/security/cert/CertificateParsingException.java
new file mode 100644
index 00000000000..61faa44386e
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CertificateParsingException.java
@@ -0,0 +1,71 @@
+/* CertificateParsingException.java -- Certificate Parsing Exception
+ Copyright (C) 1999, 2002 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.security.cert;
+
+/**
+ * Exception for parsing a DER-encoded Certificate.
+ *
+ * @author Mark Benvenuto
+ * @since 1.2
+ * @status updated to 1.4
+*/
+public class CertificateParsingException extends CertificateException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -7989222416793322029L;
+
+ /**
+ * Constructs an exception without a message string.
+ */
+ public CertificateParsingException()
+ {
+ }
+
+ /**
+ * Constructs an exception with a message string.
+ *
+ * @param msg a message to display with exception
+ */
+ public CertificateParsingException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/cert/CollectionCertStoreParameters.java b/libjava/classpath/java/security/cert/CollectionCertStoreParameters.java
new file mode 100644
index 00000000000..bac1e3b3e4f
--- /dev/null
+++ b/libjava/classpath/java/security/cert/CollectionCertStoreParameters.java
@@ -0,0 +1,121 @@
+/* CollectionCertStoreParameters -- collection-based cert store parameters
+ Copyright (C) 2003 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.security.cert;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * An implementation of {@link CertStoreParameters} with a simple,
+ * in-memory {@link Collection} of certificates and certificate
+ * revocation list.
+ *
+ * <p>Note that this class is not thread-safe, and its underlying
+ * collection may be changed at any time.
+ *
+ * @see CertStore
+ */
+public class CollectionCertStoreParameters implements CertStoreParameters
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ /** The underlying collection. */
+ private final Collection collection;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new CollectionCertStoreParameters with an empty,
+ * immutable collection.
+ */
+ public CollectionCertStoreParameters()
+ {
+ this(Collections.EMPTY_LIST);
+ }
+
+ /**
+ * Create a new CollectionCertStoreParameters with the specified
+ * collection. The argument is not copied, and subsequent changes to
+ * the collection will change this class's collection.
+ *
+ * @param collection The collection.
+ * @throws NullPointerException If <i>collection</i> is null.
+ */
+ public CollectionCertStoreParameters(Collection collection)
+ {
+ if (collection == null)
+ throw new NullPointerException();
+ this.collection = collection;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new CollectionCertStoreParameters(new ArrayList(collection));
+ }
+
+ /**
+ * Return the underlying collection. The collection is not copied
+ * before being returned, so callers may update the collection that is
+ * returned.
+ *
+ * @return The collection.
+ */
+ public Collection getCollection()
+ {
+ return collection;
+ }
+
+ /**
+ * Return a string representation of these parameters.
+ *
+ * @return The string representation of these parameters.
+ */
+ public String toString()
+ {
+ return "CollectionCertStoreParameters: [ collection: "
+ + collection + " ]";
+ }
+}
diff --git a/libjava/classpath/java/security/cert/LDAPCertStoreParameters.java b/libjava/classpath/java/security/cert/LDAPCertStoreParameters.java
new file mode 100644
index 00000000000..4414e65a092
--- /dev/null
+++ b/libjava/classpath/java/security/cert/LDAPCertStoreParameters.java
@@ -0,0 +1,140 @@
+/* LDAPCertStoreParameters.java -- LDAP CertStore parameters.
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * Parameters for CertStores that are retrieved via the <i>lightweight
+ * directory access protocol</i> (<b>LDAP</b>).
+ *
+ * @see CertStore
+ */
+public class LDAPCertStoreParameters implements CertStoreParameters
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ /** The default LDAP port. */
+ private static final int LDAP_PORT = 389;
+
+ /** The server name. */
+ private final String serverName;
+
+ /** The LDAP port. */
+ private final int port;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new LDAPCertStoreParameters object, with a servername of
+ * "localhost" and a port of 389.
+ */
+ public LDAPCertStoreParameters()
+ {
+ this("localhost", LDAP_PORT);
+ }
+
+ /**
+ * Create a new LDAPCertStoreParameters object, with a specified
+ * server name and a port of 389.
+ *
+ * @param serverName The LDAP server name.
+ * @throws NullPointerException If <i>serverName</i> is null.
+ */
+ public LDAPCertStoreParameters(String serverName)
+ {
+ this(serverName, LDAP_PORT);
+ }
+
+ /**
+ * Create a new LDAPCertStoreParameters object, with a specified
+ * server name and port.
+ *
+ * @param serverName The LDAP server name.
+ * @param port The LDAP port.
+ * @throws NullPointerException If <i>serverName</i> is null.
+ */
+ public LDAPCertStoreParameters(String serverName, int port)
+ {
+ if (serverName == null)
+ throw new NullPointerException();
+ this.serverName = serverName;
+ this.port = port;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new LDAPCertStoreParameters(serverName, port);
+ }
+
+ /**
+ * Return the server name.
+ *
+ * @return The server name.
+ */
+ public String getServerName()
+ {
+ return serverName;
+ }
+
+ /**
+ * Return the port.
+ *
+ * @return the port.
+ */
+ public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Return a string representation of these parameters.
+ *
+ * @return The string representation of these parameters.
+ */
+ public String toString()
+ {
+ return "LDAPCertStoreParameters: [ serverName: " + serverName
+ + "; port: " + port + " ]";
+ }
+}
diff --git a/libjava/classpath/java/security/cert/PKIXBuilderParameters.java b/libjava/classpath/java/security/cert/PKIXBuilderParameters.java
new file mode 100644
index 00000000000..38b3df5e78a
--- /dev/null
+++ b/libjava/classpath/java/security/cert/PKIXBuilderParameters.java
@@ -0,0 +1,145 @@
+/* PKIXBuilderParameters.java -- parameters for PKIX cert path builders
+ Copyright (C) 2003 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.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+
+import java.util.Set;
+
+/**
+ * Parameters for building certificate paths using the PKIX algorithm.
+ *
+ * @see CertPathBuilder
+ */
+public class PKIXBuilderParameters extends PKIXParameters
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The maximum path length. */
+ private int maxPathLength;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new PKIXBuilderParameters object, populating the trusted
+ * certificates set with all X.509 certificates found in the given key
+ * store. All certificates found in the key store are assumed to be
+ * trusted by this constructor.
+ *
+ * @param keystore The key store.
+ * @param targetConstraints The target certificate constraints.
+ * @throws KeyStoreException If the certificates cannot be retrieved
+ * from the key store.
+ * @throws InvalidAlgorithmParameterException If there are no
+ * certificates in the key store.
+ * @throws NullPointerException If <i>keystore</i> is null.
+ */
+ public PKIXBuilderParameters(KeyStore keystore,
+ CertSelector targetConstraints)
+ throws KeyStoreException, InvalidAlgorithmParameterException
+ {
+ super(keystore);
+ setTargetCertConstraints(targetConstraints);
+ maxPathLength = 5;
+ }
+
+ /**
+ * Create a new PKIXBuilderParameters object, populating the trusted
+ * certificates set with the elements of the given set, each of which
+ * must be a {@link TrustAnchor}.
+ *
+ * @param trustAnchors The set of trust anchors.
+ * @param targetConstraints The target certificate constraints.
+ * @throws InvalidAlgorithmParameterException If there are no
+ * certificates in the set.
+ * @throws NullPointerException If <i>trustAnchors</i> is null.
+ * @throws ClassCastException If every element in <i>trustAnchors</i>
+ * is not a {@link TrustAnchor}.
+ */
+ public PKIXBuilderParameters(Set trustAnchors, CertSelector targetConstraints)
+ throws InvalidAlgorithmParameterException
+ {
+ super(trustAnchors);
+ setTargetCertConstraints(targetConstraints);
+ maxPathLength = 5;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the maximum length of certificate paths to build.
+ *
+ * <p>If this value is 0 it is taken to mean that the certificate path
+ * should contain only one certificate. A value of -1 means that the
+ * certificate path length is unconstrained. The default value is 5.
+ *
+ * @return The maximum path length.
+ */
+ public int getMaxPathLength()
+ {
+ return maxPathLength;
+ }
+
+ /**
+ * Sets the maximum length of certificate paths to build.
+ *
+ * @param maxPathLength The new path length.
+ * @throws IllegalArgumentException If <i>maxPathLength</i> is less
+ * than -1.
+ */
+ public void setMaxPathLength(int maxPathLength)
+ {
+ if (maxPathLength < -1)
+ throw new IllegalArgumentException();
+ this.maxPathLength = maxPathLength;
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer(super.toString());
+ buf.insert(buf.length() - 2, "; Max Path Length=" + maxPathLength);
+ return buf.toString();
+ }
+}
diff --git a/libjava/classpath/java/security/cert/PKIXCertPathBuilderResult.java b/libjava/classpath/java/security/cert/PKIXCertPathBuilderResult.java
new file mode 100644
index 00000000000..5091dd41298
--- /dev/null
+++ b/libjava/classpath/java/security/cert/PKIXCertPathBuilderResult.java
@@ -0,0 +1,102 @@
+/* PKIXCertPathBuilderResult.java -- PKIX cert path bulider result
+ Copyright (C) 2003 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.security.cert;
+
+/**
+ * The result of calling the {@link
+ * CertPathBuilder#build(java.security.cert.CertPathParameters)} method
+ * of PKIX {@link CertPathBuilder}s.
+ *
+ * @see CertPathBuilder
+ * @see CertPathBuilderResult
+ */
+public class PKIXCertPathBuilderResult extends PKIXCertPathValidatorResult
+ implements CertPathBuilderResult
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The certificate path. */
+ private CertPath certPath;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new PKIXCertPathBuilderResult.
+ *
+ * @param certPath The certificate path.
+ * @param trustAnchor The trust anchor.
+ * @param policyTree The root node of the policy tree.
+ * @param subjectPublicKey The public key.
+ * @throws NullPointerException If <i>certPath</i>, <i>trustAnchor</i> or
+ * <i>subjectPublicKey</i> is null.
+ */
+ public PKIXCertPathBuilderResult(CertPath certPath,
+ TrustAnchor trustAnchor,
+ PolicyNode policyTree,
+ java.security.PublicKey subjectPublicKey)
+ {
+ super(trustAnchor, policyTree, subjectPublicKey);
+ if (certPath == null)
+ throw new NullPointerException();
+ this.certPath = certPath;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the certificate path that was built.
+ *
+ * @return The certificate path that was built.
+ */
+ public CertPath getCertPath()
+ {
+ return certPath;
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer(super.toString());
+ buf.insert(buf.length() - 2, "; CertPath=" + certPath);
+ return buf.toString();
+ }
+}
diff --git a/libjava/classpath/java/security/cert/PKIXCertPathChecker.java b/libjava/classpath/java/security/cert/PKIXCertPathChecker.java
new file mode 100644
index 00000000000..7a33576e1bb
--- /dev/null
+++ b/libjava/classpath/java/security/cert/PKIXCertPathChecker.java
@@ -0,0 +1,133 @@
+/* PKIXCertPathChecker.java -- checks X.509 certificate paths.
+ Copyright (C) 2003 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.security.cert;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * A validator for X.509 certificates when approving certificate chains.
+ *
+ * <p>Concrete subclasses can be passed to the {@link
+ * PKIXParameters#setCertPathCheckers(java.util.List)} and {@link
+ * PKIXParameters#addCertPathChecker(java.security.cert.PKIXCertPathChecker}
+ * methods, which are then used to set up PKIX certificate chain
+ * builders or validators. These classes then call the {@link
+ * #check(java.security.cert.Certificate,java.util.Collection)} method
+ * of this class, performing whatever checks on the certificate,
+ * throwing an exception if any check fails.
+ *
+ * <p>Subclasses of this must be able to perform their checks in the
+ * backward direction -- from the most-trusted certificate to the target
+ * -- and may optionally support forward checking -- from the target to
+ * the most-trusted certificate.
+ *
+ * @see PKIXParameters
+ */
+public abstract class PKIXCertPathChecker implements Cloneable
+{
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /** Default constructor. */
+ protected PKIXCertPathChecker()
+ {
+ super();
+ }
+
+ // Cloneable interface.
+ // ------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ throw new InternalError(cnse.getMessage());
+ }
+ }
+
+ // Abstract methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Initialize this PKIXCertPathChecker. If subclasses support forward
+ * checking, a value of true can be passed to this method, and
+ * certificates can be validated from the target certificate to the
+ * most-trusted certifcate.
+ *
+ * @param forward The direction of this PKIXCertPathChecker.
+ * @throws CertPathValidatorException If <i>forward</i> is true and
+ * this class does not support forward checking.
+ */
+ public abstract void init(boolean forward) throws CertPathValidatorException;
+
+ /**
+ * Returns whether or not this class supports forward checking.
+ *
+ * @return Whether or not this class supports forward checking.
+ */
+ public abstract boolean isForwardCheckingSupported();
+
+ /**
+ * Returns an immutable set of X.509 extension object identifiers (OIDs)
+ * supported by this PKIXCertPathChecker.
+ *
+ * @return An immutable set of Strings of the supported X.509 OIDs, or
+ * null if no extensions are supported.
+ */
+ public abstract Set getSupportedExtensions();
+
+ /**
+ * Checks a certificate, removing any critical extensions that are
+ * resolved in this check.
+ *
+ * @param cert The certificate to check.
+ * @param unresolvedCritExts The (mutable) collection of as-of-yet
+ * unresolved critical extensions, as OID strings.
+ * @throws CertPathValidatorException If this certificate fails this
+ * check.
+ */
+ public abstract void check(Certificate cert, Collection unresolvedCritExts)
+ throws CertPathValidatorException;
+}
diff --git a/libjava/classpath/java/security/cert/PKIXCertPathValidatorResult.java b/libjava/classpath/java/security/cert/PKIXCertPathValidatorResult.java
new file mode 100644
index 00000000000..5a1660c3bc9
--- /dev/null
+++ b/libjava/classpath/java/security/cert/PKIXCertPathValidatorResult.java
@@ -0,0 +1,142 @@
+/* PKIXCertPathValidatorResult.java -- PKIX cert path builder result
+ Copyright (C) 2003 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.security.cert;
+
+import java.security.PublicKey;
+
+/**
+ * Results returned by the {@link
+ * CertPathValidator#validate(java.security.cert.CertPath,java.security.cert.CertPathParameters)}
+ * method for PKIX {@link CertPathValidator}s.
+ *
+ * @see CertPathValidator
+ */
+public class PKIXCertPathValidatorResult implements CertPathValidatorResult
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The trust anchor. */
+ private final TrustAnchor trustAnchor;
+
+ /** The root node of the policy tree. */
+ private final PolicyNode policyTree;
+
+ /** The subject's public key. */
+ private final PublicKey subjectPublicKey;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new PKIXCertPathValidatorResult.
+ *
+ * @param trustAnchor The trust anchor.
+ * @param policyTree The root node of the policy tree.
+ * @param subjectPublicKey The public key.
+ * @throws NullPointerException If either <i>trustAnchor</i> or
+ * <i>subjectPublicKey</i> is null.
+ */
+ public PKIXCertPathValidatorResult(TrustAnchor trustAnchor,
+ PolicyNode policyTree,
+ PublicKey subjectPublicKey)
+ {
+ if (trustAnchor == null || subjectPublicKey == null)
+ throw new NullPointerException();
+ this.trustAnchor = trustAnchor;
+ this.policyTree = policyTree;
+ this.subjectPublicKey = subjectPublicKey;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the trust anchor.
+ *
+ * @return The trust anchor.
+ */
+ public TrustAnchor getTrustAnchor()
+ {
+ return trustAnchor;
+ }
+
+ /**
+ * Returns the root node of the policy tree.
+ *
+ * @return The root node of the policy tree.
+ */
+ public PolicyNode getPolicyTree()
+ {
+ return policyTree;
+ }
+
+ /**
+ * Returns the subject public key.
+ *
+ * @return The subject public key.
+ */
+ public PublicKey getPublicKey()
+ {
+ return subjectPublicKey;
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return The copy.
+ */
+ public Object clone()
+ {
+ return new PKIXCertPathValidatorResult(trustAnchor, policyTree,
+ subjectPublicKey);
+ }
+
+ /**
+ * Returns a printable string representation of this result.
+ *
+ * @return A printable string representation of this result.
+ */
+ public String toString()
+ {
+ return "[ Trust Anchor=" + trustAnchor + "; Policy Tree="
+ + policyTree + "; Subject Public Key=" + subjectPublicKey + " ]";
+ }
+}
diff --git a/libjava/classpath/java/security/cert/PKIXParameters.java b/libjava/classpath/java/security/cert/PKIXParameters.java
new file mode 100644
index 00000000000..4a987115a29
--- /dev/null
+++ b/libjava/classpath/java/security/cert/PKIXParameters.java
@@ -0,0 +1,546 @@
+/* PKIXParameters.java -- parameters for the PKIX cert path algorithm
+ Copyright (C) 2003 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.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Parameters for verifying certificate paths using the PKIX
+ * (Public-Key Infrastructure (X.509)) algorithm.
+ *
+ * @see CertPathBulider
+ */
+public class PKIXParameters implements CertPathParameters
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The trusted certificates. */
+ private final Set trustAnchors;
+
+ /** The set of initial policy identifiers. */
+ private final Set initPolicies;
+
+ /** The list of certificate stores. */
+ private final List certStores;
+
+ /** The list of path checkers. */
+ private final List pathCheckers;
+
+ /** The revocation enabled flag. */
+ private boolean revocationEnabled;
+
+ /** The explicit policy required flag. */
+ private boolean exPolicyRequired;
+
+ /** The policy mapping inhibited flag. */
+ private boolean policyMappingInhibited;
+
+ /** The any policy inhibited flag. */
+ private boolean anyPolicyInhibited;
+
+ /** The policy qualifiers rejected flag. */
+ private boolean policyQualRejected;
+
+ /** The target validation date. */
+ private Date date;
+
+ /** The signature algorithm provider. */
+ private String sigProvider;
+
+ /** The target constraints. */
+ private CertSelector targetConstraints;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new PKIXParameters object, populating the trusted
+ * certificates set with all certificates found in the given key
+ * store. All certificates found in the key store are assumed to be
+ * trusted by this constructor.
+ *
+ * @param keystore The key store.
+ * @throws KeyStoreException If the certificates cannot be retrieved
+ * from the key store.
+ * @throws InvalidAlgorithmParameterException If there are no
+ * certificates in the key store.
+ * @throws NullPointerException If <i>keystore</i> is null.
+ */
+ public PKIXParameters(KeyStore keystore)
+ throws KeyStoreException, InvalidAlgorithmParameterException
+ {
+ this();
+ for (Enumeration e = keystore.aliases(); e.hasMoreElements(); )
+ {
+ String alias = (String) e.nextElement();
+ if (!keystore.isCertificateEntry(alias))
+ continue;
+ Certificate cert = keystore.getCertificate(alias);
+ if (cert instanceof X509Certificate)
+ trustAnchors.add(new TrustAnchor((X509Certificate) cert, null));
+ }
+ if (trustAnchors.isEmpty())
+ throw new InvalidAlgorithmParameterException("no certs in the key store");
+ }
+
+ /**
+ * Create a new PKIXParameters object, populating the trusted
+ * certificates set with the elements of the given set, each of which
+ * must be a {@link TrustAnchor}.
+ *
+ * @param trustAnchors The set of trust anchors.
+ * @throws InvalidAlgorithmParameterException If there are no
+ * certificates in the set.
+ * @throws NullPointerException If <i>trustAnchors</i> is null.
+ * @throws ClassCastException If every element in <i>trustAnchors</i>
+ * is not a {@link TrustAnchor}.
+ */
+ public PKIXParameters(Set trustAnchors)
+ throws InvalidAlgorithmParameterException
+ {
+ this();
+ setTrustAnchors(trustAnchors);
+ }
+
+ /**
+ * Default constructor.
+ */
+ private PKIXParameters()
+ {
+ trustAnchors = new HashSet();
+ initPolicies = new HashSet();
+ certStores = new LinkedList();
+ pathCheckers = new LinkedList();
+ revocationEnabled = true;
+ exPolicyRequired = false;
+ policyMappingInhibited = false;
+ anyPolicyInhibited = false;
+ policyQualRejected = true;
+ }
+
+ /**
+ * Copying constructor for cloning.
+ *
+ * @param that The instance being cloned.
+ */
+ private PKIXParameters(PKIXParameters that)
+ {
+ this();
+ this.trustAnchors.addAll(that.trustAnchors);
+ this.initPolicies.addAll(that.initPolicies);
+ this.certStores.addAll(that.certStores);
+ this.pathCheckers.addAll(that.pathCheckers);
+ this.revocationEnabled = that.revocationEnabled;
+ this.exPolicyRequired = that.exPolicyRequired;
+ this.policyMappingInhibited = that.policyMappingInhibited;
+ this.anyPolicyInhibited = that.anyPolicyInhibited;
+ this.policyQualRejected = that.policyQualRejected;
+ this.date = that.date;
+ this.sigProvider = that.sigProvider;
+ this.targetConstraints = that.targetConstraints != null
+ ? (CertSelector) that.targetConstraints.clone() : null;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns an immutable set of trust anchors. The set returned will
+ * never be null and will never be empty.
+ *
+ * @return A (never null, never empty) immutable set of trust anchors.
+ */
+ public Set getTrustAnchors()
+ {
+ return Collections.unmodifiableSet(trustAnchors);
+ }
+
+ /**
+ * Sets the trust anchors of this class, replacing the current trust
+ * anchors with those in the given set. The supplied set is copied to
+ * prevent modification.
+ *
+ * @param trustAnchors The new set of trust anchors.
+ * @throws InvalidAlgorithmParameterException If there are no
+ * certificates in the set.
+ * @throws NullPointerException If <i>trustAnchors</i> is null.
+ * @throws ClassCastException If every element in <i>trustAnchors</i>
+ * is not a {@link TrustAnchor}.
+ */
+ public void setTrustAnchors(Set trustAnchors)
+ throws InvalidAlgorithmParameterException
+ {
+ if (trustAnchors.isEmpty())
+ throw new InvalidAlgorithmParameterException("no trust anchors");
+ this.trustAnchors.clear();
+ for (Iterator i = trustAnchors.iterator(); i.hasNext(); )
+ {
+ this.trustAnchors.add((TrustAnchor) i.next());
+ }
+ }
+
+ /**
+ * Returns the set of initial policy identifiers (as OID strings). If
+ * any policy is accepted, this method returns the empty set.
+ *
+ * @return An immutable set of initial policy OID strings, or the
+ * empty set if any policy is acceptable.
+ */
+ public Set getInitialPolicies()
+ {
+ return Collections.unmodifiableSet(initPolicies);
+ }
+
+ /**
+ * Sets the initial policy identifiers (as OID strings). If the
+ * argument is null or the empty set, then any policy identifier will
+ * be accepted.
+ *
+ * @param initPolicies The new set of policy strings, or null.
+ * @throws ClassCastException If any element in <i>initPolicies</i> is
+ * not a string.
+ */
+ public void setInitialPolicies(Set initPolicies)
+ {
+ this.initPolicies.clear();
+ if (initPolicies == null)
+ return;
+ for (Iterator i = initPolicies.iterator(); i.hasNext(); )
+ {
+ this.initPolicies.add((String) i.next());
+ }
+ }
+
+ /**
+ * Add a {@link CertStore} to the list of cert stores.
+ *
+ * @param store The CertStore to add.
+ */
+ public void addCertStore(CertStore store)
+ {
+ if (store != null)
+ certStores.add(store);
+ }
+
+ /**
+ * Returns an immutable list of cert stores. This method never returns
+ * null.
+ *
+ * @return The list of cert stores.
+ */
+ public List getCertStores()
+ {
+ return Collections.unmodifiableList(certStores);
+ }
+
+ /**
+ * Set the cert stores. If the argument is null the list of cert
+ * stores will be empty.
+ *
+ * @param certStores The cert stores.
+ */
+ public void setCertStores(List certStores)
+ {
+ this.certStores.clear();
+ if (certStores == null)
+ return;
+ for (Iterator i = certStores.iterator(); i.hasNext(); )
+ {
+ this.certStores.add((CertStore) i.next());
+ }
+ }
+
+ /**
+ * Returns the value of the <i>revocation enabled</i> flag. The default
+ * value for this flag is <code>true</code>.
+ *
+ * @return The <i>revocation enabled</i> flag.
+ */
+ public boolean isRevocationEnabled()
+ {
+ return revocationEnabled;
+ }
+
+ /**
+ * Sets the value of the <i>revocation enabled</i> flag.
+ *
+ * @param value The new value.
+ */
+ public void setRevocationEnabled(boolean value)
+ {
+ revocationEnabled = value;
+ }
+
+ /**
+ * Returns the value of the <i>explicit policy required</i> flag. The
+ * default value of this flag is <code>false</code>.
+ *
+ * @return The <i>explicit policy required</i> flag.
+ */
+ public boolean isExplicitPolicyRequired()
+ {
+ return exPolicyRequired;
+ }
+
+ /**
+ * Sets the value of the <i>explicit policy required</i> flag.
+ *
+ * @param value The new value.
+ */
+ public void setExplicitPolicyRequired(boolean value)
+ {
+ exPolicyRequired = value;
+ }
+
+ /**
+ * Returns the value of the <i>policy mapping inhibited</i> flag. The
+ * default value of this flag is <code>false</code>.
+ *
+ * @return The <i>policy mapping inhibited</i> flag.
+ */
+ public boolean isPolicyMappingInhibited()
+ {
+ return policyMappingInhibited;
+ }
+
+ /**
+ * Sets the value of the <i>policy mapping inhibited</i> flag.
+ *
+ * @param value The new value.
+ */
+ public void setPolicyMappingInhibited(boolean value)
+ {
+ policyMappingInhibited = value;
+ }
+
+ /**
+ * Returns the value of the <i>any policy inhibited</i> flag. The
+ * default value of this flag is <code>false</code>.
+ *
+ * @return The <i>any policy inhibited</i> flag.
+ */
+ public boolean isAnyPolicyInhibited()
+ {
+ return anyPolicyInhibited;
+ }
+
+ /**
+ * Sets the value of the <i>any policy inhibited</i> flag.
+ *
+ * @param value The new value.
+ */
+ public void setAnyPolicyInhibited(boolean value)
+ {
+ anyPolicyInhibited = value;
+ }
+
+ /**
+ * Returns the value of the <i>policy qualifiers enabled</i> flag. The
+ * default value of this flag is <code>true</code>.
+ *
+ * @return The <i>policy qualifiers enabled</i> flag.
+ */
+ public boolean getPolicyQualifiersRejected()
+ {
+ return policyQualRejected;
+ }
+
+ /**
+ * Sets the value of the <i>policy qualifiers enabled</i> flag.
+ *
+ * @param value The new value.
+ */
+ public void setPolicyQualifiersRejected(boolean value)
+ {
+ policyQualRejected = value;
+ }
+
+ /**
+ * Returns the date for which the certificate path should be
+ * validated, or null if the current time should be used. The date
+ * object is copied to prevent subsequent modification.
+ *
+ * @return The date, or null if not set.
+ */
+ public Date getDate()
+ {
+ return date != null ? (Date) date.clone() : null;
+ }
+
+ /**
+ * Sets the date for which the certificate path should be validated,
+ * or null if the current time should be used.
+ *
+ * @param date The new date, or null.
+ */
+ public void setDate(Date date)
+ {
+ if (date != null)
+ this.date = (Date) date.clone();
+ else
+ this.date = null;
+ }
+
+ /**
+ * Add a certificate path checker.
+ *
+ * @param checker The certificate path checker to add.
+ */
+ public void addCertPathChecker(PKIXCertPathChecker checker)
+ {
+ if (checker != null)
+ pathCheckers.add(checker);
+ }
+
+ /**
+ * Returns an immutable list of all certificate path checkers.
+ *
+ * @return An immutable list of all certificate path checkers.
+ */
+ public List getCertPathCheckers()
+ {
+ return Collections.unmodifiableList(pathCheckers);
+ }
+
+ /**
+ * Sets the certificate path checkers. If the argument is null, the
+ * list of checkers will merely be cleared.
+ *
+ * @param pathCheckers The new list of certificate path checkers.
+ * @throws ClassCastException If any element of <i>pathCheckers</i> is
+ * not a {@link PKIXCertPathChecker}.
+ */
+ public void setCertPathCheckers(List pathCheckers)
+ {
+ this.pathCheckers.clear();
+ if (pathCheckers == null)
+ return;
+ for (Iterator i = pathCheckers.iterator(); i.hasNext(); )
+ {
+ this.pathCheckers.add((PKIXCertPathChecker) i.next());
+ }
+ }
+
+ /**
+ * Returns the signature algorithm provider, or null if not set.
+ *
+ * @return The signature algorithm provider, or null if not set.
+ */
+ public String getSigProvider()
+ {
+ return sigProvider;
+ }
+
+ /**
+ * Sets the signature algorithm provider, or null if there is no
+ * preferred provider.
+ *
+ * @param sigProvider The signature provider name.
+ */
+ public void setSigProvider(String sigProvider)
+ {
+ this.sigProvider = sigProvider;
+ }
+
+ /**
+ * Returns the constraints placed on the target certificate, or null
+ * if there are none. The target constraints are copied to prevent
+ * subsequent modification.
+ *
+ * @return The target constraints, or null.
+ */
+ public CertSelector getTargetCertConstraints()
+ {
+ return targetConstraints != null
+ ? (CertSelector) targetConstraints.clone() : null;
+ }
+
+ /**
+ * Sets the constraints placed on the target certificate.
+ *
+ * @param targetConstraints The target constraints.
+ */
+ public void setTargetCertConstraints(CertSelector targetConstraints)
+ {
+ this.targetConstraints = targetConstraints != null
+ ? (CertSelector) targetConstraints.clone() : null;
+ }
+
+ /**
+ * Returns a copy of these parameters.
+ *
+ * @return The copy.
+ */
+ public Object clone()
+ {
+ return new PKIXParameters(this);
+ }
+
+ /**
+ * Returns a printable representation of these parameters.
+ *
+ * @return A printable representation of these parameters.
+ */
+ public String toString() {
+ return "[ Trust Anchors: " + trustAnchors + "; Initial Policy OIDs="
+ + (initPolicies != null ? initPolicies.toString() : "any")
+ + "; Validity Date=" + date + "; Signature Provider="
+ + sigProvider + "; Default Revocation Enabled=" + revocationEnabled
+ + "; Explicit Policy Required=" + exPolicyRequired
+ + "; Policy Mapping Inhibited=" + policyMappingInhibited
+ + "; Any Policy Inhibited=" + anyPolicyInhibited
+ + "; Policy Qualifiers Rejected=" + policyQualRejected
+ + "; Target Cert Contstraints=" + targetConstraints
+ + "; Certification Path Checkers=" + pathCheckers
+ + "; CertStores=" + certStores + " ]";
+ }
+}
diff --git a/libjava/classpath/java/security/cert/PolicyNode.java b/libjava/classpath/java/security/cert/PolicyNode.java
new file mode 100644
index 00000000000..58d411cd3ad
--- /dev/null
+++ b/libjava/classpath/java/security/cert/PolicyNode.java
@@ -0,0 +1,102 @@
+/* PolicyNode.java -- a single node in a policy tree
+ Copyright (C) 2003 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.security.cert;
+
+public interface PolicyNode
+{
+
+ /**
+ * Get the iterator of the child nodes of this node. The returned
+ * iterator is (naturally) unmodifiable.
+ *
+ * @return An iterator over the child nodes.
+ */
+ java.util.Iterator getChildren();
+
+ /**
+ * Get the depth of this node within the tree, starting at 0 for the
+ * root node.
+ *
+ * @return The depth of this node.
+ */
+ int getDepth();
+
+ /**
+ * Returns a set of policies (string OIDs) that will satisfy this
+ * node's policy. The root node should always return the singleton set
+ * with the element "any-policy".
+ *
+ * @return The set of expected policies.
+ */
+ java.util.Set getExpectedPolicies();
+
+ /**
+ * Returns the parent node of this node, or null if this is the root
+ * node.
+ *
+ * @return The parent node, or null.
+ */
+ PolicyNode getParent();
+
+ /**
+ * Returns a set of {@link PolicyQualifierInfo} objects that qualify
+ * the valid policy of this node. The root node should always return
+ * the empty set.
+ *
+ * @return The set of {@link PolicyQualifierInfo} objects.
+ */
+ java.util.Set getPolicyQualifiers();
+
+ /**
+ * Get the policy OID this node represents. The root node should return
+ * the special value "any-policy".
+ *
+ * @return The policy of this node.
+ */
+ String getValidPolicy();
+
+ /**
+ * Return the criticality flag of this policy node. Nodes who return
+ * true for this method should be considered critical. The root node
+ * is never critical.
+ *
+ * @return The criticality flag.
+ */
+ boolean isCritical();
+}
diff --git a/libjava/classpath/java/security/cert/PolicyQualifierInfo.java b/libjava/classpath/java/security/cert/PolicyQualifierInfo.java
new file mode 100644
index 00000000000..7dcf2315632
--- /dev/null
+++ b/libjava/classpath/java/security/cert/PolicyQualifierInfo.java
@@ -0,0 +1,168 @@
+/* PolicyQualifierInfo.java -- policy qualifier info object.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import gnu.java.io.ASN1ParsingException;
+import gnu.java.security.OID;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+/**
+ * The PolicyQualifierInfo X.509 certificate extension.
+ * PolicyQualifierInfo objects are represented by the ASN.1 structure:
+ *
+ * <pre>
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId
+ * }
+ *
+ * PolicyQualifierId ::= OBJECT IDENTIFIER
+ * </pre>
+ *
+ * @since JDK 1.4
+ */
+public final class PolicyQualifierInfo
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The <code>policyQualifierId</code> field. */
+ private OID oid;
+
+ /** The DER encoded form of this object. */
+ private byte[] encoded;
+
+ /** The DER encoded form of the <code>qualifier</code> field. */
+ private DERValue qualifier;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new PolicyQualifierInfo object from the DER encoded form
+ * passed in the byte array. The argument is copied.
+ *
+ * <p>The ASN.1 form of PolicyQualifierInfo is:
+<pre>
+PolicyQualifierInfo ::= SEQUENCE {
+ policyQualifierId PolicyQualifierId,
+ qualifier ANY DEFINED BY policyQualifierId
+}
+
+PolicyQualifierId ::= OBJECT IDENTIFIER
+</pre>
+ *
+ * @param encoded The DER encoded form.
+ * @throws IOException If the structure cannot be parsed from the
+ * encoded bytes.
+ */
+ public PolicyQualifierInfo(byte[] encoded) throws IOException
+ {
+ if (encoded == null)
+ throw new IOException("null bytes");
+ this.encoded = (byte[]) encoded.clone();
+ DERReader in = new DERReader(new ByteArrayInputStream(this.encoded));
+ DERValue qualInfo = in.read();
+ if (!qualInfo.isConstructed())
+ throw new ASN1ParsingException("malformed PolicyQualifierInfo");
+ DERValue val = in.read();
+ if (!(val.getValue() instanceof OID))
+ throw new ASN1ParsingException("value read not an OBJECT IDENTIFIER");
+ oid = (OID) val.getValue();
+ if (val.getEncodedLength() < val.getLength())
+ qualifier = in.read();
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the <code>policyQualifierId</code> field of this structure,
+ * as a dotted-decimal representation of the object identifier.
+ *
+ * @return This structure's OID field.
+ */
+ public String getPolicyQualifierId()
+ {
+ return oid.toString();
+ }
+
+ /**
+ * Returns the DER encoded form of this object; the contents of the
+ * returned byte array are equivalent to those that were passed to the
+ * constructor. The byte array is cloned every time this method is
+ * called.
+ *
+ * @return The encoded form.
+ */
+ public byte[] getEncoded()
+ {
+ return (byte[]) encoded.clone();
+ }
+
+ /**
+ * Get the <code>qualifier</code> field of this object, as a DER
+ * encoded byte array. The byte array returned is cloned every time
+ * this method is called.
+ *
+ * @return The encoded qualifier.
+ */
+ public byte[] getPolicyQualifier()
+ {
+ if (qualifier == null)
+ return new byte[0];
+ return qualifier.getEncoded();
+ }
+
+ /**
+ * Returns a printable string representation of this object.
+ *
+ * @return The string representation.
+ */
+ public String toString()
+ {
+ return "PolicyQualifierInfo { policyQualifierId ::= " + oid
+ + ", qualifier ::= " + qualifier + " }";
+ }
+}
diff --git a/libjava/classpath/java/security/cert/TrustAnchor.java b/libjava/classpath/java/security/cert/TrustAnchor.java
new file mode 100644
index 00000000000..2110ed5181d
--- /dev/null
+++ b/libjava/classpath/java/security/cert/TrustAnchor.java
@@ -0,0 +1,185 @@
+/* TrustAnchor.java -- an ultimately-trusted certificate.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import gnu.java.security.x509.X500DistinguishedName;
+
+import java.security.PublicKey;
+
+/**
+ * An ultimately-trusted certificate to serve as the root of a
+ * certificate chain.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public class TrustAnchor
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The certificate authority's distinguished name. */
+ private final X500DistinguishedName caName;
+
+ /** The certficate authority's public key. */
+ private final PublicKey caKey;
+
+ /** The certficate authority's certificate. */
+ private final X509Certificate trustedCert;
+
+ /** The encoded name constraints bytes. */
+ private final byte[] nameConstraints;
+
+ // Constnuctors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new trust anchor from a certificate and (optional) name
+ * constraints.
+ *
+ * <p>If the <i>nameConstraints</i> argument in non-null, it will be
+ * copied to prevent modification.
+ *
+ * @param trustedCert The trusted certificate.
+ * @param nameConstraints The encoded nameConstraints.
+ */
+ public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints)
+ {
+ if (trustedCert == null)
+ throw new NullPointerException();
+ this.trustedCert = trustedCert;
+ caName = null;
+ caKey = null;
+ if (nameConstraints != null)
+ this.nameConstraints = (byte[]) nameConstraints.clone();
+ else
+ this.nameConstraints = null;
+ }
+
+ /**
+ * Create a new trust anchor from a certificate authority's
+ * distinguished name, public key, and (optional) name constraints.
+ *
+ * <p>If the <i>nameConstraints</i> argument in non-null, it will be
+ * copied to prevent modification.
+ *
+ * @params caName The CA's distinguished name.
+ * @params caKey The CA's public key.
+ * @params nameConstraints The encoded nameConstraints.
+ */
+ public TrustAnchor(String caName, PublicKey caKey, byte[] nameConstraints)
+ {
+ if (caName == null || caKey == null)
+ throw new NullPointerException();
+ if (caName.length() == 0)
+ throw new IllegalArgumentException();
+ trustedCert = null;
+ this.caName = new X500DistinguishedName(caName);
+ this.caKey = caKey;
+ if (nameConstraints != null)
+ this.nameConstraints = (byte[]) nameConstraints.clone();
+ else
+ this.nameConstraints = null;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Return the trusted certificate, or null if none was specified.
+ *
+ * @return The trusted certificate.
+ */
+ public final X509Certificate getTrustedCert()
+ {
+ return trustedCert;
+ }
+
+ /**
+ * Return the certificate authority's distinguished name, or null if
+ * none was specified.
+ *
+ * @return The CA's distinguished name.
+ */
+ public final String getCAName()
+ {
+ if (caName != null)
+ return caName.toString();
+ return null;
+ }
+
+ /**
+ * Return the certificate authority's public key, or null if none was
+ * specified.
+ *
+ * @return The CA's public key.
+ */
+ public final PublicKey getCAPublicKey()
+ {
+ return caKey;
+ }
+
+ /**
+ * Return the encoded name constraints, or null if none was specified.
+ *
+ * <p>The name constraints byte array is copied when this method is
+ * called to prevent modification.
+ *
+ * @return The encoded name constraints.
+ */
+ public final byte[] getNameConstraints()
+ {
+ if (nameConstraints == null)
+ return null;
+ return (byte[]) nameConstraints.clone();
+ }
+
+ /**
+ * Return a printable representation of this trust anchor.
+ *
+ * @return The printable representation.
+ */
+ public String toString()
+ {
+ if (trustedCert == null)
+ return "[ Trusted CA Public Key=" + caKey + ", Trusted CA Issuer Name="
+ + caName.toString() + " ]";
+ return "[ Trusted CA Certificate=" + trustedCert + " ]";
+ }
+}
diff --git a/libjava/classpath/java/security/cert/X509CRL.java b/libjava/classpath/java/security/cert/X509CRL.java
new file mode 100644
index 00000000000..5657b3eb3f5
--- /dev/null
+++ b/libjava/classpath/java/security/cert/X509CRL.java
@@ -0,0 +1,397 @@
+/* X509CRL.java --- X.509 Certificate Revocation List
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.util.Date;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ The X509CRL class is the abstract class used to manage
+ X.509 Certificate Revocation Lists. The CRL is a list of
+ time stamped entries which indicate which lists have been
+ revoked. The list is signed by a Certificate Authority (CA)
+ and made publically available in a repository.
+
+ Each revoked certificate in the CRL is identified by its
+ certificate serial number. When a piece of code uses a
+ certificate, the certificates validity is checked by
+ validating its signature and determing that it is not
+ only a recently acquired CRL. The recently aquired CRL
+ is depends on the local policy in affect. The CA issues
+ a new CRL periodically and entries are removed as the
+ certificate expiration date is reached
+
+
+ A description of the X.509 v2 CRL follows below from rfc2459.
+
+ "The X.509 v2 CRL syntax is as follows. For signature calculation,
+ the data that is to be signed is ASN.1 DER encoded. ASN.1 DER
+ encoding is a tag, length, value encoding system for each element.
+
+ CertificateList ::= SEQUENCE {
+ tbsCertList TBSCertList,
+ signatureAlgorithm AlgorithmIdentifier,
+ signatureValue BIT STRING }
+
+ TBSCertList ::= SEQUENCE {
+ version Version OPTIONAL,
+ -- if present, shall be v2
+ signature AlgorithmIdentifier,
+ issuer Name,
+ thisUpdate Time,
+ nextUpdate Time OPTIONAL,
+ revokedCertificates SEQUENCE OF SEQUENCE {
+ userCertificate CertificateSerialNumber,
+ revocationDate Time,
+ crlEntryExtensions Extensions OPTIONAL
+ -- if present, shall be v2
+ } OPTIONAL,
+ crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ -- if present, shall be v2
+ }"
+
+ @author Mark Benvenuto
+
+ @since JDK 1.2
+*/
+public abstract class X509CRL extends CRL implements X509Extension
+{
+
+ /**
+ Constructs a new X509CRL.
+ */
+ protected X509CRL()
+ {
+ super("X.509");
+ }
+
+ /**
+ Compares this X509CRL to other. It checks if the
+ object if instanceOf X509CRL and then checks if
+ the encoded form matches.
+
+ @param other An Object to test for equality
+
+ @return true if equal, false otherwise
+ */
+ public boolean equals(Object other)
+ {
+ if( other instanceof X509CRL ) {
+ try {
+ X509CRL x = (X509CRL) other;
+ if( getEncoded().length != x.getEncoded().length )
+ return false;
+
+ byte[] b1 = getEncoded();
+ byte[] b2 = x.getEncoded();
+
+ for( int i = 0; i < b1.length; i++ )
+ if( b1[i] != b2[i] )
+ return false;
+
+ } catch( CRLException crle ) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ Returns a hash code for this X509CRL in its encoded
+ form.
+
+ @return A hash code of this class
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ Gets the DER ASN.1 encoded format for this X.509 CRL.
+
+ @return byte array containg encoded form
+
+ @throws CRLException if an error occurs
+ */
+ public abstract byte[] getEncoded() throws CRLException;
+
+ /**
+ Verifies that this CRL was properly signed with the
+ PublicKey that corresponds to its private key.
+
+ @param key PublicKey to verify with
+
+ @throws CRLException encoding error
+ @throws NoSuchAlgorithmException unsupported algorithm
+ @throws InvalidKeyException incorrect key
+ @throws NoSuchProviderException no provider
+ @throws SignatureException signature error
+ */
+ public abstract void verify(PublicKey key)
+ throws CRLException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ NoSuchProviderException,
+ SignatureException;
+
+ /**
+ Verifies that this CRL was properly signed with the
+ PublicKey that corresponds to its private key and uses
+ the signature engine provided by the provider.
+
+ @param key PublicKey to verify with
+ @param sigProvider Provider to use for signature algorithm
+
+ @throws CRLException encoding error
+ @throws NoSuchAlgorithmException unsupported algorithm
+ @throws InvalidKeyException incorrect key
+ @throws NoSuchProviderException incorrect provider
+ @throws SignatureException signature error
+ */
+ public abstract void verify(PublicKey key,
+ String sigProvider)
+ throws CRLException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ NoSuchProviderException,
+ SignatureException;
+
+ /**
+ Gets the version of this CRL.
+
+ The ASN.1 encoding is:
+
+ version Version OPTIONAL,
+ -- if present, shall be v2
+
+ Version ::= INTEGER { v1(0), v2(1), v3(2) }
+
+ Consult rfc2459 for more information.
+
+ @return the version number, Ex: 1 or 2
+ */
+ public abstract int getVersion();
+
+ /**
+ Returns the issuer (issuer distinguished name) of the CRL.
+ The issuer is the entity who signed and issued the
+ Certificate Revocation List.
+
+ The ASN.1 DER encoding is:
+
+ issuer Name,
+
+ Name ::= CHOICE {
+ RDNSequence }
+
+ RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+ RelativeDistinguishedName ::=
+ SET OF AttributeTypeAndValue
+
+ AttributeTypeAndValue ::= SEQUENCE {
+ type AttributeType,
+ value AttributeValue }
+
+ AttributeType ::= OBJECT IDENTIFIER
+
+ AttributeValue ::= ANY DEFINED BY AttributeType
+
+ DirectoryString ::= CHOICE {
+ teletexString TeletexString (SIZE (1..MAX)),
+ printableString PrintableString (SIZE (1..MAX)),
+ universalString UniversalString (SIZE (1..MAX)),
+ utf8String UTF8String (SIZE (1.. MAX)),
+ bmpString BMPString (SIZE (1..MAX)) }
+
+ Consult rfc2459 for more information.
+
+ @return the issuer in the Principal class
+ */
+ public abstract Principal getIssuerDN();
+
+ /**
+ Returns the thisUpdate date of the CRL.
+
+ The ASN.1 DER encoding is:
+
+ thisUpdate Time,
+
+ Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime }
+
+ Consult rfc2459 for more information.
+
+ @return the thisUpdate date
+ */
+ public abstract Date getThisUpdate();
+
+ /*
+ Gets the nextUpdate field
+
+ The ASN.1 DER encoding is:
+
+ nextUpdate Time OPTIONAL,
+
+ Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime }
+
+ Consult rfc2459 for more information.
+
+ @return the nextUpdate date
+ */
+ public abstract Date getNextUpdate();
+
+ /**
+ Gets the requeste dX509Entry for the specified
+ certificate serial number.
+
+ @return a X509CRLEntry representing the X.509 CRL entry
+ */
+ public abstract X509CRLEntry getRevokedCertificate(BigInteger serialNumber);
+
+ /**
+ Returns a Set of revoked certificates.
+
+ @return a set of revoked certificates.
+ */
+ public abstract Set getRevokedCertificates();
+
+ /**
+ Returns the DER ASN.1 encoded tbsCertList which is
+ the basic information of the list and associated certificates
+ in the encoded state. See top for more information.
+
+ The ASN.1 DER encoding is:
+
+ tbsCertList TBSCertList,
+
+ Consult rfc2459 for more information.
+
+ @return byte array representing tbsCertList
+ */
+ public abstract byte[] getTBSCertList() throws CRLException;
+
+
+ /**
+ Returns the signature for the CRL.
+
+ The ASN.1 DER encoding is:
+
+ signatureValue BIT STRING
+
+ Consult rfc2459 for more information.
+ */
+ public abstract byte[] getSignature();
+
+ /**
+ Returns the signature algorithm used to sign the CRL.
+ An examples is "SHA-1/DSA".
+
+ The ASN.1 DER encoding is:
+
+ signatureAlgorithm AlgorithmIdentifier,
+
+ AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters ANY DEFINED BY algorithm OPTIONAL }
+
+ Consult rfc2459 for more information.
+
+ The algorithm name is determined from the OID.
+
+ @return a string with the signature algorithm name
+ */
+ public abstract String getSigAlgName();
+
+ /**
+ Returns the OID for the signature algorithm used.
+ Example "1.2.840.10040.4.3" is return for SHA-1 with DSA.\
+
+ The ASN.1 DER encoding for the example is:
+
+ id-dsa-with-sha1 ID ::= {
+ iso(1) member-body(2) us(840) x9-57 (10040)
+ x9cm(4) 3 }
+
+ Consult rfc2459 for more information.
+
+ @return a string containing the OID.
+ */
+ public abstract String getSigAlgOID();
+
+ /**
+ Returns the AlgorithmParameters in the encoded form
+ for the signature algorithm used.
+
+ If access to the parameters is need, create an
+ instance of AlgorithmParameters.
+
+ @return byte array containing algorithm parameters, null
+ if no parameters are present in CRL
+ */
+ public abstract byte[] getSigAlgParams();
+
+ // 1.4 instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the X.500 distinguished name of this CRL's issuer.
+ *
+ * @return The issuer's X.500 distinguished name.
+ * @since JDK 1.4
+ */
+ public X500Principal getIssuerX500Principal()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/libjava/classpath/java/security/cert/X509CRLEntry.java b/libjava/classpath/java/security/cert/X509CRLEntry.java
new file mode 100644
index 00000000000..4c9cada4747
--- /dev/null
+++ b/libjava/classpath/java/security/cert/X509CRLEntry.java
@@ -0,0 +1,169 @@
+/* X509CRLEntry.java --- X.509 Certificate Revocation List Entry
+ Copyright (C) 1999 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.security.cert;
+
+import java.math.BigInteger;
+import java.util.Date;
+
+/**
+ Abstract class for entries in the CRL (Certificate Revocation
+ List). The ASN.1 definition for <I>revokedCertificates</I> is
+
+ revokedCertificates SEQUENCE OF SEQUENCE {
+ userCertificate CertificateSerialNumber,
+ revocationDate Time,
+ crlEntryExtensions Extensions OPTIONAL
+ -- if present, shall be v2
+ } OPTIONAL,
+
+ CertificateSerialNumber ::= INTEGER
+
+ Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime }
+
+ Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+
+ Extension ::= SEQUENCE {
+ extnID OBJECT IDENTIFIER,
+ critical BOOLEAN DEFAULT FALSE,
+ extnValue OCTET STRING }
+
+ For more information consult rfc2459.
+
+ @author Mark Benvenuto
+
+ @since JDK 1.2
+*/
+public abstract class X509CRLEntry implements X509Extension
+{
+
+ /**
+ Creates a new X509CRLEntry
+ */
+ public X509CRLEntry()
+ {}
+
+ /**
+ Compares this X509CRLEntry to other. It checks if the
+ object if instanceOf X509CRLEntry and then checks if
+ the encoded form( the inner SEQUENCE) matches.
+
+ @param other An Object to test for equality
+
+ @return true if equal, false otherwise
+ */
+ public boolean equals(Object other)
+ {
+ if( other instanceof X509CRLEntry ) {
+ try {
+ X509CRLEntry xe = (X509CRLEntry) other;
+ if( getEncoded().length != xe.getEncoded().length )
+ return false;
+
+ byte[] b1 = getEncoded();
+ byte[] b2 = xe.getEncoded();
+
+ for( int i = 0; i < b1.length; i++ )
+ if( b1[i] != b2[i] )
+ return false;
+
+ } catch( CRLException crle ) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ Returns a hash code for this X509CRLEntry in its encoded
+ form.
+
+ @return A hash code of this class
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ Gets the DER ASN.1 encoded format for this CRL Entry,
+ the inner SEQUENCE.
+
+ @return byte array containg encoded form
+
+ @throws CRLException if an error occurs
+ */
+ public abstract byte[] getEncoded() throws CRLException;
+
+ /**
+ Gets the serial number for <I>userCertificate</I> in
+ this X509CRLEntry.
+
+ @return the serial number for this X509CRLEntry.
+ */
+ public abstract BigInteger getSerialNumber();
+
+
+ /**
+ Gets the revocation date in <I>revocationDate</I> for
+ this X509CRLEntry.
+
+ @return the revocation date for this X509CRLEntry.
+ */
+ public abstract Date getRevocationDate();
+
+
+ /**
+ Checks if this X509CRLEntry has extensions.
+
+ @return true if it has extensions, false otherwise
+ */
+ public abstract boolean hasExtensions();
+
+
+ /**
+ Returns a string that represents this X509CRLEntry.
+
+ @return a string representing this X509CRLEntry.
+ */
+ public abstract String toString();
+
+}
diff --git a/libjava/classpath/java/security/cert/X509CRLSelector.java b/libjava/classpath/java/security/cert/X509CRLSelector.java
new file mode 100644
index 00000000000..3c79fba9cb8
--- /dev/null
+++ b/libjava/classpath/java/security/cert/X509CRLSelector.java
@@ -0,0 +1,440 @@
+/* X509CRLSelector.java -- selects X.509 CRLs by criteria.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import gnu.classpath.SystemProperties;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * A class for matching X.509 certificate revocation lists by criteria.
+ *
+ * <p>Use of this class requires extensive knowledge of the Internet
+ * Engineering Task Force's Public Key Infrastructure (X.509). The primary
+ * document describing this standard is <a
+ * href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
+ * Public Key Infrastructure Certificate and Certificate Revocation List
+ * (CRL) Profile</a>.
+ *
+ * <p>Note that this class is not thread-safe. If multiple threads will
+ * use or modify this class then they need to synchronize on the object.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class X509CRLSelector implements CRLSelector, Cloneable
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private static final String CRL_NUMBER_ID = "2.5.29.20";
+
+ private List issuerNames;
+ private BigInteger maxCrlNumber;
+ private BigInteger minCrlNumber;
+ private Date date;
+ private X509Certificate cert;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a new CRL selector with no criteria enabled; i.e., every CRL
+ * will be matched.
+ */
+ public X509CRLSelector()
+ {
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Add an issuer name to the set of issuer names criteria, as the DER
+ * encoded form.
+ *
+ * @param name The name to add, as DER bytes.
+ * @throws IOException If the argument is not a valid DER-encoding.
+ */
+ public void addIssuerName(byte[] name) throws IOException
+ {
+ X500Principal p = null;
+ try
+ {
+ p = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed name");
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ if (issuerNames == null)
+ issuerNames = new LinkedList();
+ issuerNames.add(p);
+ }
+
+ /**
+ * Add an issuer name to the set of issuer names criteria, as a
+ * String representation.
+ *
+ * @param name The name to add.
+ * @throws IOException If the argument is not a valid name.
+ */
+ public void addIssuerName(String name) throws IOException
+ {
+ X500Principal p = null;
+ try
+ {
+ p = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed name: " + name);
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ if (issuerNames == null)
+ issuerNames = new LinkedList();
+ issuerNames.add(p);
+ }
+
+ /**
+ * Sets the issuer names criterion. Pass <code>null</code> to clear this
+ * value. CRLs matched by this selector must have an issuer name in this
+ * set.
+ *
+ * @param names The issuer names.
+ * @throws IOException If any of the elements in the collection is not
+ * a valid name.
+ */
+ public void setIssuerNames(Collection names) throws IOException
+ {
+ if (names == null)
+ {
+ issuerNames = null;
+ return;
+ }
+ List l = new ArrayList(names.size());
+ for (Iterator it = names.iterator(); it.hasNext(); )
+ {
+ Object o = it.next();
+ if (o instanceof X500Principal)
+ l.add(o);
+ else if (o instanceof String)
+ {
+ try
+ {
+ l.add(new X500Principal((String) o));
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed name: " + o);
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ }
+ else if (o instanceof byte[])
+ {
+ try
+ {
+ l.add(new X500Principal((byte[]) o));
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed name");
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ }
+ else if (o instanceof InputStream)
+ {
+ try
+ {
+ l.add(new X500Principal((InputStream) o));
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed name");
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ }
+ else
+ throw new IOException("not a valid name: " +
+ (o != null ? o.getClass().getName() : "null"));
+
+ }
+ issuerNames = l;
+ }
+
+ /**
+ * Returns the set of issuer names that are matched by this selector,
+ * or <code>null</code> if this criteria is not set. The returned
+ * collection is not modifiable.
+ *
+ * @return The set of issuer names.
+ */
+ public Collection getIssuerNames()
+ {
+ if (issuerNames != null)
+ return Collections.unmodifiableList(issuerNames);
+ else
+ return null;
+ }
+
+ /**
+ * Returns the maximum value of the CRLNumber extension present in
+ * CRLs matched by this selector, or <code>null</code> if this
+ * criteria is not set.
+ *
+ * @return The maximum CRL number.
+ */
+ public BigInteger getMaxCRL()
+ {
+ return maxCrlNumber;
+ }
+
+ /**
+ * Returns the minimum value of the CRLNumber extension present in
+ * CRLs matched by this selector, or <code>null</code> if this
+ * criteria is not set.
+ *
+ * @return The minimum CRL number.
+ */
+ public BigInteger getMinCRL()
+ {
+ return minCrlNumber;
+ }
+
+ /**
+ * Sets the maximum value of the CRLNumber extension present in CRLs
+ * matched by this selector. Specify <code>null</code> to clear this
+ * criterion.
+ *
+ * @param maxCrlNumber The maximum CRL number.
+ */
+ public void setMaxCRLNumber(BigInteger maxCrlNumber)
+ {
+ this.maxCrlNumber = maxCrlNumber;
+ }
+
+ /**
+ * Sets the minimum value of the CRLNumber extension present in CRLs
+ * matched by this selector. Specify <code>null</code> to clear this
+ * criterion.
+ *
+ * @param minCrlNumber The minimum CRL number.
+ */
+ public void setMinCRLNumber(BigInteger minCrlNumber)
+ {
+ this.minCrlNumber = minCrlNumber;
+ }
+
+ /**
+ * Returns the date when this CRL must be valid; that is, the date
+ * must be after the thisUpdate date, but before the nextUpdate date.
+ * Returns <code>null</code> if this criterion is not set.
+ *
+ * @return The date.
+ */
+ public Date getDateAndTime()
+ {
+ return date != null ? (Date) date.clone() : null;
+ }
+
+ /**
+ * Sets the date at which this CRL must be valid. Specify
+ * <code>null</code> to clear this criterion.
+ *
+ * @param date The date.
+ */
+ public void setDateAndTime(Date date)
+ {
+ this.date = date != null ? (Date) date.clone() : null;
+ }
+
+ /**
+ * Returns the certificate being checked, or <code>null</code> if this
+ * value is not set.
+ *
+ * @return The certificate.
+ */
+ public X509Certificate getCertificateChecking()
+ {
+ return cert;
+ }
+
+ /**
+ * Sets the certificate being checked. This is not a criterion, but
+ * info used by certificate store implementations to aid in searching.
+ *
+ * @param cert The certificate.
+ */
+ public void setCertificateChecking(X509Certificate cert)
+ {
+ this.cert = cert;
+ }
+
+ /**
+ * Returns a string representation of this selector. The string will
+ * only describe the enabled criteria, so if none are enabled this will
+ * return a string that contains little else besides the class name.
+ *
+ * @return The string.
+ */
+ public String toString()
+ {
+ StringBuffer str = new StringBuffer(X509CRLSelector.class.getName());
+ String nl = SystemProperties.getProperty("line.separator");
+ String eol = ";" + nl;
+
+ str.append(" {").append(nl);
+ if (issuerNames != null)
+ str.append(" issuer names = ").append(issuerNames).append(eol);
+ if (maxCrlNumber != null)
+ str.append(" max CRL = ").append(maxCrlNumber).append(eol);
+ if (minCrlNumber != null)
+ str.append(" min CRL = ").append(minCrlNumber).append(eol);
+ if (date != null)
+ str.append(" date = ").append(date).append(eol);
+ if (cert != null)
+ str.append(" certificate = ").append(cert).append(eol);
+ str.append("}").append(nl);
+ return str.toString();
+ }
+
+ /**
+ * Checks a CRL against the criteria of this selector, returning
+ * <code>true</code> if the given CRL matches all the criteria.
+ *
+ * @param _crl The CRL being checked.
+ * @return True if the CRL matches, false otherwise.
+ */
+ public boolean match(CRL _crl)
+ {
+ if (!(_crl instanceof X509CRL))
+ return false;
+ X509CRL crl = (X509CRL) _crl;
+ if (issuerNames != null)
+ {
+ if (!issuerNames.contains(crl.getIssuerX500Principal()))
+ return false;
+ }
+ BigInteger crlNumber = null;
+ if (maxCrlNumber != null)
+ {
+ byte[] b = crl.getExtensionValue(CRL_NUMBER_ID);
+ if (b == null)
+ return false;
+ try
+ {
+ DERValue val = DERReader.read(b);
+ if (!(val.getValue() instanceof BigInteger))
+ return false;
+ crlNumber = (BigInteger) val.getValue();
+ }
+ catch (IOException ioe)
+ {
+ return false;
+ }
+ if (maxCrlNumber.compareTo(crlNumber) < 0)
+ return false;
+ }
+ if (minCrlNumber != null)
+ {
+ if (crlNumber == null)
+ {
+ byte[] b = crl.getExtensionValue(CRL_NUMBER_ID);
+ if (b == null)
+ return false;
+ try
+ {
+ DERValue val = DERReader.read(b);
+ if (!(val.getValue() instanceof BigInteger))
+ return false;
+ crlNumber = (BigInteger) val.getValue();
+ }
+ catch (IOException ioe)
+ {
+ return false;
+ }
+ }
+ if (minCrlNumber.compareTo(crlNumber) > 0)
+ return false;
+ }
+ if (date != null)
+ {
+ if (date.compareTo(crl.getThisUpdate()) < 0 ||
+ date.compareTo(crl.getNextUpdate()) > 0)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return The copy.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen);
+ }
+ }
+}
diff --git a/libjava/classpath/java/security/cert/X509CertSelector.java b/libjava/classpath/java/security/cert/X509CertSelector.java
new file mode 100644
index 00000000000..4149a37643d
--- /dev/null
+++ b/libjava/classpath/java/security/cert/X509CertSelector.java
@@ -0,0 +1,1106 @@
+/* X509CertSelector.java -- selects X.509 certificates by criteria.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.cert;
+
+import gnu.classpath.SystemProperties;
+import gnu.java.security.OID;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * A concrete implementation of {@link CertSelector} for X.509 certificates,
+ * which allows a number of criteria to be set when accepting certificates,
+ * from validity dates, to issuer and subject distinguished names, to some
+ * of the various X.509 extensions.
+ *
+ * <p>Use of this class requires extensive knowledge of the Internet
+ * Engineering Task Force's Public Key Infrastructure (X.509). The primary
+ * document describing this standard is <a
+ * href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
+ * Public Key Infrastructure Certificate and Certificate Revocation List
+ * (CRL) Profile</a>.
+ *
+ * <p>Note that this class is not thread-safe. If multiple threads will
+ * use or modify this class then they need to synchronize on the object.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class X509CertSelector implements CertSelector, Cloneable
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ private static final String AUTH_KEY_ID = "2.5.29.35";
+ private static final String SUBJECT_KEY_ID = "2.5.29.14";
+ private static final String NAME_CONSTRAINTS_ID = "2.5.29.30";
+
+ private int basicConstraints;
+ private X509Certificate cert;
+ private BigInteger serialNo;
+ private X500Principal issuer;
+ private X500Principal subject;
+ private byte[] subjectKeyId;
+ private byte[] authKeyId;
+ private boolean[] keyUsage;
+ private Date certValid;
+ private OID sigId;
+ private PublicKey subjectKey;
+ private X509EncodedKeySpec subjectKeySpec;
+ private Set keyPurposeSet;
+ private List altNames;
+ private boolean matchAllNames;
+ private byte[] nameConstraints;
+ private Set policy;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new X.509 certificate selector. The new selector will be
+ * empty, and will accept any certificate (provided that it is an
+ * {@link X509Certificate}).
+ */
+ public X509CertSelector()
+ {
+ basicConstraints = -1;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the certificate criterion, or <code>null</code> if this value
+ * was not set.
+ *
+ * @return The certificate.
+ */
+ public X509Certificate getCertificate()
+ {
+ return cert;
+ }
+
+ /**
+ * Sets the certificate criterion. If set, only certificates that are
+ * equal to the certificate passed here will be accepted.
+ *
+ * @param cert The certificate.
+ */
+ public void setCertificate(X509Certificate cert)
+ {
+ this.cert = cert;
+ }
+
+ /**
+ * Returns the serial number criterion, or <code>null</code> if this
+ * value was not set.
+ *
+ * @return The serial number.
+ */
+ public BigInteger getSerialNumber()
+ {
+ return serialNo;
+ }
+
+ /**
+ * Sets the serial number of the desired certificate. Only certificates that
+ * contain this serial number are accepted.
+ *
+ * @param serialNo The serial number.
+ */
+ public void setSerialNumber(BigInteger serialNo)
+ {
+ this.serialNo = serialNo;
+ }
+
+ /**
+ * Returns the issuer criterion as a string, or <code>null</code> if this
+ * value was not set.
+ *
+ * @return The issuer.
+ */
+ public String getIssuerAsString()
+ {
+ if (issuer != null)
+ return issuer.getName();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the issuer criterion as a sequence of DER bytes, or
+ * <code>null</code> if this value was not set.
+ *
+ * @return The issuer.
+ */
+ public byte[] getIssuerAsBytes() throws IOException
+ {
+ if (issuer != null)
+ return issuer.getEncoded();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the issuer, specified as a string representation of the issuer's
+ * distinguished name. Only certificates issued by this issuer will
+ * be accepted.
+ *
+ * @param name The string representation of the issuer's distinguished name.
+ * @throws IOException If the given name is incorrectly formatted.
+ */
+ public void setIssuer(String name) throws IOException
+ {
+ if (name != null)
+ {
+ try
+ {
+ issuer = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new IOException(iae.getMessage());
+ }
+ }
+ else
+ issuer = null;
+ }
+
+ /**
+ * Sets the issuer, specified as the DER encoding of the issuer's
+ * distinguished name. Only certificates issued by this issuer will
+ * be accepted.
+ *
+ * @param name The DER encoding of the issuer's distinguished name.
+ * @throws IOException If the given name is incorrectly formatted.
+ */
+ public void setIssuer(byte[] name) throws IOException
+ {
+ if (name != null)
+ {
+ try
+ {
+ issuer = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new IOException(iae.getMessage());
+ }
+ }
+ else
+ issuer = null;
+ }
+
+ /**
+ * Returns the subject criterion as a string, of <code>null</code> if
+ * this value was not set.
+ *
+ * @return The subject.
+ */
+ public String getSubjectAsString()
+ {
+ if (subject != null)
+ return subject.getName();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the subject criterion as a sequence of DER bytes, or
+ * <code>null</code> if this value is not set.
+ *
+ * @return The subject.
+ */
+ public byte[] getSubjectAsBytes() throws IOException
+ {
+ if (subject != null)
+ return subject.getEncoded();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the subject, specified as a string representation of the
+ * subject's distinguished name. Only certificates with the given
+ * subject will be accepted.
+ *
+ * @param name The string representation of the subject's distinguished name.
+ * @throws IOException If the given name is incorrectly formatted.
+ */
+ public void setSubject(String name) throws IOException
+ {
+ if (name != null)
+ {
+ try
+ {
+ subject = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new IOException(iae.getMessage());
+ }
+ }
+ else
+ subject = null;
+ }
+
+ /**
+ * Sets the subject, specified as the DER encoding of the subject's
+ * distinguished name. Only certificates with the given subject will
+ * be accepted.
+ *
+ * @param name The DER encoding of the subject's distinguished name.
+ * @throws IOException If the given name is incorrectly formatted.
+ */
+ public void setSubject(byte[] name) throws IOException
+ {
+ if (name != null)
+ {
+ try
+ {
+ subject = new X500Principal(name);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new IOException(iae.getMessage());
+ }
+ }
+ else
+ subject = null;
+ }
+
+ /**
+ * Returns the subject key identifier criterion, or <code>null</code> if
+ * this value was not set. Note that the byte array is cloned to prevent
+ * modification.
+ *
+ * @return The subject key identifier.
+ */
+ public byte[] getSubjectKeyIdentifier()
+ {
+ if (subjectKeyId != null)
+ return (byte[]) subjectKeyId.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the subject key identifier criterion, or <code>null</code> to clear
+ * this criterion. Note that the byte array is cloned to prevent modification.
+ *
+ * @param subjectKeyId The subject key identifier.
+ */
+ public void setSubjectKeyIdentifier(byte[] subjectKeyId)
+ {
+ this.subjectKeyId = subjectKeyId != null ? (byte[]) subjectKeyId.clone() :
+ null;
+ }
+
+ /**
+ * Returns the authority key identifier criterion, or <code>null</code> if
+ * this value was not set. Note that the byte array is cloned to prevent
+ * modification.
+ *
+ * @return The authority key identifier.
+ */
+ public byte[] getAuthorityKeyIdentifier()
+ {
+ if (authKeyId != null)
+ return (byte[]) authKeyId.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the authority key identifier criterion, or <code>null</code> to clear
+ * this criterion. Note that the byte array is cloned to prevent modification.
+ *
+ * @param subjectKeyId The subject key identifier.
+ */
+ public void setAuthorityKeyIdentifier(byte[] authKeyId)
+ {
+ this.authKeyId = authKeyId != null ? (byte[]) authKeyId.clone() : null;
+ }
+
+ /**
+ * Returns the date at which certificates must be valid, or <code>null</code>
+ * if this criterion was not set.
+ *
+ * @return The target certificate valitity date.
+ */
+ public Date getCertificateValid()
+ {
+ if (certValid != null)
+ return (Date) certValid.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the date at which certificates must be valid. Specify
+ * <code>null</code> to clear this criterion.
+ *
+ * @param certValid The certificate validity date.
+ */
+ public void setCertificateValid(Date certValid)
+ {
+ this.certValid = certValid != null ? (Date) certValid.clone() : null;
+ }
+
+ /**
+ * This method, and its related X.509 certificate extension &mdash; the
+ * private key usage period &mdash; is not supported under the Internet
+ * PKI for X.509 certificates (PKIX), described in RFC 3280. As such, this
+ * method is not supported either.
+ *
+ * <p>Do not use this method. It is not deprecated, as it is not deprecated
+ * in the Java standard, but it is basically a no-operation and simply
+ * returns <code>null</code>.
+ *
+ * @return Null.
+ */
+ public Date getPrivateKeyValid()
+ {
+ return null;
+ }
+
+ /**
+ * This method, and its related X.509 certificate extension &mdash; the
+ * private key usage period &mdash; is not supported under the Internet
+ * PKI for X.509 certificates (PKIX), described in RFC 3280. As such, this
+ * method is not supported either.
+ *
+ * <p>Do not use this method. It is not deprecated, as it is not deprecated
+ * in the Java standard, but it is basically a no-operation.
+ *
+ * @param UNUSED Is silently ignored.
+ */
+ public void setPrivateKeyValid(Date UNUSED)
+ {
+ }
+
+ /**
+ * Returns the public key algorithm ID that matching certificates must have,
+ * or <code>null</code> if this criterion was not set.
+ *
+ * @return The public key algorithm ID.
+ */
+ public String getSubjectPublicKeyAlgID()
+ {
+ return String.valueOf(sigId);
+ }
+
+ /**
+ * Sets the public key algorithm ID that matching certificates must have.
+ * Specify <code>null</code> to clear this criterion.
+ *
+ * @param sigId The public key ID.
+ * @throws IOException If the specified ID is not a valid object identifier.
+ */
+ public void setSubjectPublicKeyAlgID(String sigId) throws IOException
+ {
+ if (sigId != null)
+ {
+ try
+ {
+ OID oid = new OID(sigId);
+ int[] comp = oid.getIDs();
+ if (!checkOid(comp))
+ throw new IOException("malformed OID: " + sigId);
+ this.sigId = oid;
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed OID: " + sigId);
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ }
+ else
+ this.sigId = null;
+ }
+
+ /**
+ * Returns the subject public key criterion, or <code>null</code> if this
+ * value is not set.
+ *
+ * @return The subject public key.
+ */
+ public PublicKey getSubjectPublicKey()
+ {
+ return subjectKey;
+ }
+
+ /**
+ * Sets the subject public key criterion as an opaque representation.
+ * Specify <code>null</code> to clear this criterion.
+ *
+ * @param key The public key.
+ */
+ public void setSubjectPublicKey(PublicKey key)
+ {
+ this.subjectKey = key;
+ if (key == null)
+ {
+ subjectKeySpec = null;
+ return;
+ }
+ try
+ {
+ KeyFactory enc = KeyFactory.getInstance("X.509");
+ subjectKeySpec = (X509EncodedKeySpec)
+ enc.getKeySpec(key, X509EncodedKeySpec.class);
+ }
+ catch (Exception x)
+ {
+ subjectKey = null;
+ subjectKeySpec = null;
+ }
+ }
+
+ /**
+ * Sets the subject public key criterion as a DER-encoded key. Specify
+ * <code>null</code> to clear this value.
+ *
+ * @param key The DER-encoded key bytes.
+ * @throws IOException If the argument is not a valid DER-encoded key.
+ */
+ public void setSubjectPublicKey(byte[] key) throws IOException
+ {
+ if (key == null)
+ {
+ subjectKey = null;
+ subjectKeySpec = null;
+ return;
+ }
+ try
+ {
+ subjectKeySpec = new X509EncodedKeySpec(key);
+ KeyFactory enc = KeyFactory.getInstance("X.509");
+ subjectKey = enc.generatePublic(subjectKeySpec);
+ }
+ catch (Exception x)
+ {
+ subjectKey = null;
+ subjectKeySpec = null;
+ IOException ioe = new IOException(x.getMessage());
+ ioe.initCause(x);
+ throw ioe;
+ }
+ }
+
+ /**
+ * Returns the public key usage criterion, or <code>null</code> if this
+ * value is not set. Note that the array is cloned to prevent modification.
+ *
+ * @return The public key usage.
+ */
+ public boolean[] getKeyUsage()
+ {
+ if (keyUsage != null)
+ return (boolean[]) keyUsage.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the public key usage criterion. Specify <code>null</code> to clear
+ * this value.
+ *
+ * @param keyUsage The public key usage.
+ */
+ public void setKeyUsage(boolean[] keyUsage)
+ {
+ this.keyUsage = keyUsage != null ? (boolean[]) keyUsage.clone() : null;
+ }
+
+ /**
+ * Returns the set of extended key purpose IDs, as an unmodifiable set
+ * of OID strings. Returns <code>null</code> if this criterion is not
+ * set.
+ *
+ * @return The set of key purpose OIDs (strings).
+ */
+ public Set getExtendedKeyUsage()
+ {
+ if (keyPurposeSet != null)
+ return Collections.unmodifiableSet(keyPurposeSet);
+ else
+ return null;
+ }
+
+ /**
+ * Sets the extended key usage criterion, as a set of OID strings. Specify
+ * <code>null</code> to clear this value.
+ *
+ * @param keyPurposeSet The set of key purpose OIDs.
+ * @throws IOException If any element of the set is not a valid OID string.
+ */
+ public void setExtendedKeyUsage(Set keyPurposeSet) throws IOException
+ {
+ if (keyPurposeSet == null)
+ {
+ this.keyPurposeSet = null;
+ return;
+ }
+ Set s = new HashSet();
+ for (Iterator it = keyPurposeSet.iterator(); it.hasNext(); )
+ {
+ Object o = it.next();
+ if (!(o instanceof String))
+ throw new IOException("not a string: " + o);
+ try
+ {
+ OID oid = new OID((String) o);
+ int[] comp = oid.getIDs();
+ if (!checkOid(comp))
+ throw new IOException("malformed OID: " + o);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ IOException ioe = new IOException("malformed OID: " + o);
+ ioe.initCause(iae);
+ throw ioe;
+ }
+ }
+ this.keyPurposeSet = s;
+ }
+
+ /**
+ * Returns whether or not all specified alternative names must match.
+ * If false, a certificate is considered a match if <em>one</em> of the
+ * specified alternative names matches.
+ *
+ * @return true if all names must match.
+ */
+ public boolean getMatchAllSubjectAltNames()
+ {
+ return matchAllNames;
+ }
+
+ /**
+ * Sets whether or not all subject alternative names must be matched.
+ * If false, then a certificate will be considered a match if one
+ * alternative name matches.
+ *
+ * @param matchAllNames Whether or not all alternative names must be
+ * matched.
+ */
+ public void setMatchAllSubjectAltNames(boolean matchAllNames)
+ {
+ this.matchAllNames = matchAllNames;
+ }
+
+ /**
+ * Sets the subject alternative names critertion. Each element of the
+ * argument must be a {@link java.util.List} that contains exactly two
+ * elements: the first an {@link Integer}, representing the type of
+ * name, and the second either a {@link String} or a byte array,
+ * representing the name itself.
+ *
+ * @param altNames The alternative names.
+ * @throws IOException If any element of the argument is invalid.
+ */
+ public void setSubjectAlternativeNames(Collection altNames)
+ throws IOException
+ {
+ if (altNames == null)
+ {
+ this.altNames = null;
+ return;
+ }
+ List l = new ArrayList(altNames.size());
+ for (Iterator it = altNames.iterator(); it.hasNext(); )
+ {
+ Object o = it.next();
+ if (!(o instanceof List) || ((List) o).size() != 2 ||
+ !(((List) o).get(0) instanceof Integer) ||
+ !(((List) o).get(1) instanceof String) ||
+ !(((List) o).get(1) instanceof byte[]))
+ throw new IOException("illegal alternative name: " + o);
+ Integer i = (Integer) ((List) o).get(0);
+ if (i.intValue() < 0 || i.intValue() > 8)
+ throw new IOException("illegal alternative name: " + o +
+ ", bad id: " + i);
+ l.add(new ArrayList((List) o));
+ }
+ this.altNames = l;
+ }
+
+ /**
+ * Add a name to the subject alternative names criterion.
+ *
+ * @param id The type of name this is. Must be in the range [0,8].
+ * @param name The name.
+ * @throws IOException If the id is out of range, or if the name
+ * is null.
+ */
+ public void addSubjectAlternativeName(int id, String name)
+ throws IOException
+ {
+ if (id < 0 || id > 8 || name == null)
+ throw new IOException("illegal alternative name");
+ if (altNames == null)
+ altNames = new LinkedList();
+ ArrayList l = new ArrayList(2);
+ l.add(new Integer(id));
+ l.add(name);
+ altNames.add(l);
+ }
+
+ /**
+ * Add a name, as DER-encoded bytes, to the subject alternative names
+ * criterion.
+ *
+ * @param id The type of name this is.
+ */
+ public void addSubjectAlternativeName(int id, byte[] name)
+ throws IOException
+ {
+ if (id < 0 || id > 8 || name == null)
+ throw new IOException("illegal alternative name");
+ if (altNames == null)
+ altNames = new LinkedList();
+ ArrayList l = new ArrayList(2);
+ l.add(new Integer(id));
+ l.add(name);
+ altNames.add(l);
+ }
+
+ /**
+ * Returns the name constraints criterion, or <code>null</code> if this
+ * value is not set. Note that the byte array is cloned to prevent
+ * modification.
+ *
+ * @return The name constraints.
+ */
+ public byte[] getNameConstraints()
+ {
+ if (nameConstraints != null)
+ return (byte[]) nameConstraints.clone();
+ else
+ return null;
+ }
+
+ /**
+ * Sets the name constraints criterion; specify <code>null</code> to
+ * clear this criterion. Note that if non-null, the argument will be
+ * cloned to prevent modification.
+ *
+ * @param nameConstraints The new name constraints.
+ * @throws IOException If the argument is not a valid DER-encoded
+ * name constraints.
+ */
+ public void setNameConstraints(byte[] nameConstraints)
+ throws IOException
+ {
+ // FIXME check if the argument is valid.
+ this.nameConstraints = nameConstraints != null
+ ? (byte[]) nameConstraints.clone() : null;
+ }
+
+ /**
+ * Returns the basic constraints criterion, or -1 if this value is not set.
+ *
+ * @return The basic constraints.
+ */
+ public int getBasicConstraints()
+ {
+ return basicConstraints;
+ }
+
+ /**
+ * Sets the basic constraints criterion. Specify -1 to clear this parameter.
+ *
+ * @param basicConstraints The new basic constraints value.
+ */
+ public void setBasicConstraints(int basicConstraints)
+ {
+ if (basicConstraints < -1)
+ basicConstraints = -1;
+ this.basicConstraints = basicConstraints;
+ }
+
+ // The last two criteria not yet implemented are certificate policies
+ // and path-to-names. Both of these are somewhat advanced extensions
+ // (you could probably count the applications that actually use them
+ // on one hand), and they both have no support in the X509Certificate
+ // class.
+ //
+ // Not having support in X509Certificate is not always a problem; for
+ // example, we can compare DER-encoded values as byte arrays for some
+ // extensions. We can't, however, compare them if they are specified
+ // in a set (as policies are). We need to parse the actual value in the
+ // certificate, and check it against the specified set.
+
+ // FIXME
+// public void setPolicy(Set policy) throws IOException
+// {
+// if (policy != null)
+// {
+// for (Iterator it = policy.iterator(); it.hasNext(); )
+// try
+// {
+// OID oid = new OID((String) it.next());
+// int[] i = oid.getIDs();
+// if (!checkOid(i))
+// throw new IOException("invalid OID");
+// }
+// catch (Exception x)
+// {
+// throw new IOException("invalid OID");
+// }
+// }
+// this.policy = policy != null ? new HashSet(policy) : null;
+// }
+
+ // FIXME
+// public void setPathToNames(Collection names) throws IOException
+// {
+// if (names == null)
+// {
+// this.names = null;
+// return;
+// }
+// for (Iterator it = names.iterator(); it.hasNext(); )
+// {
+// try
+// {
+// List l = (List) it.next();
+// if (l.get(1) instanceof String)
+// addPathToName(((Integer)l.get(0)).intValue(), (String)l.get(1));
+// else
+// addPathToName(((Integer)l.get(0)).intValue(), (byte[])l.get(1));
+// }
+// catch (Exception x)
+// {
+// this.names = null;
+// throw new IOException("invalid names");
+// }
+// }
+// }
+
+ // FIXME
+// public void addPathToName(int id, String name) throws IOException
+// {
+// }
+
+ // FIXME
+// public void addPathToName(int id, byte[] name) throws IOException
+// {
+// }
+
+ // FIXME
+// public Collection getSubjectAlternativeNames()
+// {
+// return null;
+// }
+
+ // FIXME
+// public Set getPolicy()
+// {
+// return null;
+// }
+
+ // FIXME
+// public Collection getPathToNames()
+// {
+// return null;
+// }
+
+ /**
+ * Match a certificate. This method will check the given certificate
+ * against all the enabled criteria of this selector, and will return
+ * <code>true</code> if the given certificate matches.
+ *
+ * @param certificate The certificate to check.
+ * @return true if the certificate matches all criteria.
+ */
+ public boolean match(Certificate certificate)
+ {
+ if (!(certificate instanceof X509Certificate))
+ return false;
+ X509Certificate cert = (X509Certificate) certificate;
+ if (this.cert != null)
+ {
+ try
+ {
+ byte[] e1 = this.cert.getEncoded();
+ byte[] e2 = cert.getEncoded();
+ if (!Arrays.equals(e1, e2))
+ return false;
+ }
+ catch (CertificateEncodingException cee)
+ {
+ return false;
+ }
+ }
+ if (serialNo != null)
+ {
+ if (!serialNo.equals(cert.getSerialNumber()))
+ return false;
+ }
+ if (certValid != null)
+ {
+ try
+ {
+ cert.checkValidity(certValid);
+ }
+ catch (CertificateException ce)
+ {
+ return false;
+ }
+ }
+ if (issuer != null)
+ {
+ if (!issuer.equals(cert.getIssuerX500Principal()))
+ return false;
+ }
+ if (subject != null)
+ {
+ if (!subject.equals(cert.getSubjectX500Principal()))
+ return false;
+ }
+ if (sigId != null)
+ {
+ if (!sigId.equals(cert.getSigAlgOID()))
+ return false;
+ }
+ if (subjectKeyId != null)
+ {
+ byte[] b = cert.getExtensionValue(SUBJECT_KEY_ID);
+ if (!Arrays.equals(b, subjectKeyId))
+ return false;
+ }
+ if (authKeyId != null)
+ {
+ byte[] b = cert.getExtensionValue(AUTH_KEY_ID);
+ if (!Arrays.equals(b, authKeyId))
+ return false;
+ }
+ if (keyUsage != null)
+ {
+ boolean[] b = cert.getKeyUsage();
+ if (!Arrays.equals(b, keyUsage))
+ return false;
+ }
+ if (basicConstraints >= 0)
+ {
+ if (cert.getBasicConstraints() != basicConstraints)
+ return false;
+ }
+ if (keyPurposeSet != null)
+ {
+ List kp = null;
+ try
+ {
+ kp = cert.getExtendedKeyUsage();
+ }
+ catch (CertificateParsingException cpe)
+ {
+ return false;
+ }
+ if (kp == null)
+ return false;
+ for (Iterator it = keyPurposeSet.iterator(); it.hasNext(); )
+ {
+ if (!kp.contains(it.next()))
+ return false;
+ }
+ }
+ if (altNames != null)
+ {
+ Collection an = null;
+ try
+ {
+ an = cert.getSubjectAlternativeNames();
+ }
+ catch (CertificateParsingException cpe)
+ {
+ return false;
+ }
+ if (an == null)
+ return false;
+ int match = 0;
+ for (Iterator it = altNames.iterator(); it.hasNext(); )
+ {
+ List l = (List) it.next();
+ Integer id = (Integer) l.get(0);
+ String s = null;
+ byte[] b = null;
+ if (l.get(1) instanceof String)
+ s = (String) l.get(1);
+ else if (l.get(1) instanceof byte[])
+ b = (byte[]) l.get(1);
+ else
+ return false;
+ for (Iterator it2 = an.iterator(); it2.hasNext(); )
+ {
+ Object o = it2.next();
+ if (!(o instanceof List))
+ continue;
+ List l2 = (List) o;
+ if (l2.size() != 2)
+ continue;
+ if (!id.equals(l2.get(0)))
+ continue;
+ if (s != null && (l2.get(1) instanceof String) &&
+ s.equals(l2.get(1)))
+ match++;
+ else if (b != null && (l2.get(1) instanceof byte[]) &&
+ Arrays.equals(b, (byte[]) l2.get(1)))
+ match++;
+ }
+ if (match == 0 || (matchAllNames && match != altNames.size()))
+ return false;
+ }
+ }
+ if (nameConstraints != null)
+ {
+ byte[] nc = cert.getExtensionValue(NAME_CONSTRAINTS_ID);
+ if (!Arrays.equals(nameConstraints, nc))
+ return false;
+ }
+
+ // FIXME check policies.
+ // FIXME check path-to-names.
+
+ return true;
+ }
+
+ public String toString()
+ {
+ StringBuffer str = new StringBuffer(X509CertSelector.class.getName());
+ String nl = SystemProperties.getProperty("line.separator");
+ String eol = ";" + nl;
+ str.append(" {").append(nl);
+ if (cert != null)
+ str.append(" certificate = ").append(cert).append(eol);
+ if (basicConstraints >= 0)
+ str.append(" basic constraints = ").append(basicConstraints).append(eol);
+ if (serialNo != null)
+ str.append(" serial number = ").append(serialNo).append(eol);
+ if (certValid != null)
+ str.append(" valid date = ").append(certValid).append(eol);
+ if (issuer != null)
+ str.append(" issuer = ").append(issuer).append(eol);
+ if (subject != null)
+ str.append(" subject = ").append(subject).append(eol);
+ if (sigId != null)
+ str.append(" signature OID = ").append(sigId).append(eol);
+ if (subjectKey != null)
+ str.append(" subject public key = ").append(subjectKey).append(eol);
+ if (subjectKeyId != null)
+ {
+ str.append(" subject key ID = ");
+ for (int i = 0; i < subjectKeyId.length; i++)
+ {
+ str.append(Character.forDigit((subjectKeyId[i] & 0xF0) >>> 8, 16));
+ str.append(Character.forDigit((subjectKeyId[i] & 0x0F), 16));
+ if (i < subjectKeyId.length - 1)
+ str.append(':');
+ }
+ str.append(eol);
+ }
+ if (authKeyId != null)
+ {
+ str.append(" authority key ID = ");
+ for (int i = 0; i < authKeyId.length; i++)
+ {
+ str.append(Character.forDigit((authKeyId[i] & 0xF0) >>> 8, 16));
+ str.append(Character.forDigit((authKeyId[i] & 0x0F), 16));
+ if (i < authKeyId.length - 1)
+ str.append(':');
+ }
+ str.append(eol);
+ }
+ if (keyUsage != null)
+ {
+ str.append(" key usage = ");
+ for (int i = 0; i < keyUsage.length; i++)
+ str.append(keyUsage[i] ? '1' : '0');
+ str.append(eol);
+ }
+ if (keyPurposeSet != null)
+ str.append(" key purpose = ").append(keyPurposeSet).append(eol);
+ if (altNames != null)
+ str.append(" alternative names = ").append(altNames).append(eol);
+ if (nameConstraints != null)
+ str.append(" name constraints = <blob of data>").append(eol);
+ str.append("}").append(nl);
+ return str.toString();
+ }
+
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen);
+ }
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private static boolean checkOid(int[] oid)
+ {
+ return (oid != null && oid.length > 2 &&
+ (oid[0] >= 0 && oid[0] <= 2) && (oid[1] >= 0 && oid[1] <= 39));
+ }
+}
diff --git a/libjava/classpath/java/security/cert/X509Certificate.java b/libjava/classpath/java/security/cert/X509Certificate.java
new file mode 100644
index 00000000000..f6c6fcfb9a4
--- /dev/null
+++ b/libjava/classpath/java/security/cert/X509Certificate.java
@@ -0,0 +1,588 @@
+/* X509Certificate.java --- X.509 Certificate class
+ Copyright (C) 1999,2003 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.security.cert;
+
+import java.math.BigInteger;
+import java.security.Principal;
+import java.util.Date;
+
+/**
+ * X509Certificate is the abstract class for X.509 certificates.
+ * This provides a stanard class interface for accessing all
+ * the attributes of X.509 certificates.
+ *
+ * <p>In June 1996, the basic X.509 v3 format was finished by
+ * ISO/IEC and ANSI X.9. The ASN.1 DER format is below:
+ *
+ * <blockquote><pre>
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ * </pre></blockquote>
+ *
+ * <p>These certificates are widely used in various Internet
+ * protocols to support authentication. It is used in
+ * Privacy Enhanced Mail (PEM), Transport Layer Security (TLS),
+ * Secure Sockets Layer (SSL), code signing for trusted software
+ * distribution, and Secure Electronic Transactions (SET).
+ *
+ * <p>The certificates are managed and vouched for by
+ * <I>Certificate Authorities</I> (CAs). CAs are companies or
+ * groups that create certificates by placing the data in the
+ * X.509 certificate format and signing it with their private
+ * key. CAs serve as trusted third parties by certifying that
+ * the person or group specified in the certificate is who
+ * they say they are.
+ *
+ * <p>The ASN.1 defintion for <I>tbsCertificate</I> is
+ *
+ * <blockquote><pre>
+ * TBSCertificate ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ * -- If present, version shall be v2 or v3
+ * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ * -- If present, version shall be v2 or v3
+ * extensions [3] EXPLICIT Extensions OPTIONAL
+ * -- If present, version shall be v3
+ * }
+ *
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ *
+ * CertificateSerialNumber ::= INTEGER
+ *
+ * Validity ::= SEQUENCE {
+ * notBefore Time,
+ * notAfter Time }
+ *
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ *
+ * UniqueIdentifier ::= BIT STRING
+ *
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ * </pre></blockquote>
+ *
+ * Certificates are created with the CertificateFactory.
+ *
+ * <p>References:
+ *
+ * <ol>
+ * <li>Olivier Dubuisson, Philippe Fouquart (Translator) <i>ASN.1 -
+ * Communication between heterogeneous systems</i>, (C) September 2000,
+ * Morgan Kaufmann Publishers, ISBN 0-12-6333361-0. Available on-line at
+ * <a
+ * href="http://www.oss.com/asn1/dubuisson.html">http://www.oss.com/asn1/dubuisson.html</a></li>
+ * <li>R. Housley et al, <i><a href="http://www.ietf.org/rfc/rfc3280.txt">RFC
+ * 3280: Internet X.509 Public Key Infrastructure Certificate and CRL
+ * Profile</a></i>.</li>
+ * </ol>
+ *
+ * @since JDK 1.2
+ * @author Mark Benvenuto
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public abstract class X509Certificate
+ extends java.security.cert.Certificate // XXX workaround for gcj bug #17845
+ implements X509Extension
+{
+ private static final long serialVersionUID = -2491127588187038216L;
+
+ /**
+ * Constructs a new certificate of the specified type.
+ */
+ protected X509Certificate()
+ {
+ super( "X.509" );
+ }
+
+ /**
+ Checks the validity of the X.509 certificate. It is valid
+ if the current date and time are within the period specified
+ by the certificate.
+
+ The ASN.1 DER encoding is:
+
+ validity Validity,
+
+ Validity ::= SEQUENCE {
+ notBefore Time,
+ notAfter Time }
+
+ Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime }
+
+ Consult rfc2459 for more information.
+
+ @throws CertificateExpiredException if the certificate expired
+ @throws CertificateNotYetValidException if the certificate is
+ not yet valid
+ */
+ public abstract void checkValidity()
+ throws CertificateExpiredException,
+ CertificateNotYetValidException;
+
+ /**
+ Checks the validity of the X.509 certificate for the
+ specified time and date. It is valid if the specified
+ date and time are within the period specified by
+ the certificate.
+
+ @throws CertificateExpiredException if the certificate expired
+ based on the date
+ @throws CertificateNotYetValidException if the certificate is
+ not yet valid based on the date
+ */
+ public abstract void checkValidity(Date date)
+ throws CertificateExpiredException,
+ CertificateNotYetValidException;
+
+ /**
+ Returns the version of this certificate.
+
+ The ASN.1 DER encoding is:
+
+ version [0] EXPLICIT Version DEFAULT v1,
+
+ Version ::= INTEGER { v1(0), v2(1), v3(2) }
+
+ Consult rfc2459 for more information.
+
+ @return version number of certificate
+ */
+ public abstract int getVersion();
+
+ /**
+ Gets the serial number for serial Number in
+ this Certifcate. It must be a unique number
+ unique other serial numbers from the granting CA.
+
+ The ASN.1 DER encoding is:
+
+ serialNumber CertificateSerialNumber,
+
+ CertificateSerialNumber ::= INTEGER
+
+ Consult rfc2459 for more information.
+
+ @return the serial number for this X509CRLEntry.
+ */
+ public abstract BigInteger getSerialNumber();
+
+ /**
+ Returns the issuer (issuer distinguished name) of the
+ Certificate. The issuer is the entity who signed
+ and issued the Certificate.
+
+ The ASN.1 DER encoding is:
+
+ issuer Name,
+
+ Name ::= CHOICE {
+ RDNSequence }
+
+ RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+ RelativeDistinguishedName ::=
+ SET OF AttributeTypeAndValue
+
+ AttributeTypeAndValue ::= SEQUENCE {
+ type AttributeType,
+ value AttributeValue }
+
+ AttributeType ::= OBJECT IDENTIFIER
+
+ AttributeValue ::= ANY DEFINED BY AttributeType
+
+ DirectoryString ::= CHOICE {
+ teletexString TeletexString (SIZE (1..MAX)),
+ printableString PrintableString (SIZE (1..MAX)),
+ universalString UniversalString (SIZE (1..MAX)),
+ utf8String UTF8String (SIZE (1.. MAX)),
+ bmpString BMPString (SIZE (1..MAX)) }
+
+ Consult rfc2459 for more information.
+
+ @return the issuer in the Principal class
+ */
+ public abstract Principal getIssuerDN();
+
+ /**
+ Returns the subject (subject distinguished name) of the
+ Certificate. The subject is the entity who the Certificate
+ identifies.
+
+ The ASN.1 DER encoding is:
+
+ subject Name,
+
+ Consult rfc2459 for more information.
+
+ @return the issuer in the Principal class
+ */
+ public abstract Principal getSubjectDN();
+
+ /**
+ Returns the date that this certificate is not to be used
+ before, <I>notBefore</I>.
+
+ The ASN.1 DER encoding is:
+
+ validity Validity,
+
+ Validity ::= SEQUENCE {
+ notBefore Time,
+ notAfter Time }
+
+ Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime }
+
+ Consult rfc2459 for more information.
+
+ @return the date <I>notBefore</I>
+ */
+ public abstract Date getNotBefore();
+
+ /**
+ Returns the date that this certificate is not to be used
+ after, <I>notAfter</I>.
+
+ @return the date <I>notAfter</I>
+ */
+ public abstract Date getNotAfter();
+
+
+ /**
+ Returns the <I>tbsCertificate</I> from the certificate.
+
+ @return the DER encoded tbsCertificate
+
+ @throws CertificateEncodingException if encoding error occurred
+ */
+ public abstract byte[] getTBSCertificate() throws CertificateEncodingException;
+
+ /**
+ Returns the signature in its raw DER encoded format.
+
+ The ASN.1 DER encoding is:
+
+ signatureValue BIT STRING
+
+ Consult rfc2459 for more information.
+
+ @return byte array representing signature
+ */
+ public abstract byte[] getSignature();
+
+ /**
+ Returns the signature algorithm used to sign the CRL.
+ An examples is "SHA-1/DSA".
+
+ The ASN.1 DER encoding is:
+
+ signatureAlgorithm AlgorithmIdentifier,
+
+ AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters ANY DEFINED BY algorithm OPTIONAL }
+
+ Consult rfc2459 for more information.
+
+ The algorithm name is determined from the OID.
+
+ @return a string with the signature algorithm name
+ */
+ public abstract String getSigAlgName();
+
+
+ /**
+ Returns the OID for the signature algorithm used.
+ Example "1.2.840.10040.4.3" is return for SHA-1 with DSA.\
+
+ The ASN.1 DER encoding for the example is:
+
+ id-dsa-with-sha1 ID ::= {
+ iso(1) member-body(2) us(840) x9-57 (10040)
+ x9cm(4) 3 }
+
+ Consult rfc2459 for more information.
+
+ @return a string containing the OID.
+ */
+ public abstract String getSigAlgOID();
+
+
+ /**
+ Returns the AlgorithmParameters in the encoded form
+ for the signature algorithm used.
+
+ If access to the parameters is need, create an
+ instance of AlgorithmParameters.
+
+ @return byte array containing algorithm parameters, null
+ if no parameters are present in certificate
+ */
+ public abstract byte[] getSigAlgParams();
+
+
+ /**
+ Returns the issuer unique ID for this certificate.
+
+ The ASN.1 DER encoding is:
+
+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ -- If present, version shall be v2 or v3
+
+ UniqueIdentifier ::= BIT STRING
+
+ Consult rfc2459 for more information.
+
+ @return bit representation of <I>issuerUniqueID</I>
+ */
+ public abstract boolean[] getIssuerUniqueID();
+
+ /**
+ Returns the subject unique ID for this certificate.
+
+ The ASN.1 DER encoding is:
+
+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ -- If present, version shall be v2 or v3
+
+ UniqueIdentifier ::= BIT STRING
+
+ Consult rfc2459 for more information.
+
+ @return bit representation of <I>subjectUniqueID</I>
+ */
+ public abstract boolean[] getSubjectUniqueID();
+
+ /**
+ Returns a boolean array representing the <I>KeyUsage</I>
+ extension for the certificate. The KeyUsage (OID = 2.5.29.15)
+ defines the purpose of the key in the certificate.
+
+ The ASN.1 DER encoding is:
+
+ id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
+
+ KeyUsage ::= BIT STRING {
+ digitalSignature (0),
+ nonRepudiation (1),
+ keyEncipherment (2),
+ dataEncipherment (3),
+ keyAgreement (4),
+ keyCertSign (5),
+ cRLSign (6),
+ encipherOnly (7),
+ decipherOnly (8) }
+
+ Consult rfc2459 for more information.
+
+ @return bit representation of <I>KeyUsage</I>
+ */
+ public abstract boolean[] getKeyUsage();
+
+ /**
+ Returns the certificate constraints path length from the
+ critical BasicConstraints extension, (OID = 2.5.29.19).
+
+ The basic constraints extensions is used to determine if
+ the subject of the certificate is a Certificate Authority (CA)
+ and how deep the certification path may exist. The
+ <I>pathLenConstraint</I> only takes affect if <I>cA</I>
+ is set to true. "A value of zero indicates that only an
+ end-entity certificate may follow in the path." (rfc2459)
+
+ The ASN.1 DER encoding is:
+
+ id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 }
+
+ BasicConstraints ::= SEQUENCE {
+ cA BOOLEAN DEFAULT FALSE,
+ pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+
+ Consult rfc2459 for more information.
+
+ @return the length of the path constraint if BasicConstraints
+ is present and cA is TRUE. Otherwise returns -1.
+ */
+ public abstract int getBasicConstraints();
+
+ // 1.4 instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the <code>ExtendedKeyUsage</code> extension of this
+ * certificate, or null if there is no extension present. The returned
+ * value is a {@link java.util.List} strings representing the object
+ * identifiers of the extended key usages. This extension has the OID
+ * 2.5.29.37.
+ *
+ * <p>The ASN.1 definition for this extension is:
+ *
+ * <blockquote><pre>
+ * ExtendedKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ * </pre></blockquote>
+ *
+ * @return The list of extension OIDs, or null if there are none
+ * present in this certificate.
+ * @throws CertificateParsingException If this extension cannot be
+ * parsed from its encoded form.
+ */
+ public java.util.List getExtendedKeyUsage()
+ throws CertificateParsingException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the alternative names for this certificate's subject (the
+ * owner), or null if there are none.
+ *
+ * <p>This is an X.509 extension with OID 2.5.29.17 and is defined by
+ * the ASN.1 construction:
+ *
+ * <blockquote><pre>
+ * SubjectAltNames ::= GeneralNames
+ *
+ * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER
+ * }
+ * </pre></blockquote>
+ *
+ * <p>The returned collection contains one or more two-element Lists,
+ * with the first object being an Integer representing the choice
+ * above (with value 0 through 8) and the second being an (a) String
+ * if the <code>GeneralName</code> is a rfc822Name, dNSName,
+ * uniformResourceIdentifier, iPAddress, or registeredID, or (b) a
+ * byte array of the DER encoded form for any others.
+ *
+ * @return The collection of alternative names, or null if there are
+ * none.
+ * @throws CertificateParsingException If the encoded extension cannot
+ * be parsed.
+ * @since JDK 1.4
+ */
+ public java.util.Collection getSubjectAlternativeNames()
+ throws CertificateParsingException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the alternative names for this certificate's issuer, or
+ * null if there are none.
+ *
+ * <p>This is an X.509 extension with OID 2.5.29.18, and is defined by
+ * the ASN.1 construction:
+ *
+ * <blockquote><pre>
+ * IssuerAltNames ::= GeneralNames
+ * </pre></blockquote>
+ *
+ * <p>The <code>GeneralNames</code> construct and the form of the
+ * returned collection are the same as with {@link
+ * #getSubjectAlternativeNames()}.
+ *
+ * @return The collection of alternative names, or null if there are
+ * none.
+ * @throws CertificateParsingException If the encoded extension cannot
+ * be parsed.
+ * @since JDK 1.4
+ */
+ public java.util.Collection getIssuerAlternativeNames()
+ throws CertificateParsingException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the X.500 distinguished name of this certificate's subject.
+ *
+ * @return The subject's X.500 distinguished name.
+ * @since JDK 1.4
+ */
+ public javax.security.auth.x500.X500Principal getSubjectX500Principal()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the X.500 distinguished name of this certificate's issuer.
+ *
+ * @return The issuer's X.500 distinguished name.
+ * @since JDK 1.4
+ */
+ public javax.security.auth.x500.X500Principal getIssuerX500Principal()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/libjava/classpath/java/security/cert/X509Extension.java b/libjava/classpath/java/security/cert/X509Extension.java
new file mode 100644
index 00000000000..d2cb80a9f57
--- /dev/null
+++ b/libjava/classpath/java/security/cert/X509Extension.java
@@ -0,0 +1,113 @@
+/* X509Extension.java --- X.509 Extension
+ Copyright (C) 1999 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.security.cert;
+import java.util.Set;
+
+/**
+ Public interface for the X.509 Extension.
+
+ This is used for X.509 v3 Certificates and CRL v2 (Certificate
+ Revocation Lists) for managing attributes assoicated with
+ Certificates, for managing the hierarchy of certificates,
+ and for managing the distribution of CRL. This extension
+ format is used to define private extensions.
+
+ Each extensions for a certificate or CRL must be marked
+ either critical or non-critical. If the certificate/CRL
+ system encounters a critical extension not recognized then
+ it must reject the certificate. A non-critical extension
+ may be just ignored if not recognized.
+
+
+ The ASN.1 definition for this class is:
+
+ Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+
+ Extension ::= SEQUENCE {
+ extnId OBJECT IDENTIFIER,
+ critical BOOLEAN DEFAULT FALSE,
+ extnValue OCTET STRING
+ -- contains a DER encoding of a value
+ -- of the type registered for use with
+ -- the extnId object identifier value
+ }
+
+ @author Mark Benvenuto
+
+ @since JDK 1.2
+*/
+public interface X509Extension
+{
+
+ /**
+ Returns true if the certificate contains a critical extension
+ that is not supported.
+
+ @return true if has unsupported extension, false otherwise
+ */
+ boolean hasUnsupportedCriticalExtension();
+
+ /**
+ Returns a set of the CRITICAL extension OIDs from the
+ certificate/CRL that the object implementing this interface
+ manages.
+
+ @return A Set containing the OIDs. If there are no CRITICAL
+ extensions or extensions at all this returns null.
+ */
+ Set getCriticalExtensionOIDs();
+
+ /**
+ Returns a set of the NON-CRITICAL extension OIDs from the
+ certificate/CRL that the object implementing this interface
+ manages.
+
+ @return A Set containing the OIDs. If there are no NON-CRITICAL
+ extensions or extensions at all this returns null.
+ */
+ Set getNonCriticalExtensionOIDs();
+
+ /**
+ Returns the DER encoded OCTET string for the specified
+ extension value identified by a OID. The OID is a string
+ of number separated by periods. Ex: 12.23.45.67
+ */
+ byte[] getExtensionValue(String oid);
+
+}
diff --git a/libjava/classpath/java/security/cert/package.html b/libjava/classpath/java/security/cert/package.html
new file mode 100644
index 00000000000..14b12d16cc3
--- /dev/null
+++ b/libjava/classpath/java/security/cert/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.security.cert package.
+ Copyright (C) 2002 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 - java.security.cert</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/security/interfaces/DSAKey.java b/libjava/classpath/java/security/interfaces/DSAKey.java
new file mode 100644
index 00000000000..c6e819eb0e5
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/DSAKey.java
@@ -0,0 +1,56 @@
+/* DSAKey.java -- Interface for Digital Signature Algorithm key
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.interfaces;
+
+/**
+ * This interface is implemented by a class to return the parameters
+ * of a Digital Signature Algorithm (DSA) public or private key.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface DSAKey
+{
+ /**
+ * This method returns non-secret parameters of the DSA key
+ *
+ * @return The DSA parameters
+ */
+ DSAParams getParams();
+}
diff --git a/libjava/classpath/java/security/interfaces/DSAKeyPairGenerator.java b/libjava/classpath/java/security/interfaces/DSAKeyPairGenerator.java
new file mode 100644
index 00000000000..e657c54b4e6
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/DSAKeyPairGenerator.java
@@ -0,0 +1,85 @@
+/* DSAKeyPairGenerator.java -- Initialize a DSA key generator
+ Copyright (C) 1998, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.interfaces;
+
+import java.security.InvalidParameterException;
+import java.security.SecureRandom;
+
+/**
+ * This interface contains methods for intializing a Digital Signature
+ * Algorithm key generation engine. The initialize methods may be called
+ * any number of times. If no explicity initialization call is made, then
+ * the engine defaults to generating 1024-bit keys using pre-calculated
+ * base, prime, and subprime values.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface DSAKeyPairGenerator
+{
+ /**
+ * Initializes the key generator with the specified DSA parameters and
+ * random bit source
+ *
+ * @param params The DSA parameters to use
+ * @param random The random bit source to use
+ *
+ * @exception InvalidParameterException If the parameters passed are not valid
+ */
+ void initialize (DSAParams params, SecureRandom random)
+ throws InvalidParameterException;
+
+ /**
+ * Initializes the key generator to a give modulus. If the <code>genParams</code>
+ * value is <code>true</code> then new base, prime, and subprime values
+ * will be generated for the given modulus. If not, the pre-calculated
+ * values will be used. If no pre-calculated values exist for the specified
+ * modulus, an exception will be thrown. It is guaranteed that there will
+ * always be pre-calculated values for all modulus values between 512 and
+ * 1024 bits inclusives.
+ *
+ * @param modlen The modulus length
+ * @param genParams <code>true</code> to generate new DSA parameters, <code>false</code> otherwise
+ * @param random The random bit source to use
+ *
+ * @exception InvalidParameterException If a parameter is invalid
+ */
+ void initialize (int modlen, boolean genParams, SecureRandom random)
+ throws InvalidParameterException;
+}
diff --git a/libjava/classpath/java/security/interfaces/DSAParams.java b/libjava/classpath/java/security/interfaces/DSAParams.java
new file mode 100644
index 00000000000..42baeeb9570
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/DSAParams.java
@@ -0,0 +1,72 @@
+/* DSAParams.java -- Digital Signature Algorithm parameter access
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * This interface allows the Digital Signature Algorithm (DSA) parameters
+ * to be queried.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface DSAParams
+{
+ /**
+ * Returns the base, or 'g' value
+ *
+ * @return The DSA base value
+ */
+ BigInteger getG();
+
+ /**
+ * Returns the prime, or 'p' value
+ *
+ * @return The DSA prime value
+ */
+ BigInteger getP();
+
+ /**
+ * Returns the subprime, or 'q' value
+ *
+ * @return The DSA subprime value
+ */
+ BigInteger getQ();
+}
diff --git a/libjava/classpath/java/security/interfaces/DSAPrivateKey.java b/libjava/classpath/java/security/interfaces/DSAPrivateKey.java
new file mode 100644
index 00000000000..d79b34b9043
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/DSAPrivateKey.java
@@ -0,0 +1,61 @@
+/* DSAPublicKey.java -- A Digital Signature Algorithm private key
+ Copyright (C) 1998, 2000, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+
+/**
+ * This interface models a Digital Signature Algorithm (DSA) private key
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface DSAPrivateKey extends DSAKey, PrivateKey
+{
+ /**
+ * The version identifier used for serialization.
+ */
+ long serialVersionUID = 7776497482533790279L;
+
+ /**
+ * This method returns the value of the DSA private key
+ */
+ BigInteger getX();
+}
diff --git a/libjava/classpath/java/security/interfaces/DSAPublicKey.java b/libjava/classpath/java/security/interfaces/DSAPublicKey.java
new file mode 100644
index 00000000000..d73e189f607
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/DSAPublicKey.java
@@ -0,0 +1,61 @@
+/* DSAPublicKey.java -- A Digital Signature Algorithm public key
+ Copyright (C) 1998, 2000, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+
+/**
+ * This interface models a Digital Signature Algorithm (DSA) public key
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface DSAPublicKey extends DSAKey, PublicKey
+{
+ /**
+ * The version identifier used for serialization.
+ */
+ long serialVersionUID = 1234526332779022332L;
+
+ /**
+ * This method returns the value of the DSA public key
+ */
+ BigInteger getY();
+}
diff --git a/libjava/classpath/java/security/interfaces/RSAKey.java b/libjava/classpath/java/security/interfaces/RSAKey.java
new file mode 100644
index 00000000000..485fa81e05a
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/RSAKey.java
@@ -0,0 +1,57 @@
+/* RSAKey.java --- A generic RSA Key interface
+ Copyright (C) 1999 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.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ A generic RSA Key interface for public and private keys
+
+ @since JDK 1.3
+
+ @author Mark Benvenuto
+ */
+public interface RSAKey
+{
+ /**
+ Generates a modulus.
+
+ @returns a modulus
+ */
+ BigInteger getModulus();
+}
diff --git a/libjava/classpath/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java b/libjava/classpath/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
new file mode 100644
index 00000000000..d80b962d012
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
@@ -0,0 +1,111 @@
+/* RSAMultiPrimePrivateCrtKey.java --
+ Copyright (C) 2003, 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.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.spec.RSAOtherPrimeInfo;
+
+/**
+ * The interface to an RSA multi-prime private key, as defined in the PKCS#1
+ * v2.1, using the <i>Chinese Remainder Theorem</i> (CRT) information values.
+ *
+ * @since 1.4
+ * @see java.security.spec.RSAPrivateKeySpec
+ * @see java.security.spec.RSAMultiPrimePrivateCrtKeySpec
+ * @see RSAPrivateKey
+ * @see RSAPrivateCrtKey
+ */
+public interface RSAMultiPrimePrivateCrtKey extends RSAPrivateKey
+{
+ // Constants
+ // --------------------------------------------------------------------------
+ long serialVersionUID = 618058533534628008L;
+
+ // Methods
+ // --------------------------------------------------------------------------
+
+ /**
+ * Returns the public exponent.
+ *
+ * @return the public exponent.
+ */
+ BigInteger getPublicExponent();
+
+ /**
+ * Returns the primeP.
+ *
+ * @return the primeP.
+ */
+ BigInteger getPrimeP();
+
+ /**
+ * Returns the primeQ.
+ *
+ * @return the primeQ.
+ */
+ BigInteger getPrimeQ();
+
+ /**
+ * Returns the primeExponentP.
+ *
+ * @return the primeExponentP.
+ */
+ BigInteger getPrimeExponentP();
+
+ /**
+ * Returns the primeExponentQ.
+ *
+ * @return the primeExponentQ.
+ */
+ BigInteger getPrimeExponentQ();
+
+ /**
+ * Returns the crtCoefficient.
+ *
+ * @return the crtCoefficient.
+ */
+ BigInteger getCrtCoefficient();
+
+ /**
+ * Returns the otherPrimeInfo or <code>null</code> if there are only two
+ * prime factors (p and q).
+ *
+ * @return the otherPrimeInfo.
+ */
+ RSAOtherPrimeInfo[] getOtherPrimeInfo();
+}
diff --git a/libjava/classpath/java/security/interfaces/RSAPrivateCrtKey.java b/libjava/classpath/java/security/interfaces/RSAPrivateCrtKey.java
new file mode 100644
index 00000000000..96a1496cf92
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/RSAPrivateCrtKey.java
@@ -0,0 +1,95 @@
+/* RSAPrivateCrtKey.java -- An RSA private key in CRT format
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * This interface provides access to information about an RSA private
+ * key in Chinese Remainder Theorem (CRT) format.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface RSAPrivateCrtKey extends RSAPrivateKey
+{
+ long serialVersionUID = -5682214253527700368L;
+
+ /**
+ * Returns the public exponent for this key
+ *
+ * @return The public exponent for this key
+ */
+ BigInteger getPublicExponent();
+
+ /**
+ * Returns the primeP value
+ *
+ * @return The primeP value
+ */
+ BigInteger getPrimeP();
+
+ /**
+ * Returns the primeQ value
+ *
+ * @return The primeQ value
+ */
+ BigInteger getPrimeQ();
+
+ /**
+ * Returns the primeExponentP
+ *
+ * @return The primeExponentP
+ */
+ BigInteger getPrimeExponentP();
+
+ /**
+ * Returns the primeExponentQ
+ *
+ * @return The primeExponentQ
+ */
+ BigInteger getPrimeExponentQ();
+
+ /**
+ * Returns the CRT coefficient
+ *
+ * @return The CRT coefficient
+ */
+ BigInteger getCrtCoefficient();
+}
diff --git a/libjava/classpath/java/security/interfaces/RSAPrivateKey.java b/libjava/classpath/java/security/interfaces/RSAPrivateKey.java
new file mode 100644
index 00000000000..514987625a5
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/RSAPrivateKey.java
@@ -0,0 +1,60 @@
+/* RSAPrivateKey.java -- An RSA private key
+ Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+
+/**
+ * This interface provides access to information about an RSA private key.
+ *
+ * @version 0.1
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface RSAPrivateKey extends PrivateKey, RSAKey
+{
+ long serialVersionUID = 5187144804936595022L;
+
+ /**
+ * Returns the private exponent value for this key
+ *
+ * @return The private exponent value for this key
+ */
+ BigInteger getPrivateExponent();
+}
diff --git a/libjava/classpath/java/security/interfaces/RSAPublicKey.java b/libjava/classpath/java/security/interfaces/RSAPublicKey.java
new file mode 100644
index 00000000000..5fb569d1dec
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/RSAPublicKey.java
@@ -0,0 +1,60 @@
+/* RSAPublicKey.java -- An RSA public key
+ Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+
+/**
+ * This interface provides access to information about an RSA public key.
+ *
+ * @version 0.1
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface RSAPublicKey extends PublicKey, RSAKey
+{
+ long serialVersionUID = -8727434096241101194L;
+
+ /**
+ * Returns the public exponent value for this key
+ *
+ * @return The public exponent value for this key
+ */
+ BigInteger getPublicExponent();
+}
diff --git a/libjava/classpath/java/security/interfaces/package.html b/libjava/classpath/java/security/interfaces/package.html
new file mode 100644
index 00000000000..aab0d63752e
--- /dev/null
+++ b/libjava/classpath/java/security/interfaces/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.security.interfaces package.
+ Copyright (C) 2002 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 - java.security.interfaces</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/security/package.html b/libjava/classpath/java/security/package.html
new file mode 100644
index 00000000000..328b7044b81
--- /dev/null
+++ b/libjava/classpath/java/security/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.security package.
+ Copyright (C) 2002 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 - java.security</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/security/spec/AlgorithmParameterSpec.java b/libjava/classpath/java/security/spec/AlgorithmParameterSpec.java
new file mode 100644
index 00000000000..25506f55cfe
--- /dev/null
+++ b/libjava/classpath/java/security/spec/AlgorithmParameterSpec.java
@@ -0,0 +1,52 @@
+/* AlgorithmParameterSpec.java --- Algorithm Parameter Spec Interface
+ Copyright (C) 1999 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.security.spec;
+
+/**
+ A transparent interface for Algorithm Parameter Specifications.
+ It contains no member functions. It is used to group
+ algorithm parameter classes.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public interface AlgorithmParameterSpec
+{
+}
diff --git a/libjava/classpath/java/security/spec/DSAParameterSpec.java b/libjava/classpath/java/security/spec/DSAParameterSpec.java
new file mode 100644
index 00000000000..7e263291c03
--- /dev/null
+++ b/libjava/classpath/java/security/spec/DSAParameterSpec.java
@@ -0,0 +1,101 @@
+/* DSAParameterSpec.java --- DSA Parameter Specificaton class
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.security.interfaces.DSAParams;
+
+/**
+ * DSA Parameter class Specification. Used to maintain the DSA
+ * Parameters.
+ *
+ * @since 1.2
+ *
+ * @author Mark Benvenuto
+*/
+public class DSAParameterSpec implements AlgorithmParameterSpec, DSAParams
+{
+ private BigInteger p = null;
+ private BigInteger q = null;
+ private BigInteger g = null;
+
+ /**
+ * Constructs a new DSAParameterSpec with the specified p, q, and g.
+ *
+ * @param p the prime
+ * @param q the sub-prime
+ * @param g the base
+ */
+ public DSAParameterSpec(BigInteger p, BigInteger q, BigInteger g)
+ {
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ /**
+ * Returns p for the DSA algorithm.
+ *
+ * @return Returns the requested BigInteger
+ */
+ public BigInteger getP()
+ {
+ return this.p;
+ }
+
+ /**
+ * Returns p for the DSA algorithm.
+ *
+ * @return Returns the requested BigInteger
+ */
+ public BigInteger getQ()
+ {
+ return this.q;
+ }
+
+ /**
+ * Returns g for the DSA algorithm.
+ *
+ * @return Returns the requested BigInteger
+ */
+ public BigInteger getG()
+ {
+ return this.g;
+ }
+} \ No newline at end of file
diff --git a/libjava/classpath/java/security/spec/DSAPrivateKeySpec.java b/libjava/classpath/java/security/spec/DSAPrivateKeySpec.java
new file mode 100644
index 00000000000..7415fa11a45
--- /dev/null
+++ b/libjava/classpath/java/security/spec/DSAPrivateKeySpec.java
@@ -0,0 +1,113 @@
+/* DSAPrivateKeySpec.java --- DSA Private Key Specificaton class
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.spec;
+import java.math.BigInteger;
+
+/**
+ DSA Private Key class Specification. Used to maintain the DSA
+ Private Keys.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public class DSAPrivateKeySpec implements KeySpec
+{
+ private BigInteger x = null;
+ private BigInteger p = null;
+ private BigInteger q = null;
+ private BigInteger g = null;
+
+ /**
+ Constructs a new DSAPrivateKeySpec with the specified x, p, q, and g.
+
+ @param x the private key
+ @param p the prime
+ @param q the sub-prime
+ @param g the base
+ */
+ public DSAPrivateKeySpec(BigInteger x, BigInteger p, BigInteger q, BigInteger g)
+ {
+ this.x = x;
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ /**
+ Returns private key x for the DSA algorithm.
+
+ @return Returns the requested BigInteger
+ */
+ public BigInteger getX()
+ {
+ return this.x;
+ }
+
+ /**
+ Returns p for the DSA algorithm.
+
+ @return Returns the requested BigInteger
+ */
+ public BigInteger getP()
+ {
+ return this.p;
+ }
+
+ /**
+ Returns p for the DSA algorithm.
+
+ @return Returns the requested BigInteger
+ */
+ public BigInteger getQ()
+ {
+ return this.q;
+ }
+
+ /**
+ Returns g for the DSA algorithm.
+
+ @return Returns the requested BigInteger
+ */
+ public BigInteger getG()
+ {
+ return this.g;
+ }
+
+}
diff --git a/libjava/classpath/java/security/spec/DSAPublicKeySpec.java b/libjava/classpath/java/security/spec/DSAPublicKeySpec.java
new file mode 100644
index 00000000000..ac1310c1caa
--- /dev/null
+++ b/libjava/classpath/java/security/spec/DSAPublicKeySpec.java
@@ -0,0 +1,113 @@
+/* DSAPublicKeySpec.java --- DSA Public Key Specificaton class
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security.spec;
+import java.math.BigInteger;
+
+/**
+ DSA Public Key class Specification. Used to maintain the DSA
+ Public Keys.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public class DSAPublicKeySpec implements KeySpec
+{
+ private BigInteger y = null;
+ private BigInteger p = null;
+ private BigInteger q = null;
+ private BigInteger g = null;
+
+ /**
+ Constructs a new DSAPublicKeySpec with the specified y, p, q, and g.
+
+ @param y the public key
+ @param p the prime
+ @param q the sub-prime
+ @param g the base
+ */
+ public DSAPublicKeySpec(BigInteger y, BigInteger p, BigInteger q, BigInteger g)
+ {
+ this.y = y;
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ /**
+ Returns public key y for the DSA algorithm.
+
+ @return Returns the requested BigInteger
+ */
+ public BigInteger getY()
+ {
+ return this.y;
+ }
+
+ /**
+ Returns p for the DSA algorithm.
+
+ @return Returns the requested BigInteger
+ */
+ public BigInteger getP()
+ {
+ return this.p;
+ }
+
+ /**
+ Returns p for the DSA algorithm.
+
+ @return Returns the requested BigInteger
+ */
+ public BigInteger getQ()
+ {
+ return this.q;
+ }
+
+ /**
+ Returns g for the DSA algorithm.
+
+ @return Returns the requested BigInteger
+ */
+ public BigInteger getG()
+ {
+ return this.g;
+ }
+
+}
diff --git a/libjava/classpath/java/security/spec/EncodedKeySpec.java b/libjava/classpath/java/security/spec/EncodedKeySpec.java
new file mode 100644
index 00000000000..c5baf55fd7a
--- /dev/null
+++ b/libjava/classpath/java/security/spec/EncodedKeySpec.java
@@ -0,0 +1,85 @@
+/* EncodedKeySpec.java --- Encoded Key Specificaton class
+ Copyright (C) 1999 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.security.spec;
+
+/**
+ Encoded Key Specification class which is used to store
+ byte encoded keys.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public abstract class EncodedKeySpec implements KeySpec
+{
+
+ private byte[] encodedKey;
+
+ /**
+ Constructs a new EncodedKeySpec with the specified encoded key.
+
+ @param encodedKey A key to store
+ */
+ public EncodedKeySpec(byte[] encodedKey)
+ {
+ this.encodedKey = encodedKey;
+ }
+
+ /**
+ Gets the encoded key in byte format.
+
+ @returns the encoded key
+ */
+ public byte[] getEncoded()
+ {
+ return this.encodedKey;
+ }
+
+ /**
+ Returns the name of the key format used.
+
+ This name is the format such as "PKCS#8" or "X.509" which
+ if it matches a Key class name of the same type can be
+ transformed using the apporiate KeyFactory.
+
+ @return a string representing the name
+ */
+ public abstract String getFormat();
+
+}
diff --git a/libjava/classpath/java/security/spec/InvalidKeySpecException.java b/libjava/classpath/java/security/spec/InvalidKeySpecException.java
new file mode 100644
index 00000000000..c2ec6b03b5a
--- /dev/null
+++ b/libjava/classpath/java/security/spec/InvalidKeySpecException.java
@@ -0,0 +1,74 @@
+/* InvalidKeySpecException.java -- invalid KeySpec Exception
+ Copyright (C) 1999, 2002 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.security.spec;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Exception for an invalid key specification.
+ *
+ * @author Mark Benvenuto
+ * @see KeySpec
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InvalidKeySpecException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 3546139293998810778L;
+
+ /**
+ * Constructs an InvalidKeySpecException without a message string.
+ */
+ public InvalidKeySpecException()
+ {
+ }
+
+ /**
+ * Constructs an InvalidKeySpecException with a message string.
+ *
+ * @param msg a message to display with exception
+ */
+ public InvalidKeySpecException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/spec/InvalidParameterSpecException.java b/libjava/classpath/java/security/spec/InvalidParameterSpecException.java
new file mode 100644
index 00000000000..481e11e306b
--- /dev/null
+++ b/libjava/classpath/java/security/spec/InvalidParameterSpecException.java
@@ -0,0 +1,76 @@
+/* InvalidParameterSpecException.java --- invalid ParameterSpec Exception
+ Copyright (C) 1999, 2002 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.security.spec;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Exception for an invalid algorithm specification.
+ *
+ * @author Mark Benvenuto
+ * @see AlogorithmParameters
+ * @see AlogorithmParameterSpec
+ * @see DSAParameterSpec
+ * @since 1.2
+ * @status updated to 1.4
+*/
+public class InvalidParameterSpecException extends GeneralSecurityException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -970468769593399342L;
+
+ /**
+ * Constructs an InvalidParameterSpecException without a message string.
+ */
+ public InvalidParameterSpecException()
+ {
+ }
+
+ /**
+ * Constructs an InvalidParameterSpecException with a message string.
+ *
+ * @param msg a message to display with exception
+ */
+ public InvalidParameterSpecException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/security/spec/KeySpec.java b/libjava/classpath/java/security/spec/KeySpec.java
new file mode 100644
index 00000000000..93f1a6db277
--- /dev/null
+++ b/libjava/classpath/java/security/spec/KeySpec.java
@@ -0,0 +1,52 @@
+/* KeySpec.java --- Key Specification interface
+ Copyright (C) 1999 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.security.spec;
+
+/**
+ A transparent interface for Key Specifications.
+ It contains no member functions. It is used to group
+ key classes.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public interface KeySpec
+{
+}
diff --git a/libjava/classpath/java/security/spec/PKCS8EncodedKeySpec.java b/libjava/classpath/java/security/spec/PKCS8EncodedKeySpec.java
new file mode 100644
index 00000000000..4a4f1eccea7
--- /dev/null
+++ b/libjava/classpath/java/security/spec/PKCS8EncodedKeySpec.java
@@ -0,0 +1,81 @@
+/* PKCS8EncodedKeySpec.java --- PKCS8 Encoded Key Specificaton class
+ Copyright (C) 1999, 2001 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.security.spec;
+
+/**
+ PKCS8 Encoded Key Specification class which is used to store
+ "PKCS#8" byte encoded keys.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public class PKCS8EncodedKeySpec extends EncodedKeySpec
+{
+ /**
+ Constructs a new PKCS8EncodedKeySpec with the specified encoded key.
+
+ @param encodedKey A key to store, assumed to be "PKCS#8"
+ */
+ public PKCS8EncodedKeySpec(byte[] encodedKey)
+ {
+ super( encodedKey );
+ }
+
+ /**
+ Gets the encoded key in byte format.
+
+ @returns the encoded key
+*/
+ public byte[] getEncoded()
+ {
+ return super.getEncoded();
+ }
+
+ /**
+ Returns the name of the key format used which is "PKCS#8"
+
+ @return a string representing the name
+*/
+ public final String getFormat()
+ {
+ return "PKCS#8";
+ }
+
+}
diff --git a/libjava/classpath/java/security/spec/PSSParameterSpec.java b/libjava/classpath/java/security/spec/PSSParameterSpec.java
new file mode 100644
index 00000000000..7a14a24fbe4
--- /dev/null
+++ b/libjava/classpath/java/security/spec/PSSParameterSpec.java
@@ -0,0 +1,90 @@
+/* PSSParameterSpec.java --
+ Copyright (C) 2003, 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.security.spec;
+
+/**
+ * This class specifies a parameter spec for RSA PSS encoding scheme, as
+ * defined in the PKCS#1 v2.1.
+ *
+ * @since 1.4
+ * @see AlgorithmParameterSpec
+ * @see java.security.Signature
+ */
+public class PSSParameterSpec implements AlgorithmParameterSpec
+{
+ // Constants and fields
+ // --------------------------------------------------------------------------
+
+ private int saltLen;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /**
+ * Creates a new <code>PSSParameterSpec</code> given the salt length as
+ * defined in PKCS#1.
+ *
+ * @param saltLen the length of salt in bits to be used in PKCS#1 PSS encoding.
+ * @throws IllegalArgumentException if <code>saltLen</code> is less than
+ * <code>0</code>.
+ */
+ public PSSParameterSpec(int saltLen)
+ {
+ super();
+
+ if (saltLen < 0)
+ throw new IllegalArgumentException();
+ this.saltLen = saltLen;
+ }
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ /**
+ * Returns the salt length in bits.
+ *
+ * @return the salt length.
+ */
+ public int getSaltLength()
+ {
+ return this.saltLen;
+ }
+}
diff --git a/libjava/classpath/java/security/spec/RSAKeyGenParameterSpec.java b/libjava/classpath/java/security/spec/RSAKeyGenParameterSpec.java
new file mode 100644
index 00000000000..0df8dec783e
--- /dev/null
+++ b/libjava/classpath/java/security/spec/RSAKeyGenParameterSpec.java
@@ -0,0 +1,97 @@
+/* RSAKeyGenParameterSpec.java --- RSA Key Generator Parameter Spec Class
+ Copyright (C) 1999 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.security.spec;
+import java.math.BigInteger;
+
+/**
+ This class generates a set of RSA Key parameters used in the generation
+ of RSA keys.
+
+ @since JDK 1.3
+
+ @author Mark Benvenuto
+*/
+public class RSAKeyGenParameterSpec implements AlgorithmParameterSpec
+{
+ private int keysize;
+ private BigInteger publicExponent;
+
+ /**
+ Public Exponent F0 = 3
+ */
+ public static final BigInteger F0 = new BigInteger("3");
+
+ /**
+ Public Exponent F4 = 3
+ */
+ public static final BigInteger F4 = new BigInteger("65537");
+
+ /**
+ Create a new RSAKeyGenParameterSpec to store the RSA key's keysize
+ and public exponent
+
+ @param keysize Modulus size of key in bits
+ @param publicExponent - the exponent
+ */
+ public RSAKeyGenParameterSpec(int keysize, BigInteger publicExponent)
+ {
+ this.keysize = keysize;
+ this.publicExponent = publicExponent;
+ }
+
+ /**
+ Return the size of the key.
+
+ @return the size of the key.
+ */
+ public int getKeysize()
+ {
+ return keysize;
+ }
+
+ /**
+ Return the public exponent.
+
+ @return the public exponent.
+ */
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+}
diff --git a/libjava/classpath/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java b/libjava/classpath/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
new file mode 100644
index 00000000000..519a0291373
--- /dev/null
+++ b/libjava/classpath/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
@@ -0,0 +1,217 @@
+/* PSSParameterSpec.java --
+ Copyright (C) 2003, 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.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies an RSA multi-prime private key, as defined in the
+ * PKCS#1 v2.1, using the <i>Chinese Remainder Theorem</i> (CRT) information
+ * values for efficiency.
+ *
+ * @since 1.4
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see PKCS8EncodedKeySpec
+ * @see RSAPrivateKeySpec
+ * @see RSAPublicKeySpec
+ * @see RSAOtherPrimeInfo
+ */
+public class RSAMultiPrimePrivateCrtKeySpec extends RSAPrivateKeySpec
+{
+ // Constants and fields
+ // --------------------------------------------------------------------------
+
+ private BigInteger publicExponent;
+ private BigInteger primeP;
+ private BigInteger primeQ;
+ private BigInteger primeExponentP;
+ private BigInteger primeExponentQ;
+ private BigInteger crtCoefficient;
+ private RSAOtherPrimeInfo[] otherPrimeInfo;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /**
+ * <p>Creates a new <code>RSAMultiPrimePrivateCrtKeySpec</code> given the
+ * modulus, publicExponent, privateExponent, primeP, primeQ, primeExponentP,
+ * primeExponentQ, crtCoefficient, and otherPrimeInfo as defined in PKCS#1
+ * v2.1.</p>
+ *
+ * <p>Note that <code>otherPrimeInfo</code> is cloned when constructing this
+ * object.</p>
+ *
+ * @param modulus the modulus n.
+ * @param publicExponent the public exponent e.
+ * @param privateExponent the private exponent d.
+ * @param primeP the prime factor p of n.
+ * @param primeQ the prime factor q of n.
+ * @param primeExponentP this is d mod (p-1).
+ * @param primeExponentQ this is d mod (q-1).
+ * @param crtCoefficient the Chinese Remainder Theorem coefficient q-1 mod p.
+ * @param otherPrimeInfo triplets of the rest of primes, <code>null</code>
+ * can be specified if there are only two prime factors (p and q).
+ * @throws NullPointerException if any of the parameters, i.e. modulus,
+ * publicExponent, privateExponent, primeP, primeQ, primeExponentP,
+ * primeExponentQ, crtCoefficient, is <code>null</code>.
+ * @throws IllegalArgumentException if an empty, i.e. 0-length,
+ * otherPrimeInfo is specified.
+ */
+ public RSAMultiPrimePrivateCrtKeySpec(BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger primeP,
+ BigInteger primeQ,
+ BigInteger primeExponentP,
+ BigInteger primeExponentQ,
+ BigInteger crtCoefficient,
+ RSAOtherPrimeInfo[] otherPrimeInfo)
+ {
+ super(modulus, privateExponent);
+
+ if (modulus == null)
+ throw new NullPointerException("modulus");
+ if (publicExponent == null)
+ throw new NullPointerException("publicExponent");
+ if (privateExponent == null)
+ throw new NullPointerException("privateExponent");
+ if (primeP == null)
+ throw new NullPointerException("primeP");
+ if (primeQ == null)
+ throw new NullPointerException("primeQ");
+ if (primeExponentP == null)
+ throw new NullPointerException("primeExponentP");
+ if (primeExponentQ == null)
+ throw new NullPointerException("primeExponentQ");
+ if (crtCoefficient == null)
+ throw new NullPointerException("crtCoefficient");
+ if (otherPrimeInfo != null)
+ if (otherPrimeInfo.length == 0)
+ throw new IllegalArgumentException();
+ else
+ this.otherPrimeInfo = (RSAOtherPrimeInfo[]) otherPrimeInfo.clone();
+
+ this.publicExponent = publicExponent;
+ this.primeP = primeP;
+ this.primeQ = primeQ;
+ this.primeExponentP = primeExponentP;
+ this.primeExponentQ = primeExponentQ;
+ this.crtCoefficient = crtCoefficient;
+ }
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ /**
+ * Returns the public exponent.
+ *
+ * @return the public exponent.
+ */
+ public BigInteger getPublicExponent()
+ {
+ return this.publicExponent;
+ }
+
+ /**
+ * Returns the primeP.
+ *
+ * @return the primeP.
+ */
+ public BigInteger getPrimeP()
+ {
+ return this.primeP;
+ }
+
+ /**
+ * Returns the primeQ.
+ *
+ * @return the primeQ.
+ */
+ public BigInteger getPrimeQ()
+ {
+ return this.primeQ;
+ }
+
+ /**
+ * Returns the primeExponentP.
+ *
+ * @return the primeExponentP.
+ */
+ public BigInteger getPrimeExponentP()
+ {
+ return this.primeExponentP;
+ }
+
+ /**
+ * Returns the primeExponentQ.
+ *
+ * @return the primeExponentQ.
+ */
+ public BigInteger getPrimeExponentQ()
+ {
+ return this.primeExponentQ;
+ }
+
+ /**
+ * Returns the crtCoefficient.
+ *
+ * @return the crtCoefficient.
+ */
+ public BigInteger getCrtCoefficient()
+ {
+ return this.crtCoefficient;
+ }
+
+ /**
+ * Returns a copy of the otherPrimeInfo or <code>null</code> if there are
+ * only two prime factors (p and q).
+ *
+ * @return the otherPrimeInfo.
+ */
+ public RSAOtherPrimeInfo[] getOtherPrimeInfo()
+ {
+ return this.otherPrimeInfo == null
+ ? null
+ : (RSAOtherPrimeInfo[]) this.otherPrimeInfo.clone();
+ }
+}
diff --git a/libjava/classpath/java/security/spec/RSAOtherPrimeInfo.java b/libjava/classpath/java/security/spec/RSAOtherPrimeInfo.java
new file mode 100644
index 00000000000..654bcb574d8
--- /dev/null
+++ b/libjava/classpath/java/security/spec/RSAOtherPrimeInfo.java
@@ -0,0 +1,133 @@
+/* RSAOtherPrimeInfo.java --
+ Copyright (C) 2003, 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.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class represents the triplet (prime, exponent, and coefficient) inside
+ * RSA's OtherPrimeInfo structure, as defined in the PKCS#1 v2.1. The ASN.1
+ * syntax of RSA's OtherPrimeInfo is as follows:
+ *
+ * <pre>
+ * OtherPrimeInfo ::= SEQUENCE {
+ * prime INTEGER,
+ * exponent INTEGER,
+ * coefficient INTEGER
+ * }
+ * </pre>
+ *
+ * @since 1.4
+ * @see RSAPrivateCrtKeySpec
+ * @see java.security.interfaces.RSAMultiPrimePrivateCrtKey
+ */
+public class RSAOtherPrimeInfo
+{
+ // Constants and fields
+ // --------------------------------------------------------------------------
+
+ private BigInteger prime;
+ private BigInteger primeExponent;
+ private BigInteger crtCoefficient;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /**
+ * Creates a new <code>RSAOtherPrimeInfo</code> given the prime,
+ * primeExponent, and crtCoefficient as defined in PKCS#1.
+ *
+ * @param prime the prime factor of n.
+ * @param primeExponent the exponent.
+ * @param crtCoefficient the Chinese Remainder Theorem coefficient.
+ * @throws NullPointerException if any of the parameters, i.e. prime,
+ * primeExponent, crtCoefficient, is <code>null</code>.
+ */
+ public RSAOtherPrimeInfo(BigInteger prime, BigInteger primeExponent,
+ BigInteger crtCoefficient)
+ {
+ super();
+
+ if (prime == null)
+ throw new NullPointerException("prime");
+ if (primeExponent == null)
+ throw new NullPointerException("primeExponent");
+ if (crtCoefficient == null)
+ throw new NullPointerException("crtCoefficient");
+
+ this.prime = prime;
+ this.primeExponent = primeExponent;
+ this.crtCoefficient = crtCoefficient;
+ }
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ /**
+ * Returns the prime.
+ *
+ * @return the prime.
+ */
+ public final BigInteger getPrime()
+ {
+ return this.prime;
+ }
+
+ /**
+ * Returns the prime's exponent.
+ *
+ * @return the primeExponent.
+ */
+ public final BigInteger getExponent()
+ {
+ return this.primeExponent;
+ }
+
+ /**
+ * Returns the prime's crtCoefficient.
+ *
+ * @return the crtCoefficient.
+ */
+ public final BigInteger getCrtCoefficient()
+ {
+ return this.crtCoefficient;
+ }
+}
diff --git a/libjava/classpath/java/security/spec/RSAPrivateCrtKeySpec.java b/libjava/classpath/java/security/spec/RSAPrivateCrtKeySpec.java
new file mode 100644
index 00000000000..a904c305d65
--- /dev/null
+++ b/libjava/classpath/java/security/spec/RSAPrivateCrtKeySpec.java
@@ -0,0 +1,151 @@
+/* RSAPrivateCrtKeySpec.java --- RSA Private Certificate Key Specificaton class
+ Copyright (C) 1999 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.security.spec;
+import java.math.BigInteger;
+
+/**
+ RSA Private Certificate Key class Specification. Used to
+ maintain the RSA Private Certificate Keys with the
+ <I>Chinese Remainder Theorem</I>(CRT) as specified by PKCS#1.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public class RSAPrivateCrtKeySpec extends RSAPrivateKeySpec
+{
+ private BigInteger publicExponent;
+ private BigInteger primeP;
+ private BigInteger primeQ;
+ private BigInteger primeExponentP;
+ private BigInteger primeExponentQ;
+ private BigInteger crtCoefficient;
+
+ /**
+ Constructs a new RSAPrivateKeySpec with the specified
+ variables.
+
+ @param modulus the RSA modulus
+ @param publicExponent the public key exponent
+ @param privateExponent the private key exponent
+ @param primeP the prime P
+ @param primeQ the prime Q
+ @param primeExponentP the prime exponent P
+ @param primeExponentQ the prime exponent P
+ @param crtCoefficient the CRT coefficient
+ */
+ public RSAPrivateCrtKeySpec(BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger primeP,
+ BigInteger primeQ,
+ BigInteger primeExponentP,
+ BigInteger primeExponentQ,
+ BigInteger crtCoefficient)
+ {
+ super( modulus, privateExponent);
+ this.publicExponent = publicExponent;
+ this.primeP = primeP;
+ this.primeQ = primeQ;
+ this.primeExponentP = primeExponentP;
+ this.primeExponentQ = primeExponentQ;
+ this.crtCoefficient = crtCoefficient;
+ }
+
+ /**
+ Gets the RSA public exponent.
+
+ @return the RSA public exponent
+ */
+ public BigInteger getPublicExponent()
+ {
+ return this.publicExponent;
+ }
+
+ /**
+ Gets the RSA prime P.
+
+ @return the RSA prime P
+ */
+ public BigInteger getPrimeP()
+ {
+ return this.primeP;
+ }
+
+ /**
+ Gets the RSA prime Q.
+
+ @return the RSA prime Q
+ */
+ public BigInteger getPrimeQ()
+ {
+ return this.primeQ;
+ }
+
+ /**
+ Gets the RSA prime exponent P.
+
+ @return the RSA prime exponent P
+ */
+ public BigInteger getPrimeExponentP()
+ {
+ return this.primeExponentP;
+ }
+
+ /**
+ Gets the RSA prime exponent P.
+
+ @return the RSA prime exponent Q
+ */
+ public BigInteger getPrimeExponentQ()
+ {
+ return this.primeExponentQ;
+ }
+
+ /**
+ Gets the RSA CRT coefficient.
+
+ @return the RSA CRT coefficient
+ */
+ public BigInteger getCrtCoefficient()
+ {
+ return this.crtCoefficient;
+ }
+
+}
diff --git a/libjava/classpath/java/security/spec/RSAPrivateKeySpec.java b/libjava/classpath/java/security/spec/RSAPrivateKeySpec.java
new file mode 100644
index 00000000000..d29f261cfb3
--- /dev/null
+++ b/libjava/classpath/java/security/spec/RSAPrivateKeySpec.java
@@ -0,0 +1,88 @@
+/* RSAPrivateKeySpec.java --- RSA Private Key Specificaton class
+ Copyright (C) 1999 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.security.spec;
+import java.math.BigInteger;
+
+/**
+ RSA Private Key class Specification. Used to maintain the RSA
+ Private Keys.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public class RSAPrivateKeySpec implements KeySpec
+{
+ private BigInteger modulus;
+ private BigInteger privateExponent;
+
+ /**
+ Constructs a new RSAPrivateKeySpec with the specified
+ modulus and privateExponent.
+
+ @param modulus the RSA modulus
+ @param privateExponent the private key exponent
+ */
+ public RSAPrivateKeySpec(BigInteger modulus, BigInteger privateExponent)
+ {
+ this.modulus = modulus;
+ this.privateExponent = privateExponent;
+ }
+
+ /**
+ Gets the RSA modulus.
+
+ @return the RSA modulus
+ */
+ public BigInteger getModulus()
+ {
+ return this.modulus;
+ }
+
+ /**
+ Gets the RSA private exponent.
+
+ @return the RSA private exponent
+ */
+ public BigInteger getPrivateExponent()
+ {
+ return this.privateExponent;
+ }
+
+}
diff --git a/libjava/classpath/java/security/spec/RSAPublicKeySpec.java b/libjava/classpath/java/security/spec/RSAPublicKeySpec.java
new file mode 100644
index 00000000000..21283aa643b
--- /dev/null
+++ b/libjava/classpath/java/security/spec/RSAPublicKeySpec.java
@@ -0,0 +1,88 @@
+/* RSAPublicKeySpec.java --- RSA Public Key Specificaton class
+ Copyright (C) 1999 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.security.spec;
+import java.math.BigInteger;
+
+/**
+ RSA Public Key class Specification. Used to maintain the RSA
+ Public Keys.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public class RSAPublicKeySpec implements KeySpec
+{
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+
+ /**
+ Constructs a new RSAPublicKeySpec with the specified
+ modulus and publicExponent.
+
+ @param modulus the RSA modulus
+ @param publicExponent the public key exponent
+ */
+ public RSAPublicKeySpec(BigInteger modulus, BigInteger publicExponent)
+ {
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ }
+
+ /**
+ Gets the RSA modulus.
+
+ @return the RSA modulus
+ */
+ public BigInteger getModulus()
+ {
+ return this.modulus;
+ }
+
+ /**
+ Gets the RSA public exponent.
+
+ @return the RSA public exponent
+ */
+ public BigInteger getPublicExponent()
+ {
+ return this.publicExponent;
+ }
+
+}
diff --git a/libjava/classpath/java/security/spec/X509EncodedKeySpec.java b/libjava/classpath/java/security/spec/X509EncodedKeySpec.java
new file mode 100644
index 00000000000..de35960296d
--- /dev/null
+++ b/libjava/classpath/java/security/spec/X509EncodedKeySpec.java
@@ -0,0 +1,82 @@
+/* X509EncodedKeySpec.java --- X.509 Encoded Key Specificaton class
+ Copyright (C) 1999, 2001 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.security.spec;
+
+/**
+ X.509 Encoded Key Specification class which is used to store
+ "X.509" byte encoded keys.
+
+ @since JDK 1.2
+
+ @author Mark Benvenuto
+*/
+public class X509EncodedKeySpec extends EncodedKeySpec
+{
+
+ /**
+ Constructs a new X509EncodedKeySpec with the specified encoded key.
+
+ @param encodedKey A key to store, assumed to be "X.509"
+ */
+ public X509EncodedKeySpec(byte[] encodedKey)
+ {
+ super( encodedKey );
+ }
+
+ /**
+ Gets the encoded key in byte format.
+
+ @returns the encoded key
+ */
+ public byte[] getEncoded()
+ {
+ return super.getEncoded();
+ }
+
+ /**
+ Returns the name of the key format used which is "X.509"
+
+ @return a string representing the name
+ */
+ public final String getFormat()
+ {
+ return "X.509";
+ }
+
+}
diff --git a/libjava/classpath/java/security/spec/package.html b/libjava/classpath/java/security/spec/package.html
new file mode 100644
index 00000000000..8e818896a15
--- /dev/null
+++ b/libjava/classpath/java/security/spec/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.security.spec package.
+ Copyright (C) 2002 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 - java.security.spec</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/sql/Array.java b/libjava/classpath/java/sql/Array.java
new file mode 100644
index 00000000000..51628757885
--- /dev/null
+++ b/libjava/classpath/java/sql/Array.java
@@ -0,0 +1,185 @@
+/* Array.java -- Interface for accessing SQL array object
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.util.Map;
+
+/**
+ * This interface provides methods for accessing SQL array types.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Array
+{
+ /**
+ * Returns the name of the SQL type of the elements in this
+ * array. This name is database specific.
+ *
+ * @param The name of the SQL type of the elements in this array.
+ * @exception SQLException If an error occurs.
+ */
+ String getBaseTypeName() throws SQLException;
+
+ /**
+ * Returns the JDBC type identifier of the elements in this
+ * array. This will be one of the values defined in the
+ * <code>Types</code> class.
+ *
+ * @return The JDBC type of the elements in this array.
+ * @exception SQLException If an error occurs.
+ * @see Types
+ */
+ int getBaseType() throws SQLException;
+
+ /**
+ * Returns the contents of this array. This object returned
+ * will be an array of Java objects of the appropriate types.
+ *
+ * @return The contents of the array as an array of Java objects.
+ * @exception SQLException If an error occurs.
+ */
+ Object getArray() throws SQLException;
+
+ /**
+ * Returns the contents of this array. The specified
+ * <code>Map</code> will be used to override selected mappings
+ * between SQL types and Java classes.
+ *
+ * @param map A mapping of SQL types to Java classes.
+ * @return The contents of the array as an array of Java objects.
+ * @exception SQLException If an error occurs.
+ */
+ Object getArray(Map map) throws SQLException;
+
+ /**
+ * Returns a portion of this array starting at <code>index</code>
+ * into the array and continuing for <code>count</code>
+ * elements. Fewer than the requested number of elements will be
+ * returned if the array does not contain the requested number of elements.
+ * The object returned will be an array of Java objects of
+ * the appropriate types.
+ *
+ * @param offset The offset into this array to start returning elements from.
+ * @param count The requested number of elements to return.
+ * @return The requested portion of the array.
+ * @exception SQLException If an error occurs.
+ */
+ Object getArray(long index, int count) throws SQLException;
+
+ /**
+ * This method returns a portion of this array starting at <code>index</code>
+ * into the array and continuing for <code>count</code>
+ * elements. Fewer than the requested number of elements will be
+ * returned if the array does not contain the requested number of elements.
+ * The object returned will be an array of Java objects. The specified
+ * <code>Map</code> will be used for overriding selected SQL type to
+ * Java class mappings.
+ *
+ * @param offset The offset into this array to start returning elements from.
+ * @param count The requested number of elements to return.
+ * @param map A mapping of SQL types to Java classes.
+ * @return The requested portion of the array.
+ * @exception SQLException If an error occurs.
+ */
+ Object getArray(long index, int count, Map map) throws SQLException;
+
+ /**
+ * Returns the elements in the array as a <code>ResultSet</code>.
+ * Each row of the result set will have two columns. The first will be
+ * the index into the array of that row's contents. The second will be
+ * the actual value of that array element.
+ *
+ * @return The elements of this array as a <code>ResultSet</code>.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ ResultSet getResultSet() throws SQLException;
+
+ /**
+ * This method returns the elements in the array as a <code>ResultSet</code>.
+ * Each row of the result set will have two columns. The first will be
+ * the index into the array of that row's contents. The second will be
+ * the actual value of that array element. The specified <code>Map</code>
+ * will be used to override selected default mappings of SQL types to
+ * Java classes.
+ *
+ * @param map A mapping of SQL types to Java classes.
+ * @return The elements of this array as a <code>ResultSet</code>.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ ResultSet getResultSet(Map map) throws SQLException;
+
+ /**
+ * This method returns a portion of the array as a <code>ResultSet</code>.
+ * The returned portion will start at <code>index</code> into the
+ * array and up to <code>count</code> elements will be returned.
+ * <p>
+ * Each row of the result set will have two columns. The first will be
+ * the index into the array of that row's contents. The second will be
+ * the actual value of that array element.
+ *
+ * @param offset The index into the array to start returning elements from.
+ * @param length The requested number of elements to return.
+ * @return The requested elements of this array as a <code>ResultSet</code>.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ ResultSet getResultSet(long index, int count) throws SQLException;
+
+ /**
+ * This method returns a portion of the array as a <code>ResultSet</code>.
+ * The returned portion will start at <code>index</code> into the
+ * array and up to <code>count</code> elements will be returned.
+ *
+ * <p> Each row of the result set will have two columns. The first will be
+ * the index into the array of that row's contents. The second will be
+ * the actual value of that array element. The specified <code>Map</code>
+ * will be used to override selected default mappings of SQL types to
+ * Java classes.</p>
+ *
+ * @param offset The index into the array to start returning elements from.
+ * @param length The requested number of elements to return.
+ * @param map A mapping of SQL types to Java classes.
+ * @return The requested elements of this array as a <code>ResultSet</code>.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ ResultSet getResultSet(long index, int count, Map map)
+ throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/BatchUpdateException.java b/libjava/classpath/java/sql/BatchUpdateException.java
new file mode 100644
index 00000000000..c2e186548db
--- /dev/null
+++ b/libjava/classpath/java/sql/BatchUpdateException.java
@@ -0,0 +1,141 @@
+/* BatchUpdateException.java -- Exception for batch oriented SQL errors
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+/**
+ * This class extends <code>SQLException</code> to count the successful
+ * updates in each statement in a batch that was successfully updated prior
+ * to the error.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class BatchUpdateException extends SQLException
+{
+ static final long serialVersionUID = 5977529877145521757L;
+
+ /**
+ * This is the array of update counts for the commands which completed
+ * successfully prior to the error.
+ */
+ private int[] updateCounts;
+
+ /**
+ * This method initializes a new instance of <code>BatchUpdateException</code>
+ * with the specified descriptive error message, SQL state, and update count
+ * information. The vendor specific error code will be initialized to 0.
+ *
+ * @param message The descriptive error message.
+ * @param SQLState The SQL state information for this error.
+ * @param vendorCode
+ * @param updateCounts The update count information for this error.
+ */
+ public BatchUpdateException(String message, String SQLState, int vendorCode,
+ int[] updateCounts)
+ {
+ super(message, SQLState, vendorCode);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * This method initializes a new instance of <code>BatchUpdateException</code>
+ * with the specified descriptive error message, SQL state, and update count
+ * information. The vendor specific error code will be initialized to 0.
+ *
+ * @param message The descriptive error message.
+ * @param SQLState The SQL state information for this error.
+ * @param updateCounts The update count information for this error.
+ */
+ public BatchUpdateException(String message, String SQLState,
+ int[] updateCounts)
+ {
+ super(message, SQLState);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * This method initializes a new instance of <code>BatchUpdateException</code>
+ * with the specified descriptive error message and update count information.
+ * The SQL state will be initialized to <code>null</code> and the vendor
+ * specific error code will be initialized to 0.
+ *
+ * @param message The descriptive error message.
+ * @param updateCounts The update count information for this error.
+ */
+ public BatchUpdateException(String message, int[] updateCounts)
+ {
+ super(message);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Initializes a new instance of <code>BatchUpdateException</code>
+ * with the specified update count information and no descriptive error
+ * message. This SQL state will be initialized to <code>null</code> and
+ * the vendor specific error code will be initialized to 0.
+ *
+ * @param updateCounts The update count array.
+ */
+ public BatchUpdateException(int[] updateCounts)
+ {
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Initializes a new instance of <code>BatchUpdateException</code>
+ * with no descriptive error message. The SQL state and update count will
+ * be initialized to <code>null</code> and the vendor specific error code will
+ * initialized to 0.
+ */
+ public BatchUpdateException()
+ {
+ super();
+ }
+
+ /**
+ * This method returns the update count information for this error. If
+ * not <code>null</code> this is an array of <code>int</code>'s that are
+ * the update accounts for each command that was successfully executed.
+ * The array elements are in the order that the commands were executed.
+ *
+ * @return The update count information, which may be <code>null</code>.
+ */
+ public int[] getUpdateCounts()
+ {
+ return updateCounts;
+ }
+}
diff --git a/libjava/classpath/java/sql/Blob.java b/libjava/classpath/java/sql/Blob.java
new file mode 100644
index 00000000000..616839d01be
--- /dev/null
+++ b/libjava/classpath/java/sql/Blob.java
@@ -0,0 +1,131 @@
+/* Blob.java -- Access a SQL Binary Large OBject.
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * This interface specified methods for accessing a SQL BLOB (Binary
+ * Large OBject) type.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.2
+ */
+public interface Blob
+{
+ /**
+ * This method returns the number of bytes in the BLOB.
+ *
+ * @return The number of bytes in the BLOB.
+ * @exception SQLException If an error occurs.
+ */
+ long length() throws SQLException;
+
+ /**
+ * This method returns up to the requested bytes of this BLOB as a
+ * <code>byte</code> array.
+ *
+ * @param pos The index into the BLOB to start returning bytes from.
+ * @param length The requested number of bytes to return.
+ * @return The requested bytes from the BLOB.
+ * @exception SQLException If an error occurs.
+ */
+ byte[] getBytes(long pos, int length) throws SQLException;
+
+ /**
+ * This method returns a stream that will read the bytes of the BLOB.
+ *
+ * @return A stream that will read the bytes of the BLOB.
+ * @exception SQLException If an error occurs.
+ */
+ InputStream getBinaryStream() throws SQLException;
+
+ /**
+ * This method returns the index into the BLOB at which the first instance
+ * of the specified bytes occur. The searching starts at the specified
+ * index into the BLOB.
+ *
+ * @param pattern The byte pattern to search for.
+ * @param offset The index into the BLOB to starting searching for the pattern.
+ * @return The offset at which the pattern is first found, or -1 if the
+ * pattern is not found.
+ * @exception SQLException If an error occurs.
+ */
+ long position(byte[] pattern, long start) throws SQLException;
+
+ /**
+ * This method returns the index into the BLOB at which the first instance
+ * of the specified pattern occurs. The searching starts at the specified
+ * index into this BLOB. The bytes in the specified <code>Blob</code> are
+ * used as the search pattern.
+ *
+ * @param pattern The <code>Blob</code> containing the byte pattern to
+ * search for.
+ * @param offset The index into the BLOB to starting searching for the pattern.
+ * @return The offset at which the pattern is first found, or -1 if the
+ * pattern is not found.
+ * @exception SQLException If an error occurs.
+ */
+ long position(Blob pattern, long start) throws SQLException;
+
+ /**
+ * @exception SQLException If an error occurs.
+ * @since 1.4
+ */
+ int setBytes(long pos, byte[] bytes) throws SQLException;
+
+ /**
+ * @exception SQLException If an error occurs.
+ * @since 1.4
+ */
+ int setBytes(long pos, byte[] bytes, int offset, int len)
+ throws SQLException;
+
+ /**
+ * @exception SQLException If an error occurs.
+ * @since 1.4
+ */
+ OutputStream setBinaryStream(long pos) throws SQLException;
+
+ /**
+ * @exception SQLException If an error occurs.
+ * @since 1.4
+ */
+ void truncate(long len) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/CallableStatement.java b/libjava/classpath/java/sql/CallableStatement.java
new file mode 100644
index 00000000000..452294144a0
--- /dev/null
+++ b/libjava/classpath/java/sql/CallableStatement.java
@@ -0,0 +1,651 @@
+/* CallableStatement.java -- A statement for calling stored procedures.
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.util.Calendar;
+import java.util.Map;
+
+/**
+ * This interface provides a mechanism for calling stored procedures.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface CallableStatement extends PreparedStatement
+{
+ /**
+ * This method registers the specified parameter as an output parameter
+ * of the specified SQL type.
+ *
+ * @param index The index of the parameter to register as output.
+ * @param type The SQL type value from <code>Types</code>.
+ * @exception SQLException If an error occurs.
+ */
+ void registerOutParameter(int parameterIndex, int sqlType)
+ throws SQLException;
+
+ /**
+ * This method registers the specified parameter as an output parameter
+ * of the specified SQL type and scale.
+ *
+ * @param index The index of the parameter to register as output.
+ * @param type The SQL type value from <code>Types</code>.
+ * @param scale The scale of the value that will be returned.
+ * @exception SQLException If an error occurs.
+ */
+ void registerOutParameter(int parameterIndex, int sqlType, int scale)
+ throws SQLException;
+
+ /**
+ * This method tests whether the value of the last parameter that was fetched
+ * was actually a SQL NULL value.
+ *
+ * @return <code>true</code> if the last parameter fetched was a NULL,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean wasNull() throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>String</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>String</code>.
+ * @exception SQLException If an error occurs.
+ */
+ String getString(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>boolean</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>boolean</code>.
+ * @exception SQLException If an error occurs.
+ */
+ boolean getBoolean(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>byte</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>byte</code>.
+ * @exception SQLException If an error occurs.
+ */
+ byte getByte(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>short</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>short</code>.
+ * @exception SQLException If an error occurs.
+ */
+ short getShort(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>int</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>int</code>.
+ * @exception SQLException If an error occurs.
+ */
+ int getInt(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>long</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>long</code>.
+ * @exception SQLException If an error occurs.
+ */
+ long getLong(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>float</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>float</code>.
+ * @exception SQLException If an error occurs.
+ */
+ float getFloat(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>double</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>double</code>.
+ * @exception SQLException If an error occurs.
+ */
+ double getDouble(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>BigDecimal</code>.
+ *
+ * @param parameterIndex The index of the parameter to return.
+ * @param scale The number of digits to the right of the decimal to return.
+ * @return The parameter value as a <code>BigDecimal</code>.
+ * @exception SQLException If an error occurs.
+ * @deprecated Use getBigDecimal(int parameterIndex)
+ * or getBigDecimal(String parameterName) instead.
+ */
+ BigDecimal getBigDecimal(int parameterIndex, int scale)
+ throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * byte array.
+ *
+ * @param parameterIndex The index of the parameter to return.
+ * @return The parameter value as a byte array
+ * @exception SQLException If an error occurs.
+ */
+ byte[] getBytes(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>java.sql.Date</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>java.sql.Date</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Date getDate(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>java.sql.Time</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>java.sql.Time</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Time getTime(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>java.sql.Timestamp</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>java.sql.Timestamp</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Timestamp getTimestamp(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>Object</code>.
+ *
+ * @param parameterIndex The index of the parameter to return.
+ * @return The parameter value as an <code>Object</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Object getObject(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>BigDecimal</code>.
+ *
+ * @param parameterIndex The index of the parameter to return.
+ * @return The parameter value as a <code>BigDecimal</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ BigDecimal getBigDecimal(int parameterIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>Object</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @param map The mapping to use for conversion from SQL to Java types.
+ * @return The parameter value as an <code>Object</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Object getObject(int index, Map map) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>Ref</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>Ref</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Ref getRef(int index) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>Blob</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>Blob</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Blob getBlob(int index) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>Clob</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>Clob</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Clob getClob(int index) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>Array</code>.
+ *
+ * @param parameterIndex The index of the parameter to return.
+ * @return The parameter value as a <code>Array</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Array getArray(int index) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>java.sql.Date</code>.
+ *
+ * @param parameterIndex The index of the parameter to return.
+ * @param cal The <code>Calendar</code> to use for timezone and locale.
+ * @return The parameter value as a <code>java.sql.Date</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Date getDate(int parameterIndex, Calendar cal) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>java.sql.Time</code>.
+ *
+ * @param parameterIndex The index of the parameter to return.
+ * @param cal The <code>Calendar</code> to use for timezone and locale.
+ * @return The parameter value as a <code>java.sql.Time</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Time getTime(int parameterIndex, Calendar cal) throws SQLException;
+
+ /**
+ * This method returns the value of the specified parameter as a Java
+ * <code>java.sql.Timestamp</code>.
+ *
+ * @param index The index of the parameter to return.
+ * @return The parameter value as a <code>java.sql.Timestamp</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Timestamp getTimestamp(int parameterIndex, Calendar cal)
+ throws SQLException;
+
+ /**
+ * This method registers the specified parameter as an output parameter
+ * of the specified SQL type.
+ *
+ * @param index The index of the parameter to register as output.
+ * @param type The SQL type value from <code>Types</code>.
+ * @param name The user defined data type name.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ void registerOutParameter(int paramIndex, int sqlType,
+ String typeName)
+ throws SQLException;
+
+ /**
+ * This method registers the specified parameter as an output parameter
+ * of the specified SQL type.
+ *
+ * @param parameterName The name of the parameter to register as output.
+ * @param sqlType The SQL type value from <code>Types</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.4
+ */
+ void registerOutParameter(String parameterName, int sqlType)
+ throws SQLException;
+
+ /**
+ * This method registers the specified parameter as an output parameter
+ * of the specified SQL type. This version of registerOutParameter is used
+ * for NUMERIC or DECIMAL types.
+ *
+ * @param parameterName The name of the parameter to register as output.
+ * @param sqlType The SQL type value from <code>Types</code>.
+ * @param scale Number of digits to the right of the decimal point.
+ * @exception SQLException If an error occurs.
+ * @since 1.4
+ */
+ void registerOutParameter(String parameterName, int sqlType,
+ int scale)
+ throws SQLException;
+
+
+ /**
+ * This method registers the specified parameter as an output parameter
+ * of the specified SQL type. This version of registerOutParameter is used
+ * for user-named or REF types. If the type of the output parameter does
+ * not have such a type, the typeName argument is ignored.
+ *
+ * @param parameterName The name of the parameter to register as output.
+ * @param sqlType The SQL type value from <code>Types</code>.
+ * @param typeName The SQL structured type name.
+ * @exception SQLException If an error occurs.
+ * @since 1.4
+ */
+ void registerOutParameter(String parameterName, int sqlType,
+ String typeName)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ URL getURL(int parameterIndex) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setURL(String parameterName, URL val) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setNull(String parameterName, int sqlType) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setBoolean(String parameterName, boolean x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setByte(String parameterName, byte x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setShort(String parameterName, short x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setInt(String parameterName, int x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setLong(String parameterName, long x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setFloat(String parameterName, float x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setDouble(String parameterName, double x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setBigDecimal(String parameterName, BigDecimal x)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setString(String parameterName, String x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setBytes(String parameterName, byte[] x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setDate(String parameterName, Date x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setTime(String parameterName, Time x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setTimestamp(String parameterName, Timestamp x)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setAsciiStream(String parameterName, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setBinaryStream(String parameterName, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setObject(String parameterName, Object x, int targetSqlType,
+ int scale)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setObject(String parameterName, Object x, int targetSqlType)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setObject(String parameterName, Object x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setCharacterStream(String parameterName, Reader reader,
+ int length)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setDate(String parameterName, Date x, Calendar cal)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setTime(String parameterName, Time x, Calendar cal)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setTimestamp(String parameterName, Timestamp x, Calendar cal)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setNull(String parameterName, int sqlType, String typeName)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ String getString(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean getBoolean(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ byte getByte(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ short getShort(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getInt(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ long getLong(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ float getFloat(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ double getDouble(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ byte[] getBytes(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Date getDate(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Time getTime(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Timestamp getTimestamp(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Object getObject(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ BigDecimal getBigDecimal(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Object getObject(String parameterName, Map map) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Ref getRef(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Blob getBlob(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Clob getClob(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Array getArray(String parameterName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Date getDate(String parameterName, Calendar cal) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Time getTime(String parameterName, Calendar cal) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Timestamp getTimestamp(String parameterName, Calendar cal)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ URL getURL(String parameterName) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/Clob.java b/libjava/classpath/java/sql/Clob.java
new file mode 100644
index 00000000000..8789da5967a
--- /dev/null
+++ b/libjava/classpath/java/sql/Clob.java
@@ -0,0 +1,152 @@
+/* Clob.java -- Access Character Large OBjects
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+
+/**
+ * This interface contains methods for accessing a SQL CLOB (Character
+ * Large OBject) type.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Clob
+{
+ /**
+ * This method returns the number of characters in the CLOB.
+ *
+ * @return The number of characters in the CLOB.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ long length() throws SQLException;
+
+ /**
+ * This method returns the specified portion of the CLOB as a
+ * <code>String</code>.
+ *
+ * @param offset The index into the CLOB (index values start at 1) to
+ * start returning characters from.
+ * @param length The requested number of characters to return.
+ * @return The requested CLOB section, as a <code>String</code>.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ String getSubString(long pos, int length) throws SQLException;
+
+ /**
+ * This method returns a character stream that reads the contents of the
+ * CLOB.
+ *
+ * @return A character stream to read the CLOB's contents.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ Reader getCharacterStream() throws SQLException;
+
+ /**
+ * This method returns a byte stream that reads the contents of the
+ * CLOB as a series of ASCII bytes.
+ *
+ * @return A stream to read the CLOB's contents.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ InputStream getAsciiStream() throws SQLException;
+
+ /**
+ * This method returns the index into the CLOB of the first occurrence of
+ * the specified character pattern (supplied by the caller as a
+ * <code>String</code>). The search begins at the specified index.
+ *
+ * @param searchstr The character pattern to search for, passed as a
+ * <code>String</code>.
+ * @param start. The index into the CLOB to start search (indexes start
+ * at 1).
+ * @return The index at which the pattern was found (indexes start at 1),
+ * or -1 if the pattern was not found.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ long position(String searchstr, long start) throws SQLException;
+
+ /**
+ * This method returns the index into the CLOB of the first occurrence of
+ * the specified character pattern (supplied by the caller as a
+ * <code>Clob</code>). The search begins at the specified index.
+ *
+ * @param searchstr The character pattern to search for, passed as a
+ * <code>Clob</code>.
+ * @param start. The index into the CLOB to start search (indexes start
+ * at 1).
+ * @return The index at which the pattern was found (indexes start at 1),
+ * or -1 if the pattern was not found.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ long position(Clob searchstr, long start) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int setString(long pos, String str) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int setString(long pos, String str, int offset, int len)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ OutputStream setAsciiStream(long pos) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Writer setCharacterStream(long pos) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void truncate(long len) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/Connection.java b/libjava/classpath/java/sql/Connection.java
new file mode 100644
index 00000000000..48ec12dd09f
--- /dev/null
+++ b/libjava/classpath/java/sql/Connection.java
@@ -0,0 +1,420 @@
+/* Connection.java -- Manage a database connection.
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.util.Map;
+
+/**
+ * This interface provides methods for managing a connection to a database.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Connection
+{
+ /**
+ * This transaction isolation level indicates that transactions are not
+ * supported.
+ */
+ int TRANSACTION_NONE = 0;
+
+ /**
+ * This transaction isolation level indicates that one transaction can
+ * read modifications by other transactions before the other transactions
+ * have committed their changes. This could result in invalid reads.
+ */
+ int TRANSACTION_READ_UNCOMMITTED = 1;
+
+ /**
+ * This transaction isolation leve indicates that only committed data from
+ * other transactions will be read. If a transaction reads a row, then
+ * another transaction commits a change to that row, the first transaction
+ * would retrieve the changed row on subsequent reads of the same row.
+ */
+ int TRANSACTION_READ_COMMITTED = 2;
+
+ /**
+ * This transaction isolation level indicates that only committed data from
+ * other transactions will be read. It also ensures that data read from
+ * a row will not be different on a subsequent read even if another
+ * transaction commits a change.
+ */
+ int TRANSACTION_REPEATABLE_READ = 4;
+
+ /**
+ * This transaction isolation level indicates that only committed data from
+ * other transactions will be read. It also ensures that data read from
+ * a row will not be different on a subsequent read even if another
+ * transaction commits a change. Additionally, rows modified by other
+ * transactions will not affect the result set returned during subsequent
+ * executions of the same WHERE clause in this transaction.
+ */
+ int TRANSACTION_SERIALIZABLE = 8;
+
+ /**
+ * This method creates a new SQL statement. The default result set type
+ * and concurrency will be used.
+ *
+ * @return A new <code>Statement</code> object.
+ * @exception SQLException If an error occurs.
+ * @see Statement
+ */
+ Statement createStatement() throws SQLException;
+
+ /**
+ * This method creates a new <code>PreparedStatement</code> for the specified
+ * SQL string. This method is designed for use with parameterized
+ * statements. The default result set type and concurrency will be used.
+ *
+ * @param The SQL statement to use in creating this
+ * <code>PreparedStatement</code>.
+ * @return A new <code>PreparedStatement</code>.
+ * @exception SQLException If an error occurs.
+ * @see PreparedStatement
+ */
+ PreparedStatement prepareStatement(String sql) throws SQLException;
+
+ /**
+ * This method creates a new <code>CallableStatement</code> for the
+ * specified SQL string. Thie method is designed to be used with
+ * stored procedures. The default result set type and concurrency
+ * will be used.
+ *
+ * @param The SQL statement to use in creating this
+ * <code>CallableStatement</code>.
+ * @return A new <code>CallableStatement</code>.
+ * @exception SQLException If an error occurs.
+ * @see CallableStatement
+ */
+ CallableStatement prepareCall(String sql) throws SQLException;
+
+ /**
+ * This method converts the specified generic SQL statement into the
+ * native grammer of the database this object is connected to.
+ *
+ * @param The JDBC generic SQL statement.
+ * @return The native SQL statement.
+ * @exception SQLException If an error occurs.
+ */
+ String nativeSQL(String sql) throws SQLException;
+
+ /**
+ * This method turns auto commit mode on or off. In auto commit mode,
+ * every SQL statement is committed its own transaction. Otherwise a
+ * transaction must be explicitly committed or rolled back.
+ *
+ * @param autoCommit <code>true</code> to enable auto commit mode,
+ * <code>false</code> to disable it.
+ * @exception SQLException If an error occurs.
+ * @see commit
+ * @see rollback
+ */
+ void setAutoCommit(boolean autoCommit) throws SQLException;
+
+ /**
+ * This method tests whether or not auto commit mode is currently enabled.
+ * In auto commit mode, every SQL statement is committed its own transaction.
+ * Otherwise a transaction must be explicitly committed or rolled back.
+ *
+ * @return <code>true</code> if auto commit mode is enabled,
+ * <code>false</code> otherwise.
+ *
+ * @exception SQLException If an error occurs.
+ *
+ * @see commit
+ * @see rollback
+ */
+ boolean getAutoCommit() throws SQLException;
+
+ /**
+ * This method commits any SQL statements executed on this connection since
+ * the last commit or rollback.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void commit() throws SQLException;
+
+ /**
+ * This method rolls back any SQL statements executed on this connection
+ * since the last commit or rollback.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void rollback() throws SQLException;
+
+ /**
+ * This method immediately closes this database connection.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void close() throws SQLException;
+
+ /**
+ * This method tests whether or not this connection has been closed.
+ *
+ * @return <code>true</code> if the connection is closed, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isClosed() throws SQLException;
+
+ /**
+ * This method returns the meta data for this database connection.
+ *
+ * @return The meta data for this database.
+ * @exception SQLException If an error occurs.
+ * @see DatabaseMetaData
+ */
+ DatabaseMetaData getMetaData() throws SQLException;
+
+ /**
+ * This method turns read only mode on or off. It may not be called while
+ * a transaction is in progress.
+ *
+ * @param readOnly <code>true</code> if this connection is read only,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ void setReadOnly(boolean readOnly) throws SQLException;
+
+ /**
+ * This method tests whether or not this connection is in read only mode.
+ *
+ * @return <code>true</code> if the connection is read only <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isReadOnly() throws SQLException;
+
+ /**
+ * This method sets the name of the catalog in use by this connection.
+ * Note that this method does nothing if catalogs are not supported by
+ * this database.
+ *
+ * @param catalog The name of the catalog to use for this connection.
+ * @exception SQLException If an error occurs.
+ */
+ void setCatalog(String catalog) throws SQLException;
+
+ /**
+ * This method returns the name of the catalog in use by this connection,
+ * if any.
+ *
+ * @return The name of the catalog, or <code>null</code> if one does not
+ * exist or catalogs are not supported by this database.
+ * @exception SQLException If an error occurs.
+ */
+ String getCatalog() throws SQLException;
+
+ /**
+ * This method sets the current transaction isolation mode. This must
+ * be one of the constants defined in this interface.
+ *
+ * @param level The transaction isolation level.
+ * @exception SQLException If an error occurs.
+ */
+ void setTransactionIsolation(int level) throws SQLException;
+
+ /**
+ * This method returns the current transaction isolation mode. This will
+ * be one of the constants defined in this interface.
+ *
+ * @return The transaction isolation level.
+ * @exception SQLException If an error occurs.
+ */
+ int getTransactionIsolation() throws SQLException;
+
+ /**
+ * This method returns the first warning that occurred on this connection,
+ * if any. If there were any subsequence warnings, they will be chained
+ * to the first one.
+ *
+ * @return The first <code>SQLWarning</code> that occurred, or
+ * <code>null</code> if there have been no warnings.
+ * @exception SQLException If an error occurs.
+ */
+ SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * This method clears all warnings that have occurred on this connection.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void clearWarnings() throws SQLException;
+
+ /**
+ * This method creates a new SQL statement with the specified type and
+ * concurrency. Valid values for these parameters are specified in the
+ * <code>ResultSet</code> class.
+ *
+ * @param resultSetType The type of result set to use for this statement.
+ * @param resultSetConcurrency. The type of concurrency to be used in
+ * the result set for this statement.
+ * @return A new <code>Statement</code> object.
+ * @exception SQLException If an error occurs.
+ * @see Statement
+ * @see ResultSet
+ */
+ Statement createStatement(int resultSetType, int resultSetConcurrency)
+ throws SQLException;
+
+ /**
+ * This method creates a new <code>PreparedStatement</code> for the specified
+ * SQL string. This method is designed for use with parameterized
+ * statements. The specified result set type and concurrency will be used.
+ * Valid values for these parameters are specified in the
+ * <code>ResultSet</code> class.
+ *
+ * @param The SQL statement to use in creating this
+ * <code>PreparedStatement</code>.
+ * @param resultSetType The type of result set to use for this statement.
+ * @param resultSetConcurrency. The type of concurrency to be used in
+ * the result set for this statement.
+ * @return A new <code>PreparedStatement</code>.
+ * @exception SQLException If an error occurs.
+ * @see PreparedStatement
+ * @see ResultSet
+ */
+ PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException;
+
+ /**
+ * This method creates a new <code>CallableStatement</code> for the
+ * specified SQL string. Thie method is designed to be used with
+ * stored procedures. The specified result set type and concurrency
+ * will be used. Valid values for these parameters are specified in the
+ * <code>ResultSet</code> class.
+ *
+ * @param The SQL statement to use in creating this
+ * <code>PreparedStatement</code>.
+ * @param resultSetType The type of result set to use for this statement.
+ * @param resultSetConcurrency. The type of concurrency to be used in
+ * the result set for this statement.
+ * @return A new <code>CallableStatement</code>.
+ * @exception SQLException If an error occurs.
+ * @see CallableStatement
+ * @see ResultSet
+ */
+ CallableStatement prepareCall(String sql, int resultSetType, int
+ resultSetConcurrency) throws SQLException;
+
+ /**
+ * This method returns the mapping of SQL types to Java classes
+ * currently in use by this connection. This mapping will have no
+ * entries unless they have been manually added.
+ *
+ * @return The SQL type to Java class mapping.
+ * @exception SQLException If an error occurs.
+ */
+ Map getTypeMap() throws SQLException;
+
+ /**
+ * This method sets the mapping table for SQL types to Java classes.
+ * Any entries in this map override the defaults.
+ *
+ * @param map The new SQL mapping table.
+ * @exception SQLException If an error occurs.
+ */
+ void setTypeMap(Map map) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setHoldability(int holdability) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getHoldability() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Savepoint setSavepoint() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Savepoint setSavepoint(String name) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void rollback(Savepoint savepoint) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void releaseSavepoint(Savepoint savepoint) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Statement createStatement(int resultSetType, int
+ resultSetConcurrency, int resultSetHoldability) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ PreparedStatement prepareStatement(String sql, int resultSetType, int
+ resultSetConcurrency, int resultSetHoldability) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ CallableStatement prepareCall(String sql, int resultSetType, int
+ resultSetConcurrency, int resultSetHoldability) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ PreparedStatement prepareStatement(String sql, String[] columnNames)
+ throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/DataTruncation.java b/libjava/classpath/java/sql/DataTruncation.java
new file mode 100644
index 00000000000..ec522c0251c
--- /dev/null
+++ b/libjava/classpath/java/sql/DataTruncation.java
@@ -0,0 +1,157 @@
+/* DataTruncation.java -- Warning when data has been truncated.
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+/**
+ * This exception is thrown when a piece of data is unexpectedly
+ * truncated in JDBC.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class DataTruncation extends SQLWarning
+{
+ static final long serialVersionUID = 6464298989504059473L;
+
+ /**
+ * The original size of the data.
+ */
+ private int dataSize;
+
+ /**
+ * The index of the parameter or column whose value was truncated.
+ */
+ private int index;
+
+ /**
+ * Indicates whether or not a parameter value was truncated.
+ */
+ private boolean parameter;
+
+ /**
+ * Indicates whether or not a data column value was truncated.
+ */
+ private boolean read;
+
+ /**
+ * This is the size of the data after truncation.
+ */
+ private int transferSize;
+
+ /**
+ * This method initializes a new instance of <code>DataTruncation</code>
+ * with the specified values. The descriptive error message for this
+ * exception will be "Data truncation", the SQL state will be "01004"
+ * and the vendor specific error code will be set to 0.
+ *
+ * @param index The index of the parameter or column that was truncated.
+ * @param parameter <code>true</code> if a parameter was truncated,
+ * <code>false</code> otherwise.
+ * @param read <code>true</code> if a data column was truncated,
+ * <code>false</code> otherwise.
+ * @param dataSize The original size of the data.
+ * @param transferSize The size of the data after truncation.
+ */
+ public DataTruncation(int index, boolean parameter, boolean read, int
+ dataSize, int transferSize)
+ {
+ super("Data truncation", "01004");
+
+ this.index = index;
+ this.parameter = parameter;
+ this.read = read;
+ this.dataSize = dataSize;
+ this.transferSize = transferSize;
+ }
+
+ /**
+ * This method returns the index of the column or parameter that was
+ * truncated.
+ *
+ * @return The index of the column or parameter that was truncated.
+ */
+ public int getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * This method determines whether or not it was a parameter that was
+ * truncated.
+ *
+ * @return <code>true</code> if a parameter was truncated, <code>false</code>
+ * otherwise.
+ */
+ public boolean getParameter()
+ {
+ return parameter;
+ }
+
+ /**
+ * This method determines whether or not it was a column that was
+ * truncated.
+ *
+ * @return <code>true</code> if a column was truncated, <code>false</code>
+ * otherwise.
+ */
+ public boolean getRead()
+ {
+ return read;
+ }
+
+ /**
+ * This method returns the original size of the parameter or column that
+ * was truncated.
+ *
+ * @return The original size of the parameter or column that was truncated.
+ */
+ public int getDataSize()
+ {
+ return dataSize;
+ }
+
+ /**
+ * This method returns the size of the parameter or column after it was
+ * truncated.
+ *
+ * @return The size of the parameter or column after it was truncated.
+ */
+ public int getTransferSize()
+ {
+ return transferSize;
+ }
+}
diff --git a/libjava/classpath/java/sql/DatabaseMetaData.java b/libjava/classpath/java/sql/DatabaseMetaData.java
new file mode 100644
index 00000000000..d34c4e2f927
--- /dev/null
+++ b/libjava/classpath/java/sql/DatabaseMetaData.java
@@ -0,0 +1,2214 @@
+/* DatabaseMetaData.java -- Information about the database itself.
+ Copyright (C) 1999, 2000, 2001, 2002 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.sql;
+
+public interface DatabaseMetaData
+{
+ /**
+ * It is unknown whether or not the procedure returns a result.
+ */
+ int procedureResultUnknown = 0;
+
+ /**
+ * The procedure does not return a result.
+ */
+ int procedureNoResult = 1;
+
+ /**
+ * The procedure returns a result.
+ */
+ int procedureReturnsResult = 2;
+
+ /**
+ * The column type is unknown.
+ */
+ int procedureColumnUnknown = 0;
+
+ /**
+ * The column type is input.
+ */
+ int procedureColumnIn = 1;
+
+ /**
+ * The column type is input/output.
+ */
+ int procedureColumnInOut = 2;
+
+ /**
+ * The column type is output
+ */
+ int procedureColumnOut = 4;
+
+ /**
+ * The column is used for return values.
+ */
+ int procedureColumnReturn = 5;
+
+ /**
+ * The column is used for storing results
+ */
+ int procedureColumnResult = 3;
+
+ /**
+ * NULL values are not allowed.
+ */
+ int procedureNoNulls = 0;
+
+ /**
+ * NULL values are allowed.
+ */
+ int procedureNullable = 1;
+
+ /**
+ * It is unknown whether or not NULL values are allowed.
+ */
+ int procedureNullableUnknown = 2;
+
+ /**
+ * The column does not allow NULL
+ */
+ int columnNoNulls = 0;
+
+ /**
+ * The column does allow NULL
+ */
+ int columnNullable = 1;
+
+ /**
+ * It is unknown whether or not the column allows NULL
+ */
+ int columnNullableUnknown = 2;
+
+ /**
+ * The best row's scope is only guaranteed to be valid so long as the
+ * row is actually being used.
+ */
+ int bestRowTemporary = 0;
+
+ /**
+ * The best row identifier is valid to the end of the transaction.
+ */
+ int bestRowTransaction = 1;
+
+ /**
+ * The best row identifier is valid to the end of the session.
+ */
+ int bestRowSession = 2;
+
+ /**
+ * The best row may or may not be a pseudo-column.
+ */
+ int bestRowUnknown = 0;
+
+ /**
+ * The best row identifier is not a pseudo-column.
+ */
+ int bestRowNotPseudo = 1;
+
+ /**
+ * The best row identifier is a pseudo-column.
+ */
+ int bestRowPseudo = 2;
+
+ /**
+ * It is unknown whether or not the version column is a pseudo-column.
+ */
+ int versionColumnUnknown = 0;
+
+ /**
+ * The version column is not a pseudo-column
+ */
+ int versionColumnNotPseudo = 1;
+
+ /**
+ * The version column is a pseudo-column
+ */
+ int versionColumnPseudo = 2;
+
+ /**
+ * Foreign key changes are cascaded in updates or deletes.
+ */
+ int importedKeyCascade = 0;
+
+ /**
+ * Column may not be updated or deleted in use as a foreign key.
+ */
+ int importedKeyRestrict = 1;
+
+ /**
+ * When primary key is updated or deleted, the foreign key is set to NULL.
+ */
+ int importedKeySetNull = 2;
+
+ /**
+ * If the primary key is a foreign key, it cannot be udpated or deleted.
+ */
+ int importedKeyNoAction = 3;
+
+ /**
+ * If the primary key is updated or deleted, the foreign key is set to
+ * a default value.
+ */
+ int importedKeySetDefault = 4;
+
+ /**
+ * Wish I knew what this meant.
+ */
+ int importedKeyInitiallyDeferred = 5;
+
+ /**
+ * Wish I knew what this meant.
+ */
+ int importedKeyInitiallyImmediate = 6;
+
+ /**
+ * Wish I knew what this meant.
+ */
+ int importedKeyNotDeferrable = 7;
+
+ /**
+ * A NULL value is not allowed for this data type.
+ */
+ int typeNoNulls = 0;
+
+ /**
+ * A NULL value is allowed for this data type.
+ */
+ int typeNullable = 1;
+
+ /**
+ * It is unknown whether or not NULL values are allowed for this data type.
+ */
+ int typeNullableUnknown = 2;
+
+ /**
+ * Where clauses are not supported for this type.
+ */
+ int typePredNone = 0;
+
+ /**
+ * Only "WHERE..LIKE" style WHERE clauses are allowed on this data type.
+ */
+ int typePredChar = 1;
+
+ /**
+ * All WHERE clauses except "WHERE..LIKE" style are allowed on this data type.
+ */
+ int typePredBasic = 2;
+
+ /**
+ * Any type of WHERE clause is allowed for this data type.
+ */
+ int typeSearchable = 3;
+
+ /**
+ * This column contains table statistics.
+ */
+ short tableIndexStatistic = 0;
+
+ /**
+ * This table index is clustered.
+ */
+ short tableIndexClustered = 1;
+
+ /**
+ * This table index is hashed.
+ */
+ short tableIndexHashed = 2;
+
+ /**
+ * This table index is of another type.
+ */
+ short tableIndexOther = 3;
+
+ short attributeNoNulls = 0;
+
+ short attributeNullable = 1;
+
+ short attributeNullableUnknown = 2;
+
+ int sqlStateXOpen = 1;
+
+ int sqlStateSQL99 = 2;
+
+ /**
+ * This method tests whether or not all the procedures returned by
+ * the <code>getProcedures</code> method can be called by this user.
+ *
+ * @return <code>true</code> if all the procedures can be called,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean allProceduresAreCallable() throws SQLException;
+
+ /**
+ * This method tests whether or not all the table returned by the
+ * <code>getTables</code> method can be selected by this user.
+ *
+ * @return <code>true</code> if all the procedures can be called,
+ * <code>false</code> otherwise.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ boolean allTablesAreSelectable() throws SQLException;
+
+ /**
+ * This method returns the URL for this database.
+ *
+ * @return The URL string for this database, or <code>null</code> if it
+ * is not known.
+ * @exception SQLException If an error occurs.
+ */
+ String getURL() throws SQLException;
+
+ /**
+ * This method returns the database username for this connection.
+ *
+ * @return The database username.
+ * @exception SQLException If an error occurs.
+ */
+ String getUserName() throws SQLException;
+
+ /**
+ * This method tests whether or not the database is in read only mode.
+ *
+ * @return <code>true</code> if the database is in read only mode,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isReadOnly() throws SQLException;
+
+ /**
+ * This method tests whether or not NULL's sort as high values.
+ *
+ * @return <code>true</code> if NULL's sort as high values, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean nullsAreSortedHigh() throws SQLException;
+
+ /**
+ * This method tests whether or not NULL's sort as low values.
+ *
+ * @return <code>true</code> if NULL's sort as low values, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean nullsAreSortedLow() throws SQLException;
+
+ /**
+ * This method tests whether or not NULL's sort as high values.
+ *
+ * @return <code>true</code> if NULL's sort as high values, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean nullsAreSortedAtStart() throws SQLException;
+
+ /**
+ * This method test whether or not NULL's are sorted to the end
+ * of the list regardless of ascending or descending sort order.
+ *
+ * @return <code>true</code> if NULL's always sort to the end,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean nullsAreSortedAtEnd() throws SQLException;
+
+ /**
+ * This method returns the name of the database product.
+ *
+ * @return The database product.
+ * @exception SQLException If an error occurs.
+ */
+ String getDatabaseProductName() throws SQLException;
+
+ /**
+ * This method returns the version of the database product.
+ *
+ * @return The version of the database product.
+ * @exception SQLException If an error occurs.
+ */
+ String getDatabaseProductVersion() throws SQLException;
+
+ /**
+ * This method returns the name of the JDBC driver.
+ *
+ * @return The name of the JDBC driver.
+ * @exception SQLException If an error occurs.
+ */
+ String getDriverName() throws SQLException;
+
+ /**
+ * This method returns the version of the JDBC driver.
+ *
+ * @return The version of the JDBC driver.
+ * @exception SQLException If an error occurs.
+ */
+ String getDriverVersion() throws SQLException;
+
+ /**
+ * This method returns the major version number of the JDBC driver.
+ *
+ * @return The major version number of the JDBC driver.
+ */
+ int getDriverMajorVersion();
+
+ /**
+ * This method returns the minor version number of the JDBC driver.
+ *
+ * @return The minor version number of the JDBC driver.
+ */
+ int getDriverMinorVersion();
+
+ /**
+ * This method tests whether or not the database uses local files to
+ * store tables.
+ *
+ * @return <code>true</code> if the database uses local files,
+ * <code>false</code> otherwise.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ boolean usesLocalFiles() throws SQLException;
+
+ /**
+ * This method tests whether or not the database uses a separate file for
+ * each table.
+ *
+ * @return <code>true</code> if the database uses a separate file for each
+ * table <code>false</code> otherwise.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ boolean usesLocalFilePerTable() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports identifiers
+ * with mixed case.
+ *
+ * @return <code>true</code> if the database supports mixed case identifiers,
+ * <code>false</code> otherwise.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsMixedCaseIdentifiers() throws SQLException;
+
+ /**
+ * This method tests whether or not the database treats mixed case
+ * identifiers as all upper case.
+ *
+ * @return <code>true</code> if the database treats all identifiers as
+ * upper case, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean storesUpperCaseIdentifiers() throws SQLException;
+
+ /**
+ * This method tests whether or not the database treats mixed case
+ * identifiers as all lower case.
+ *
+ * @return <code>true</code> if the database treats all identifiers as
+ * lower case, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean storesLowerCaseIdentifiers() throws SQLException;
+
+ /**
+ * This method tests whether or not the database stores mixed case
+ * identifers even if it treats them as case insensitive.
+ *
+ * @return <code>true</code> if the database stores mixed case identifiers,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean storesMixedCaseIdentifiers() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports quoted identifiers
+ * with mixed case.
+ *
+ * @return <code>true</code> if the database supports mixed case quoted
+ * identifiers, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsMixedCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * This method tests whether or not the database treats mixed case
+ * quoted identifiers as all upper case.
+ *
+ * @return <code>true</code> if the database treats all quoted identifiers
+ * as upper case, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean storesUpperCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * This method tests whether or not the database treats mixed case
+ * quoted identifiers as all lower case.
+ *
+ * @return <code>true</code> if the database treats all quoted identifiers
+ * as lower case, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean storesLowerCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * This method tests whether or not the database stores mixed case
+ * quoted identifers even if it treats them as case insensitive.
+ *
+ * @return <code>true</code> if the database stores mixed case quoted
+ * identifiers, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean storesMixedCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * This metohd returns the quote string for SQL identifiers.
+ *
+ * @return The quote string for SQL identifers, or a space if quoting
+ * is not supported.
+ * @exception SQLException If an error occurs.
+ */
+ String getIdentifierQuoteString() throws SQLException;
+
+ /**
+ * This method returns a comma separated list of all the SQL keywords in
+ * the database that are not in SQL92.
+ *
+ * @return The list of SQL keywords not in SQL92.
+ * @exception SQLException If an error occurs.
+ */
+ String getSQLKeywords() throws SQLException;
+
+ /**
+ * This method returns a comma separated list of math functions.
+ *
+ * @return The list of math functions.
+ * @exception SQLException If an error occurs.
+ */
+ String getNumericFunctions() throws SQLException;
+
+ /**
+ * This method returns a comma separated list of string functions.
+ *
+ * @return The list of string functions.
+ * @exception SQLException If an error occurs.
+ */
+ String getStringFunctions() throws SQLException;
+
+ /**
+ * This method returns a comma separated list of of system functions.
+ *
+ * @return A comma separated list of system functions.
+ * @exception SQLException If an error occurs.
+ */
+ String getSystemFunctions() throws SQLException;
+
+ /**
+ * This method returns comma separated list of time/date functions.
+ *
+ * @return The list of time/date functions.
+ * @exception SQLException If an error occurs.
+ */
+ String getTimeDateFunctions() throws SQLException;
+
+ /**
+ * This method returns the string used to escape wildcards in search strings.
+ *
+ * @return The string used to escape wildcards in search strings.
+ * @exception SQLException If an error occurs.
+ */
+ String getSearchStringEscape() throws SQLException;
+
+ /**
+ * This methods returns non-standard characters that can appear in
+ * unquoted identifiers.
+ *
+ * @return Non-standard characters that can appear in unquoted identifiers.
+ * @exception SQLException If an error occurs.
+ */
+ String getExtraNameCharacters() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports
+ * "ALTER TABLE ADD COLUMN"
+ *
+ * @return <code>true</code> if column add supported, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsAlterTableWithAddColumn() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports
+ * "ALTER TABLE DROP COLUMN"
+ *
+ * @return <code>true</code> if column drop supported, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsAlterTableWithDropColumn() throws SQLException;
+
+ /**
+ * This method tests whether or not column aliasing is supported.
+ *
+ * @return <code>true</code> if column aliasing is supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsColumnAliasing() throws SQLException;
+
+ /**
+ * This method tests whether the concatenation of a NULL and non-NULL
+ * value results in a NULL. This will always be true in fully JDBC compliant
+ * drivers.
+ *
+ * @return <code>true</code> if concatenating NULL and a non-NULL value
+ * returns a NULL, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean nullPlusNonNullIsNull() throws SQLException;
+
+ /**
+ * Tests whether or not CONVERT is supported.
+ *
+ * @return <code>true</code> if CONVERT is supported, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsConvert() throws SQLException;
+
+ /**
+ * This method tests whether or not CONVERT can be performed between the
+ * specified types. The types are contants from <code>Types</code>.
+ *
+ * @param fromType The SQL type to convert from.
+ * @param toType The SQL type to convert to.
+ * @return <code>true</code> if the conversion can be performed,
+ * <code>false</code> otherwise.
+ * @see Types
+ */
+ boolean supportsConvert(int fromType, int toType) throws
+ SQLException;
+
+ /**
+ * This method tests whether or not table correlation names are
+ * supported. This will be always be <code>true</code> in a fully JDBC
+ * compliant driver.
+ *
+ * @return <code>true</code> if table correlation names are supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsTableCorrelationNames() throws SQLException;
+
+ /**
+ * This method tests whether correlation names must be different from the
+ * name of the table.
+ *
+ * @return <code>true</code> if the correlation name must be different from
+ * the table name, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsDifferentTableCorrelationNames() throws SQLException;
+
+ /**
+ * This method tests whether or not expressions are allowed in an
+ * ORDER BY lists.
+ *
+ * @return <code>true</code> if expressions are allowed in ORDER BY
+ * lists, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsExpressionsInOrderBy() throws SQLException;
+
+ /**
+ * This method tests whether or ORDER BY on a non-selected column is
+ * allowed.
+ *
+ * @return <code>true</code> if a non-selected column can be used in an
+ * ORDER BY, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsOrderByUnrelated() throws SQLException;
+
+ /**
+ * This method tests whether or not GROUP BY is supported.
+ *
+ * @return <code>true</code> if GROUP BY is supported, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsGroupBy() throws SQLException;
+
+ /**
+ * This method tests whether GROUP BY on a non-selected column is
+ * allowed.
+ *
+ * @return <code>true</code> if a non-selected column can be used in a
+ * GROUP BY, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsGroupByUnrelated() throws SQLException;
+
+ /**
+ * This method tests whether or not a GROUP BY can add columns not in the
+ * select if it includes all the columns in the select.
+ *
+ * @return <code>true</code> if GROUP BY an add columns provided it includes
+ * all columns in the select, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsGroupByBeyondSelect() throws SQLException;
+
+ /**
+ * This method tests whether or not the escape character is supported in
+ * LIKE expressions. A fully JDBC compliant driver will always return
+ * <code>true</code>.
+ *
+ * @return <code>true</code> if escapes are supported in LIKE expressions,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsLikeEscapeClause() throws SQLException;
+
+ /**
+ * This method tests whether multiple result sets for a single statement are
+ * supported.
+ *
+ * @return <code>true</code> if multiple result sets are supported for a
+ * single statement, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsMultipleResultSets() throws SQLException;
+
+ /**
+ * This method test whether or not multiple transactions may be open
+ * at once, as long as they are on different connections.
+ *
+ * @return <code>true</code> if multiple transactions on different
+ * connections are supported, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsMultipleTransactions() throws SQLException;
+
+ /**
+ * This method tests whether or not columns can be defined as NOT NULL. A
+ * fully JDBC compliant driver always returns <code>true</code>.
+ *
+ * @return <code>true</code> if NOT NULL columns are supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsNonNullableColumns() throws SQLException;
+
+ /**
+ * This method tests whether or not the minimum grammer for ODBC is supported.
+ * A fully JDBC compliant driver will always return <code>true</code>.
+ *
+ * @return <code>true</code> if the ODBC minimum grammar is supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsMinimumSQLGrammar() throws SQLException;
+
+ /**
+ * This method tests whether or not the core grammer for ODBC is supported.
+ *
+ * @return <code>true</code> if the ODBC core grammar is supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsCoreSQLGrammar() throws SQLException;
+
+ /**
+ * This method tests whether or not the extended grammer for ODBC is supported.
+ *
+ * @return <code>true</code> if the ODBC extended grammar is supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsExtendedSQLGrammar() throws SQLException;
+
+ /**
+ * This method tests whether or not the ANSI92 entry level SQL
+ * grammar is supported. A fully JDBC compliant drivers must return
+ * <code>true</code>.
+ *
+ * @return <code>true</code> if the ANSI92 entry level SQL grammar is
+ * supported, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsANSI92EntryLevelSQL() throws SQLException;
+
+ /**
+ * This method tests whether or not the ANSI92 intermediate SQL
+ * grammar is supported.
+ *
+ * @return <code>true</code> if the ANSI92 intermediate SQL grammar is
+ * supported, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsANSI92IntermediateSQL() throws SQLException;
+
+ /**
+ * This method tests whether or not the ANSI92 full SQL
+ * grammar is supported.
+ *
+ * @return <code>true</code> if the ANSI92 full SQL grammar is
+ * supported, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsANSI92FullSQL() throws SQLException;
+
+ /**
+ * This method tests whether or not the SQL integrity enhancement
+ * facility is supported.
+ *
+ * @return <code>true</code> if the integrity enhancement facility is
+ * supported, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsIntegrityEnhancementFacility() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports outer joins.
+ *
+ * @return <code>true</code> if outer joins are supported, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsOuterJoins() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports full outer joins.
+ *
+ * @return <code>true</code> if full outer joins are supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsFullOuterJoins() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports limited outer joins.
+ *
+ * @return <code>true</code> if limited outer joins are supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsLimitedOuterJoins() throws SQLException;
+
+ /**
+ * This method returns the vendor's term for "schema".
+ *
+ * @return The vendor's term for schema.
+ * @exception SQLException if an error occurs.
+ */
+ String getSchemaTerm() throws SQLException;
+
+ /**
+ * This method returns the vendor's term for "procedure".
+ *
+ * @return The vendor's term for procedure.
+ * @exception SQLException if an error occurs.
+ */
+ String getProcedureTerm() throws SQLException;
+
+ /**
+ * This method returns the vendor's term for "catalog".
+ *
+ * @return The vendor's term for catalog.
+ * @exception SQLException if an error occurs.
+ */
+ String getCatalogTerm() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name appears at the beginning of
+ * a fully qualified table name.
+ *
+ * @return <code>true</code> if the catalog name appears at the beginning,
+ * <code>false</code> if it appears at the end.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isCatalogAtStart() throws SQLException;
+
+ /**
+ * This method returns the separator between the catalog name and the
+ * table name.
+ *
+ * @return The separator between the catalog name and the table name.
+ * @exception SQLException If an error occurs.
+ */
+ String getCatalogSeparator() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in a data
+ * manipulation statement.
+ *
+ * @return <code>true</code> if a catalog name can appear in a data
+ * manipulation statement, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSchemasInDataManipulation() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in a procedure
+ * call
+ *
+ * @return <code>true</code> if a catalog name can appear in a procedure
+ * call, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSchemasInProcedureCalls() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in a table definition.
+ *
+ * @return <code>true</code> if a catalog name can appear in a table
+ * definition, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSchemasInTableDefinitions() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in an index definition.
+ *
+ * @return <code>true</code> if a catalog name can appear in an index
+ * definition, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSchemasInIndexDefinitions() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in privilege definitions.
+ *
+ * @return <code>true</code> if a catalog name can appear in privilege
+ * definition, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSchemasInPrivilegeDefinitions() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in a data
+ * manipulation statement.
+ *
+ * @return <code>true</code> if a catalog name can appear in a data
+ * manipulation statement, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsCatalogsInDataManipulation() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in a procedure
+ * call
+ *
+ * @return <code>true</code> if a catalog name can appear in a procedure
+ * call, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsCatalogsInProcedureCalls() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in a table definition.
+ *
+ * @return <code>true</code> if a catalog name can appear in a table
+ * definition, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsCatalogsInTableDefinitions() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in an index definition.
+ *
+ * @return <code>true</code> if a catalog name can appear in an index
+ * definition, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsCatalogsInIndexDefinitions() throws SQLException;
+
+ /**
+ * This method tests whether a catalog name can appear in privilege definitions.
+ *
+ * @return <code>true</code> if a catalog name can appear in privilege
+ * definition, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException;
+
+ /**
+ * This method tests whether or not that database supports positioned
+ * deletes.
+ *
+ * @return <code>true</code> if positioned deletes are supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsPositionedDelete() throws SQLException;
+
+ /**
+ * This method tests whether or not that database supports positioned
+ * updates.
+ *
+ * @return <code>true</code> if positioned updates are supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsPositionedUpdate() throws SQLException;
+
+ /**
+ * This method tests whether or not SELECT FOR UPDATE is supported by the
+ * database.
+ *
+ * @return <code>true</code> if SELECT FOR UPDATE is supported
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSelectForUpdate() throws SQLException;
+
+ /**
+ * This method tests whether or not stored procedures are supported on
+ * this database.
+ *
+ * @return <code>true</code> if stored procedures are supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsStoredProcedures() throws SQLException;
+
+ /**
+ * This method tests whether or not subqueries are allowed in comparisons.
+ * A fully JDBC compliant driver will always return <code>true</code>.
+ *
+ * @return <code>true</code> if subqueries are allowed in comparisons,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSubqueriesInComparisons() throws SQLException;
+
+ /**
+ * This method tests whether or not subqueries are allowed in exists
+ * expressions. A fully JDBC compliant driver will always return
+ * <code>true</code>.
+ *
+ * @return <code>true</code> if subqueries are allowed in exists
+ * expressions, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSubqueriesInExists() throws SQLException;
+
+ /**
+ * This method tests whether subqueries are allowed in IN statements.
+ * A fully JDBC compliant driver will always return <code>true</code>.
+ *
+ * @return <code>true</code> if the driver supports subqueries in IN
+ * statements, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSubqueriesInIns() throws SQLException;
+
+ /**
+ * This method tests whether or not subqueries are allowed in quantified
+ * expressions. A fully JDBC compliant driver will always return
+ * <code>true</code>.
+ *
+ * @return <code>true</code> if subqueries are allowed in quantified
+ * expressions, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsSubqueriesInQuantifieds() throws SQLException;
+
+ /**
+ * This method test whether or not correlated subqueries are allowed. A
+ * fully JDBC compliant driver will always return <code>true</code>.
+ *
+ * @return <code>true</code> if correlated subqueries are allowed,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsCorrelatedSubqueries() throws SQLException;
+
+ /**
+ * This method tests whether or not the UNION statement is supported.
+ *
+ * @return <code>true</code> if UNION is supported, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsUnion() throws SQLException;
+
+ /**
+ * This method tests whether or not the UNION ALL statement is supported.
+ *
+ * @return <code>true</code> if UNION ALL is supported, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsUnionAll() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports cursors
+ * remaining open across commits.
+ *
+ * @return <code>true</code> if cursors can remain open across commits,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsOpenCursorsAcrossCommit() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports cursors
+ * remaining open across rollbacks.
+ *
+ * @return <code>true</code> if cursors can remain open across rollbacks,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsOpenCursorsAcrossRollback() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports statements
+ * remaining open across commits.
+ *
+ * @return <code>true</code> if statements can remain open across commits,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsOpenStatementsAcrossCommit() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports statements
+ * remaining open across rollbacks.
+ *
+ * @return <code>true</code> if statements can remain open across rollbacks,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsOpenStatementsAcrossRollback() throws SQLException;
+
+ /**
+ * This method returns the number of hex characters allowed in an inline
+ * binary literal.
+ *
+ * @return The number of hex characters allowed in a binary literal, 0 meaning
+ * either an unknown or unlimited number.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxBinaryLiteralLength() throws SQLException;
+
+ /**
+ * This method returns the maximum length of a character literal.
+ *
+ * @return The maximum length of a character literal.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxCharLiteralLength() throws SQLException;
+
+ /**
+ * This method returns the maximum length of a column name.
+ *
+ * @return The maximum length of a column name.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxColumnNameLength() throws SQLException;
+
+ /**
+ * This method returns the maximum number of columns in a GROUP BY statement.
+ *
+ * @return The maximum number of columns in a GROUP BY statement.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxColumnsInGroupBy() throws SQLException;
+
+ /**
+ * This method returns the maximum number of columns in an index.
+ *
+ * @return The maximum number of columns in an index.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxColumnsInIndex() throws SQLException;
+
+ /**
+ * This method returns the maximum number of columns in an ORDER BY statement.
+ *
+ * @return The maximum number of columns in an ORDER BY statement.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxColumnsInOrderBy() throws SQLException;
+
+ /**
+ * This method returns the maximum number of columns in a SELECT statement.
+ *
+ * @return The maximum number of columns in a SELECT statement.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxColumnsInSelect() throws SQLException;
+
+ /**
+ * This method returns the maximum number of columns in a table.
+ *
+ * @return The maximum number of columns in a table.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxColumnsInTable() throws SQLException;
+
+ /**
+ * This method returns the maximum number of connections this client
+ * can have to the database.
+ *
+ * @return The maximum number of database connections.
+ * @SQLException If an error occurs.
+ */
+ int getMaxConnections() throws SQLException;
+
+ /**
+ * This method returns the maximum length of a cursor name.
+ *
+ * @return The maximum length of a cursor name.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxCursorNameLength() throws SQLException;
+
+ /**
+ * This method returns the maximum length of an index.
+ *
+ * @return The maximum length of an index.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxIndexLength() throws SQLException;
+
+ /**
+ * This method returns the maximum length of a schema name.
+ *
+ * @return The maximum length of a schema name.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxSchemaNameLength() throws SQLException;
+
+ /**
+ * This method returns the maximum length of a procedure name.
+ *
+ * @return The maximum length of a procedure name.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxProcedureNameLength() throws SQLException;
+
+ /**
+ * This method returns the maximum length of a catalog name.
+ *
+ * @return The maximum length of a catalog name.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxCatalogNameLength() throws SQLException;
+
+ /**
+ * This method returns the maximum size of a row in bytes.
+ *
+ * @return The maximum size of a row.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxRowSize() throws SQLException;
+
+ /**
+ * This method tests whether or not the maximum row size includes BLOB's
+ *
+ * @return <code>true</code> if the maximum row size includes BLOB's,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean doesMaxRowSizeIncludeBlobs() throws SQLException;
+
+ /**
+ * This method includes the maximum length of a SQL statement.
+ *
+ * @return The maximum length of a SQL statement.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxStatementLength() throws SQLException;
+
+ /**
+ * This method returns the maximum number of statements that can be
+ * active at any time.
+ *
+ * @return The maximum number of statements that can be active at any time.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxStatements() throws SQLException;
+
+ /**
+ * This method returns the maximum length of a table name.
+ *
+ * @return The maximum length of a table name.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxTableNameLength() throws SQLException;
+
+ /**
+ * This method returns the maximum number of tables that may be referenced
+ * in a SELECT statement.
+ *
+ * @return The maximum number of tables allowed in a SELECT statement.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxTablesInSelect() throws SQLException;
+
+ /**
+ * This method returns the maximum length of a user name.
+ *
+ * @return The maximum length of a user name.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxUserNameLength() throws SQLException;
+
+ /**
+ * This method returns the default transaction isolation level of the
+ * database.
+ *
+ * @return The default transaction isolation level of the database.
+ * @exception SQLException If an error occurs.
+ * @see Connection
+ */
+ int getDefaultTransactionIsolation() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports transactions.
+ *
+ * @return <code>true</code> if the database supports transactions,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsTransactions() throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports the specified
+ * transaction isolation level.
+ *
+ * @param level The transaction isolation level.
+ *
+ * @return <code>true</code> if the specified transaction isolation level
+ * is supported, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsTransactionIsolationLevel(int level) throws
+ SQLException;
+
+ /**
+ * This method tests whether or not DDL and DML statements allowed within
+ * the same transaction.
+ *
+ * @return <code>true</code> if DDL and DML statements are allowed in the
+ * same transaction, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsDataDefinitionAndDataManipulationTransactions()
+ throws SQLException;
+
+ /**
+ * This method tests whether or not only DML statement are allowed
+ * inside a transaction.
+ *
+ * @return <code>true</code> if only DML statements are allowed in
+ * transactions, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsDataManipulationTransactionsOnly() throws
+ SQLException;
+
+ /**
+ * This method tests whether or not a DDL statement will cause the
+ * current transaction to be automatically committed.
+ *
+ * @return <code>true</code> if DDL causes an immediate transaction commit,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean dataDefinitionCausesTransactionCommit() throws SQLException;
+
+ /**
+ * This method tests whether or not DDL statements are ignored in
+ * transactions.
+ *
+ * @return <code>true</code> if DDL statements are ignored in transactions,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean dataDefinitionIgnoredInTransactions() throws SQLException;
+
+ /**
+ * This method returns a list of all the stored procedures matching the
+ * specified pattern in the given schema and catalog. This is returned
+ * a <code>ResultSet</code> with the following columns:
+ * <p>
+ * <ol>
+ * <li>PROCEDURE_CAT - The catalog the procedure is in, which may be
+ * <code>null</code>.</li>
+ * <li>PROCEDURE_SCHEM - The schema the procedures is in, which may be
+ * <code>null</code>.</li>
+ * <li>PROCEDURE_NAME - The name of the procedure.</li>
+ * <li>Unused</li>
+ * <li>Unused</li>
+ * <li>Unused</li>
+ * <li>REMARKS - A description of the procedure</li>
+ * <li>PROCEDURE_TYPE - Indicates the return type of the procedure, which
+ * is one of the contstants defined in this class
+ * (<code>procedureResultUnknown</code>, <code>procedureNoResult</code>, or
+ * <code>procedureReturnsResult</code>).</li>
+ * </ol>
+ *
+ * @param catalog The name of the catalog to return stored procedured from,
+ * or "" to return procedures from all catalogs.
+ * @param schemaPattern A schema pattern for the schemas to return stored
+ * procedures from, or "" to return procedures from all schemas.
+ * @param namePattern The pattern of procedures names to return.
+ * @returns A <code>ResultSet</code> with all the requested procedures.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getProcedures(String catalog, String schemaPattern, String
+ procedureNamePattern) throws SQLException;
+
+ /**
+ * This method returns a list of the parameter and result columns for
+ * the requested stored procedures. This is returned in the form of a
+ * <code>ResultSet</code> with the following columns:
+ * <p>
+ * <ol>
+ * <li>PROCEDURE_CAT - The catalog the procedure is in, which may be
+ * <code>null</code>.</li>
+ * <li>PROCEDURE_SCHEM - The schema the procedures is in, which may be
+ * <code>null</code>.</li>
+ * <li>PROCEDURE_NAME - The name of the procedure.</li>
+ * <li>COLUMN_NAME - The name of the column</li>
+ * <li>COLUMN_TYPE - The type of the column, which will be one of the
+ * contants defined in this class (<code>procedureColumnUnknown</code>,
+ * <code>procedureColumnIn</code>, <code>procedureColumnInOut</code>,
+ * <code>procedureColumnOut</code>, <code>procedureColumnReturn</code>,
+ * or <code>procedureColumnResult</code>).</li>
+ * <li>DATA_TYPE - The SQL type of the column. This is one of the constants
+ * defined in <code>Types</code>.</li>
+ * <li>TYPE_NAME - The string name of the data type for this column.</li>
+ * <li>PRECISION - The precision of the column.</li>
+ * <li>LENGTH - The length of the column in bytes</li>
+ * <li>SCALE - The scale of the column.</li>
+ * <li>RADIX - The radix of the column.</li>
+ * <li>NULLABLE - Whether or not the column is NULLABLE. This is one of
+ * the constants defined in this class (<code>procedureNoNulls</code>,
+ * <code>procedureNullable</code>, or <code>procedureNullableUnknown</code>)</li>
+ * <li>REMARKS - A description of the column.</li>
+ * </ol>
+ *
+ * @param catalog The name of the catalog to return stored procedured from,
+ * or "" to return procedures from all catalogs.
+ * @param schemaPattern A schema pattern for the schemas to return stored
+ * procedures from, or "" to return procedures from all schemas.
+ * @param namePattern The pattern of procedures names to return.
+ * @param columnPattern The pattern of column names to return.
+ * @returns A <code>ResultSet</code> with all the requested procedures.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getProcedureColumns(String catalog, String schemaPattern,
+ String procedureNamePattern, String columnNamePattern) throws
+ SQLException;
+
+ /**
+ * This method returns a list of the requested table as a
+ * <code>ResultSet</code> with the following columns:
+ *
+ * <ol>
+ * <li>TABLE_CAT - The catalog the table is in, which may be <code>null</code>.</li>
+ * <li>TABLE_SCHEM - The schema the table is in, which may be <code>null</code>.</li>
+ * <li>TABLE_NAME - The name of the table.</li>
+ * <li>TABLE_TYPE - A string describing the table type. This will be one
+ * of the values returned by the <code>getTableTypes()</code> method.</li>
+ * <li>REMARKS - Comments about the table.</li>
+ * </ol>
+ *
+ * @param catalog The name of the catalog to return tables from,
+ * or "" to return tables from all catalogs.
+ * @param schemaPattern A schema pattern for the schemas to return tables
+ * from, or "" to return tables from all schemas.
+ * @param namePattern The pattern of table names to return.
+ * @param types The list of table types to include; null returns all types.
+ * @returns A <code>ResultSet</code> with all the requested tables.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getTables(String catalog, String schemaPattern, String
+ tableNamePattern, String[] types) throws SQLException;
+
+ /**
+ * This method returns the list of database schemas as a
+ * <code>ResultSet</code>, with one column - TABLE_SCHEM - that is the
+ * name of the schema.
+ *
+ * @return A <code>ResultSet</code> with all the requested schemas.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getSchemas() throws SQLException;
+
+ /**
+ * This method returns the list of database catalogs as a
+ * <code>ResultSet</code> with one column - TABLE_CAT - that is the
+ * name of the catalog.
+ *
+ * @return A <code>ResultSet</code> with all the requested catalogs.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getCatalogs() throws SQLException;
+
+ /**
+ * This method returns the list of database table types as a
+ * <code>ResultSet</code> with one column - TABLE_TYPE - that is the
+ * name of the table type.
+ *
+ * @return A <code>ResultSet</code> with all the requested table types.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getTableTypes() throws SQLException;
+
+ /**
+ * This method returns a list of the tables columns for
+ * the requested tables. This is returned in the form of a
+ * <code>ResultSet</code> with the following columns:
+ * <p>
+ * <ol>
+ * <li>TABLE_CAT - The catalog the table is in, which may be
+ * <code>null</code>.</li>
+ * <li>TABLE_SCHEM - The schema the tables is in, which may be
+ * <code>null</code>.</li>
+ * <li>TABLE_NAME - The name of the table.</li>
+ * <li>COLUMN_NAME - The name of the column</li>
+ * <li>DATA_TYPE - The SQL type of the column. This is one of the constants
+ * defined in <code>Types</code>.</li>
+ * <li>TYPE_NAME - The string name of the data type for this column.</li>
+ * <li>COLUMN_SIZE - The size of the column.</li>
+ * <li>Unused</li>
+ * <li>NUM_PREC_RADIX - The radix of the column.</li>
+ * <li>NULLABLE - Whether or not the column is NULLABLE. This is one of
+ * the constants defined in this class (<code>tableNoNulls</code>,
+ * <code>tableNullable</code>, or <code>tableNullableUnknown</code>)</li>
+ * <li>REMARKS - A description of the column.</li>
+ * <li>COLUMN_DEF - The default value for the column, may be <code>null</code>.</li>
+ * <li>SQL_DATA_TYPE - Unused</li>
+ * <li>SQL_DATETIME_SUB - Unused</li>
+ * <li>CHAR_OCTET_LENGTH - For character columns, the maximum number of bytes
+ * in the column.</li>
+ * <li>ORDINAL_POSITION - The index of the column in the table.</li>
+ * <li>IS_NULLABLE - "NO" means no, "YES" means maybe, and an empty string
+ * means unknown.</li>
+ * </ol>
+ *
+ * @param catalog The name of the catalog to return table from,
+ * or "" to return tables from all catalogs.
+ * @param schemaPattern A schema pattern for the schemas to return
+ * tables from, or "" to return tables from all schemas.
+ * @param namePattern The pattern of tables names to return.
+ * @param columnPattern The pattern of column names to return.
+ * @returns A <code>ResultSet</code> with all the requested tables.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getColumns(String catalog, String schemaPattern, String
+ tableNamePattern, String columnNamePattern) throws SQLException;
+
+ /**
+ * This method returns the access rights that have been granted to the
+ * requested columns. This information is returned as a <code>ResultSet</code>
+ * with the following columns:
+ *
+ * <ol>
+ * <li>TABLE_CAT - The catalog the table is in, which may be
+ * <code>null</code>.</li>
+ * <li>TABLE_SCHEM - The schema the tables is in, which may be
+ * <code>null</code>.</li>
+ * <li>TABLE_NAME - The name of the table.</li>
+ * <li>COLUMN_NAME - The name of the column.</li>
+ * <li>GRANTOR - The entity that granted the access.</li>
+ * <li>GRANTEE - The entity granted the access.</li>
+ * <li>PRIVILEGE - The name of the privilege granted.</li>
+ * <li>IS_GRANTABLE - "YES" if the grantee can grant the privilege to
+ * others, "NO" if not, and <code>null</code> if unknown.</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param table The table name to return information for.
+ * @param columnPattern A pattern of column names to return information for.
+ * @return A <code>ResultSet</code> with all the requested privileges.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getColumnPrivileges(String catalog, String schema, String
+ table, String columnNamePattern) throws SQLException;
+
+ /**
+ * This method returns the access rights that have been granted to the
+ * requested tables. This information is returned as a <code>ResultSet</code>
+ * with the following columns:
+ *
+ * <ol>
+ * <li>TABLE_CAT - The catalog the table is in, which may be
+ * <code>null</code>.</li>
+ * <li>TABLE_SCHEM - The schema the tables is in, which may be
+ * <code>null</code>.</li>
+ * <li>TABLE_NAME - The name of the table.</li>
+ * <li>GRANTOR - The entity that granted the access.</li>
+ * <li>GRANTEE - The entity granted the access.</li>
+ * <li>PRIVILEGE - The name of the privilege granted.</li>
+ * <li>IS_GRANTABLE - "YES" if the grantee can grant the privilege to
+ * others, "NO" if not, and <code>null</code> if unknown.</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param tablePattern The table name pattern of tables to return
+ * information for.
+ * @return A <code>ResultSet</code> with all the requested privileges.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getTablePrivileges(String catalog, String schemaPattern,
+ String tableNamePattern) throws SQLException;
+
+ /**
+ * This method returns the best set of columns for uniquely identifying
+ * a row. It returns this information as a <code>ResultSet</code> with
+ * the following columns:
+ *
+ * <ol>
+ * <li>SCOPE - The scope of the results returned. This is one of the
+ * constants defined in this class (<code>bestRowTemporary</code>,
+ * <code>bestRowTransaction</code>, or <code>bestRowSession</code>).</li>
+ * <li>COLUMN_NAME - The name of the column.</li>
+ * <li>DATA_TYPE - The SQL type of the column. This is one of the constants
+ * defined in <code>Types</code>.</li>
+ * <li>TYPE_NAME - The string name of the data type for this column.</li>
+ * <li>COLUMN_SIZE - The precision of the columns</li>
+ * <li>BUFFER_LENGTH - Unused</li>
+ * <li>DECIMAL_DIGITS - The scale of the column.</li>
+ * <li>PSEUDO_COLUMN - Whether or not the best row identifier is a
+ * pseudo_column. This is one of the constants defined in this class
+ * (<code>bestRowUnknown</code>, <code>bestRowNotPseudo</code>, or
+ * <code>bestRowPseudo</code>).</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param table The table name to return information for.
+ * @param columnPattern A pattern of column names to return information for.
+ * @param scope One of the best row id scope constants from this class.
+ * @param nullable <code>true</code> to include columns that are nullable,
+ * <code>false</code> otherwise.
+ * @return A <code>ResultSet</code> with the best row identifier.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getBestRowIdentifier(String catalog, String schema,
+ String table, int scope, boolean nullable) throws SQLException;
+
+ /**
+ * This method returns the set of columns that are automatically updated
+ * when the row is update. It returns this information as a
+ * <code>ResultSet</code> with the following columns:
+ *
+ * <ol>
+ * <li>SCOPE - Unused</li>
+ * <li>COLUMN_NAME - The name of the column.</li>
+ * <li>DATA_TYPE - The SQL type of the column. This is one of the constants
+ * defined in <code>Types</code>.</li>
+ * <li>TYPE_NAME - The string name of the data type for this column.</li>
+ * <li>COLUMN_SIZE - The precision of the columns</li>
+ * <li>BUFFER_LENGTH - Unused</li>
+ * <li>DECIMAL_DIGITS - The scale of the column.</li>
+ * <li>PSEUDO_COLUMN - Whether or not the best row identifier is a
+ * pseudo_column. This is one of the constants defined in this class
+ * (<code>versionRowUnknown</code>, <code>versionRowNotPseudo</code>, or
+ * <code>versionRowPseudo</code>).</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param table The table name to return information for.
+ * @param columnPattern A pattern of column names to return information for.
+ * @return A <code>ResultSet</code> with the version columns.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getVersionColumns(String catalog, String schema,
+ String table) throws SQLException;
+
+ /**
+ * This method returns a list of a table's primary key columns. These
+ * are returned as a <code>ResultSet</code> with the following columns.
+ *
+ * <ol>
+ * <li>TABLE_CAT - The catalog of the table, which may be <code>null</code>.</li>
+ * <li>TABLE_SCHEM - The schema of the table, which may be <code>null</code>.</li>
+ * <li>TABLE_NAME - The name of the table.</li>
+ * <li>COLUMN_NAME - The name of the column.</li>
+ * <li>KEY_SEQ - The sequence number of the column within the primary key.</li>
+ * <li>PK_NAME - The name of the primary key, which may be <code>null</code>.</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param table The table name to return information for.
+ * @param columnPattern A pattern of column names to return information for.
+ * @return A <code>ResultSet</code> with the primary key columns.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getPrimaryKeys(String catalog, String schema, String table)
+ throws SQLException;
+
+ /**
+ * This method returns a list of the table's foreign keys. These are
+ * returned as a <code>ResultSet</code> with the following columns:
+ *
+ * <ol>
+ * <li>PKTABLE_CAT - The catalog of the table the key was imported from.</li>
+ * <li>PKTABLE_SCHEM - The schema of the table the key was imported from.</li>
+ * <li>PKTABLE_NAME - The name of the table the key was imported from.</li>
+ * <li>PKCOLUMN_NAME - The name of the column that was imported.</li>
+ * <li>FKTABLE_CAT - The foreign key catalog name.</li>
+ * <li>FKTABLE_SCHEM - The foreign key schema name.</li>
+ * <li>FKTABLE_NAME - The foreign key table name.</li>
+ * <li>FKCOLUMN_NAME - The foreign key column name.</li>
+ * <li>KEY_SEQ - The sequence number of the column within the foreign key.</li>
+ * <li>UPDATE_RULE - How the foreign key behaves when the primary key is
+ * updated. This is one of the constants defined in this class
+ * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
+ * <code>importedKeySetNull</code>, <code>importedKeySetDefault</code>, or
+ * <code>importedKeyRestrict</code>).</li>
+ * <li>DELETE_RULE - How the foreign key behaves when the primary key is
+ * deleted. This is one of the constants defined in this class
+ * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
+ * <code>importedKeySetNull</code>, or <code>importedKeySetDefault</code>)</li>
+ * <li>FK_NAME - The name of the foreign key.</li>
+ * <li>PK_NAME - The name of the primary key.</li>
+ * <li>DEFERRABILITY - The deferrability value. This is one of the
+ * constants defined in this table (<code>importedKeyInitiallyDeferred</code>,
+ * <code>importedKeyInitiallyImmediate</code>, or
+ * <code>importedKeyNotDeferrable</code>).</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param table The table name to return information for.
+ *
+ * @return A <code>ResultSet</code> with the foreign key columns.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getImportedKeys(String catalog, String schema,
+ String table) throws SQLException;
+
+ /**
+ * This method returns a list of the table's which use this table's
+ * primary key as a foreign key. The information is
+ * returned as a <code>ResultSet</code> with the following columns:
+ *
+ * <ol>
+ * <li>PKTABLE_CAT - The catalog of the table the key was imported from.</li>
+ * <li>PKTABLE_SCHEM - The schema of the table the key was imported from.</li>
+ * <li>PKTABLE_NAME - The name of the table the key was imported from.</li>
+ * <li>PKCOLUMN_NAME - The name of the column that was imported.</li>
+ * <li>FKTABLE_CAT - The foreign key catalog name.</li>
+ * <li>FKTABLE_SCHEM - The foreign key schema name.</li>
+ * <li>FKTABLE_NAME - The foreign key table name.</li>
+ * <li>FKCOLUMN_NAME - The foreign key column name.</li>
+ * <li>KEY_SEQ - The sequence number of the column within the foreign key.</li>
+ * <li>UPDATE_RULE - How the foreign key behaves when the primary key is
+ * updated. This is one of the constants defined in this class
+ * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
+ * <code>importedKeySetNull</code>, <code>importedKeySetDefault</code>, or
+ * <code>importedKeyRestrict</code>).</li>
+ * <li>DELETE_RULE - How the foreign key behaves when the primary key is
+ * deleted. This is one of the constants defined in this class
+ * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
+ * <code>importedKeySetNull</code>, or <code>importedKeySetDefault</code>)</li>
+ * <li>FK_NAME - The name of the foreign key.</li>
+ * <li>PK_NAME - The name of the primary key.</li>
+ * <li>DEFERRABILITY - The deferrability value. This is one of the
+ * constants defined in this table (<code>importedKeyInitiallyDeferred</code>,
+ * <code>importedKeyInitiallyImmediate</code>, or
+ * <code>importedKeyNotDeferrable</code>).</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param table The table name to return information for.
+ * @return A <code>ResultSet</code> with the requested information
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getExportedKeys(String catalog, String schema,
+ String table) throws SQLException;
+
+ /**
+ * This method returns a description of how one table imports another
+ * table's primary key as a foreign key. The information is
+ * returned as a <code>ResultSet</code> with the following columns:
+ *
+ * <ol>
+ * <li>PKTABLE_CAT - The catalog of the table the key was imported from.</li>
+ * <li>PKTABLE_SCHEM - The schema of the table the key was imported from.</li>
+ * <li>PKTABLE_NAME - The name of the table the key was imported from.</li>
+ * <li>PKCOLUMN_NAME - The name of the column that was imported.</li>
+ * <li>FKTABLE_CAT - The foreign key catalog name.</li>
+ * <li>FKTABLE_SCHEM - The foreign key schema name.</li>
+ * <li>FKTABLE_NAME - The foreign key table name.</li>
+ * <li>FKCOLUMN_NAME - The foreign key column name.</li>
+ * <li>KEY_SEQ - The sequence number of the column within the foreign key.</li>
+ * <li>UPDATE_RULE - How the foreign key behaves when the primary key is
+ * updated. This is one of the constants defined in this class
+ * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
+ * <code>importedKeySetNull</code>, <code>importedKeySetDefault</code>, or
+ * <code>importedKeyRestrict</code>).</li>
+ * <li>DELETE_RULE - How the foreign key behaves when the primary key is
+ * deleted. This is one of the constants defined in this class
+ * (<code>importedNoAction</code>, <code>importedKeyCascade</code>,
+ * <code>importedKeySetNull</code>, or <code>importedKeySetDefault</code>)</li>
+ * <li>FK_NAME - The name of the foreign key.</li>
+ * <li>PK_NAME - The name of the primary key.</li>
+ * <li>DEFERRABILITY - The deferrability value. This is one of the
+ * constants defined in this table (<code>importedKeyInitiallyDeferred</code>,
+ * <code>importedKeyInitiallyImmediate</code>, or
+ * <code>importedKeyNotDeferrable</code>).</li>
+ * </ol>
+ *
+ * @param primCatalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs, on the exporting side.
+ * @param primSchema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema, on the exporting side.
+ * @param primTable The table name to return information for, on the exporting
+ * side.
+ * @param forCatalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs, on the importing side.
+ * @param forSchema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema on the importing side.
+ * @param forTable The table name to return information for on the importing
+ * side.
+ * @return A <code>ResultSet</code> with the requested information
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getCrossReference(String primaryCatalog, String
+ primarySchema, String primaryTable, String foreignCatalog, String
+ foreignSchema, String foreignTable) throws SQLException;
+
+ /**
+ * This method returns a list of the SQL types supported by this
+ * database. The information is returned as a <code>ResultSet</code>
+ * with the following columns:
+ *
+ * <ol>
+ * <li>TYPE_NAME - The name of the data type.</li>
+ * <li>DATA_TYPE - A data type constant from <code>Types</code> for this
+ * type.</li>
+ * <li>PRECISION - The maximum precision of this type.</li>
+ * <li>LITERAL_PREFIX - Prefix value used to quote a literal, which may be
+ * <code>null</code>.</li>
+ * <li>LITERAL_SUFFIX - Suffix value used to quote a literal, which may be
+ * <code>null</code>.</li>
+ * <li>CREATE_PARAMS - The parameters used to create the type, which may be
+ * <code>null</code>.</li>
+ * <li>NULLABLE - Whether or not this type supports NULL values. This will
+ * be one of the constants defined in this interface
+ * (<code>typeNoNulls</code>, <code>typeNullable</code>, or
+ * <code>typeNullableUnknown</code>).</li>
+ * <li>CASE_SENSITIVE - Whether or not the value is case sensitive.</li>
+ * <li>SEARCHABLE - Whether or not "LIKE" expressions are supported in
+ * WHERE clauses for this type. This will be one of the constants defined
+ * in this interface (<code>typePredNone</code>, <code>typePredChar</code>,
+ * <code>typePredBasic</code>, or <code>typeSearchable</code>).</li>
+ * <li>UNSIGNED_ATTRIBUTE - Is the value of this type unsigned.</li>
+ * <li>FIXED_PREC_SCALE - Whether or not this type can be used for money.</li>
+ * <li>AUTO_INCREMENT - Whether or not this type supports auto-incrementing.</li>
+ * <li>LOCAL_TYPE_NAME - A localized name for this data type.</li>
+ * <li>MINIMUM_SCALE - The minimum scale supported by this type.</li>
+ * <li>MAXIMUM_SCALE - The maximum scale supported by this type.</li>
+ * <li>SQL_DATA_TYPE - Unused.</li>
+ * <li>SQL_DATETIME_SUB - Unused.</li>
+ * <li>NUM_PREC_RADIX - The radix of this data type.</li>
+ * </ol>
+ *
+ * @return A <code>ResultSet</code> with the list of available data types.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getTypeInfo() throws SQLException;
+
+ /**
+ * This method returns information about a tables indices and statistics.
+ * It is returned as a <code>ResultSet</code> with the following columns:
+ *
+ * <ol>
+ * <li>TABLE_CAT - The catalog of the table, which may be <code>null</code>.</li>
+ * <li>TABLE_SCHEM - The schema of the table, which may be <code>null</code>.</li>
+ * <li>TABLE_NAME - The name of the table.</li>
+ * <li>NON_UNIQUE - Are index values non-unique?</li>
+ * <li>INDEX_QUALIFIER The index catalog, which may be <code>null</code></li>
+ * <li>INDEX_NAME - The name of the index.</li>
+ * <li>TYPE - The type of index, which will be one of the constants defined
+ * in this interface (<code>tableIndexStatistic</code>,
+ * <code>tableIndexClustered</code>, <code>tableIndexHashed</code>, or
+ * <code>tableIndexOther</code>).</li>
+ * <li>ORDINAL_POSITION - The sequence number of this column in the index.
+ * This will be 0 when the index type is <code>tableIndexStatistic</code>.</li>
+ * <li>COLUMN_NAME - The name of this column in the index.</li>
+ * <li>ASC_OR_DESC - "A" for an ascending sort sequence, "D" for a
+ * descending sort sequence or <code>null</code> if a sort sequence is not
+ * supported.</li>
+ * <li>CARDINALITY - The number of unique rows in the index, or the number
+ * of rows in the table if the index type is <code>tableIndexStatistic</code>.</li>
+ * <li>PAGES - The number of pages used for the index, or the number of pages
+ * in the table if the index type is <code>tableIndexStatistic</code>.</li>
+ * <li>FILTER_CONDITION - The filter condition for this index, which may be
+ * <code>null</code>.</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or
+ * <code>null</code> to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param table The table name to return information for.
+ * @param unique <code>true</code> to return only unique indexes,
+ * <code>false</code> otherwise.
+ * @param approx <code>true</code> if data values can be approximations,
+ * <code>false</code> otherwise.
+ * @return A <code>ResultSet</code> with the requested index information
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getIndexInfo(String catalog, String schema, String table,
+ boolean unique, boolean approximate) throws SQLException;
+
+ /**
+ * This method tests whether or not the datbase supports the specified
+ * result type.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ *
+ * @return <code>true</code> if the result set type is supported,
+ * <code>false</code> otherwise.
+ *
+ * @exception SQLException If an error occurs.
+ *
+ * @see ResultSet
+ */
+ boolean supportsResultSetType(int type) throws SQLException;
+
+ /**
+ * This method tests whether the specified result set type and result set
+ * concurrency type are supported by the database.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @param concur The desired concurrency type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type is supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean supportsResultSetConcurrency(int type, int concurrency)
+ throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type sees its
+ * own updates.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type sees its own updates,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean ownUpdatesAreVisible(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type sees its
+ * own deletes.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type sees its own deletes,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean ownDeletesAreVisible(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type sees its
+ * own inserts.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type sees its own inserts,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean ownInsertsAreVisible(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type sees
+ * updates committed by others.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type sees other updates,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean othersUpdatesAreVisible(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type sees
+ * deletes committed by others.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type sees other deletes,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean othersDeletesAreVisible(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type sees
+ * inserts committed by others.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type sees other inserts,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean othersInsertsAreVisible(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type can detect
+ * a visible update by calling the <code>rowUpdated</code> method.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type can detect visible updates
+ * using <code>rowUpdated</code>, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean updatesAreDetected(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type can detect
+ * a visible delete by calling the <code>rowUpdated</code> method.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type can detect visible deletes
+ * using <code>rowUpdated</code>, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean deletesAreDetected(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified result set type can detect
+ * a visible insert by calling the <code>rowUpdated</code> method.
+ *
+ * @param type The desired result type, which is one of the constants
+ * defined in <code>ResultSet</code>.
+ * @return <code>true</code> if the result set type can detect visible inserts
+ * using <code>rowUpdated</code>, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ boolean insertsAreDetected(int type) throws SQLException;
+
+ /**
+ * This method tests whether or not the database supports batch updates.
+ *
+ * @return <code>true</code> if batch updates are supported,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean supportsBatchUpdates() throws SQLException;
+
+ /**
+ * This method returns the list of user defined data types in use. These
+ * are returned as a <code>ResultSet</code> with the following columns:
+ *
+ * <ol>
+ * <li>TYPE_CAT - The catalog name, which may be <code>null</code>.</li>
+ * <li>TYPE_SCEHM - The schema name, which may be <code>null</code>.</li>
+ * <li>TYPE_NAME - The user defined data type name.</li>
+ * <li>CLASS_NAME - The Java class name this type maps to.</li>
+ * <li>DATA_TYPE - A type identifier from <code>Types</code> for this type.
+ * This will be one of <code>JAVA_OBJECT</code>, <code>STRUCT</code>, or
+ * <code>DISTINCT</code>.</li>
+ * <li>REMARKS - Comments about this data type.</li>
+ * </ol>
+ *
+ * @param catalog The catalog to retrieve information from, or the empty string
+ * to return entities not associated with a catalog, or <code>null</code>
+ * to return information from all catalogs.
+ * @param schema The schema to retrieve information from, or the empty string
+ * to return entities not associated with a schema.
+ * @param typePattern The type name pattern to match.
+ * @param types The type identifier patterns (from <code>Types</code>) to
+ * match.
+ * @return A <code>ResultSet</code> with the requested type information
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet getUDTs(String catalog, String schemaPattern, String
+ typeNamePattern, int[] types) throws SQLException;
+
+ /**
+ * This method returns the <code>Connection</code> object that was used
+ * to generate the metadata in this object.
+ *
+ * @return The connection for this object.
+ * @exception SQLException If an error occurs.
+ */
+ Connection getConnection() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean supportsSavepoints() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean supportsNamedParameters() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean supportsMultipleOpenResults() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean supportsGetGeneratedKeys() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ ResultSet getSuperTypes(String catalog, String schemaPattern,
+ String typeNamePattern) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ ResultSet getSuperTables(String catalog, String schemaPattern,
+ String tableNamePattern) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ ResultSet getAttributes(String catalog, String schemaPattern, String
+ typeNamePattern, String attributeNamePattern) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean supportsResultSetHoldability(int holdability)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getResultSetHoldability() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getDatabaseMajorVersion() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getDatabaseMinorVersion() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getJDBCMajorVersion() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getJDBCMinorVersion() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getSQLStateType() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean locatorsUpdateCopy() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean supportsStatementPooling() throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/Date.java b/libjava/classpath/java/sql/Date.java
new file mode 100644
index 00000000000..48a274f331e
--- /dev/null
+++ b/libjava/classpath/java/sql/Date.java
@@ -0,0 +1,188 @@
+/* Date.java -- Wrapper around java.util.Date
+ Copyright (C) 1999, 2000, 2003 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.sql;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+/**
+ * This class is a wrapper around java.util.Date to allow the JDBC
+ * driver to identify the value as a SQL Date.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Date extends java.util.Date
+{
+ static final long serialVersionUID = 1511598038487230103L;
+
+ /**
+ * Used for parsing and formatting this date.
+ */
+ private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+
+ /**
+ * This method initializes a new instance of this class with the
+ * specified year, month, and day.
+ *
+ * @param year The year of this date minue 1900.
+ * @param month The month of this date (0-11).
+ * @param day The day of this date (1-31).
+ *
+ * @deprecated
+ */
+ public Date(int year, int month, int day)
+ {
+ super(year, month, day);
+ }
+
+ /**
+ * This method initializes a new instance of this class with the
+ * specified time value representing the number of seconds since
+ * Jan 1, 1970 at 12:00 midnight GMT.
+ *
+ * @param time The time value to intialize this date to.
+ */
+ public Date(long date)
+ {
+ super(date);
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public int getHours() throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public int getMinutes() throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public int getSeconds() throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public void setHours(int newValue) throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public void setMinutes(int newValue) throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public void setSeconds(int newValue) throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method returns a new instance of this class by parsing a
+ * date in JDBC format into a Java date.
+ *
+ * @param str The string to parse.
+ * @return The resulting <code>java.sql.Date</code> value.
+ *
+ * @deprecated
+ */
+ public static Date valueOf (String str)
+ {
+ try
+ {
+ java.util.Date d = (java.util.Date) sdf.parseObject(str);
+
+ if (d == null)
+ throw new IllegalArgumentException(str);
+ else
+ return new Date(d.getTime());
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException(str);
+ }
+ }
+
+ /**
+ * This method returns this date in JDBC format.
+ *
+ * @return This date as a string.
+ *
+ * @deprecated
+ */
+ public String toString()
+ {
+ return sdf.format(this);
+ }
+}
diff --git a/libjava/classpath/java/sql/Driver.java b/libjava/classpath/java/sql/Driver.java
new file mode 100644
index 00000000000..10f83ef2f8b
--- /dev/null
+++ b/libjava/classpath/java/sql/Driver.java
@@ -0,0 +1,123 @@
+/* Driver.java -- A JDBC driver
+ Copyright (C) 1999, 2000 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.sql;
+
+import java.util.Properties;
+
+/**
+ * This interface specifies a mechanism for accessing a JDBC database
+ * driver. When the class implementing this method is loaded, it should
+ * register an instance of itself with the <code>DriverManager</code> in
+ * a static initializer.
+ * <p>
+ * Because the <code>DriverManager</code> might attempt to use several
+ * drivers to find one that can connect to the requested database,
+ * this driver should not cause large numbers of classes and code to
+ * be loaded. If another driver is the one that ends up performing the
+ * request, any loading done by this driver would be wasted.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Driver
+{
+ /**
+ * This method connects to the specified database using the connection
+ * properties supplied. If the driver does not understand the database
+ * URL, it should return <code>null</code> instead of throwing an
+ * exception since the <code>DriverManager</code> will probe a driver
+ * in this manner.
+ *
+ * @param url The URL string for this connection.
+ * @param properties The list of database connection properties.
+ * @return A <code>Connection</code> object for the newly established
+ * connection, or <code>null</code> if the URL is not understood.
+ * @exception SQLException If an error occurs.
+ */
+ Connection connect(String url, Properties info) throws SQLException;
+
+ /**
+ * This method tests whether or not the driver believes it can connect to
+ * the specified database. The driver should only test whether it
+ * understands and accepts the URL. It should not necessarily attempt to
+ * probe the database for a connection.
+ *
+ * @param The database URL string.
+ * @return <code>true</code> if the drivers can connect to the database,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean acceptsURL(String url) throws SQLException;
+
+ /**
+ * This method returns an array of possible properties that could be
+ * used to connect to the specified database.
+ *
+ * @param url The URL string of the database to connect to.
+ * @param properties The list of properties the caller is planning to use
+ * to connect to the database.
+ * @return A list of possible additional properties for a connection to this
+ * database. This list may be empty.
+ * @exception SQLException If an error occurs.
+ */
+ DriverPropertyInfo[] getPropertyInfo(String url, Properties properties)
+ throws SQLException;
+
+ /**
+ * This method returns the major version number of the driver.
+ *
+ * @return The major version number of the driver.
+ */
+ int getMajorVersion();
+
+ /**
+ * This method returns the minor version number of the driver.
+ *
+ * @return The minor version number of the driver.
+ */
+ int getMinorVersion();
+
+ /**
+ * This method tests whether or not the driver is JDBC compliant. This
+ * method should only return <code>true</code> if the driver has been
+ * certified as JDBC compliant.
+ *
+ * @return <code>true</code> if the driver has been certified JDBC compliant,
+ * <code>false</code> otherwise.
+ */
+ boolean jdbcCompliant();
+}
diff --git a/libjava/classpath/java/sql/DriverManager.java b/libjava/classpath/java/sql/DriverManager.java
new file mode 100644
index 00000000000..9e252abcc60
--- /dev/null
+++ b/libjava/classpath/java/sql/DriverManager.java
@@ -0,0 +1,346 @@
+/* DriverManager.java -- Manage JDBC drivers
+ Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.sql;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * This class manages the JDBC drivers in the system. It maintains a
+ * registry of drivers and locates the appropriate driver to handle a
+ * JDBC database URL.
+ * <p>
+ * On startup, <code>DriverManager</code> loads all the managers specified
+ * by the system property <code>jdbc.drivers</code>. The value of this
+ * property should be a colon separated list of fully qualified driver
+ * class names. Additional drivers can be loaded at any time by
+ * simply loading the driver class with <code>class.forName(String)</code>.
+ * The driver should automatically register itself in a static
+ * initializer.
+ * <p>
+ * The methods in this class are all <code>static</code>. This class
+ * cannot be instantiated.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class DriverManager
+{
+ /**
+ * This is the log stream for JDBC drivers.
+ */
+ private static PrintStream log_stream;
+
+ /**
+ * This is the log writer for JDBC drivers.
+ */
+ private static PrintWriter log_writer;
+
+ /**
+ * This is the login timeout used by JDBC drivers.
+ */
+ private static int login_timeout;
+
+ /**
+ * This is the list of JDBC drivers that are loaded.
+ */
+ private static Vector drivers;
+ // Hmm, seems like we might want to do a Hashtable and lookup by something,
+ // but what would it be?
+
+ // Load all drivers on startup
+ static
+ {
+ drivers = new Vector();
+
+ String driver_string = System.getProperty("jdbc.drivers");
+ if (driver_string != null)
+ {
+ StringTokenizer st = new StringTokenizer(driver_string);
+ while (st.hasMoreTokens())
+ {
+ String driver_classname = st.nextToken();
+
+ try
+ {
+ Class.forName(driver_classname); // The driver registers itself
+ }
+ catch (Exception e)
+ {
+ // Ignore not founds
+ }
+ }
+ }
+
+ }
+
+ /** Can't be instantiated. */
+ private DriverManager()
+ {
+ }
+
+ /**
+ * This method returns the log writer being used by all JDBC drivers.
+ * This method should be used in place of the deprecated
+ * <code>getLogStream</code> method.
+ *
+ * @return The log writer in use by JDBC drivers.
+ */
+ public static PrintWriter getLogWriter()
+ {
+ return log_writer;
+ }
+
+ /**
+ * This method sets the log writer being used by JDBC drivers. This is a
+ * system-wide parameter that affects all drivers. Note that since there
+ * is no way to retrieve a <code>PrintStream</code> from a
+ * <code>PrintWriter</code>, this method cannot set the log stream in
+ * use by JDBC. Thus any older drivers may not see this setting.
+ *
+ * @param out The new log writer for JDBC.
+ */
+ public static void setLogWriter(PrintWriter out)
+ {
+ DriverManager.log_writer = out;
+ }
+
+/**
+ * This method attempts to return a connection to the specified
+ * JDBC URL string using the specified connection properties.
+ *
+ * @param url The JDBC URL string to connect to.
+ * @param properties The connection properties.
+ *
+ * @return A <code>Connection</code> to that URL.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ public static Connection getConnection(String url, Properties properties)
+ throws SQLException
+ {
+ Driver d = getDriver(url);
+ if (d == null)
+ throw new SQLException("Driver not found for URL: " + url);
+
+ return d.connect(url, properties);
+ }
+
+
+ /**
+ * This method attempts to return a connection to the specified
+ * JDBC URL string using the specified username and password.
+ *
+ * @param url The JDBC URL string to connect to.
+ * @param user The username to connect with.
+ * @param password The password to connect with.
+ * @return A <code>Connection</code> to that URL.
+ * @exception SQLException If an error occurs.
+ */
+ public static Connection getConnection(String url, String user,
+ String password) throws SQLException
+ {
+ Properties p = new Properties();
+
+ if (user != null)
+ p.setProperty("user", user);
+ if (password != null)
+ p.setProperty("password", password);
+
+ return getConnection(url, p);
+ }
+
+ /**
+ * This method attempts to return a connection to the specified
+ * JDBC URL string.
+ *
+ * @param url The JDBC URL string to connect to.
+ *
+ * @return A <code>Connection</code> to that URL.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ public static Connection getConnection(String url) throws SQLException
+ {
+ return getConnection(url, new Properties());
+ }
+
+ /**
+ * This method returns a driver that can connect to the specified
+ * JDBC URL string. This will be selected from among drivers loaded
+ * at initialization time and those drivers manually loaded by the
+ * same class loader as the caller.
+ *
+ * @param url The JDBC URL string to find a driver for.
+ *
+ * @return A <code>Driver</code> that can connect to the specified
+ * URL.
+ *
+ * @exception SQLException If an error occurs, or no suitable driver can be found.
+ */
+ public static Driver getDriver(String url) throws SQLException
+ {
+ // FIXME: Limit driver search to the appropriate subset of loaded drivers.
+ Enumeration e = drivers.elements();
+ while(e.hasMoreElements())
+ {
+ Driver d = (Driver)e.nextElement();
+ if (d.acceptsURL(url))
+ return d;
+ }
+
+ throw new SQLException("No driver found for " + url);
+ }
+
+ /**
+ * This method registers a new driver with the manager. This is normally
+ * called by the driver itself in a static initializer.
+ *
+ * @param driver The new <code>Driver</code> to add.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ public static void registerDriver(Driver driver) throws SQLException
+ {
+ if (! drivers.contains(driver))
+ drivers.addElement(driver);
+ }
+
+/**
+ * This method de-registers a driver from the manager.
+ *
+ * @param driver The <code>Driver</code> to unregister.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ public static void deregisterDriver(Driver driver) throws SQLException
+ {
+ if (drivers.contains(driver))
+ drivers.removeElement(driver);
+ }
+
+ /**
+ * This method returns a list of all the currently registered JDBC drivers
+ * that were loaded by the current <code>ClassLoader</code>.
+ *
+ * @return An <code>Enumeration</code> of all currently loaded JDBC drivers.
+ */
+ public static Enumeration getDrivers()
+ {
+ Vector v = new Vector();
+ Enumeration e = drivers.elements();
+
+ // Is this right?
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+
+ while(e.hasMoreElements())
+ {
+ Object obj = e.nextElement();
+
+ ClassLoader loader = obj.getClass().getClassLoader();
+
+ if (loader == null)
+ loader = ClassLoader.getSystemClassLoader();
+ if (! loader.equals(cl))
+ continue;
+
+ v.addElement(obj);
+ }
+
+ return v.elements();
+ }
+
+ /**
+ * This method set the login timeout used by JDBC drivers. This is a
+ * system-wide parameter that applies to all drivers.
+ *
+ * @param login_timeout The new login timeout value.
+ */
+ public static void setLoginTimeout(int seconds)
+ {
+ DriverManager.login_timeout = login_timeout;
+ }
+
+ /**
+ * This method returns the login timeout in use by JDBC drivers systemwide.
+ *
+ * @return The login timeout.
+ */
+ public static int getLoginTimeout()
+ {
+ return login_timeout;
+ }
+
+ /**
+ * This method sets the log stream in use by JDBC.
+ *
+ * @param log_stream The log stream in use by JDBC.
+ *
+ * @deprecated Use <code>setLogWriter</code> instead.
+ */
+ public static void setLogStream(PrintStream out)
+ {
+ DriverManager.log_stream = log_stream;
+ }
+
+ /**
+ * This method returns the log stream in use by JDBC.
+ *
+ * @return The log stream in use by JDBC.
+ *
+ * @deprecated Use <code>getLogWriter()</code> instead.
+ */
+ public static PrintStream getLogStream()
+ {
+ return log_stream;
+ }
+
+ /**
+ * This method prints the specified line to the log stream.
+ *
+ * @param str The string to write to the log stream.
+ */
+ public static void println(String message)
+ {
+ if (log_stream != null) // Watch for user not using logging
+ log_stream.println(message);
+ }
+}
diff --git a/libjava/classpath/java/sql/DriverPropertyInfo.java b/libjava/classpath/java/sql/DriverPropertyInfo.java
new file mode 100644
index 00000000000..34e40fa0c3e
--- /dev/null
+++ b/libjava/classpath/java/sql/DriverPropertyInfo.java
@@ -0,0 +1,88 @@
+/* DriverPropertyInfo.java -- Property information about drivers.
+ Copyright (C) 1999 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.sql;
+
+/**
+ * This class holds a driver property that can be used for querying or
+ * setting driver configuration parameters.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class DriverPropertyInfo
+{
+ /**
+ * The name of the property.
+ */
+ public String name;
+
+ /**
+ * A description of the property, possibly <code>null</code>.
+ */
+ public String description;
+
+ /**
+ * A flag indicating whether or not a value for this property is required
+ * in order to connect to the database.
+ */
+ public boolean required;
+
+ /**
+ * This is the value of the property.
+ */
+ public String value;
+
+ /**
+ * If values are restricted to certain choices, this is the list of valid
+ * ones. Otherwise it is <code>null</code>.
+ */
+ public String[] choices;
+
+ /**
+ * This method initializes a new instance of <code>DriverPropertyInfo</code>
+ * with the specified name and value. All other fields are defaulted.
+ *
+ * @param name The name of the property.
+ * @param value The value to assign to the property.
+ */
+ public DriverPropertyInfo(String name, String value)
+ {
+ this.name = name;
+ this.value = value;
+ }
+}
diff --git a/libjava/classpath/java/sql/ParameterMetaData.java b/libjava/classpath/java/sql/ParameterMetaData.java
new file mode 100644
index 00000000000..b3a75fd2058
--- /dev/null
+++ b/libjava/classpath/java/sql/ParameterMetaData.java
@@ -0,0 +1,103 @@
+/* ParameterMetaData.java
+ Copyright (C) 2002 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.sql;
+
+/**
+ * @since 1.4
+ */
+public interface ParameterMetaData
+{
+ int parameterNoNulls = 0;
+
+ int parameterNullable = 1;
+
+ int parameterNullableUnknown = 2;
+
+ int parameterModeUnknown = 0;
+
+ int parameterModeIn = 1;
+
+ int parameterModeInOut = 2;
+
+ int parameterModeOut = 4;
+
+ /**
+ * @since 1.4
+ */
+ int getParameterCount() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int isNullable(int param) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean isSigned(int param) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getPrecision(int param) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getScale(int param) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getParameterType(int param) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ String getParameterTypeName(int param) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ String getParameterClassName(int param) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getParameterMode(int param) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/PreparedStatement.java b/libjava/classpath/java/sql/PreparedStatement.java
new file mode 100644
index 00000000000..3aedbc59300
--- /dev/null
+++ b/libjava/classpath/java/sql/PreparedStatement.java
@@ -0,0 +1,438 @@
+/* PreparedStatement.java -- Interface for pre-compiled statements.
+ Copyright (C) 1999, 2000 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.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.util.Calendar;
+
+/**
+ * This interface provides a mechanism for executing pre-compiled
+ * statements. This provides greater efficiency when calling the same
+ * statement multiple times. Parameters are allowed in a statement,
+ * providings for maximum reusability.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface PreparedStatement extends Statement
+{
+ /**
+ * This method executes a prepared SQL query and returns its ResultSet.
+ *
+ * @return The ResultSet of the SQL statement.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet executeQuery() throws SQLException;
+
+ /**
+ * This method executes an SQL INSERT, UPDATE or DELETE statement. SQL
+ * statements that return nothing such as SQL DDL statements can be executed.
+ *
+ * @return The result is either the row count for INSERT, UPDATE or DELETE
+ * statements; or 0 for SQL statements that return nothing.
+ * @exception SQLException If an error occurs.
+ */
+ int executeUpdate() throws SQLException;
+
+ /**
+ * This method populates the specified parameter with a SQL NULL value
+ * for the specified type.
+ *
+ * @param index The index of the parameter to set.
+ * @param type The SQL type identifier of the parameter from <code>Types</code>
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void setNull(int parameterIndex, int sqlType) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>boolean</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setBoolean(int parameterIndex, boolean x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>byte</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setByte(int parameterIndex, byte x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>short</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setShort(int parameterIndex, short x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>int</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setInt(int parameterIndex, int x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>long</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setLong(int parameterIndex, long x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>float</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setFloat(int parameterIndex, float x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>double</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setDouble(int parameterIndex, double x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>java.math.BigDecimal</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setBigDecimal(int parameterIndex, BigDecimal x) throws
+ SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>String</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setString(int parameterIndex, String x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>byte</code> array value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setBytes(int parameterIndex, byte[] x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>java.sql.Date</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setDate(int parameterIndex, Date x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>java.sql.Time</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setTime(int parameterIndex, Time x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>java.sql.Timestamp</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setTimestamp(int parameterIndex, Timestamp x)
+ throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * ASCII <code>InputStream</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param length The number of bytes in the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void setAsciiStream(int parameterIndex, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * Unicode UTF-8 <code>InputStream</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param length The number of bytes in the stream.
+ * @exception SQLException If an error occurs.
+ * @deprecated
+ */
+ void setUnicodeStream(int parameterIndex, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * binary <code>InputStream</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param length The number of bytes in the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void setBinaryStream(int parameterIndex, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * This method clears all of the input parameter that have been
+ * set on this statement.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void clearParameters() throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>Object</code> value. The specified SQL object type will be used.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param type The SQL type to use for the parameter, from <code>Types</code>
+ * @param scale The scale of the value, for numeric values only.
+ * @exception SQLException If an error occurs.
+ * @see Types
+ */
+ void setObject(int parameterIndex, Object x, int targetSqlType,
+ int scale) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>Object</code> value. The specified SQL object type will be used.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param type The SQL type to use for the parameter, from <code>Types</code>
+ * @exception SQLException If an error occurs.
+ * @see Types
+ */
+ void setObject(int parameterIndex, Object x, int targetSqlType)
+ throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>Object</code> value. The default object type to SQL type mapping
+ * will be used.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setObject(int parameterIndex, Object x) throws SQLException;
+
+ /**
+ * This method executes a prepared SQL query.
+ * Some prepared statements return multiple results; the execute method
+ * handles these complex statements as well as the simpler form of
+ * statements handled by executeQuery and executeUpdate.
+ *
+ * @return The result of the SQL statement.
+ * @exception SQLException If an error occurs.
+ */
+ boolean execute() throws SQLException;
+
+ /**
+ * This method adds a set of parameters to the batch for JDBC 2.0.
+ * @exception SQLException If an error occurs.
+ */
+ void addBatch() throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * character <code>Reader</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param length The number of bytes in the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void setCharacterStream(int parameterIndex, Reader reader,
+ int length) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>Ref</code> value. The default object type to SQL type mapping
+ * will be used.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setRef(int i, Ref x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>Blob</code> value. The default object type to SQL type mapping
+ * will be used.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setBlob(int i, Blob x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>Clob</code> value. The default object type to SQL type mapping
+ * will be used.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setClob(int i, Clob x) throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>Array</code> value. The default object type to SQL type mapping
+ * will be used.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @exception SQLException If an error occurs.
+ */
+ void setArray(int i, Array x) throws SQLException;
+
+ /**
+ * This method returns meta data for the result set from this statement.
+ *
+ * @return Meta data for the result set from this statement.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSetMetaData getMetaData() throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>java.sql.Date</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param calendar The <code>Calendar</code> to use for timezone and locale.
+ * @exception SQLException If an error occurs.
+ */
+ void setDate(int parameterIndex, Date x, Calendar cal)
+ throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>java.sql.Time</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param calendar The <code>Calendar</code> to use for timezone and locale.
+ * @exception SQLException If an error occurs.
+ */
+ void setTime(int parameterIndex, Time x, Calendar cal)
+ throws SQLException;
+
+ /**
+ * This method sets the specified parameter from the given Java
+ * <code>java.sql.Timestamp</code> value.
+ *
+ * @param index The index of the parameter value to set.
+ * @param value The value of the parameter.
+ * @param calendar The <code>Calendar</code> to use for timezone and locale.
+ * @exception SQLException If an error occurs.
+ */
+ void setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
+ throws SQLException;
+
+ /**
+ * This method populates the specified parameter with a SQL NULL value
+ * for the specified type.
+ *
+ * @param index The index of the parameter to set.
+ * @param type The SQL type identifier of the parameter from <code>Types</code>
+ * @param name The name of the data type, for user defined types.
+ * @exception SQLException If an error occurs.
+ */
+ void setNull(int paramIndex, int sqlType, String typeName)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setURL(int parameterIndex, URL x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ ParameterMetaData getParameterMetaData() throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/Ref.java b/libjava/classpath/java/sql/Ref.java
new file mode 100644
index 00000000000..4ebd5e64898
--- /dev/null
+++ b/libjava/classpath/java/sql/Ref.java
@@ -0,0 +1,75 @@
+/* Ref.java -- Reference to a SQL structured type.
+ Copyright (C) 1999, 2000 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.sql;
+
+import java.util.Map;
+
+/**
+ * This interface provides a mechanism for obtaining information about
+ * a SQL structured type
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.2
+ */
+public interface Ref
+{
+ /**
+ * This method returns the fully qualified name of the SQL structured
+ * type of the referenced item.
+ *
+ * @return The fully qualified name of the SQL structured type.
+ * @exception SQLException If an error occurs.
+ * @since 1.2
+ */
+ String getBaseTypeName() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Object getObject(Map map) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ Object getObject() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void setObject(Object value) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/ResultSet.java b/libjava/classpath/java/sql/ResultSet.java
new file mode 100644
index 00000000000..97f2897d423
--- /dev/null
+++ b/libjava/classpath/java/sql/ResultSet.java
@@ -0,0 +1,1530 @@
+/* ResultSet.java -- A SQL statement result set.
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.util.Calendar;
+import java.util.Map;
+
+/**
+ * This interface provides access to the data set returned by a SQL
+ * statement. An instance of this interface is returned by the various
+ * execution methods in the <code>Statement</code>.
+ *
+ * <p> This class models a cursor, which can be stepped through one row at a
+ * time. Methods are provided for accessing columns by column name or by
+ * index.</p>
+ *
+ * <p> Note that a result set is invalidated if the statement that returned
+ * it is closed.</p>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface ResultSet
+{
+ /**
+ * The rows will be processed in order from first to last.
+ */
+ int FETCH_FORWARD = 1000;
+
+ /**
+ * The rows will be processed in order from last to first.
+ */
+ int FETCH_REVERSE = 1001;
+
+ /**
+ * The rows will be processed in an unknown order
+ */
+ int FETCH_UNKNOWN = 1002;
+
+ /**
+ * This type of result set may only step forward through the rows returned.
+ */
+ int TYPE_FORWARD_ONLY = 1003;
+
+ /**
+ * This type of result set is scrollable and is not sensitive to changes
+ * made by other statements.
+ */
+ int TYPE_SCROLL_INSENSITIVE = 1004;
+
+ /**
+ * This type of result set is scrollable and is also sensitive to changes
+ * made by other statements.
+ */
+ int TYPE_SCROLL_SENSITIVE = 1005;
+
+ /**
+ * The concurrency mode of for the result set may not be modified.
+ */
+ int CONCUR_READ_ONLY = 1007;
+
+ /**
+ * The concurrency mode of for the result set may be modified.
+ */
+ int CONCUR_UPDATABLE = 1008;
+
+ int HOLD_CURSORS_OVER_COMMIT = 1;
+
+ int CLOSE_CURSORS_AT_COMMIT = 2;
+
+ /**
+ * This method advances to the next row in the result set. Any streams
+ * open on the current row are closed automatically.
+ *
+ * @return <code>true</code> if the next row exists, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean next() throws SQLException;
+
+ /**
+ * This method closes the result set and frees any associated resources.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void close() throws SQLException;
+
+ /**
+ * This method tests whether the value of the last column that was fetched
+ * was actually a SQL NULL value.
+ *
+ * @return <code>true</code> if the last column fetched was a NULL,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean wasNull() throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>String</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>String</code>.
+ * @exception SQLException If an error occurs.
+ */
+ String getString(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>boolean</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>boolean</code>.
+ * @exception SQLException If an error occurs.
+ */
+ boolean getBoolean(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>byte</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>byte</code>.
+ * @exception SQLException If an error occurs.
+ */
+ byte getByte(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>short</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>short</code>.
+ * @exception SQLException If an error occurs.
+ */
+ short getShort(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>int</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>int</code>.
+ * @exception SQLException If an error occurs.
+ */
+ int getInt(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>long</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>long</code>.
+ * @exception SQLException If an error occurs.
+ */
+ long getLong(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>float</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>float</code>.
+ * @exception SQLException If an error occurs.
+ */
+ float getFloat(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>double</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>double</code>.
+ * @exception SQLException If an error occurs.
+ */
+ double getDouble(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>BigDecimal</code>.
+ *
+ * @param index The index of the column to return.
+ * @param scale The number of digits to the right of the decimal to return.
+ * @return The column value as a <code>BigDecimal</code>.
+ * @exception SQLException If an error occurs.
+ * @deprecated
+ */
+ BigDecimal getBigDecimal(int columnIndex, int scale)
+ throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * byte array.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a byte array
+ * @exception SQLException If an error occurs.
+ */
+ byte[] getBytes(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>java.sql.Date</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>java.sql.Date</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Date getDate(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>java.sql.Time</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>java.sql.Time</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Time getTime(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>java.sql.Timestamp</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>java.sql.Timestamp</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Timestamp getTimestamp(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as an ASCII
+ * stream. Note that all the data from this stream must be read before
+ * fetching the value of any other column. Please also be aware that
+ * calling <code>next()</code> or <code>close()</code> on this result set
+ * will close this stream as well.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as an ASCII <code>InputStream</code>.
+ * @exception SQLException If an error occurs.
+ */
+ InputStream getAsciiStream(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Unicode UTF-8
+ * stream. Note that all the data from this stream must be read before
+ * fetching the value of any other column. Please also be aware that
+ * calling <code>next()</code> or <code>close()</code> on this result set
+ * will close this stream as well.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a Unicode UTF-8 <code>InputStream</code>.
+ * @exception SQLException If an error occurs.
+ * @deprecated Use getCharacterStream instead.
+ */
+ InputStream getUnicodeStream(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a raw byte
+ * stream. Note that all the data from this stream must be read before
+ * fetching the value of any other column. Please also be aware that
+ * calling <code>next()</code> or <code>close()</code> on this result set
+ * will close this stream as well.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a raw byte <code>InputStream</code>.
+ * @exception SQLException If an error occurs.
+ */
+ InputStream getBinaryStream(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>String</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>String</code>.
+ * @exception SQLException If an error occurs.
+ */
+ String getString(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>boolean</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>boolean</code>.
+ * @exception SQLException If an error occurs.
+ */
+ boolean getBoolean(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>byte</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>byte</code>.
+ * @exception SQLException If an error occurs.
+ */
+ byte getByte(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>short</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>short</code>.
+ * @exception SQLException If an error occurs.
+ */
+ short getShort(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>int</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>int</code>.
+ * @exception SQLException If an error occurs.
+ */
+ int getInt(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>long</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>long</code>.
+ * @exception SQLException If an error occurs.
+ */
+ long getLong(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>float</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>float</code>.
+ * @exception SQLException If an error occurs.
+ */
+ float getFloat(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>double</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>double</code>.
+ * @exception SQLException If an error occurs.
+ */
+ double getDouble(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>BigDecimal</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>BigDecimal</code>.
+ * @exception SQLException If an error occurs.
+ * @deprecated
+ */
+ BigDecimal getBigDecimal(String columnName, int scale)
+ throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * byte array.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a byte array
+ * @exception SQLException If an error occurs.
+ */
+ byte[] getBytes(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>java.sql.Date</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>java.sql.Date</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Date getDate(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>java.sql.Time</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>java.sql.Time</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Time getTime(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>java.sql.Timestamp</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>java.sql.Timestamp</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Timestamp getTimestamp(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as an ASCII
+ * stream. Note that all the data from this stream must be read before
+ * fetching the value of any other column. Please also be aware that
+ * calling <code>next()</code> or <code>close()</code> on this result set
+ * will close this stream as well.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as an ASCII <code>InputStream</code>.
+ * @exception SQLException If an error occurs.
+ */
+ InputStream getAsciiStream(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Unicode UTF-8
+ * stream. Note that all the data from this stream must be read before
+ * fetching the value of any other column. Please also be aware that
+ * calling <code>next()</code> or <code>close()</code> on this result set
+ * will close this stream as well.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a Unicode UTF-8 <code>InputStream</code>.
+ * @exception SQLException If an error occurs.
+ * @deprecated Use getCharacterStream instead.
+ */
+ InputStream getUnicodeStream(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a raw byte
+ * stream. Note that all the data from this stream must be read before
+ * fetching the value of any other column. Please also be aware that
+ * calling <code>next()</code> or <code>close()</code> on this result set
+ * will close this stream as well.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a raw byte <code>InputStream</code>.
+ * @exception SQLException If an error occurs.
+ */
+ InputStream getBinaryStream(String columnName) throws SQLException;
+
+ /**
+ * This method returns the first SQL warning associated with this result
+ * set. Any additional warnings will be chained to this one.
+ *
+ * @return The first SQLWarning for this result set, or <code>null</code> if
+ * there are no warnings.
+ * @exception SQLException If an error occurs.
+ */
+ SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * This method clears all warnings associated with this result set.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void clearWarnings() throws SQLException;
+
+ /**
+ * This method returns the name of the database cursor used by this
+ * result set.
+ *
+ * @return The name of the database cursor used by this result set.
+ * @exception SQLException If an error occurs.
+ */
+ String getCursorName() throws SQLException;
+
+ /**
+ * This method returns data about the columns returned as part of the
+ * result set as a <code>ResultSetMetaData</code> instance.
+ *
+ * @return The <code>ResultSetMetaData</code> instance for this result set.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSetMetaData getMetaData() throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>Object</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as an <code>Object</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Object getObject(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>Object</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as an <code>Object</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Object getObject(String columnName) throws SQLException;
+
+ /**
+ * This method returns the column index of the specified named column.
+ *
+ * @param column The name of the column.
+ * @return The index of the column.
+ * @exception SQLException If an error occurs.
+ */
+ int findColumn(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a character
+ * stream. Note that all the data from this stream must be read before
+ * fetching the value of any other column. Please also be aware that
+ * calling <code>next()</code> or <code>close()</code> on this result set
+ * will close this stream as well.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as an character <code>Reader</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Reader getCharacterStream(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a character
+ * stream. Note that all the data from this stream must be read before
+ * fetching the value of any other column. Please also be aware that
+ * calling <code>next()</code> or <code>close()</code> on this result set
+ * will close this stream as well.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as an character <code>Reader</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Reader getCharacterStream(String columnName) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>BigDecimal</code>.
+ *
+ * @param index The index of the column to return.
+ * @return The column value as a <code>BigDecimal</code>.
+ * @exception SQLException If an error occurs.
+ */
+ BigDecimal getBigDecimal(int columnIndex) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>BigDecimal</code>.
+ *
+ * @param column The name of the column to return.
+ * @return The column value as a <code>BigDecimal</code>.
+ * @exception SQLException If an error occurs.
+ */
+ BigDecimal getBigDecimal(String columnName) throws SQLException;
+
+ /**
+ * This method tests whether or not the cursor is before the first row
+ * in the result set.
+ *
+ * @return <code>true</code> if the cursor is positioned before the first
+ * row, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isBeforeFirst() throws SQLException;
+
+ /**
+ * This method tests whether or not the cursor is after the last row
+ * in the result set.
+ *
+ * @return <code>true</code> if the cursor is positioned after the last
+ * row, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isAfterLast() throws SQLException;
+
+ /**
+ * This method tests whether or not the cursor is positioned on the first
+ * row in the result set.
+ *
+ * @return <code>true</code> if the cursor is positioned on the first
+ * row, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isFirst() throws SQLException;
+
+ /**
+ * This method tests whether or not the cursor is on the last row
+ * in the result set.
+ *
+ * @return <code>true</code> if the cursor is positioned on the last
+ * row, <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isLast() throws SQLException;
+
+ /**
+ * This method repositions the cursor to before the first row in the
+ * result set.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void beforeFirst() throws SQLException;
+
+ /**
+ * This method repositions the cursor to after the last row in the result
+ * set.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void afterLast() throws SQLException;
+
+ /**
+ * This method repositions the cursor on the first row in the
+ * result set.
+ *
+ * @return <code>true</code> if the cursor is on a valid row;
+ * <code>false</code> if there are no rows in the result set.
+ * @exception SQLException If an error occurs.
+ */
+ boolean first() throws SQLException;
+
+ /**
+ * This method repositions the cursor on the last row in the result
+ * set.
+ *
+ * @return <code>true</code> if the cursor is on a valid row;
+ * <code>false</code> if there are no rows in the result set.
+ * @exception SQLException If an error occurs.
+ */
+ boolean last() throws SQLException;
+
+ /**
+ * This method returns the current row number in the cursor. Numbering
+ * begins at index 1.
+ *
+ * @return The current row number, or 0 if there is not current row.
+ * @exception SQLException If an error occurs.
+ */
+ int getRow() throws SQLException;
+
+ /**
+ * This method positions the result set to the specified absolute row.
+ * Positive numbers are row offsets from the beginning of the result
+ * set (numbering starts from row 1) and negative numbers are row offsets
+ * from the end of the result set (numbering starts from -1).
+ *
+ * @param row The row to position the result set to.
+ *
+ * @return <code>true</code> if the current position was changed,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean absolute(int row) throws SQLException;
+
+ /**
+ * This method moves the result set position relative to the current row.
+ * The offset can be positive or negative.
+ *
+ * @param row The relative row position to move to.
+ * @return <code>true</code> if the current position was changed,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean relative(int rows) throws SQLException;
+
+ /**
+ * This method moves the current position to the previous row in the
+ * result set.
+ *
+ * @return <code>true</code> if the previous row exists, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean previous() throws SQLException;
+
+ /**
+ * This method provides a hint to the driver about which direction the
+ * result set will be processed in.
+ *
+ * @param direction The direction in which rows will be processed. (Values?)
+ * @exception SQLException If an error occurs.
+ */
+ void setFetchDirection(int direction) throws SQLException;
+
+ /**
+ * This method returns the current fetch direction for this result set.
+ *
+ * @return The fetch direction for this result set.
+ * @exception SQLException If an error occurs.
+ */
+ int getFetchDirection() throws SQLException;
+
+ /**
+ * This method provides a hint to the driver about how many rows at a
+ * time it should fetch from the database.
+ *
+ * @param rows The number of rows the driver should fetch per call.
+ * @exception SQLException If an error occurs.
+ */
+ void setFetchSize(int rows) throws SQLException;
+
+ /**
+ * This method returns the current number of rows that will be fetched
+ * from the database at a time.
+ *
+ * @return The current fetch size for this result set.
+ * @exception SQLException If an error occurs.
+ */
+ int getFetchSize() throws SQLException;
+
+ /**
+ * This method returns the result set type of this result set. This will
+ * be one of the TYPE_* constants defined in this interface.
+ *
+ * @return The result set type.
+ * @exception SQLException If an error occurs.
+ */
+ int getType() throws SQLException;
+
+ /**
+ * This method returns the concurrency type of this result set. This will
+ * be one of the CONCUR_* constants defined in this interface.
+ *
+ * @return The result set concurrency type.
+ * @exception SQLException If an error occurs.
+ */
+ int getConcurrency() throws SQLException;
+
+ /**
+ * This method tests whether or not the current row in the result set
+ * has been updated. Updates must be visible in order of this method to
+ * detect the update.
+ *
+ * @return <code>true</code> if the row has been updated, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean rowUpdated() throws SQLException;
+
+ /**
+ * This method tests whether or not the current row in the result set
+ * has been inserted. Inserts must be visible in order of this method to
+ * detect the insert.
+ *
+ * @return <code>true</code> if the row has been inserted, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean rowInserted() throws SQLException;
+
+ /**
+ * This method tests whether or not the current row in the result set
+ * has been deleted. Deletes must be visible in order of this method to
+ * detect the deletion.
+ *
+ * @return <code>true</code> if the row has been deleted, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean rowDeleted() throws SQLException;
+
+ /**
+ * This method updates the specified column to have a NULL value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @return index The index of the column to update.
+ * @exception SQLException If an error occurs.
+ */
+ void updateNull(int columnIndex) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a boolean value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateBoolean(int columnIndex, boolean x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a byte value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateByte(int columnIndex, byte x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a short value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateShort(int columnIndex, short x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have an int value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateInt(int columnIndex, int x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a long value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateLong(int columnIndex, long x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a float value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateFloat(int columnIndex, float x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a double value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateDouble(int columnIndex, double x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a BigDecimal value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateBigDecimal(int columnIndex, BigDecimal x)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column to have a String value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateString(int columnIndex, String x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a byte array value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateBytes(int columnIndex, byte[] x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a java.sql.Date value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateDate(int columnIndex, Date x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a java.sql.Time value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateTime(int columnIndex, Time x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a java.sql.Timestamp value.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateTimestamp(int columnIndex, Timestamp x)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column from an ASCII text stream.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @param length The length of the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void updateAsciiStream(int columnIndex, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column from a binary stream.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @param length The length of the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void updateBinaryStream(int columnIndex, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column from a character stream.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @param length The length of the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void updateCharacterStream(int columnIndex, Reader x, int length)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column to have an Object value.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void updateObject(int columnIndex, Object x, int scale)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column to have an Object value.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param index The index of the column to update.
+ * @param value The new value of the column.
+ * @param scale The scale of the object in question, which is used only
+ * for numeric type objects.
+ * @exception SQLException If an error occurs.
+ */
+ void updateObject(int columnIndex, Object x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a NULL value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @return name The name of the column to update.
+ * @exception SQLException If an error occurs.
+ */
+ void updateNull(String columnName) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a boolean value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateBoolean(String columnName, boolean x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a byte value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateByte(String columnName, byte x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a short value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateShort(String columnName, short x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have an int value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateInt(String columnName, int x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a long value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateLong(String columnName, long x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a float value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateFloat(String columnName, float x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a double value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateDouble(String columnName, double x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a BigDecimal value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateBigDecimal(String columnName, BigDecimal x)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column to have a String value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateString(String columnName, String x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a byte array value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateBytes(String columnName, byte[] x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a java.sql.Date value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateDate(String columnName, Date x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a java.sql.Time value. This
+ * does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateTime(String columnName, Time x) throws SQLException;
+
+ /**
+ * This method updates the specified column to have a java.sql.Timestamp value.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateTimestamp(String columnName, Timestamp x)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column from an ASCII text stream.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @param length The length of the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void updateAsciiStream(String columnName, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column from a binary stream.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @param length The length of the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void updateBinaryStream(String columnName, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column from a character stream.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @param length The length of the stream.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void updateCharacterStream(String columnName, Reader reader,
+ int length) throws SQLException;
+
+ /**
+ * This method updates the specified column to have an Object value.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @exception SQLException If an error occurs.
+ */
+ void updateObject(String columnName, Object x, int scale)
+ throws SQLException;
+
+ /**
+ * This method updates the specified column to have an Object value.
+ * This does not update the actual database. <code>updateRow</code> must be
+ * called in order to do that.
+ *
+ * @param name The name of the column to update.
+ * @param value The new value of the column.
+ * @param scale The scale of the object in question, which is used only
+ * for numeric type objects.
+ * @exception SQLException If an error occurs.
+ */
+ void updateObject(String columnName, Object x) throws SQLException;
+
+ /**
+ * This method inserts the current row into the database. The result set
+ * must be positioned on the insert row in order to call this method
+ * successfully.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void insertRow() throws SQLException;
+
+ /**
+ * This method updates the current row in the database.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void updateRow() throws SQLException;
+
+ /**
+ * This method deletes the current row in the database.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void deleteRow() throws SQLException;
+
+ /**
+ * This method refreshes the contents of the current row from the database.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void refreshRow() throws SQLException;
+
+ /**
+ * This method cancels any changes that have been made to a row. If
+ * the <code>rowUpdate</code> method has been called, then the changes
+ * cannot be undone.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void cancelRowUpdates() throws SQLException;
+
+ /**
+ * This method positions the result set to the "insert row", which allows
+ * a new row to be inserted into the database from the result set.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void moveToInsertRow() throws SQLException;
+
+ /**
+ * This method moves the result set position from the insert row back to
+ * the current row that was selected prior to moving to the insert row.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void moveToCurrentRow() throws SQLException;
+
+ /**
+ * This method returns a the <code>Statement</code> that was used to
+ * produce this result set.
+ *
+ * @return The <code>Statement</code> used to produce this result set.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ Statement getStatement() throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>Object</code> using the specified SQL type to Java type map.
+ *
+ * @param index The index of the column to return.
+ * @param map The SQL type to Java type map to use.
+ * @return The value of the column as an <code>Object</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Object getObject(int i, Map map) throws SQLException;
+
+ /**
+ * This method returns a <code>Ref</code> for the specified column which
+ * represents the structured type for the column.
+ *
+ * @param index The index of the column to return.
+ * @return A <code>Ref</code> object for the column
+ * @exception SQLException If an error occurs.
+ */
+ Ref getRef(int i) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a BLOB.
+ *
+ * @param index The index of the column value to return.
+ * @return The value of the column as a BLOB.
+ * @exception SQLException If an error occurs.
+ */
+ Blob getBlob(int i) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a CLOB.
+ *
+ * @param index The index of the column value to return.
+ * @return The value of the column as a CLOB.
+ * @exception SQLException If an error occurs.
+ */
+ Clob getClob(int i) throws SQLException;
+
+ /**
+ * This method returns the specified column value as an <code>Array</code>.
+ *
+ * @param index The index of the column value to return.
+ * @return The value of the column as an <code>Array</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Array getArray(int i) throws SQLException;
+
+ /**
+ * This method returns the value of the specified column as a Java
+ * <code>Object</code> using the specified SQL type to Java type map.
+ *
+ * @param name The name of the column to return.
+ * @param map The SQL type to Java type map to use.
+ * @return The value of the column as an <code>Object</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Object getObject(String colName, Map map) throws SQLException;
+
+ /**
+ * This method returns a <code>Ref</code> for the specified column which
+ * represents the structured type for the column.
+ *
+ * @param index The index of the column to return.
+ * @return A <code>Ref</code> object for the column
+ * @exception SQLException If an error occurs.
+ */
+ Ref getRef(String colName) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a BLOB.
+ *
+ * @param name The name of the column value to return.
+ * @return The value of the column as a BLOB.
+ * @exception SQLException If an error occurs.
+ */
+ Blob getBlob(String colName) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a CLOB.
+ *
+ * @param name The name of the column value to return.
+ * @return The value of the column as a CLOB.
+ * @exception SQLException If an error occurs.
+ */
+ Clob getClob(String colName) throws SQLException;
+
+ /**
+ * This method returns the specified column value as an <code>Array</code>.
+ *
+ * @param name The name of the column value to return.
+ * @return The value of the column as an <code>Array</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Array getArray(String colName) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a
+ * <code>java.sql.Date</code>. The specified <code>Calendar</code> is used
+ * to generate a value for the date if the database does not support
+ * timezones.
+ *
+ * @param index The index of the column value to return.
+ * @param cal The <code>Calendar</code> to use for calculating timezones.
+ * @return The value of the column as a <code>java.sql.Date</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Date getDate(int columnIndex, Calendar cal) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a
+ * <code>java.sql.Date</code>. The specified <code>Calendar</code> is used
+ * to generate a value for the date if the database does not support
+ * timezones.
+ *
+ * @param name The name of the column value to return.
+ * @param cal The <code>Calendar</code> to use for calculating timezones.
+ * @return The value of the column as a <code>java.sql.Date</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Date getDate(String columnName, Calendar cal) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a
+ * <code>java.sql.Time</code>. The specified <code>Calendar</code> is used
+ * to generate a value for the time if the database does not support
+ * timezones.
+ *
+ * @param index The index of the column value to return.
+ * @param cal The <code>Calendar</code> to use for calculating timezones.
+ * @return The value of the column as a <code>java.sql.Time</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Time getTime(int columnIndex, Calendar cal) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a
+ * <code>java.sql.Time</code>. The specified <code>Calendar</code> is used
+ * to generate a value for the time if the database does not support
+ * timezones.
+ *
+ * @param name The name of the column value to return.
+ * @param cal The <code>Calendar</code> to use for calculating timezones.
+ * @return The value of the column as a <code>java.sql.Time</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Time getTime(String columnName, Calendar cal) throws SQLException;
+
+ /**
+ * This method returns the specified column value as a
+ * <code>java.sql.Timestamp</code>. The specified <code>Calendar</code> is used
+ * to generate a value for the timestamp if the database does not support
+ * timezones.
+ *
+ * @param index The index of the column value to return.
+ * @param cal The <code>Calendar</code> to use for calculating timezones.
+ * @return The value of the column as a <code>java.sql.Timestamp</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Timestamp getTimestamp(int columnIndex, Calendar cal)
+ throws SQLException;
+
+ /**
+ * This method returns the specified column value as a
+ * <code>java.sql.Timestamp</code>. The specified <code>Calendar</code> is used
+ * to generate a value for the timestamp if the database does not support
+ * timezones.
+ *
+ * @param name The name of the column value to return.
+ * @param cal The <code>Calendar</code> to use for calculating timezones.
+ *
+ * @return The value of the column as a <code>java.sql.Timestamp</code>.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ Timestamp getTimestamp(String columnName, Calendar cal)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ URL getURL(int columnIndex) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ URL getURL(String columnName) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void updateRef(int columnIndex, Ref x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void updateRef(String columnName, Ref x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void updateBlob(int columnIndex, Blob x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void updateBlob(String columnName, Blob x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void updateClob(int columnIndex, Clob x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void updateClob(String columnName, Clob x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void updateArray(int columnIndex, Array x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void updateArray(String columnName, Array x) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/ResultSetMetaData.java b/libjava/classpath/java/sql/ResultSetMetaData.java
new file mode 100644
index 00000000000..0086677ee60
--- /dev/null
+++ b/libjava/classpath/java/sql/ResultSetMetaData.java
@@ -0,0 +1,281 @@
+/* ResultSetMetaData.java -- Returns information about the ResultSet
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+/**
+ * This interface provides a mechanism for obtaining information about
+ * the columns that are present in a <code>ResultSet</code>.
+ * <p>
+ * Note that in this class column indexes start at 1, not 0.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface ResultSetMetaData
+{
+ /**
+ * The column does not allow NULL's.
+ */
+ int columnNoNulls = 0;
+
+ /**
+ * The column allows NULL's.
+ */
+ int columnNullable = 1;
+
+ /**
+ * It is unknown whether or not the column allows NULL's.
+ */
+ int columnNullableUnknown = 2;
+
+ /**
+ * This method returns the number of columns in the result set.
+ *
+ * @return The number of columns in the result set.
+ * @exception SQLException If an error occurs.
+ */
+ int getColumnCount() throws SQLException;
+
+ /**
+ * This method test whether or not the column is an auto-increment column.
+ * Auto-increment columns are read-only.
+ *
+ * @param index The index of the column to test.
+ * @return <code>true</code> if the column is auto-increment, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isAutoIncrement(int column) throws SQLException;
+
+ /**
+ * This method tests whether or not a column is case sensitive in its values.
+ *
+ * @param index The index of the column to test.
+ * @return <code>true</code> if the column value is case sensitive,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isCaseSensitive(int column) throws SQLException;
+
+ /**
+ * This method tests whether not the specified column can be used in
+ * a WHERE clause.
+ *
+ * @param index The index of the column to test.
+ * @return <code>true</code> if the column may be used in a WHERE clause,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isSearchable(int column) throws SQLException;
+
+ /**
+ * This method tests whether or not the column stores a monetary value.
+ *
+ * @param index The index of the column to test.
+ * @return <code>true</code> if the column contains a monetary value,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isCurrency(int column) throws SQLException;
+
+ /**
+ * This method returns a value indicating whether or not the specified
+ * column may contain a NULL value.
+ *
+ * @param index The index of the column to test.
+ * @return A constant indicating whether or not the column can contain NULL,
+ * which will be one of <code>columnNoNulls</code>,
+ * <code>columnNullable</code>, or <code>columnNullableUnknown</code>.
+ * @exception SQLException If an error occurs.
+ */
+ int isNullable(int column) throws SQLException;
+
+ /**
+ * This method tests whether or not the value of the specified column
+ * is signed or unsigned.
+ *
+ * @param index The index of the column to test.
+ * @return <code>true</code> if the column value is signed, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isSigned(int column) throws SQLException;
+
+ /**
+ * This method returns the maximum number of characters that can be used
+ * to display a value in this column.
+ *
+ * @param index The index of the column to check.
+ * @return The maximum number of characters that can be used to display a
+ * value for this column.
+ * @exception SQLException If an error occurs.
+ */
+ int getColumnDisplaySize(int column) throws SQLException;
+
+ /**
+ * This method returns a string that should be used as a caption for this
+ * column for user display purposes.
+ *
+ * @param index The index of the column to check.
+ * @return A display string for the column.
+ * @exception SQLException If an error occurs.
+ */
+ String getColumnLabel(int column) throws SQLException;
+
+ /**
+ * This method returns the name of the specified column.
+ *
+ * @param index The index of the column to return the name of.
+ * @return The name of the column.
+ * @exception SQLException If an error occurs.
+ */
+ String getColumnName(int column) throws SQLException;
+
+ /**
+ * This method returns the name of the schema that contains the specified
+ * column.
+ *
+ * @param index The index of the column to check the schema name for.
+ * @return The name of the schema that contains the column.
+ * @exception SQLException If an error occurs.
+ */
+ String getSchemaName(int column) throws SQLException;
+
+ /**
+ * This method returns the precision of the specified column, which is the
+ * number of decimal digits it contains.
+ *
+ * @param index The index of the column to check the precision on.
+ * @return The precision of the specified column.
+ * @exception SQLException If an error occurs.
+ */
+ int getPrecision(int column) throws SQLException;
+
+ /**
+ * This method returns the scale of the specified column, which is the
+ * number of digits to the right of the decimal point.
+ *
+ * @param index The index column to check the scale of.
+ * @return The scale of the column.
+ * @exception SQLException If an error occurs.
+ */
+ int getScale(int column) throws SQLException;
+
+ /**
+ * This method returns the name of the table containing the specified
+ * column.
+ *
+ * @param index The index of the column to check the table name for.
+ * @return The name of the table containing the column.
+ * @exception SQLException If an error occurs.
+ */
+ String getTableName(int column) throws SQLException;
+
+ /**
+ * This method returns the name of the catalog containing the specified
+ * column.
+ *
+ * @param index The index of the column to check the catalog name for.
+ * @return The name of the catalog containing the column.
+ * @exception SQLException If an error occurs.
+ */
+ String getCatalogName(int column) throws SQLException;
+
+ /**
+ * This method returns the SQL type of the specified column. This will
+ * be one of the constants from <code>Types</code>.
+ *
+ * @param index The index of the column to check the SQL type of.
+ * @return The SQL type for this column.
+ * @exception SQLException If an error occurs.
+ * @see Types
+ */
+ int getColumnType(int column) throws SQLException;
+
+ /**
+ * This method returns the name of the SQL type for this column.
+ *
+ * @param index The index of the column to check the SQL type name for.
+ * @return The name of the SQL type for this column.
+ * @exception SQLException If an error occurs.
+ */
+ String getColumnTypeName(int column) throws SQLException;
+
+ /**
+ * This method tests whether or not the specified column is read only.
+ *
+ * @param index The index of the column to check.
+ * @return <code>true</code> if the column is read only, <code>false</code>
+ * otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isReadOnly(int column) throws SQLException;
+
+ /**
+ * This method tests whether or not the column may be writable. This
+ * does not guarantee that a write will be successful.
+ *
+ * @param index The index of the column to check for writability.
+ * @return <code>true</code> if the column may be writable,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isWritable(int column) throws SQLException;
+
+ /**
+ * This method tests whether or not the column is writable. This
+ * does guarantee that a write will be successful.
+ *
+ * @param index The index of the column to check for writability.
+ * @return <code>true</code> if the column is writable,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean isDefinitelyWritable(int column) throws SQLException;
+
+ /**
+ * This method returns the name of the Java class which will be used to
+ * create objects representing the data in this column.
+ *
+ * @param index The index of the column to check.
+ * @return The name of the Java class that will be used for values in
+ * this column.
+ * @exception SQLException If an error occurs.
+ */
+ String getColumnClassName(int column) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/SQLData.java b/libjava/classpath/java/sql/SQLData.java
new file mode 100644
index 00000000000..2ba1fb18d05
--- /dev/null
+++ b/libjava/classpath/java/sql/SQLData.java
@@ -0,0 +1,72 @@
+/* SQLData.java -- Custom mapping for a user defined datatype
+ Copyright (C) 1999, 2000 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.sql;
+
+/**
+ * This interface is used for mapping SQL data to user defined datatypes.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface SQLData
+{
+ /**
+ * This method returns the user defined datatype name for this object.
+ *
+ * @return The user defined data type name for this object.
+ * @exception SQLException If an error occurs.
+ */
+ String getSQLTypeName() throws SQLException;
+
+ /**
+ * This method populates the data in the object from the specified stream.
+ *
+ * @param stream The stream to read the data from.
+ * @param name The data type name of the data on the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void readSQL(SQLInput stream, String typeName) throws SQLException;
+
+ /**
+ * This method writes the data in this object to the specified stream.
+ *
+ * @param stream The stream to write the data to.
+ * @exception SQLException If an error occurs.
+ */
+ void writeSQL(SQLOutput stream) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/SQLException.java b/libjava/classpath/java/sql/SQLException.java
new file mode 100644
index 00000000000..8c502f2df7c
--- /dev/null
+++ b/libjava/classpath/java/sql/SQLException.java
@@ -0,0 +1,167 @@
+/* SQLException.java -- General SQL exception
+ Copyright (C) 1999, 2000 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.sql;
+
+/**
+ * This exception is thrown when a database error occurs.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class SQLException extends Exception
+{
+ static final long serialVersionUID = 2135244094396331484L;
+
+ /**
+ * This is the next exception in the chain
+ */
+ private SQLException next;
+
+ /**
+ * This is the state of the SQL statement at the time of the error.
+ */
+ private String SQLState;
+
+ /**
+ * The vendor error code for this error
+ */
+ private int vendorCode;
+
+ /**
+ * This method initializes a nwe instance of <code>SQLException</code>
+ * with the specified descriptive error message, SQL state string, and
+ * vendor code.
+ *
+ * @param message A string describing the nature of the error.
+ * @param SQLState A string containing the SQL state of the error.
+ * @param vendorCode The vendor error code associated with this error.
+ */
+ public SQLException(String message, String SQLState, int vendorCode)
+ {
+ super(message);
+ this.SQLState = SQLState;
+ this.vendorCode = vendorCode;
+ }
+
+ /**
+ * This method initializes a new instance of <code>SQLException</code>
+ * with the specified descriptive error message and SQL state string.
+ * The vendor error code of this instance will be 0.
+ *
+ * @param message A string describing the nature of the error.
+ * @param SQLState A string containing the SQL state of the error.
+ */
+ public SQLException(String message, String SQLState)
+ {
+ this(message, SQLState, 0);
+ }
+
+ /**
+ * This method initializes a new instance of <code>SQLException</code>
+ * with the specified descriptive error message. The SQL state of this
+ * instance will be <code>null</code> and the vendor error code will be 0.
+ *
+ * @param message A string describing the nature of the error.
+ */
+ public SQLException(String message)
+ {
+ this(message, null, 0);
+ }
+
+ /**
+ * This method initializes a new instance of <code>SQLException</code>
+ * that does not have a descriptive messages and SQL state, and which
+ * has a vendor error code of 0.
+ */
+ public SQLException()
+ {
+ this(null, null, 0);
+ }
+
+ /**
+ * This method returns the SQLState information associated with this
+ * error. The value returned is a <code>String</code> which is formatted
+ * using the XOPEN SQL state conventions.
+ *
+ * @return The SQL state, which may be <code>null</code>.
+ */
+ public String getSQLState()
+ {
+ return SQLState;
+ }
+
+ /**
+ * This method returns the vendor specific error code associated with
+ * this error.
+ *
+ * @return The vendor specific error code associated with this error.
+ */
+ public int getErrorCode()
+ {
+ return vendorCode;
+ }
+
+ /**
+ * This method returns the exception that is chained to this object.
+ *
+ * @return The exception chained to this object, which may be
+ * <code>null</code>.
+ */
+ public SQLException getNextException()
+ {
+ return next;
+ }
+
+ /**
+ * This method adds a new exception to the end of the chain of exceptions
+ * that are chained to this object.
+ *
+ * @param e The exception to add to the end of the chain.
+ */
+ public void setNextException(SQLException e)
+ {
+ if (e == null)
+ return;
+
+ SQLException list_entry = this;
+ while (list_entry.getNextException() != null)
+ list_entry = list_entry.getNextException();
+
+ list_entry.next = e;
+ }
+}
diff --git a/libjava/classpath/java/sql/SQLInput.java b/libjava/classpath/java/sql/SQLInput.java
new file mode 100644
index 00000000000..730627d9a9e
--- /dev/null
+++ b/libjava/classpath/java/sql/SQLInput.java
@@ -0,0 +1,259 @@
+/* SQLInput.java -- Read SQL values from a stream
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+
+/**
+ * This interface provides methods for reading values from a stream
+ * that is connected to a SQL structured or distinct type. It is used
+ * for custom mapping of user defined data types.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface SQLInput
+{
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>String</code>.
+ *
+ * @return The value read from the stream as a <code>String</code>.
+ * @exception SQLException If an error occurs.
+ */
+ String readString() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>boolean</code>.
+ *
+ * @return The value read from the stream as a <code>boolean</code>.
+ * @exception SQLException If an error occurs.
+ */
+ boolean readBoolean() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>byte</code>.
+ *
+ * @return The value read from the stream as a <code>byte</code>.
+ * @exception SQLException If an error occurs.
+ */
+ byte readByte() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>short</code>.
+ *
+ * @return The value read from the stream as a <code>short</code>.
+ * @exception SQLException If an error occurs.
+ */
+ short readShort() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>int</code>.
+ *
+ * @return The value read from the stream as an <code>int</code>.
+ * @exception SQLException If an error occurs.
+ */
+ int readInt() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>long</code>.
+ *
+ * @return The value read from the stream as a <code>long</code>.
+ * @exception SQLException If an error occurs.
+ */
+ long readLong() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>float</code>.
+ *
+ * @return The value read from the stream as a <code>float</code>.
+ * @exception SQLException If an error occurs.
+ */
+ float readFloat() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>double</code>.
+ *
+ * @return The value read from the stream as a <code>double</code>.
+ * @exception SQLException If an error occurs.
+ */
+ double readDouble() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>BigDecimal</code>.
+ *
+ * @return The value read from the stream as a <code>BigDecimal</code>.
+ * @exception SQLException If an error occurs.
+ */
+ BigDecimal readBigDecimal() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * byte array
+ *
+ * @return The value read from the stream as a byte array.
+ * @exception SQLException If an error occurs.
+ */
+ byte[] readBytes() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>java.sql.Date</code>.
+ *
+ * @return The value read from the stream as a <code>java.sql.Date</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Date readDate() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>java.sql.Time</code>.
+ *
+ * @return The value read from the stream as a <code>java.sql.Time</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Time readTime() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>java.sql.Timestamp</code>.
+ *
+ * @return The value read from the stream as a <code>java.sql.Timestamp</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Timestamp readTimestamp() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a character
+ * <code>Reader</code>.
+ *
+ * @return The value read from the stream as a <code>Reader</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Reader readCharacterStream() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a ASCII text
+ * <code>InputStream</code>.
+ *
+ * @return The value read from the stream as an <code>InputStream</code>.
+ * @exception SQLException If an error occurs.
+ */
+ InputStream readAsciiStream() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a binary
+ * <code>InputStream</code>.
+ *
+ * @return The value read from the stream as an <code>InputStream</code>.
+ * @exception SQLException If an error occurs.
+ */
+ InputStream readBinaryStream() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java
+ * <code>Object</code>.
+ *
+ * @return The value read from the stream as an <code>Object</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Object readObject() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java SQL
+ * <code>Ref</code>.
+ *
+ * @return The value read from the stream as an <code>Ref</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Ref readRef() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java SQL
+ * <code>Blob</code>.
+ *
+ * @return The value read from the stream as a <code>Blob</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Blob readBlob() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java SQL
+ * <code>Clob</code>.
+ *
+ * @return The value read from the stream as a <code>Clob</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Clob readClob() throws SQLException;
+
+ /**
+ * This method reads the next item from the stream a Java SQL
+ * <code>Array</code>.
+ *
+ * @return The value read from the stream as an <code>Array</code>.
+ * @exception SQLException If an error occurs.
+ */
+ Array readArray() throws SQLException;
+
+ /**
+ * This method tests whether or not the last value read was a SQL
+ * NULL value.
+ *
+ * @return <code>true</code> if the last value read was a NULL,
+ * <code>false</code> otherwise.
+ * @exception SQLException If an error occurs.
+ */
+ boolean wasNull() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ URL readURL() throws SQLException;
+}
+
diff --git a/libjava/classpath/java/sql/SQLOutput.java b/libjava/classpath/java/sql/SQLOutput.java
new file mode 100644
index 00000000000..8e6c88f8cf6
--- /dev/null
+++ b/libjava/classpath/java/sql/SQLOutput.java
@@ -0,0 +1,257 @@
+/* SQLOutput.java -- Write SQL values to a stream
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+
+/**
+ * This interface provides methods for writing Java types to a SQL stream.
+ * It is used for implemented custom type mappings for user defined data
+ * types.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface SQLOutput
+{
+ /**
+ * This method writes the specified Java <code>String</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeString(String x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>boolean</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeBoolean(boolean x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>byte</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeByte(byte x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>short</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeShort(short x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>int</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeInt(int x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>long</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeLong(long x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>float</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeFloat(float x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>double</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeDouble(double x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>BigDecimal</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeBigDecimal(BigDecimal x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>byte</code> array
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeBytes(byte[] x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>java.sql.Date</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeDate(Date x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>java.sql.Time</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeTime(Time x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>java.sql.Timestamp</code>
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeTimestamp(Timestamp x) throws SQLException;
+
+ /**
+ * This method writes the specified Java character stream
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeCharacterStream(Reader x) throws SQLException;
+
+ /**
+ * This method writes the specified ASCII text stream
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeAsciiStream(InputStream x) throws SQLException;
+
+ /**
+ * This method writes the specified uninterpreted binary byte stream
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeBinaryStream(InputStream x) throws SQLException;
+
+ /**
+ * This method writes the specified Java <code>SQLData</code> object
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeObject(SQLData x) throws SQLException;
+
+ /**
+ * This method writes the specified Java SQL <code>Ref</code> object
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeRef(Ref x) throws SQLException;
+
+ /**
+ * This method writes the specified Java SQL <code>Blob</code> object
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeBlob(Blob x) throws SQLException;
+
+ /**
+ * This method writes the specified Java SQL <code>Clob</code> object
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeClob(Clob x) throws SQLException;
+
+ /**
+ * This method writes the specified Java SQL <code>Struct</code> object
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeStruct(Struct x) throws SQLException;
+
+ /**
+ * This method writes the specified Java SQL <code>Array</code> object
+ * to the SQL stream.
+ *
+ * @param value The value to write to the stream.
+ * @exception SQLException If an error occurs.
+ */
+ void writeArray(Array x) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ void writeURL(URL x) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/SQLPermission.java b/libjava/classpath/java/sql/SQLPermission.java
new file mode 100644
index 00000000000..101fa0161b4
--- /dev/null
+++ b/libjava/classpath/java/sql/SQLPermission.java
@@ -0,0 +1,57 @@
+/* SQLPermission.java
+ Copyright (C) 2002 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.sql;
+
+import java.security.BasicPermission;
+
+/**
+ * @since 1.3
+ */
+public final class SQLPermission extends BasicPermission
+{
+ public SQLPermission(String name)
+ {
+ super(name);
+ }
+
+ public SQLPermission(String name, String actions)
+ {
+ super(name, actions);
+ }
+}
diff --git a/libjava/classpath/java/sql/SQLWarning.java b/libjava/classpath/java/sql/SQLWarning.java
new file mode 100644
index 00000000000..841d137e13a
--- /dev/null
+++ b/libjava/classpath/java/sql/SQLWarning.java
@@ -0,0 +1,120 @@
+/* SQLWarning.java -- Database access warnings.
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+/**
+ * This exception is thrown when a database warning occurs.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class SQLWarning extends SQLException
+{
+ static final long serialVersionUID = 3917336774604784856L;
+
+ /**
+ * This method initializes a nwe instance of <code>SQLWarning</code>
+ * with the specified descriptive error message, SQL state string, and
+ * vendor code.
+ *
+ * @param message A string describing the nature of the error.
+ * @param SQLState A string containing the SQL state of the error.
+ * @param vendorCode The vendor error code associated with this error.
+ */
+ public SQLWarning(String reason, String SQLState, int vendorCode)
+ {
+ super(reason, SQLState, vendorCode);
+ }
+
+ /**
+ * This method initializes a new instance of <code>SQLWarning</code>
+ * with the specified descriptive error message and SQL state string.
+ * The vendor error code of this instance will be 0.
+ *
+ * @param message A string describing the nature of the error.
+ * @param SQLState A string containing the SQL state of the error.
+ */
+ public SQLWarning(String message, String SQLState)
+ {
+ super(message, SQLState);
+ }
+
+ /**
+ * This method initializes a new instance of <code>SQLWarning</code>
+ * with the specified descriptive error message. The SQL state of this
+ * instance will be <code>null</code> and the vendor error code will be 0.
+ *
+ * @param message A string describing the nature of the error.
+ */
+ public SQLWarning(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * This method initializes a new instance of <code>SQLWarning</code>
+ * that does not have a descriptive messages and SQL state, and which
+ * has a vendor error code of 0.
+ */
+ public SQLWarning()
+ {
+ super();
+ }
+
+ /**
+ * This method returns the exception that is chained to this object.
+ *
+ * @return The exception chained to this object, which may be
+ * <code>null</code>.
+ */
+ public SQLWarning getNextWarning()
+ {
+ return (SQLWarning) super.getNextException();
+ }
+
+ /**
+ * This method adds a new exception to the end of the chain of exceptions
+ * that are chained to this object.
+ *
+ * @param w The exception to add to the end of the chain.
+ */
+ public void setNextWarning(SQLWarning w)
+ {
+ super.setNextException(w);
+ }
+}
diff --git a/libjava/classpath/java/sql/Savepoint.java b/libjava/classpath/java/sql/Savepoint.java
new file mode 100644
index 00000000000..a4d89ae6e50
--- /dev/null
+++ b/libjava/classpath/java/sql/Savepoint.java
@@ -0,0 +1,55 @@
+/* SavePoint.java -- Returns information about the ResultSet
+ Copyright (C) 2002 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.sql;
+
+/**
+ * @since 1.4
+ */
+public interface Savepoint
+{
+ /**
+ * @since 1.4
+ */
+ int getSavepointId() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ String getSavepointName() throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/Statement.java b/libjava/classpath/java/sql/Statement.java
new file mode 100644
index 00000000000..42e8e8e8816
--- /dev/null
+++ b/libjava/classpath/java/sql/Statement.java
@@ -0,0 +1,366 @@
+/* Statement.java -- Interface for executing SQL statements.
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+/**
+ * This interface provides a mechanism for executing SQL statements.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Statement
+{
+ int CLOSE_CURRENT_RESULT = 1;
+ int KEEP_CURRENT_RESULT = 2;
+ int CLOSE_ALL_RESULTS = 3;
+ int SUCCESS_NO_INFO = -2;
+ int EXECUTE_FAILED = -3;
+ int RETURN_GENERATED_KEYS = 1;
+ int NO_GENERATED_KEYS = 2;
+
+ /**
+ * This method executes the specified SQL SELECT statement and returns a
+ * (possibly empty) <code>ResultSet</code> with the results of the query.
+ *
+ * @param sql The SQL statement to execute.
+ * @return The result set of the SQL statement.
+ * @exception SQLException If an error occurs.
+ */
+ ResultSet executeQuery(String sql) throws SQLException;
+
+ /**
+ * This method executes the specified SQL INSERT, UPDATE, or DELETE statement
+ * and returns the number of rows affected, which may be 0.
+ *
+ * @param sql The SQL statement to execute.
+ * @return The number of rows affected by the SQL statement.
+ * @exception SQLException If an error occurs.
+ */
+ int executeUpdate(String sql) throws SQLException;
+
+ /**
+ * This method closes the statement and frees any associated resources.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void close() throws SQLException;
+
+ /**
+ * This method returns the maximum length of any column value in bytes.
+ *
+ * @return The maximum length of any column value in bytes.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxFieldSize() throws SQLException;
+
+ /**
+ * This method sets the limit for the maximum length of any column in bytes.
+ *
+ * @param maxsize The new maximum length of any column in bytes.
+ * @exception SQLException If an error occurs.
+ */
+ void setMaxFieldSize(int max) throws SQLException;
+
+ /**
+ * This method returns the maximum possible number of rows in a result set.
+ *
+ * @return The maximum possible number of rows in a result set.
+ * @exception SQLException If an error occurs.
+ */
+ int getMaxRows() throws SQLException;
+
+ /**
+ * This method sets the maximum number of rows that can be present in a
+ * result set.
+ *
+ * @param maxrows The maximum possible number of rows in a result set.
+ * @exception SQLException If an error occurs.
+ */
+ void setMaxRows(int max) throws SQLException;
+
+ /**
+ * This method sets the local escape processing mode on or off. The
+ * default value is on.
+ *
+ * @param escape <code>true</code> to enable local escape processing,
+ * <code>false</code> to disable it.
+ * @exception SQLException If an error occurs.
+ */
+ void setEscapeProcessing(boolean enable) throws SQLException;
+
+ /**
+ * The method returns the number of seconds a statement may be in process
+ * before timing out. A value of 0 means there is no timeout.
+ *
+ * @return The SQL statement timeout in seconds.
+ * @exception SQLException If an error occurs.
+ */
+ int getQueryTimeout() throws SQLException;
+
+ /**
+ * This method sets the number of seconds a statement may be in process
+ * before timing out. A value of 0 means there is no timeout.
+ *
+ * @param timeout The new SQL statement timeout value.
+ * @exception SQLException If an error occurs.
+ */
+ void setQueryTimeout(int seconds) throws SQLException;
+
+ /**
+ * This method cancels an outstanding statement, if the database supports
+ * that operation.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void cancel() throws SQLException;
+
+ /**
+ * This method returns the first SQL warning attached to this statement.
+ * Subsequent warnings will be chained to this one.
+ *
+ * @return The first SQL warning for this statement.
+ * @exception SQLException If an error occurs.
+ */
+ SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * This method clears any SQL warnings that have been attached to this
+ * statement.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void clearWarnings() throws SQLException;
+
+ /**
+ * This method sets the cursor name that will be used by the result set.
+ *
+ * @param name The cursor name to use for this statement.
+ * @exception SQLException If an error occurs.
+ */
+ void setCursorName(String name) throws SQLException;
+
+ /**
+ * This method executes an arbitrary SQL statement of any time. The
+ * methods <code>getResultSet</code>, <code>getMoreResults</code> and
+ * <code>getUpdateCount</code> retrieve the results.
+ *
+ * @return <code>true</code> if a result set was returned, <code>false</code>
+ * if an update count was returned.
+ * @exception SQLException If an error occurs.
+ */
+ boolean execute(String sql) throws SQLException;
+
+ /**
+ * This method returns the result set of the SQL statement that was
+ * executed. This should be called only once per result set returned.
+ *
+ * @return The result set of the query, or <code>null</code> if there was
+ * no result set (for example, if the statement was an UPDATE).
+ * @exception SQLException If an error occurs.
+ * @see execute
+ */
+ ResultSet getResultSet() throws SQLException;
+
+ /**
+ * This method returns the update count of the SQL statement that was
+ * executed. This should be called only once per executed SQL statement.
+ *
+ * @return The update count of the query, or -1 if there was no update
+ * count (for example, if the statement was a SELECT).
+ * @exception SQLException If an error occurs.
+ * @see execute
+ */
+ int getUpdateCount() throws SQLException;
+
+ /**
+ * This method advances the result set pointer to the next result set,
+ * which can then be retrieved using <code>getResultSet</code>
+ *
+ * @return <code>true</code> if there is another result set,
+ * <code>false</code> otherwise (for example, the next result is an
+ * update count).
+ * @exception SQLException If an error occurs.
+ * @see execute
+ */
+ boolean getMoreResults() throws SQLException;
+
+ /**
+ * This method informs the driver which direction the result set will
+ * be accessed in.
+ *
+ * @param direction The direction the result set will be accessed in (?????)
+ * @exception SQLException If an error occurs.
+ */
+ void setFetchDirection(int direction) throws SQLException;
+
+ /**
+ * This method returns the current direction that the driver thinks the
+ * result set will be accessed int.
+ *
+ * @return The direction the result set will be accessed in (????)
+ * @exception SQLException If an error occurs.
+ */
+ int getFetchDirection() throws SQLException;
+
+ /**
+ * This method informs the driver how many rows it should fetch from the
+ * database at a time.
+ *
+ * @param numrows The number of rows the driver should fetch at a time
+ * to populate the result set.
+ * @exception SQLException If an error occurs.
+ */
+ void setFetchSize(int rows) throws SQLException;
+
+ /**
+ * This method returns the number of rows the driver believes should be
+ * fetched from the database at a time.
+ *
+ * @return The number of rows that will be fetched from the database at a time.
+ * @exception SQLException If an error occurs.
+ */
+ int getFetchSize() throws SQLException;
+
+ /**
+ * This method returns the concurrency type of the result set for this
+ * statement. This will be one of the concurrency types defined in
+ * <code>ResultSet</code>.
+ *
+ * @return The concurrency type of the result set for this statement.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ int getResultSetConcurrency() throws SQLException;
+
+ /**
+ * This method returns the result set type for this statement. This will
+ * be one of the result set types defined in <code>ResultSet</code>.
+ *
+ * @return The result set type for this statement.
+ * @exception SQLException If an error occurs.
+ * @see ResultSet
+ */
+ int getResultSetType() throws SQLException;
+
+ /**
+ * This method adds a SQL statement to a SQL batch. A driver is not
+ * required to implement this method.
+ *
+ * @param sql The sql statement to add to the batch.
+ * @exception SQLException If an error occurs.
+ */
+ void addBatch(String sql) throws SQLException;
+
+ /**
+ * This method clears out any SQL statements that have been populated in
+ * the current batch. A driver is not required to implement this method.
+ *
+ * @exception SQLException If an error occurs.
+ */
+ void clearBatch() throws SQLException;
+
+ /**
+ * This method executes the SQL batch and returns an array of update
+ * counts - one for each SQL statement in the batch - ordered in the same
+ * order the statements were added to the batch. A driver is not required
+ * to implement this method.
+ *
+ * @return An array of update counts for this batch.
+ * @exception SQLException If an error occurs.
+ */
+ int[] executeBatch() throws SQLException;
+
+ /**
+ * This method returns the <code>Connection</code> instance that was
+ * used to create this object.
+ *
+ * @return The connection used to create this object.
+ * @exception SQLException If an error occurs.
+ */
+ Connection getConnection() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean getMoreResults(int current) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ ResultSet getGeneratedKeys() throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int executeUpdate(String sql, int autoGeneratedKeys)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int executeUpdate(String sql, int[] columnIndexes)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int executeUpdate(String sql, String[] columnNames)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean execute(String sql, int autoGeneratedKeys)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean execute(String sql, int[] columnIndexes) throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ boolean execute(String sql, String[] columnNames)
+ throws SQLException;
+
+ /**
+ * @since 1.4
+ */
+ int getResultSetHoldability() throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/Struct.java b/libjava/classpath/java/sql/Struct.java
new file mode 100644
index 00000000000..5cbc88e133a
--- /dev/null
+++ b/libjava/classpath/java/sql/Struct.java
@@ -0,0 +1,77 @@
+/* Struct.java -- Mapping for a SQL structured type.
+ Copyright (C) 1999, 2000, 2002 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.sql;
+
+import java.util.Map;
+
+/**
+ * This interface implements the standard type mapping for a SQL
+ * structured type.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Struct
+{
+ /**
+ * This method returns the name of the SQL structured type for this
+ * object.
+ *
+ * @return The SQL structured type name.
+ * @exception SQLException If an error occurs.
+ */
+ String getSQLTypeName() throws SQLException;
+
+ /**
+ * This method returns the attributes of this SQL structured type.
+ *
+ * @return The attributes of this structure type.
+ * @exception SQLException If an error occurs.
+ */
+ Object[] getAttributes() throws SQLException;
+
+ /**
+ * This method returns the attributes of this SQL structured type.
+ * The specified map of type mappings overrides the default mappings.
+ *
+ * @param map The map of SQL type mappings.
+ * @return The attributes of this structure type.
+ * @exception SQLException If a error occurs.
+ */
+ Object[] getAttributes(Map map) throws SQLException;
+}
diff --git a/libjava/classpath/java/sql/Time.java b/libjava/classpath/java/sql/Time.java
new file mode 100644
index 00000000000..eb6ef2d651e
--- /dev/null
+++ b/libjava/classpath/java/sql/Time.java
@@ -0,0 +1,205 @@
+/* Time.java -- Wrapper around java.util.Date
+ Copyright (C) 1999, 2000, 2002, 2003 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.sql;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+/**
+ * This class is a wrapper around java.util.Date to allow the JDBC
+ * driver to identify the value as a SQL Time.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Time extends java.util.Date
+{
+ static final long serialVersionUID = 8397324403548013681L;
+
+ /**
+ * Used for parsing and formatting this date.
+ */
+ private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public int getDate() throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public int getDay() throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public int getMonth() throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public int getYear() throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public void setDate(int newValue) throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public void setMonth(int newValue) throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method always throws an IllegalArgumentException.
+ *
+ * @throws IllegalArgumentException when it's called.
+ * @deprecated
+ */
+ public void setYear(int newValue) throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * This method returns a new instance of this class by parsing a
+ * date in JDBC format into a Java date.
+ *
+ * @param str The string to parse.
+ * @return The resulting <code>java.sql.Time</code> value.
+ *
+ * @deprecated
+ */
+ public static Time valueOf (String str)
+ {
+ try
+ {
+ java.util.Date d = (java.util.Date) sdf.parseObject(str);
+
+ if (d == null)
+ throw new IllegalArgumentException(str);
+ else
+ return new Time(d.getTime());
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException(str);
+ }
+ }
+
+ /**
+ * This method initializes a new instance of this class with the
+ * specified year, month, and day.
+ *
+ * @param hour The hour for this Time (0-23)
+ * @param minute The minute for this time (0-59)
+ * @param second The second for this time (0-59)
+ * @deprecated
+ */
+ public Time(int hour, int minute, int second)
+ {
+ super(System.currentTimeMillis());
+
+ setHours(hour);
+ setMinutes(minute);
+ setSeconds(second);
+ }
+
+ /**
+ * This method initializes a new instance of this class with the
+ * specified time value representing the number of seconds since
+ * Jan 1, 1970 at 12:00 midnight GMT.
+ *
+ * @param time The time value to intialize this <code>Time</code> to.
+ */
+ public Time(long date)
+ {
+ super(date);
+ }
+
+ /**
+ * This method returns this date in JDBC format.
+ *
+ * @return This date as a string.
+ *
+ * @deprecated
+ */
+ public String toString ()
+ {
+ return sdf.format (this);
+ }
+
+}
+
diff --git a/libjava/classpath/java/sql/Timestamp.java b/libjava/classpath/java/sql/Timestamp.java
new file mode 100644
index 00000000000..f3459b22f3e
--- /dev/null
+++ b/libjava/classpath/java/sql/Timestamp.java
@@ -0,0 +1,315 @@
+/* Time.java -- Wrapper around java.util.Date
+ Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.sql;
+
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+/**
+ * This class is a wrapper around java.util.Date to allow the JDBC
+ * driver to identify the value as a SQL Timestamp. Note that this
+ * class also adds an additional field for nano-seconds, and so
+ * is not completely identical to <code>java.util.Date</code> as
+ * the <code>java.sql.Date</code> and <code>java.sql.Time</code>
+ * classes are.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Timestamp extends java.util.Date
+{
+ static final long serialVersionUID = 2745179027874758501L;
+
+ /**
+ * Used for parsing and formatting this date.
+ */
+ private static SimpleDateFormat dateFormat =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private static DecimalFormat decimalFormat = new DecimalFormat("000000000");
+ private static StringBuffer sbuf = new StringBuffer(29);
+
+ /**
+ * The nanosecond value for this object
+ */
+ private int nanos;
+
+ /**
+ * This method returns a new instance of this class by parsing a
+ * date in JDBC format into a Java date.
+ *
+ * @param str The string to parse.
+ * @return The resulting <code>java.sql.Timestamp</code> value.
+ */
+ public static Timestamp valueOf(String str)
+ {
+ int nanos = 0;
+ int dot = str.indexOf('.');
+ if (dot != -1)
+ {
+ if (str.lastIndexOf('.') != dot)
+ throw new IllegalArgumentException(str);
+
+ int len = str.length() - dot - 1;
+ if (len < 1 || len > 9)
+ throw new IllegalArgumentException(str);
+
+ nanos = Integer.parseInt(str.substring(dot + 1));
+ for (int i = len; i < 9; i++)
+ nanos *= 10;
+
+ str = str.substring(0, dot);
+
+ }
+
+ try
+ {
+ java.util.Date d;
+ synchronized (dateFormat)
+ {
+ d = (java.util.Date) dateFormat.parseObject(str);
+ }
+
+ if (d == null)
+ throw new IllegalArgumentException(str);
+
+ Timestamp ts = new Timestamp(d.getTime() + nanos / 1000000);
+ ts.nanos = nanos;
+ return ts;
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException(str);
+ }
+ }
+
+ /**
+ * This method initializes a new instance of this class with the
+ * specified year, month, and day.
+ *
+ * @param year The year for this Timestamp (year - 1900)
+ * @param month The month for this Timestamp (0-11)
+ * @param day The day for this Timestamp (1-31)
+ * @param hour The hour for this Timestamp (0-23)
+ * @param minute The minute for this Timestamp (0-59)
+ * @param second The second for this Timestamp (0-59)
+ * @param nanos The nanosecond value for this Timestamp (0 to 999,999,9999)
+ * @deprecated
+ */
+ public Timestamp(int year, int month, int day, int hour, int minute,
+ int second, int nanos)
+ {
+ super(year, month, day, hour, minute, second);
+ this.nanos = nanos;
+ }
+
+ /**
+ * This method initializes a new instance of this class with the
+ * specified time value representing the number of milliseconds since
+ * Jan 1, 1970 at 12:00 midnight GMT.
+ *
+ * @param time The time value to intialize this <code>Time</code> to.
+ */
+ public Timestamp(long date)
+ {
+ super(date - (date % 1000));
+ nanos = (int) (date % 1000) * 1000000;
+ }
+
+ /**
+ * Return the value of this Timestamp as the number of milliseconds
+ * since Jan 1, 1970 at 12:00 midnight GMT.
+ */
+ public long getTime()
+ {
+ return super.getTime() + (nanos / 1000000);
+ }
+
+ /**
+ * This method returns this date in JDBC format.
+ *
+ * @return This date as a string.
+ */
+ public String toString()
+ {
+ synchronized (dateFormat)
+ {
+ sbuf.setLength(0);
+ dateFormat.format(this, sbuf, null);
+ sbuf.append('.');
+ decimalFormat.format(nanos, sbuf, null);
+ int end = sbuf.length() - 1;
+ while (end > 20 && sbuf.charAt(end) == '0')
+ end--;
+ return sbuf.substring(0, end + 1);
+ }
+ }
+
+ /**
+ * This method returns the nanosecond value for this object.
+ * @return The nanosecond value for this object.
+ */
+ public int getNanos()
+ {
+ return nanos;
+ }
+
+ /**
+ * This method sets the nanosecond value for this object.
+ *
+ * @param nanos The nanosecond value for this object.
+ */
+ public void setNanos(int nanos)
+ {
+ this.nanos = nanos;
+ }
+
+ /**
+ * This methods tests whether this object is earlier than the specified
+ * object.
+ *
+ * @param ts The other <code>Timestamp</code> to test against.
+ * @return <code>true</code> if this object is earlier than the other object,
+ * <code>false</code> otherwise.
+ */
+ public boolean before(Timestamp ts)
+ {
+ long time1 = getTime();
+ long time2 = ts.getTime();
+ if (time1 < time2 || (time1 == time2 && getNanos() < ts.getNanos()))
+ return true;
+ return false;
+ }
+
+ /**
+ * This methods tests whether this object is later than the specified
+ * object.
+ *
+ * @param ts The other <code>Timestamp</code> to test against.
+ *
+ * @return <code>true</code> if this object is later than the other object,
+ * <code>false</code> otherwise.
+ */
+ public boolean after(Timestamp ts)
+ {
+ long time1 = getTime();
+ long time2 = ts.getTime();
+ if (time1 > time2 || (time1 == time2 && getNanos() > ts.getNanos()))
+ return true;
+ return false;
+ }
+
+ /**
+ * This method these the specified <code>Object</code> for equality
+ * against this object. This will be true if an only if the specified
+ * object is an instance of <code>Timestamp</code> and has the same
+ * time value fields.
+ *
+ * @param obj The object to test against for equality.
+ *
+ * @return <code>true</code> if the specified object is equal to this
+ * object, <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof Timestamp))
+ return false;
+
+ return equals((Timestamp) obj);
+ }
+
+ /**
+ * This method tests the specified timestamp for equality against this
+ * object. This will be true if and only if the specified object is
+ * not <code>null</code> and contains all the same time value fields
+ * as this object.
+ *
+ * @param ts The <code>Timestamp</code> to test against for equality.
+ *
+ * @return <code>true</code> if the specified object is equal to this
+ * object, <code>false</code> otherwise.
+ */
+ public boolean equals(Timestamp ts)
+ {
+ if (ts == null)
+ return false;
+
+ if (ts.getTime() != getTime())
+ return false;
+
+ if (ts.getNanos() != getNanos())
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Compare two Timestamp
+ * @param when the other Timestamp.
+ * @return 0, if the date represented
+ * by obj is exactly the same as the time represented by this
+ * object, a negative if this Timestamp is before the other Timestamp, and
+ * a positive value otherwise.
+ * @since 1.2
+ */
+ public int compareTo(Timestamp ts)
+ {
+ int s = super.compareTo((java.util.Date) ts);
+ if (s != 0)
+ return s;
+ // If Date components were equal, then we check the nanoseconds.
+ return nanos - ts.nanos;
+ }
+
+ /**
+ * Compares this Timestamp to another. This behaves like
+ * <code>compareTo(Timestamp)</code>, but it may throw a
+ * <code>ClassCastException</code>
+ * @param obj the other Timestamp.
+ * @return 0, if the Timestamp represented
+ * by obj is exactly the same as the time represented by this
+ * object, a negative if this Timestamp is before the other Timestamp, and
+ * a positive value otherwise.
+ * @exception ClassCastException if obj is not of type Timestamp.
+ * @since 1.2
+ */
+ public int compareTo(Object obj)
+ {
+ return compareTo((Timestamp) obj);
+ }
+}
diff --git a/libjava/classpath/java/sql/Types.java b/libjava/classpath/java/sql/Types.java
new file mode 100644
index 00000000000..7dd41411ada
--- /dev/null
+++ b/libjava/classpath/java/sql/Types.java
@@ -0,0 +1,85 @@
+/* Types.java -- SQL type constants
+ Copyright (C) 1999, 2001 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.sql;
+
+/**
+ * This class contains constants that are used to identify SQL data types.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Types
+{
+ // These should be self explanatory. People need a SQL book, not
+ // Javadoc comments for these.
+ public static final int BIT = -7;
+ public static final int TINYINT = -6;
+ public static final int SMALLINT = 5;
+ public static final int INTEGER = 4;
+ public static final int BIGINT = -5;
+ public static final int FLOAT = 6;
+ public static final int REAL = 7;
+ public static final int DOUBLE = 8;
+ public static final int NUMERIC = 2;
+ public static final int DECIMAL = 3;
+ public static final int CHAR = 1;
+ public static final int VARCHAR = 12;
+ public static final int LONGVARCHAR = -1;
+ public static final int DATE = 91;
+ public static final int TIME = 92;
+ public static final int TIMESTAMP = 93;
+ public static final int BINARY = -2;
+ public static final int VARBINARY = -3;
+ public static final int LONGVARBINARY = -4;
+ public static final int NULL = 0;
+ public static final int OTHER = 1111;
+ public static final int JAVA_OBJECT = 2000;
+ public static final int DISTINCT = 2001;
+ public static final int STRUCT = 2002;
+ public static final int ARRAY = 2003;
+ public static final int BLOB = 2004;
+ public static final int CLOB = 2005;
+ public static final int REF = 2006;
+ public static final int DATALINK = 70;
+ public static final int BOOLEAN = 16;
+
+ // This class can't be instantiated.
+ private Types()
+ {
+ }
+}
diff --git a/libjava/classpath/java/sql/package.html b/libjava/classpath/java/sql/package.html
new file mode 100644
index 00000000000..e8982f529b4
--- /dev/null
+++ b/libjava/classpath/java/sql/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.sql package.
+ Copyright (C) 2002 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 - java.sql</title></head>
+
+<body>
+<p>Interfaces and classes to connect to a database and wrappers for data
+in the database and result queries.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/text/Annotation.java b/libjava/classpath/java/text/Annotation.java
new file mode 100644
index 00000000000..cecb44aaf0e
--- /dev/null
+++ b/libjava/classpath/java/text/Annotation.java
@@ -0,0 +1,113 @@
+/* Annotation.java -- Wrapper for a text attribute object
+ Copyright (C) 1998, 1999 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.text;
+
+/**
+ * This class is used as a wrapper for a text attribute object. Annotation
+ * objects are associated with a specific range of text. Changing either
+ * the text range or the underlying text invalidates the object.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Annotation
+{
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * This is the attribute object being wrappered
+ */
+private Object attrib;
+
+/*************************************************************************/
+
+/**
+ * Constructors
+ */
+
+/**
+ * This method initializes a new instance of <code>Annotation</code> to
+ * wrapper the specified text attribute object.
+ *
+ * @param attrib The text attribute <code>Object</code> to wrapper.
+ */
+public
+Annotation(Object attrib)
+{
+ this.attrib = attrib;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * This method returns the text attribute object this <code>Annotation</code>
+ * instance is wrappering.
+ *
+ * @return The text attribute object for this <code>Annotation</code>.
+ */
+public Object
+getValue()
+{
+ return(attrib);
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns a <code>String</code> representation of this
+ * object.
+ *
+ * @return This object as a <code>String</code>.
+ */
+public String
+toString()
+{
+ return(getClass().getName() + "[value=" + attrib.toString() + "]");
+}
+
+} // class Annotation
+
diff --git a/libjava/classpath/java/text/AttributedCharacterIterator.java b/libjava/classpath/java/text/AttributedCharacterIterator.java
new file mode 100644
index 00000000000..e5686ba346d
--- /dev/null
+++ b/libjava/classpath/java/text/AttributedCharacterIterator.java
@@ -0,0 +1,268 @@
+/* AttributedCharacterIterator.java -- Iterate over attributes
+ Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.io.InvalidObjectException;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This interface extends the <code>CharacterIterator</code> interface
+ * in order to support iteration over character attributes as well as
+ * over the characters themselves.
+ * <p>
+ * In addition to attributes of specific characters, this interface
+ * supports the concept of the "attribute run", which is an attribute
+ * that is defined for a particular value across an entire range of
+ * characters or which is undefined over a range of characters.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface AttributedCharacterIterator extends CharacterIterator
+{
+ /**
+ * This class defines attribute keys that are used as text attributes.
+ */
+ public static class Attribute implements Serializable
+ {
+ private static final long serialVersionUID = -9142742483513960612L;
+
+ /**
+ * This is the attribute for the language of the text. The value of
+ * attributes of this key type are instances of <code>Locale</code>.
+ */
+ public static final Attribute LANGUAGE = new Attribute ("LANGUAGE");
+
+ /**
+ * This is the attribute for the reading form of text. This is used
+ * for storing pronunciation along with the written text for languages
+ * which need it. The value of attributes of this key type are
+ * instances of <code>Annotation</code> which wrappers a <code>String</code>.
+ */
+ public static final Attribute READING = new Attribute ("READING");
+
+ /**
+ * This is the attribute for input method segments. The value of attributes
+ * of this key type are instances of <code>Annotation</code> which wrapper
+ * a <code>String</code>.
+ */
+ public static final Attribute INPUT_METHOD_SEGMENT =
+ new Attribute ("INPUT_METHOD_SEGMENT");
+
+ /**
+ * This is the name of the attribute key
+ * @serial
+ */
+ private String name;
+
+ /**
+ * This method initializes a new instance of this class with the specified
+ * name.
+ *
+ * @param name The name of this attribute key.
+ */
+ protected Attribute (String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * This method returns the name of this attribute.
+ *
+ * @return The attribute name
+ */
+ protected String getName()
+ {
+ return name;
+ }
+
+ /**
+ * This method resolves an instance of <code>AttributedCharacterIterator.Attribute</code>
+ * that is being deserialized to one of the three pre-defined attribute
+ * constants. It does this by comparing the names of the attributes. The
+ * constant that the deserialized object resolves to is returned.
+ *
+ * @return The resolved contant value
+ *
+ * @exception InvalidObjectException If the object being deserialized cannot be resolved.
+ */
+ protected Object readResolve() throws InvalidObjectException
+ {
+ if (this.equals (READING))
+ return READING;
+
+ if (this.equals (LANGUAGE))
+ return LANGUAGE;
+
+ if (this.equals (INPUT_METHOD_SEGMENT))
+ return INPUT_METHOD_SEGMENT;
+
+ throw new InvalidObjectException ("Can't resolve Attribute: " + getName());
+ }
+
+ /**
+ * This method tests this object for equality against the specified object.
+ * The two objects will be considered equal if and only if:
+ * <ul>
+ * <li>The specified object is not <code>null</code>.
+ * <li>The specified object is an instance of <code>AttributedCharacterIterator.Attribute</code>.
+ * <li>The specified object has the same attribute name as this object.
+ * </ul>
+ *
+ * @param The <code>Object</code> to test for equality against this object.
+ *
+ * @return <code>true</code> if the specified object is equal to this one, <code>false</code> otherwise.
+ */
+ public final boolean equals (Object obj)
+ {
+ if (obj == this)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * This method returns a hash value for this object.
+ *
+ * @return A hash value for this object.
+ */
+ public final int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ * This method returns a <code>String</code> representation of this object.
+ *
+ * @return A <code>String</code> representation of this object.
+ */
+ public String toString()
+ {
+ return getClass().getName() + "(" + getName() + ")";
+ }
+
+ } // Inner class Attribute
+
+ /**
+ * This method returns a list of all keys that are defined for the
+ * text range. This can be an empty list if no attributes are defined.
+ *
+ * @return A list of keys
+ */
+ Set getAllAttributeKeys();
+
+ /**
+ * This method returns a <code>Map</code> of the attributed defined for
+ * the current character.
+ *
+ * @return A <code>Map</code> of the attributes for the current character.
+ */
+ Map getAttributes();
+
+ /**
+ * This method returns the value of the specified attribute for the
+ * current character. If the attribute is not defined for the current
+ * character, <code>null</code> is returned.
+ *
+ * @param attrib The attribute to retrieve the value of.
+ *
+ * @return The value of the specified attribute
+ */
+ Object getAttribute (AttributedCharacterIterator.Attribute attrib);
+
+ /**
+ * This method returns the index of the first character in the run that
+ * contains all attributes defined for the current character.
+ *
+ * @return The start index of the run
+ */
+ int getRunStart();
+
+ /**
+ * This method returns the index of the first character in the run that
+ * contains all attributes in the specified <code>Set</code> defined for
+ * the current character.
+ *
+ * @param attribs The <code>Set</code> of attributes.
+ *
+ * @return The start index of the run.
+ */
+ int getRunStart (Set attribs);
+
+ /**
+ * This method returns the index of the first character in the run that
+ * contains the specified attribute defined for the current character.
+ *
+ * @param attrib The attribute.
+ *
+ * @return The start index of the run.
+ */
+ int getRunStart (AttributedCharacterIterator.Attribute attrib);
+
+ /**
+ * This method returns the index of the character after the end of the run
+ * that contains all attributed defined for the current character.
+ *
+ * @return The end index of the run.
+ */
+ int getRunLimit();
+
+ /**
+ * This method returns the index of the character after the end of the run
+ * that contains all attributes in the specified <code>Set</code> defined
+ * for the current character.
+ *
+ * @param attribs The <code>Set</code> of attributes.
+ *
+ * @return The end index of the run.
+ */
+ int getRunLimit (Set attribs);
+
+ /**
+ * This methods returns the index of the character after the end of the run
+ * that contains the specified attribute defined for the current character.
+ *
+ * @param attrib The attribute.
+ *
+ * @return The end index of the run.
+ */
+ int getRunLimit (AttributedCharacterIterator.Attribute attrib);
+
+} // interface AttributedCharacterIterator
diff --git a/libjava/classpath/java/text/AttributedString.java b/libjava/classpath/java/text/AttributedString.java
new file mode 100644
index 00000000000..b9ced8f5ac2
--- /dev/null
+++ b/libjava/classpath/java/text/AttributedString.java
@@ -0,0 +1,425 @@
+/* AttributedString.java -- Models text with attributes
+ Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class models a <code>String</code> with attributes over various
+ * subranges of the string. It allows applications to access this
+ * information via the <code>AttributedCharcterIterator</code> interface.
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class AttributedString
+{
+
+/*************************************************************************/
+
+/*
+ * Inner Classes
+ */
+
+/**
+ * This class contains the attributes and ranges of text over which
+ * that attributes apply.
+ */
+final class AttributeRange
+{
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * A Map of the attributes
+ */
+Map attribs;
+
+/**
+ * The beginning index of the attributes
+ */
+int begin_index;
+
+/**
+ * The ending index of the attributes
+ */
+int end_index;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+AttributeRange(Map attribs, int begin_index, int end_index)
+{
+ this.attribs = attribs;
+ this.begin_index = begin_index;
+ this.end_index = end_index;
+}
+
+} // Inner class AttributeRange
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * This object holds the string we are representing.
+ */
+private StringCharacterIterator sci;
+
+/**
+ * This is the attribute information
+ */
+private AttributeRange[] attribs;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * This method initializes a new instance of <code>AttributedString</code>
+ * that represents the specified <code>String</code> with no attributes.
+ *
+ * @param str The <code>String</code> to be attributed.
+ */
+public
+AttributedString(String str)
+{
+ sci = new StringCharacterIterator(str);
+ attribs = new AttributeRange[0];
+}
+
+/*************************************************************************/
+
+/**
+ * This method initializes a new instance of <code>AttributedString</code>
+ * that represents that specified <code>String</code> with the specified
+ * attributes over the entire length of the <code>String</code>.
+ *
+ * @param str The <code>String</code> to be attributed.
+ * @param attributes The attribute list.
+ */
+public
+AttributedString(String str, Map attributes)
+{
+ this(str);
+
+ attribs = new AttributeRange[1];
+ attribs[0] = new AttributeRange(attributes, 0, str.length());
+}
+
+/*************************************************************************/
+
+/**
+ * This method initializes a new instance of <code>AttributedString</code>
+ * that will use the text and attribute information from the specified
+ * <code>AttributedCharacterIterator</code>.
+ *
+ * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
+ */
+public
+AttributedString(AttributedCharacterIterator aci)
+{
+ this(aci, aci.getBeginIndex(), aci.getEndIndex(), null);
+}
+
+/*************************************************************************/
+
+/**
+ * This method initializes a new instance of <code>AttributedString</code>
+ * that will use the text and attribute information from the specified
+ * subrange of the specified <code>AttributedCharacterIterator</code>.
+ *
+ * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
+ * @param begin_index The beginning index of the text subrange.
+ * @param end_index The ending index of the text subrange.
+ */
+public
+AttributedString(AttributedCharacterIterator aci, int begin_index,
+ int end_index)
+{
+ this(aci, begin_index, end_index, null);
+}
+
+/*************************************************************************/
+
+/**
+ * This method initializes a new instance of <code>AttributedString</code>
+ * that will use the text and attribute information from the specified
+ * subrange of the specified <code>AttributedCharacterIterator</code>.
+ * Only attributes from the source iterator that are present in the
+ * specified array of attributes will be included in the attribute list
+ * for this object.
+ *
+ * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
+ * @param begin_index The beginning index of the text subrange.
+ * @param end_index The ending index of the text subrange.
+ * @param attributes A list of attributes to include from the iterator, or <code>null</code> to include all attributes.
+ */
+public
+AttributedString(AttributedCharacterIterator aci, int begin_index,
+ int end_index, AttributedCharacterIterator.Attribute[] attributes)
+{
+ // Validate some arguments
+ if ((begin_index < 0) || (end_index < begin_index))
+ throw new IllegalArgumentException("Bad index values");
+
+ StringBuffer sb = new StringBuffer("");
+
+ // Get the valid attribute list
+ Set all_attribs = aci.getAllAttributeKeys();
+ if (attributes != null)
+ all_attribs.retainAll(Arrays.asList(attributes));
+
+ // Loop through and extract the attributes
+ char c = aci.setIndex(begin_index);
+
+ ArrayList accum = new ArrayList();
+ do
+ {
+ sb.append(c);
+
+ Iterator iter = all_attribs.iterator();
+ while(iter.hasNext())
+ {
+ Object obj = iter.next();
+
+ // What should we do if this is not true?
+ if (!(obj instanceof AttributedCharacterIterator.Attribute))
+ continue;
+
+ AttributedCharacterIterator.Attribute attrib =
+ (AttributedCharacterIterator.Attribute)obj;
+
+ // Make sure the attribute is defined.
+ int rl = aci.getRunLimit(attrib);
+ if (rl == -1)
+ continue;
+ if (rl > end_index)
+ rl = end_index;
+ rl -= begin_index;
+
+ // Check to see if we already processed this one
+ int rs = aci.getRunStart(attrib);
+ if ((rs < aci.getIndex()) && (aci.getIndex() != begin_index))
+ continue;
+
+ // If the attribute run starts before the beginning index, we
+ // need to junk it if it is an Annotation.
+ Object attrib_obj = aci.getAttribute(attrib);
+ if (rs < begin_index)
+ {
+ if (attrib_obj instanceof Annotation)
+ continue;
+
+ rs = begin_index;
+ }
+ else
+ {
+ rs -= begin_index;
+ }
+
+ // Create a map object. Yes this will only contain one attribute
+ Map new_map = new Hashtable();
+ new_map.put(attrib, attrib_obj);
+
+ // Add it to the attribute list.
+ accum.add(new AttributeRange(new_map, rs, rl));
+ }
+
+ c = aci.next();
+ }
+ while(c != CharacterIterator.DONE);
+
+ attribs = new AttributeRange[accum.size()];
+ attribs = (AttributeRange[]) accum.toArray(attribs);
+
+ sci = new StringCharacterIterator(sb.toString());
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * This method adds a new attribute that will cover the entire string.
+ *
+ * @param attrib The attribute to add.
+ * @param value The value of the attribute.
+ */
+public void
+addAttribute(AttributedCharacterIterator.Attribute attrib, Object value)
+{
+ addAttribute(attrib, value, 0, sci.getEndIndex());
+}
+
+/*************************************************************************/
+
+/**
+ * This method adds a new attribute that will cover the specified subrange
+ * of the string.
+ *
+ * @param attrib The attribute to add.
+ * @param value The value of the attribute, which may be null.
+ * @param begin_index The beginning index of the subrange.
+ * @param end_index The ending index of the subrange.
+ *
+ * @exception IllegalArgumentException If attribute is <code>null</code> or the subrange is not valid.
+ */
+public void
+addAttribute(AttributedCharacterIterator.Attribute attrib, Object value,
+ int begin_index, int end_index)
+{
+ if (attrib == null)
+ throw new IllegalArgumentException("null attribute");
+
+ HashMap hm = new HashMap();
+ hm.put(attrib, value);
+
+ addAttributes(hm, begin_index, end_index);
+}
+
+/*************************************************************************/
+
+/**
+ * This method adds all of the attributes in the specified list to the
+ * specified subrange of the string.
+ *
+ * @param attributes The list of attributes.
+ * @param begin_index The beginning index.
+ * @param end_index The ending index
+ *
+ * @param IllegalArgumentException If the list is <code>null</code> or the subrange is not valid.
+ */
+public void
+addAttributes(Map attributes, int begin_index, int end_index)
+{
+ if (attributes == null)
+ throw new IllegalArgumentException("null attribute");
+
+ if ((begin_index < 0) || (end_index > sci.getEndIndex()) ||
+ (end_index < begin_index))
+ throw new IllegalArgumentException("bad range");
+
+ AttributeRange[] new_list = new AttributeRange[attribs.length + 1];
+ System.arraycopy(attribs, 0, new_list, 0, attribs.length);
+ attribs = new_list;
+ attribs[attribs.length - 1] = new AttributeRange(attributes, begin_index,
+ end_index);
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns an <code>AttributedCharacterIterator</code> that
+ * will iterate over the entire string.
+ *
+ * @return An <code>AttributedCharacterIterator</code> for the entire string.
+ */
+public AttributedCharacterIterator
+getIterator()
+{
+ return(new AttributedStringIterator(sci, attribs, 0, sci.getEndIndex(), null));
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns an <code>AttributedCharacterIterator</code> that
+ * will iterate over the entire string. This iterator will return information
+ * about the list of attributes in the specified array. Attributes not in
+ * the array may or may not be returned by the iterator. If the specified
+ * array is <code>null</code>, all attributes will be returned.
+ *
+ * @param attributes A list of attributes to include in the returned iterator.
+ *
+ * @return An <code>AttributedCharacterIterator</code> for this string.
+ */
+public AttributedCharacterIterator
+getIterator(AttributedCharacterIterator.Attribute[] attributes)
+{
+ return(getIterator(attributes, 0, sci.getEndIndex()));
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns an <code>AttributedCharacterIterator</code> that
+ * will iterate over the specified subrange. This iterator will return information
+ * about the list of attributes in the specified array. Attributes not in
+ * the array may or may not be returned by the iterator. If the specified
+ * array is <code>null</code>, all attributes will be returned.
+ *
+ * @param attributes A list of attributes to include in the returned iterator.
+ * @param begin_index The beginning index of the subrange.
+ * @param end_index The ending index of the subrange.
+ *
+ * @return An <code>AttributedCharacterIterator</code> for this string.
+ */
+public AttributedCharacterIterator
+getIterator(AttributedCharacterIterator.Attribute[] attributes,
+ int begin_index, int end_index)
+{
+ if ((begin_index < 0) || (end_index > sci.getEndIndex()) ||
+ (end_index < begin_index))
+ throw new IllegalArgumentException("bad range");
+
+ return(new AttributedStringIterator(sci, attribs, begin_index, end_index,
+ attributes));
+}
+
+} // class AttributedString
+
diff --git a/libjava/classpath/java/text/AttributedStringIterator.java b/libjava/classpath/java/text/AttributedStringIterator.java
new file mode 100644
index 00000000000..7d7bf270cef
--- /dev/null
+++ b/libjava/classpath/java/text/AttributedStringIterator.java
@@ -0,0 +1,348 @@
+/* AttributedStringIterator.java -- Class to iterate over AttributedString
+ Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class implements the AttributedCharacterIterator interface. It
+ * is used by AttributedString.getIterator().
+ *
+ * @version 0.0
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+class AttributedStringIterator implements AttributedCharacterIterator
+{
+
+/*************************************************************************/
+
+/**
+ * Instance Variables
+ */
+
+/**
+ * The character iterator containing the text
+ */
+private CharacterIterator ci;
+
+/**
+ * The list of attributes and ranges
+ */
+private AttributedString.AttributeRange[] attribs;
+
+/**
+ * The list of attributes that the user is interested in. We may,
+ * at our option, not return any other attributes.
+ */
+private AttributedCharacterIterator.Attribute[] restricts;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+AttributedStringIterator(StringCharacterIterator sci,
+ AttributedString.AttributeRange[] attribs,
+ int begin_index, int end_index,
+ AttributedCharacterIterator.Attribute[] restricts)
+{
+ this.ci = new StringCharacterIterator(sci, begin_index, end_index);
+ this.attribs = attribs;
+ this.restricts = restricts;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+// First we have a bunch of stupid redirects. If StringCharacterIterator
+// weren't final, I just would have extended that for this class. Alas, no.
+
+public Object
+clone()
+{
+ return(ci.clone());
+}
+
+public char
+current()
+{
+ return(ci.current());
+}
+
+public char
+next()
+{
+ return(ci.next());
+}
+
+public char
+previous()
+{
+ return(ci.previous());
+}
+
+public char
+first()
+{
+ return(ci.first());
+}
+
+public char
+last()
+{
+ return(ci.last());
+}
+
+public int
+getIndex()
+{
+ return(ci.getIndex());
+}
+
+public char
+setIndex(int index)
+{
+ return(ci.setIndex(index));
+}
+
+public int
+getBeginIndex()
+{
+ return(ci.getBeginIndex());
+}
+
+public int
+getEndIndex()
+{
+ return(ci.getEndIndex());
+}
+
+/*
+ * Here is where the AttributedCharacterIterator methods start.
+ */
+
+/*************************************************************************/
+
+/**
+ * Returns a list of all the attribute keys that are defined anywhere
+ * on this string.
+ */
+public Set
+getAllAttributeKeys()
+{
+ HashSet s = new HashSet();
+ if (attribs == null)
+ return(s);
+
+ for (int i = 0; i < attribs.length; i++)
+ {
+ if (attribs[i].begin_index > getEndIndex()
+ || attribs[i].end_index <= getBeginIndex())
+ continue;
+
+ Set key_set = attribs[i].attribs.keySet();
+ Iterator iter = key_set.iterator();
+ while (iter.hasNext())
+ {
+ s.add(iter.next());
+ }
+ }
+
+ return(s);
+}
+
+/*************************************************************************/
+
+/**
+ * Various methods that determine how far the run extends for various
+ * attribute combinations.
+ */
+
+public int
+getRunLimit()
+{
+ return(getRunLimit(getAttributes().keySet()));
+}
+
+public int
+getRunLimit(AttributedCharacterIterator.Attribute attrib)
+{
+ HashSet s = new HashSet();
+ s.add(attrib);
+
+ return(getRunLimit(s));
+}
+
+public synchronized int
+getRunLimit(Set attribute_set)
+{
+ boolean hit = false;
+ int runLimit = ci.getEndIndex ();
+ int pos = ci.getIndex ();
+
+ for (int i = 0; i < attribs.length; ++i)
+ {
+ if (pos >= attribs[i].begin_index &&
+ pos < attribs[i].end_index)
+ {
+ Iterator iter = attribute_set.iterator();
+ while(iter.hasNext())
+ if (attribs[i].attribs.containsKey(iter.next()))
+ {
+ hit = true;
+ runLimit = Math.min(runLimit, attribs[i].end_index);
+ }
+ }
+ }
+ if (hit)
+ return runLimit;
+ else
+ return ci.getEndIndex();
+}
+
+/*************************************************************************/
+
+/**
+ * Various methods that determine where the run begins for various
+ * attribute combinations.
+ */
+
+public int
+getRunStart()
+{
+ return(getRunStart(getAttributes().keySet()));
+}
+
+public int
+getRunStart(AttributedCharacterIterator.Attribute attrib)
+{
+ HashSet s = new HashSet();
+ s.add(attrib);
+
+ return(getRunStart(s));
+}
+
+public int
+getRunStart(Set attribute_set)
+{
+ boolean hit = false;
+ int runBegin = 0;
+ int pos = ci.getIndex ();
+
+ for (int i = 0; i < attribs.length; ++i)
+ {
+ if (pos >= attribs[i].begin_index &&
+ pos <= attribs[i].end_index)
+ {
+ Iterator iter = attribute_set.iterator();
+ while(iter.hasNext())
+ if (attribs[i].attribs.containsKey(iter.next()))
+ {
+ hit = true;
+ runBegin = Math.max(runBegin, attribs[i].begin_index);
+ }
+ }
+ }
+ if (hit)
+ return runBegin;
+ else
+ return -1;
+}
+
+/*************************************************************************/
+
+public Object
+getAttribute(AttributedCharacterIterator.Attribute attrib)
+{
+ if (attribs == null)
+ return(null);
+
+ for (int i = 0; i < attribs.length; i++)
+ {
+ Set key_set = attribs[i].attribs.keySet();
+ Iterator iter = key_set.iterator();
+ while (iter.hasNext())
+ {
+ Object obj = iter.next();
+
+ // Check for attribute match and range match
+ if (obj.equals(attrib))
+ if ((ci.getIndex() >= attribs[i].begin_index) &&
+ (ci.getIndex() < attribs[i].end_index))
+ return(attribs[i].attribs.get(obj));
+ }
+ }
+
+ return(null);
+}
+
+/*************************************************************************/
+
+/**
+ * Return a list of all the attributes and values defined for this
+ * character
+ */
+public Map
+getAttributes()
+{
+ HashMap m = new HashMap();
+ if (attribs == null)
+ return(m);
+
+ for (int i = 0; i < attribs.length; i++)
+ {
+ if ((ci.getIndex() >= attribs[i].begin_index) &&
+ (ci.getIndex() < attribs[i].end_index))
+ m.putAll(attribs[i].attribs);
+ }
+
+ return(m);
+}
+
+} // class AttributedStringIterator
+
diff --git a/libjava/classpath/java/text/BreakIterator.java b/libjava/classpath/java/text/BreakIterator.java
new file mode 100644
index 00000000000..d021dceba73
--- /dev/null
+++ b/libjava/classpath/java/text/BreakIterator.java
@@ -0,0 +1,374 @@
+/* BreakIterator.java -- Breaks text into elements
+ Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * This class iterates over text elements such as words, lines, sentences,
+ * and characters. It can only iterate over one of these text elements at
+ * a time. An instance of this class configured for the desired iteration
+ * type is created by calling one of the static factory methods, not
+ * by directly calling a constructor.
+ *
+ * The standard iterators created by the factory methods in this
+ * class will be valid upon creation. That is, their methods will
+ * not cause exceptions if called before you call setText().
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @date March 19, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.1.
+ */
+public abstract class BreakIterator implements Cloneable
+{
+ /**
+ * This value is returned by the <code>next()</code> and
+ * <code>previous</code> in order to indicate that the end of the
+ * text has been reached.
+ */
+ // The value was discovered by writing a test program.
+ public static final int DONE = -1;
+
+ /**
+ * This method initializes a new instance of <code>BreakIterator</code>.
+ * This protected constructor is available to subclasses as a default
+ * no-arg superclass constructor.
+ */
+ protected BreakIterator ()
+ {
+ }
+
+ /**
+ * Create a clone of this object.
+ */
+ public Object clone ()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * This method returns the index of the current text element boundary.
+ *
+ * @return The current text boundary.
+ */
+ public abstract int current ();
+
+ /**
+ * This method returns the first text element boundary in the text being
+ * iterated over.
+ *
+ * @return The first text boundary.
+ */
+ public abstract int first ();
+
+ /**
+ * This methdod returns the offset of the text element boundary following
+ * the specified offset.
+ *
+ * @param offset The text index from which to find the next text boundary.
+ *
+ * @param The next text boundary following the specified index.
+ */
+ public abstract int following (int pos);
+
+ /**
+ * This method returns a list of locales for which instances of
+ * <code>BreakIterator</code> are available.
+ *
+ * @return A list of available locales
+ */
+ public static synchronized Locale[] getAvailableLocales ()
+ {
+ Locale[] l = new Locale[1];
+ l[0] = Locale.US;
+ return l;
+ }
+
+ private static BreakIterator getInstance (String type, Locale loc)
+ {
+ String className;
+ try
+ {
+ ResourceBundle res
+ = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ loc, ClassLoader.getSystemClassLoader());
+ className = res.getString(type);
+ }
+ catch (MissingResourceException x)
+ {
+ return null;
+ }
+ try
+ {
+ Class k = Class.forName(className);
+ return (BreakIterator) k.newInstance();
+ }
+ catch (ClassNotFoundException x1)
+ {
+ return null;
+ }
+ catch (InstantiationException x2)
+ {
+ return null;
+ }
+ catch (IllegalAccessException x3)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * This method returns an instance of <code>BreakIterator</code> that will
+ * iterate over characters as defined in the default locale.
+ *
+ * @return A <code>BreakIterator</code> instance for the default locale.
+ */
+ public static BreakIterator getCharacterInstance ()
+ {
+ return getCharacterInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>BreakIterator</code> that will
+ * iterate over characters as defined in the specified locale. If the
+ * desired locale is not available, the default locale is used.
+ *
+ * @param locale The desired locale.
+ *
+ * @return A <code>BreakIterator</code> instance for the default locale.
+ */
+ public static BreakIterator getCharacterInstance (Locale loc)
+ {
+ BreakIterator r = getInstance ("CharacterIterator", loc);
+ if (r == null)
+ r = new gnu.java.text.CharacterBreakIterator ();
+ return r;
+ }
+
+ /**
+ * This method returns an instance of <code>BreakIterator</code> that will
+ * iterate over line breaks as defined in the default locale.
+ *
+ * @return A <code>BreakIterator</code> instance for the default locale.
+ */
+ public static BreakIterator getLineInstance ()
+ {
+ return getLineInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>BreakIterator</code> that will
+ * iterate over line breaks as defined in the specified locale. If the
+ * desired locale is not available, the default locale is used.
+ *
+ * @param locale The desired locale.
+ *
+ * @return A <code>BreakIterator</code> instance for the default locale.
+ */
+ public static BreakIterator getLineInstance (Locale loc)
+ {
+ BreakIterator r = getInstance ("LineIterator", loc);
+ if (r == null)
+ r = new gnu.java.text.LineBreakIterator ();
+ return r;
+ }
+
+ /**
+ * This method returns an instance of <code>BreakIterator</code> that will
+ * iterate over sentences as defined in the default locale.
+ *
+ * @return A <code>BreakIterator</code> instance for the default locale.
+ */
+ public static BreakIterator getSentenceInstance ()
+ {
+ return getSentenceInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>BreakIterator</code> that will
+ * iterate over sentences as defined in the specified locale. If the
+ * desired locale is not available, the default locale is used.
+ *
+ * @param locale The desired locale.
+ *
+ * @return A <code>BreakIterator</code> instance for the default locale.
+ */
+ public static BreakIterator getSentenceInstance (Locale loc)
+ {
+ BreakIterator r = getInstance ("SentenceIterator", loc);
+ if (r == null)
+ r = new gnu.java.text.SentenceBreakIterator ();
+ return r;
+ }
+
+ /**
+ * This method returns the text this object is iterating over as a
+ * <code>CharacterIterator</code>.
+ *
+ * @param The text being iterated over.
+ */
+ public abstract CharacterIterator getText ();
+
+ /**
+ * This method returns an instance of <code>BreakIterator</code> that will
+ * iterate over words as defined in the default locale.
+ *
+ * @return A <code>BreakIterator</code> instance for the default locale.
+ */
+ public static BreakIterator getWordInstance ()
+ {
+ return getWordInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>BreakIterator</code> that will
+ * iterate over words as defined in the specified locale. If the
+ * desired locale is not available, the default locale is used.
+ *
+ * @param locale The desired locale.
+ *
+ * @return A <code>BreakIterator</code> instance for the default locale.
+ */
+ public static BreakIterator getWordInstance (Locale loc)
+ {
+ BreakIterator r = getInstance ("WordIterator", loc);
+ if (r == null)
+ r = new gnu.java.text.WordBreakIterator ();
+ return r;
+ }
+
+ /**
+ * This method tests whether or not the specified position is a text
+ * element boundary.
+ *
+ * @param offset The text position to test.
+ *
+ * @return <code>true</code> if the position is a boundary,
+ * <code>false</code> otherwise.
+ */
+ public boolean isBoundary (int pos)
+ {
+ if (pos == 0)
+ return true;
+ return following (pos - 1) == pos;
+ }
+
+ /**
+ * This method returns the last text element boundary in the text being
+ * iterated over.
+ *
+ * @return The last text boundary.
+ */
+ public abstract int last ();
+
+ /**
+ * This method returns the text element boundary following the current
+ * text position.
+ *
+ * @return The next text boundary.
+ */
+ public abstract int next ();
+
+ /**
+ * This method returns the n'th text element boundary following the current
+ * text position.
+ *
+ * @param n The number of text element boundaries to skip.
+ *
+ * @return The next text boundary.
+ */
+ public abstract int next (int n);
+
+ /**
+ * This methdod returns the offset of the text element boundary preceding
+ * the specified offset.
+ *
+ * @param offset The text index from which to find the preceding
+ * text boundary.
+ *
+ * @returns The next text boundary preceding the specified index.
+ */
+ public int preceding (int pos)
+ {
+ if (following (pos) == DONE)
+ last ();
+ while (previous () >= pos)
+ ;
+ return current ();
+ }
+
+ /**
+ * This method returns the text element boundary preceding the current
+ * text position.
+ *
+ * @return The previous text boundary.
+ */
+ public abstract int previous ();
+
+ /**
+ * This method sets the text string to iterate over.
+ *
+ * @param str The <code>String</code> to iterate over.
+ */
+ public void setText (String newText)
+ {
+ setText (new StringCharacterIterator (newText));
+ }
+
+ /**
+ * This method sets the text to iterate over from the specified
+ * <code>CharacterIterator</code>.
+ *
+ * @param ci The desired <code>CharacterIterator</code>.
+ */
+ public abstract void setText (CharacterIterator newText);
+}
diff --git a/libjava/classpath/java/text/CharacterIterator.java b/libjava/classpath/java/text/CharacterIterator.java
new file mode 100644
index 00000000000..6b3f951d1fb
--- /dev/null
+++ b/libjava/classpath/java/text/CharacterIterator.java
@@ -0,0 +1,144 @@
+/* CharacterIterator.java -- Iterate over a character range
+ Copyright (C) 1998, 2001 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.text;
+
+/**
+ * This interface defines a mechanism for iterating over a range of
+ * characters. For a given range of text, a beginning and ending index,
+ * as well as a current index are defined. These values can be queried
+ * by the methods in this interface. Additionally, various methods allow
+ * the index to be set.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface CharacterIterator extends Cloneable
+{
+ /**
+ * This is a special constant value that is returned when the beginning or
+ * end of the character range has been reached.
+ */
+ char DONE = '\uFFFF';
+
+ /**
+ * This method returns the character at the current index position
+ *
+ * @return The character at the current index position.
+ */
+ char current();
+
+ /**
+ * This method increments the current index and then returns the character
+ * at the new index value. If the index is already at <code>getEndIndex() - 1</code>,
+ * it will not be incremented.
+ *
+ * @return The character at the position of the incremented index value,
+ * or <code>DONE</code> if the index has reached getEndIndex() - 1
+ */
+ char next();
+
+ /**
+ * This method decrements the current index and then returns the character
+ * at the new index value. If the index value is already at the beginning
+ * index, it will not be decremented.
+ *
+ * @return The character at the position of the decremented index value,
+ * or <code>DONE</code> if index was already equal to the beginning index value.
+ */
+ char previous();
+
+ /**
+ * This method sets the index value to the beginning of the range and returns
+ * the character there.
+ *
+ * @return The character at the beginning of the range, or <code>DONE</code> if the range is empty.
+ */
+ char first();
+
+ /**
+ * This method sets the index value to <code>getEndIndex() - 1</code> and
+ * returns the character there. If the range is empty, then the index value
+ * will be set equal to the beginning index.
+ *
+ * @return The character at the end of the range, or <code>DONE</code> if the range is empty.
+ */
+ char last();
+
+ /**
+ * This method returns the current value of the index.
+ *
+ * @return The current index value
+ */
+ int getIndex();
+
+ /**
+ * This method sets the value of the index to the specified value, then
+ * returns the character at that position.
+ *
+ * @param index The new index value.
+ *
+ * @return The character at the new index value or <code>DONE</code> if the index value is equal to <code>getEndIndex</code>.
+ */
+ char setIndex (int index) throws IllegalArgumentException;
+
+ /**
+ * This method returns the character position of the first character in the
+ * range.
+ *
+ * @return The index of the first character in the range.
+ */
+ int getBeginIndex();
+
+ /**
+ * This method returns the character position of the end of the text range.
+ * This will actually be the index of the first character following the
+ * end of the range. In the event the text range is empty, this will be
+ * equal to the first character in the range.
+ *
+ * @return The index of the end of the range.
+ */
+ int getEndIndex();
+
+ /**
+ * This method creates a copy of this <code>CharacterIterator</code>.
+ *
+ * @return A copy of this <code>CharacterIterator</code>.
+ */
+ Object clone();
+
+} // interface CharacterIterator
diff --git a/libjava/classpath/java/text/ChoiceFormat.java b/libjava/classpath/java/text/ChoiceFormat.java
new file mode 100644
index 00000000000..23c8a8c3af0
--- /dev/null
+++ b/libjava/classpath/java/text/ChoiceFormat.java
@@ -0,0 +1,503 @@
+/* ChoiceFormat.java -- Format over a range of numbers
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.util.Vector;
+
+/**
+ * This class allows a format to be specified based on a range of numbers.
+ * To use this class, first specify two lists of formats and range terminators.
+ * These lists must be arrays of equal length. The format of index
+ * <code>i</code> will be selected for value <code>X</code> if
+ * <code>terminator[i] &lt;= X &lt; limit[i + 1]</code>. If the value X is not
+ * included in any range, then either the first or last format will be
+ * used depending on whether the value X falls outside the range.
+ * <p>
+ * This sounds complicated, but that is because I did a poor job of
+ * explaining it. Consider the following example:
+ * <p>
+ *
+<pre>terminators = { 1, ChoiceFormat.nextDouble(1) }
+formats = { "file", "files" }</pre>
+ *
+ * <p>
+ * In this case if the actual number tested is one or less, then the word
+ * "file" is used as the format value. If the number tested is greater than
+ * one, then "files" is used. This allows plurals to be handled
+ * gracefully. Note the use of the method <code>nextDouble</code>. This
+ * method selects the next highest double number than its argument. This
+ * effectively makes any double greater than 1.0 cause the "files" string
+ * to be selected. (Note that all terminator values are specified as
+ * doubles.
+ * <p>
+ * Note that in order for this class to work properly, the range terminator
+ * array must be sorted in ascending order and the format string array
+ * must be the same length as the terminator array.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @date March 9, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.1.
+ */
+public class ChoiceFormat extends NumberFormat
+{
+ /**
+ * This method sets new range terminators and format strings for this
+ * object based on the specified pattern. This pattern is of the form
+ * "term#string|term#string...". For example "1#Sunday|2#Monday|#Tuesday".
+ *
+ * @param pattern The pattern of terminators and format strings.
+ *
+ * @exception IllegalArgumentException If the pattern is not valid
+ */
+ public void applyPattern (String newPattern)
+ {
+ // Note: we assume the same kind of quoting rules apply here.
+ // This isn't explicitly documented. But for instance we accept
+ // '#' as a literal hash in a format string.
+ int index = 0, max = newPattern.length();
+ Vector stringVec = new Vector ();
+ Vector limitVec = new Vector ();
+ StringBuffer buf = new StringBuffer ();
+
+ while (true)
+ {
+ // Find end of double.
+ int dstart = index;
+ while (index < max)
+ {
+ char c = newPattern.charAt(index);
+ if (c == '#' || c == '\u2064' || c == '<')
+ break;
+ ++index;
+ }
+
+ if (index == max)
+ throw new IllegalArgumentException ("unexpected end of text");
+ Double d = new Double (newPattern.substring(dstart, index));
+
+ if (newPattern.charAt(index) == '<')
+ d = new Double (nextDouble (d.doubleValue()));
+
+ limitVec.addElement(d);
+
+ // Scan text.
+ ++index;
+ buf.setLength(0);
+ while (index < max)
+ {
+ char c = newPattern.charAt(index);
+ if (c == '\'' && index < max + 1
+ && newPattern.charAt(index + 1) == '\'')
+ {
+ buf.append(c);
+ ++index;
+ }
+ else if (c == '\'' && index < max + 2)
+ {
+ buf.append(newPattern.charAt(index + 1));
+ index += 2;
+ }
+ else if (c == '|')
+ break;
+ else
+ buf.append(c);
+ ++index;
+ }
+
+ stringVec.addElement(buf.toString());
+ if (index == max)
+ break;
+ ++index;
+ }
+
+ choiceFormats = new String[stringVec.size()];
+ stringVec.copyInto(choiceFormats);
+
+ choiceLimits = new double[limitVec.size()];
+ for (int i = 0; i < choiceLimits.length; ++i)
+ {
+ Double d = (Double) limitVec.elementAt(i);
+ choiceLimits[i] = d.doubleValue();
+ }
+ }
+
+ /**
+ * This method initializes a new instance of <code>ChoiceFormat</code> that
+ * generates its range terminator and format string arrays from the
+ * specified pattern. This pattern is of the form
+ * "term#string|term#string...". For example "1#Sunday|2#Monday|#Tuesday".
+ * This is the same pattern type used by the <code>applyPattern</code>
+ * method.
+ *
+ * @param pattern The pattern of terminators and format strings.
+ *
+ * @exception IllegalArgumentException If the pattern is not valid
+ */
+ public ChoiceFormat (String newPattern)
+ {
+ super ();
+ applyPattern (newPattern);
+ }
+
+ /**
+ * This method initializes a new instance of <code>ChoiceFormat</code> that
+ * will use the specified range terminators and format strings.
+ *
+ * @param choiceLimits The array of range terminators
+ * @param choiceFormats The array of format strings
+ */
+ public ChoiceFormat (double[] choiceLimits, String[] choiceFormats)
+ {
+ super ();
+ setChoices (choiceLimits, choiceFormats);
+ }
+
+ /**
+ * This method tests this object for equality with the specified
+ * object. This will be true if and only if:
+ * <ul>
+ * <li>The specified object is not <code>null</code>.</li>
+ * <li>The specified object is an instance of <code>ChoiceFormat</code>.</li>
+ * <li>The termination ranges and format strings are identical to
+ * this object's. </li>
+ * </ul>
+ *
+ * @param obj The object to test for equality against.
+ *
+ * @return <code>true</code> if the specified object is equal to
+ * this one, <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof ChoiceFormat))
+ return false;
+ ChoiceFormat cf = (ChoiceFormat) obj;
+ if (choiceLimits.length != cf.choiceLimits.length)
+ return false;
+ for (int i = choiceLimits.length - 1; i >= 0; --i)
+ {
+ if (choiceLimits[i] != cf.choiceLimits[i]
+ || !choiceFormats[i].equals(cf.choiceFormats[i]))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This method appends the appropriate format string to the specified
+ * <code>StringBuffer</code> based on the supplied <code>long</code>
+ * argument.
+ *
+ * @param number The number used for determine (based on the range
+ * terminators) which format string to append.
+ * @param sb The <code>StringBuffer</code> to append the format string to.
+ * @param status Unused.
+ *
+ * @return The <code>StringBuffer</code> with the format string appended.
+ */
+ public StringBuffer format (long num, StringBuffer appendBuf,
+ FieldPosition pos)
+ {
+ return format ((double) num, appendBuf, pos);
+ }
+
+ /**
+ * This method appends the appropriate format string to the specified
+ * <code>StringBuffer</code> based on the supplied <code>double</code>
+ * argument.
+ *
+ * @param number The number used for determine (based on the range
+ * terminators) which format string to append.
+ * @param sb The <code>StringBuffer</code> to append the format string to.
+ * @param status Unused.
+ *
+ * @return The <code>StringBuffer</code> with the format string appended.
+ */
+ public StringBuffer format (double num, StringBuffer appendBuf,
+ FieldPosition pos)
+ {
+ if (choiceLimits.length == 0)
+ return appendBuf;
+
+ int index = 0;
+ if (! Double.isNaN(num) && num >= choiceLimits[0])
+ {
+ for (; index < choiceLimits.length - 1; ++index)
+ {
+ if (choiceLimits[index] <= num && num < choiceLimits[index + 1])
+ break;
+ }
+ }
+
+ return appendBuf.append(choiceFormats[index]);
+ }
+
+ /**
+ * This method returns the list of format strings in use.
+ *
+ * @return The list of format objects.
+ */
+ public Object[] getFormats ()
+ {
+ return (Object[]) choiceFormats.clone();
+ }
+
+ /**
+ * This method returns the list of range terminators in use.
+ *
+ * @return The list of range terminators.
+ */
+ public double[] getLimits ()
+ {
+ return (double[]) choiceLimits.clone();
+ }
+
+ /**
+ * This method returns a hash value for this object
+ *
+ * @return A hash value for this object.
+ */
+ public int hashCode ()
+ {
+ int hash = 0;
+ for (int i = 0; i < choiceLimits.length; ++i)
+ {
+ long v = Double.doubleToLongBits(choiceLimits[i]);
+ hash ^= (v ^ (v >>> 32));
+ hash ^= choiceFormats[i].hashCode();
+ }
+ return hash;
+ }
+
+ /**
+ * This method returns the lowest possible double greater than the
+ * specified double. If the specified double value is equal to
+ * <code>Double.NaN</code> then that is the value returned.
+ *
+ * @param d The specified double
+ *
+ * @return The lowest double value greater than the specified double.
+ */
+ public static final double nextDouble (double d)
+ {
+ return nextDouble (d, true);
+ }
+
+ /**
+ * This method returns a double that is either the next highest double
+ * or next lowest double compared to the specified double depending on the
+ * value of the passed boolean parameter. If the boolean parameter is
+ * <code>true</code>, then the lowest possible double greater than the
+ * specified double will be returned. Otherwise the highest possible
+ * double less than the specified double will be returned.
+ *
+ * @param d The specified double
+ * @param positive <code>true</code> to return the next highest
+ * double, <code>false</code> otherwise.
+ *
+ * @return The next highest or lowest double value.
+ */
+ public static double nextDouble (double d, boolean next)
+ {
+ if (Double.isInfinite(d) || Double.isNaN(d))
+ return d;
+
+ long bits = Double.doubleToLongBits(d);
+
+ long mantMask = (1L << mantissaBits) - 1;
+ long mantissa = bits & mantMask;
+
+ long expMask = (1L << exponentBits) - 1;
+ long exponent = (bits >>> mantissaBits) & expMask;
+
+ if (next ^ (bits < 0)) // Increment magnitude
+ {
+ if (mantissa == (1L << mantissaBits) - 1)
+ {
+ mantissa = 0L;
+ exponent++;
+
+ // Check for absolute overflow.
+ if (exponent >= (1L << mantissaBits))
+ return (bits > 0) ? Double.POSITIVE_INFINITY
+ : Double.NEGATIVE_INFINITY;
+ }
+ else
+ mantissa++;
+ }
+ else // Decrement magnitude
+ {
+ if (exponent == 0L && mantissa == 0L)
+ {
+ // The only case where there is a change of sign
+ return next ? Double.MIN_VALUE : -Double.MIN_VALUE;
+ }
+ else
+ {
+ if (mantissa == 0L)
+ {
+ mantissa = (1L << mantissaBits) - 1;
+ exponent--;
+ }
+ else
+ mantissa--;
+ }
+ }
+
+ long result = bits < 0 ? 1 : 0;
+ result = (result << exponentBits) | exponent;
+ result = (result << mantissaBits) | mantissa;
+ return Double.longBitsToDouble(result);
+ }
+
+ /**
+ * I'm not sure what this method is really supposed to do, as it is
+ * not documented.
+ */
+ public Number parse (String sourceStr, ParsePosition pos)
+ {
+ int index = pos.getIndex();
+ for (int i = 0; i < choiceLimits.length; ++i)
+ {
+ if (sourceStr.startsWith(choiceFormats[i], index))
+ {
+ pos.setIndex(index + choiceFormats[i].length());
+ return new Double (choiceLimits[i]);
+ }
+ }
+ pos.setErrorIndex(index);
+ return new Double (Double.NaN);
+ }
+
+ /**
+ * This method returns the highest possible double less than the
+ * specified double. If the specified double value is equal to
+ * <code>Double.NaN</code> then that is the value returned.
+ *
+ * @param d The specified double
+ *
+ * @return The highest double value less than the specified double.
+ */
+ public static final double previousDouble (double d)
+ {
+ return nextDouble (d, false);
+ }
+
+ /**
+ * This method sets new range terminators and format strings for this
+ * object.
+ *
+ * @param choiceLimits The new range terminators
+ * @param choiceFormats The new choice formats
+ */
+ public void setChoices (double[] choiceLimits, String[] choiceFormats)
+ {
+ if (choiceLimits == null || choiceFormats == null)
+ throw new NullPointerException ();
+ if (choiceLimits.length != choiceFormats.length)
+ throw new IllegalArgumentException ();
+ this.choiceFormats = (String[]) choiceFormats.clone();
+ this.choiceLimits = (double[]) choiceLimits.clone();
+ }
+
+ private void quoteString (StringBuffer dest, String text)
+ {
+ int max = text.length();
+ for (int i = 0; i < max; ++i)
+ {
+ char c = text.charAt(i);
+ if (c == '\'')
+ {
+ dest.append(c);
+ dest.append(c);
+ }
+ else if (c == '#' || c == '|' || c == '\u2064' || c == '<')
+ {
+ dest.append('\'');
+ dest.append(c);
+ dest.append('\'');
+ }
+ else
+ dest.append(c);
+ }
+ }
+
+ /**
+ * This method returns the range terminator list and format string list
+ * as a <code>String</code> suitable for using with the
+ * <code>applyPattern</code> method.
+ *
+ * @return A pattern string for this object
+ */
+ public String toPattern ()
+ {
+ StringBuffer result = new StringBuffer ();
+ for (int i = 0; i < choiceLimits.length; ++i)
+ {
+ result.append(choiceLimits[i]);
+ result.append('#');
+ quoteString (result, choiceFormats[i]);
+ }
+ return result.toString();
+ }
+
+ /**
+ * This is the list of format strings. Note that this variable is
+ * specified by the serialization spec of this class.
+ */
+ private String[] choiceFormats;
+
+ /**
+ * This is the list of range terminator values. Note that this variable is
+ * specified by the serialization spec of this class.
+ */
+ private double[] choiceLimits;
+
+ // Number of mantissa bits in double.
+ private static final int mantissaBits = 52;
+ // Number of exponent bits in a double.
+ private static final int exponentBits = 11;
+
+ private static final long serialVersionUID = 1795184449645032964L;
+}
diff --git a/libjava/classpath/java/text/CollationElementIterator.java b/libjava/classpath/java/text/CollationElementIterator.java
new file mode 100644
index 00000000000..60b148ef7c1
--- /dev/null
+++ b/libjava/classpath/java/text/CollationElementIterator.java
@@ -0,0 +1,467 @@
+/* CollationElementIterator.java -- Walks through collation elements
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.util.ArrayList;
+
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to JDK 1.1.
+ */
+
+/**
+ * This class walks through the character collation elements of a
+ * <code>String</code> as defined by the collation rules in an instance of
+ * <code>RuleBasedCollator</code>. There is no public constructor for
+ * this class. An instance is created by calling the
+ * <code>getCollationElementIterator</code> method on
+ * <code>RuleBasedCollator</code>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Guilhem Lavaux (guilhem.lavaux@free.fr)
+ */
+public final class CollationElementIterator
+{
+ /**
+ * This is a constant value that is returned to indicate that the end of
+ * the string was encountered.
+ */
+ public static final int NULLORDER = -1;
+
+ /**
+ * This is the RuleBasedCollator this object was created from.
+ */
+ RuleBasedCollator collator;
+
+ /**
+ * This is the String that is being iterated over.
+ */
+ String text;
+
+ /**
+ * This is the index into the collation decomposition where we are currently scanning.
+ */
+ int index;
+
+ /**
+ * This is the index into the String where we are currently scanning.
+ */
+ int textIndex;
+
+ /**
+ * Array containing the collation decomposition of the
+ * text given to the constructor.
+ */
+ private RuleBasedCollator.CollationElement[] text_decomposition;
+
+ /**
+ * Array containing the index of the specified block.
+ */
+ private int[] text_indexes;
+
+ /**
+ * This method initializes a new instance of <code>CollationElementIterator</code>
+ * to iterate over the specified <code>String</code> using the rules in the
+ * specified <code>RuleBasedCollator</code>.
+ *
+ * @param collator The <code>RuleBasedCollation</code> used for calculating collation values
+ * @param text The <code>String</code> to iterate over.
+ */
+ CollationElementIterator(RuleBasedCollator collator, String text)
+ {
+ this.collator = collator;
+
+ setText (text);
+ }
+
+ RuleBasedCollator.CollationElement nextBlock()
+ {
+ if (index >= text_decomposition.length)
+ return null;
+
+ RuleBasedCollator.CollationElement e = text_decomposition[index];
+
+ textIndex = text_indexes[index+1];
+
+ index++;
+
+ return e;
+ }
+
+ RuleBasedCollator.CollationElement previousBlock()
+ {
+ if (index == 0)
+ return null;
+
+ index--;
+ RuleBasedCollator.CollationElement e = text_decomposition[index];
+
+ textIndex = text_indexes[index+1];
+
+ return e;
+ }
+
+ /**
+ * This method returns the collation ordering value of the next character sequence
+ * in the string (it may be an extended character following collation rules).
+ * This method will return <code>NULLORDER</code> if the
+ * end of the string was reached.
+ *
+ * @return The collation ordering value.
+ */
+ public int next()
+ {
+ RuleBasedCollator.CollationElement e = nextBlock();
+
+ if (e == null)
+ return NULLORDER;
+
+ return e.getValue();
+ }
+
+ /**
+ * This method returns the collation ordering value of the previous character
+ * in the string. This method will return <code>NULLORDER</code> if the
+ * beginning of the string was reached.
+ *
+ * @return The collation ordering value.
+ */
+ public int previous()
+ {
+ RuleBasedCollator.CollationElement e = previousBlock();
+
+ if (e == null)
+ return NULLORDER;
+
+ return e.getValue();
+ }
+
+ /**
+ * This method returns the primary order value for the given collation
+ * value.
+ *
+ * @param value The collation value returned from <code>next()</code> or <code>previous()</code>.
+ *
+ * @return The primary order value of the specified collation value. This is the high 16 bits.
+ */
+ public static int primaryOrder(int order)
+ {
+ // From the JDK 1.2 spec.
+ return order >>> 16;
+ }
+
+ /**
+ * This method resets the internal position pointer to read from the
+ * beginning of the <code>String</code> again.
+ */
+ public void reset()
+ {
+ index = 0;
+ textIndex = 0;
+ }
+
+ /**
+ * This method returns the secondary order value for the given collation
+ * value.
+ *
+ * @param value The collation value returned from <code>next()</code> or <code>previous()</code>.
+ *
+ * @return The secondary order value of the specified collation value. This is the bits 8-15.
+ */
+ public static short secondaryOrder(int order)
+ {
+ // From the JDK 1.2 spec.
+ return (short) ((order >>> 8) & 255);
+ }
+
+ /**
+ * This method returns the tertiary order value for the given collation
+ * value.
+ *
+ * @param value The collation value returned from <code>next()</code> or <code>previous()</code>.
+ *
+ * @return The tertiary order value of the specified collation value. This is the low eight bits.
+ */
+ public static short tertiaryOrder(int order)
+ {
+ // From the JDK 1.2 spec.
+ return (short) (order & 255);
+ }
+
+ /**
+ * This method sets the <code>String</code> that it is iterating over
+ * to the specified <code>String</code>.
+ *
+ * @param text The new <code>String</code> to iterate over.
+ *
+ * @since 1.2
+ */
+ public void setText(String text)
+ {
+ int idx = 0;
+ int idx_idx = 0;
+ int alreadyExpanded = 0;
+ int idxToMove = 0;
+
+ this.text = text;
+ this.index = 0;
+
+ String work_text = text.intern();
+
+ ArrayList a_element = new ArrayList();
+ ArrayList a_idx = new ArrayList();
+
+ // Build element collection ordered as they come in "text".
+ while (idx < work_text.length())
+ {
+ String key, key_old;
+
+ Object object = null;
+ int p = 1;
+
+ // IMPROVE: use a TreeMap with a prefix-ordering rule.
+ key_old = key = null;
+ do
+ {
+ if (object != null)
+ key_old = key;
+ key = work_text.substring (idx, idx+p);
+ object = collator.prefix_tree.get (key);
+ if (object != null && idx < alreadyExpanded)
+ {
+ RuleBasedCollator.CollationElement prefix = (RuleBasedCollator.CollationElement)object;
+ if (prefix.expansion != null &&
+ prefix.expansion.startsWith(work_text.substring(0, idx)))
+ {
+ object = null;
+ key = key_old;
+ }
+ }
+ p++;
+ }
+ while (idx+p <= work_text.length());
+
+ if (object == null)
+ key = key_old;
+
+ RuleBasedCollator.CollationElement prefix =
+ (RuleBasedCollator.CollationElement) collator.prefix_tree.get (key);
+
+ /*
+ * First case: There is no such sequence in the database.
+ * We will have to build one from the context.
+ */
+ if (prefix == null)
+ {
+ /*
+ * We are dealing with sequences in an expansion. They
+ * are treated as accented characters (tertiary order).
+ */
+ if (alreadyExpanded > 0)
+ {
+ RuleBasedCollator.CollationElement e =
+ collator.getDefaultAccentedElement (work_text.charAt (idx));
+
+ a_element.add (e);
+ a_idx.add (new Integer(idx_idx));
+ idx++;
+ alreadyExpanded--;
+ if (alreadyExpanded == 0)
+ {
+ /* There is not any characters left in the expansion set.
+ * We can increase the pointer in the source string.
+ */
+ idx_idx += idxToMove;
+ idxToMove = 0;
+ }
+ else
+ idx_idx++;
+ }
+ else
+ {
+ /* This is a normal character. */
+ RuleBasedCollator.CollationElement e =
+ collator.getDefaultElement (work_text.charAt (idx));
+ Integer i_ref = new Integer(idx_idx);
+
+ /* Don't forget to mark it as a special sequence so the
+ * string can be ordered.
+ */
+ a_element.add (RuleBasedCollator.SPECIAL_UNKNOWN_SEQ);
+ a_idx.add (i_ref);
+ a_element.add (e);
+ a_idx.add (i_ref);
+ idx_idx++;
+ idx++;
+ }
+ continue;
+ }
+
+ /*
+ * Second case: Here we have found a matching sequence.
+ * Here we have an expansion string prepend it to the "work text" and
+ * add the corresponding sorting element. We must also mark
+ */
+ if (prefix.expansion != null)
+ {
+ work_text = prefix.expansion
+ + work_text.substring (idx+prefix.key.length());
+ idx = 0;
+ a_element.add (prefix);
+ a_idx.add (new Integer(idx_idx));
+ if (alreadyExpanded == 0)
+ idxToMove = prefix.key.length();
+ alreadyExpanded += prefix.expansion.length()-prefix.key.length();
+ }
+ else
+ {
+ /* Third case: the simplest. We have got the prefix and it
+ * has not to be expanded.
+ */
+ a_element.add (prefix);
+ a_idx.add (new Integer(idx_idx));
+ idx += prefix.key.length();
+ /* If the sequence is in an expansion, we must decrease the
+ * counter.
+ */
+ if (alreadyExpanded > 0)
+ {
+ alreadyExpanded -= prefix.key.length();
+ if (alreadyExpanded == 0)
+ {
+ idx_idx += idxToMove;
+ idxToMove = 0;
+ }
+ }
+ else
+ idx_idx += prefix.key.length();
+ }
+ }
+
+ text_decomposition = (RuleBasedCollator.CollationElement[])
+ a_element.toArray(new RuleBasedCollator.CollationElement[a_element.size()]);
+ text_indexes = new int[a_idx.size()+1];
+ for (int i = 0; i < a_idx.size(); i++)
+ {
+ text_indexes[i] = ((Integer)a_idx.get(i)).intValue();
+ }
+ text_indexes[a_idx.size()] = text.length();
+ }
+
+ /**
+ * This method sets the <code>String</code> that it is iterating over
+ * to the <code>String</code> represented by the specified
+ * <code>CharacterIterator</code>.
+ *
+ * @param source The <code>CharacterIterator</code> containing the new
+ * <code>String</code> to iterate over.
+ */
+ public void setText(CharacterIterator source)
+ {
+ StringBuffer expand = new StringBuffer();
+
+ // For now assume we read from the beginning of the string.
+ for (char c = source.first();
+ c != CharacterIterator.DONE;
+ c = source.next())
+ expand.append(c);
+
+ setText(expand.toString());
+ }
+
+ /**
+ * This method returns the current offset into the <code>String</code>
+ * that is being iterated over.
+ *
+ * @return The iteration index position.
+ *
+ * @since 1.2
+ */
+ public int getOffset()
+ {
+ return textIndex;
+ }
+
+ /**
+ * This method sets the iteration index position into the current
+ * <code>String</code> to the specified value. This value must not
+ * be negative and must not be greater than the last index position
+ * in the <code>String</code>.
+ *
+ * @param offset The new iteration index position.
+ *
+ * @exception IllegalArgumentException If the new offset is not valid.
+ */
+ public void setOffset(int offset)
+ {
+ if (offset < 0)
+ throw new IllegalArgumentException("Negative offset: " + offset);
+
+ if (offset > (text.length() - 1))
+ throw new IllegalArgumentException("Offset too large: " + offset);
+
+ for (index = 0; index < text_decomposition.length; index++)
+ {
+ if (offset <= text_indexes[index])
+ break;
+ }
+ /*
+ * As text_indexes[0] == 0, we should not have to take care whether index is
+ * greater than 0. It is always.
+ */
+ if (text_indexes[index] == offset)
+ textIndex = offset;
+ else
+ textIndex = text_indexes[index-1];
+ }
+
+ /**
+ * This method returns the maximum length of any expansion sequence that
+ * ends with the specified collation order value. (Whatever that means).
+ *
+ * @param value The collation order value
+ *
+ * @param The maximum length of an expansion sequence.
+ */
+ public int getMaxExpansion(int value)
+ {
+ return 1;
+ }
+}
diff --git a/libjava/classpath/java/text/CollationKey.java b/libjava/classpath/java/text/CollationKey.java
new file mode 100644
index 00000000000..f7e3a2476de
--- /dev/null
+++ b/libjava/classpath/java/text/CollationKey.java
@@ -0,0 +1,199 @@
+/* CollationKey.java -- Precomputed collation value
+ Copyright (C) 1998, 1999, 2000, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * This class represents a pre-computed series of bits representing a
+ * <code>String</code> for under a particular <code>Collator</code>. This
+ * value may be compared bitwise against another <code>CollationKey</code>
+ * representing a different <code>String</code> under the same
+ * <code>Collator</code> in a manner than is usually more efficient than
+ * using the raw <code>Collator</code> compare methods. There is overhead
+ * associated with calculating this value, so it is generally not
+ * advisable to compute <code>CollationKey</code>'s unless multiple
+ * comparisons against a <code>String</code> will be done. (For example,
+ * in a sort routine).
+ * <p>
+ * This class cannot be instantiated directly. Instead, a
+ * <code>CollationKey</code> is created by calling the
+ * <code>getCollationKey</code> method on an instance of <code>Collator</code>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @date March 25, 1999
+ */
+public final class CollationKey implements Comparable
+{
+ /**
+ * This is the <code>Collator</code> this object was created from.
+ */
+ private Collator collator;
+
+ /**
+ * This is the <code>String</code> this object represents.
+ */
+ private String originalText;
+
+ /**
+ * This is the bit value for this key.
+ */
+ private byte[] key;
+
+ CollationKey (Collator collator, String originalText, byte[] key)
+ {
+ this.collator = collator;
+ this.originalText = originalText;
+ this.key = key;
+ }
+
+ /**
+ * This method compares the specified object to this one. An integer is
+ * returned which indicates whether the specified object is less than,
+ * greater than, or equal to this object.
+ *
+ * @param ck The <code>CollationKey</code> to compare against this one.
+ *
+ * @return A negative integer if this object is less than the specified object, 0 if it is equal or a positive integer if it is greater than the specified object.
+ */
+ public int compareTo (CollationKey ck)
+ {
+ int max = Math.min (key.length, ck.key.length);
+
+ for (int i = 0; i < max; ++i)
+ {
+ if (key[i] != ck.key[i])
+ return key[i] - ck.key[i];
+ }
+
+ return key.length - ck.key.length;
+ }
+
+ /**
+ * This method compares the specified object to this one. The specified
+ * object must be an instance of <code>CollationKey</code> or an exception
+ * will be thrown. An integer is returned which indicates whether the
+ * specified object is less than, greater than, or equal to this object.
+ *
+ * @param obj The <code>Object</code> to compare against this one.
+ *
+ * @return A negative integer if this object is less than the specified object, 0 if it is equal or a positive integer if it is greater than the specified object.
+ */
+ public int compareTo (Object obj)
+ {
+ return compareTo ((CollationKey) obj);
+ }
+
+ /**
+ * This method tests the specified <code>Object</code> for equality with
+ * this object. This will be true if and only if:
+ * <p>
+ * <ul>
+ * <li>The specified object must not be <code>null</code></li>
+ * <li>The specified object is an instance of <code>CollationKey</code>.</li>
+ * <li>The specified object was created from the same <code>Collator</code>
+ * as this object.</li>
+ * <li>The specified object has the same source string and bit key as
+ * this object.</li>
+ * </ul>
+ *
+ * @param obj The <code>Object</code> to test for equality.
+ *
+ * @return <code>true</code> if the specified object is equal to this one, <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof CollationKey))
+ return false;
+
+ CollationKey ck = (CollationKey) obj;
+
+ if (ck.collator != collator)
+ return false;
+
+ if (!ck.getSourceString ().equals (getSourceString ()))
+ return false;
+
+ if (!ck.toByteArray ().equals (toByteArray ()))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * This method returns the <code>String</code> that this object was created
+ * from.
+ *
+ * @return The source <code>String</code> for this object.
+ */
+ public String getSourceString()
+ {
+ return originalText;
+ }
+
+ /**
+ * This method returns a hash value for this object. The hash value
+ * returned will be the hash code of the bit key so that identical bit
+ * keys will return the same value.
+ *
+ * @return A hash value for this object.
+ */
+ public int hashCode()
+ {
+ // We just follow BitSet instead of thinking up something new.
+ long h = originalText.hashCode();
+ for (int i = key.length - 1; i >= 0; --i)
+ h ^= key[i] * (i + 1);
+ return (int) ((h >> 32) ^ h);
+ }
+
+ /**
+ * This method returns the collation bit sequence as a byte array.
+ *
+ * @param A byte array containing the collation bit sequence.
+ */
+ public byte[] toByteArray()
+ {
+ return key;
+ }
+}
diff --git a/libjava/classpath/java/text/Collator.java b/libjava/classpath/java/text/Collator.java
new file mode 100644
index 00000000000..633bc672527
--- /dev/null
+++ b/libjava/classpath/java/text/Collator.java
@@ -0,0 +1,400 @@
+/* Collator.java -- Perform locale dependent String comparisons.
+ Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.util.Comparator;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * This class is the abstract superclass of classes which perform
+ * locale dependent <code>String</code> comparisons. A caller requests
+ * an instance of <code>Collator</code> for a particular locale using
+ * the <code>getInstance()</code> static method in this class. That method
+ * will return a locale specific subclass of <code>Collator</code> which
+ * can be used to perform <code>String</code> comparisons for that locale.
+ * If a subclass of <code>Collator</code> cannot be located for a particular
+ * locale, a default instance for the current locale will be returned.
+ *
+ * In addition to setting the correct locale, there are two additional
+ * settings that can be adjusted to affect <code>String</code> comparisons:
+ * strength and decomposition. The strength value determines the level
+ * of signficance of character differences required for them to sort
+ * differently. (For example, whether or not capital letters are considered
+ * different from lower case letters). The decomposition value affects how
+ * variants of the same character are treated for sorting purposes. (For
+ * example, whether or not an accent is signficant or not). These settings
+ * are described in detail in the documentation for the methods and values
+ * that are related to them.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @date March 18, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Mostly complete, but parts stubbed out. Look for FIXME.
+ */
+public abstract class Collator implements Comparator, Cloneable
+{
+ /**
+ * This constant is a strength value which indicates that only primary
+ * differences between characters will be considered signficant. As an
+ * example, two completely different English letters such as 'a' and 'b'
+ * are considered to have a primary difference.
+ */
+ public static final int PRIMARY = 0;
+
+ /**
+ * This constant is a strength value which indicates that only secondary
+ * or primary differences between characters will be considered
+ * significant. An example of a secondary difference between characters
+ * are instances of the same letter with different accented forms.
+ */
+ public static final int SECONDARY = 1;
+
+ /**
+ * This constant is a strength value which indicates that tertiary,
+ * secondary, and primary differences will be considered during sorting.
+ * An example of a tertiary difference is capitalization of a given letter.
+ * This is the default value for the strength setting.
+ */
+ public static final int TERTIARY = 2;
+
+ /**
+ * This constant is a strength value which indicates that any difference
+ * at all between character values are considered significant.
+ */
+ public static final int IDENTICAL = 3;
+
+ /**
+ * This constant indicates that accented characters won't be decomposed
+ * when performing comparisons. This will yield the fastest results, but
+ * will only work correctly in call cases for languages which do not
+ * use accents such as English.
+ */
+ public static final int NO_DECOMPOSITION = 0;
+
+ /**
+ * This constant indicates that only characters which are canonical variants
+ * in Unicode 2.0 will be decomposed prior to performing comparisons. This
+ * will cause accented languages to be sorted correctly. This is the
+ * default decomposition value.
+ */
+ public static final int CANONICAL_DECOMPOSITION = 1;
+
+ /**
+ * This constant indicates that both canonical variants and compatibility
+ * variants in Unicode 2.0 will be decomposed prior to performing
+ * comparisons. This is the slowest mode, but is required to get the
+ * correct sorting for certain languages with certain special formats.
+ */
+ public static final int FULL_DECOMPOSITION = 2;
+
+ /**
+ * This method initializes a new instance of <code>Collator</code> to have
+ * the default strength (TERTIARY) and decomposition
+ * (CANONICAL_DECOMPOSITION) settings. This constructor is protected and
+ * is for use by subclasses only. Non-subclass callers should use the
+ * static <code>getInstance()</code> methods of this class to instantiate
+ * <code>Collation</code> objects for the desired locale.
+ */
+ protected Collator ()
+ {
+ strength = TERTIARY;
+ decmp = CANONICAL_DECOMPOSITION;
+ }
+
+ /**
+ * This method compares the two <code>String</code>'s and returns an
+ * integer indicating whether or not the first argument is less than,
+ * equal to, or greater than the second argument. The comparison is
+ * performed according to the rules of the locale for this
+ * <code>Collator</code> and the strength and decomposition rules in
+ * effect.
+ *
+ * @param str1 The first object to compare
+ * @param str2 The second object to compare
+ *
+ * @return A negative integer if str1 &lt; str2, 0 if str1 == str2, or
+ * a positive integer if str1 &gt; str2.
+ */
+ public abstract int compare (String source, String target);
+
+ /**
+ * This method compares the two <code>Object</code>'s and returns an
+ * integer indicating whether or not the first argument is less than,
+ * equal to, or greater than the second argument. These two objects
+ * must be <code>String</code>'s or an exception will be thrown.
+ *
+ * @param obj1 The first object to compare
+ * @param obj2 The second object to compare
+ *
+ * @return A negative integer if obj1 &lt; obj2, 0 if obj1 == obj2, or
+ * a positive integer if obj1 &gt; obj2.
+ *
+ * @exception ClassCastException If the arguments are not instances
+ * of <code>String</code>.
+ */
+ public int compare (Object o1, Object o2)
+ {
+ return compare ((String) o1, (String) o2);
+ }
+
+ /**
+ * This method tests the specified object for equality against this
+ * object. This will be true if and only if the following conditions are
+ * met:
+ * <ul>
+ * <li>The specified object is not <code>null</code>.</li>
+ * <li>The specified object is an instance of <code>Collator</code>.</li>
+ * <li>The specified object has the same strength and decomposition
+ * settings as this object.</li>
+ * </ul>
+ *
+ * @param obj The <code>Object</code> to test for equality against
+ * this object.
+ *
+ * @return <code>true</code> if the specified object is equal to
+ * this one, <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof Collator))
+ return false;
+ Collator c = (Collator) obj;
+ return decmp == c.decmp && strength == c.strength;
+ }
+
+ /**
+ * This method tests whether the specified <code>String</code>'s are equal
+ * according to the collation rules for the locale of this object and
+ * the current strength and decomposition settings.
+ *
+ * @param str1 The first <code>String</code> to compare
+ * @param str2 The second <code>String</code> to compare
+ *
+ * @return <code>true</code> if the two strings are equal,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals (String source, String target)
+ {
+ return compare (source, target) == 0;
+ }
+
+ /**
+ * This method returns a copy of this <code>Collator</code> object.
+ *
+ * @return A duplicate of this object.
+ */
+ public Object clone ()
+ {
+ try
+ {
+ return super.clone ();
+ }
+ catch (CloneNotSupportedException _)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * This method returns an array of <code>Locale</code> objects which is
+ * the list of locales for which <code>Collator</code> objects exist.
+ *
+ * @return The list of locales for which <code>Collator</code>'s exist.
+ */
+ public static synchronized Locale[] getAvailableLocales ()
+ {
+ // FIXME
+ Locale[] l = new Locale[1];
+ l[0] = Locale.US;
+ return l;
+ }
+
+ /**
+ * This method transforms the specified <code>String</code> into a
+ * <code>CollationKey</code> for faster comparisons. This is useful when
+ * comparisons against a string might be performed multiple times, such
+ * as during a sort operation.
+ *
+ * @param str The <code>String</code> to convert.
+ *
+ * @return A <code>CollationKey</code> for the specified <code>String</code>.
+ */
+ public abstract CollationKey getCollationKey (String source);
+
+ /**
+ * This method returns the current decomposition setting for this
+ * object. This * will be one of NO_DECOMPOSITION,
+ * CANONICAL_DECOMPOSITION, or * FULL_DECOMPOSITION. See the
+ * documentation for those constants for an * explanation of this
+ * setting.
+ *
+ * @return The current decomposition setting.
+ */
+ public synchronized int getDecomposition ()
+ {
+ return decmp;
+ }
+
+ /**
+ * This method returns an instance of <code>Collator</code> for the
+ * default locale.
+ *
+ * @return A <code>Collator</code> for the default locale.
+ */
+ public static Collator getInstance ()
+ {
+ return getInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>Collator</code> for the
+ * specified locale. If no <code>Collator</code> exists for the desired
+ * locale, a <code>Collator</code> for the default locale will be returned.
+ *
+ * @param locale The desired localed to load a <code>Collator</code> for.
+ *
+ * @return A <code>Collator</code> for the requested locale
+ */
+ public static Collator getInstance (Locale loc)
+ {
+ ResourceBundle res;
+ String pattern;
+ try
+ {
+ res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ loc, ClassLoader.getSystemClassLoader());
+ pattern = res.getString("collation_rules");
+ }
+ catch (MissingResourceException x)
+ {
+ pattern = "<0<1<2<3<4<5<6<7<8<9<A,a<b,B<c,C<d,D<e,E<f,F<g,G<h,H<i,I<j,J<k,K" +
+ "<l,L<m,M<n,N<o,O<p,P<q,Q<r,R<s,S<t,T<u,U<v,V<w,W<x,X<y,Y<z,Z";
+ }
+ try
+ {
+ return new RuleBasedCollator (pattern);
+ }
+ catch (ParseException x)
+ {
+ throw (InternalError)new InternalError().initCause(x);
+ }
+ }
+
+ /**
+ * This method returns the current strength setting for this object. This
+ * will be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL. See the
+ * documentation for those constants for an explanation of this setting.
+ *
+ * @return The current strength setting.
+ */
+ public synchronized int getStrength ()
+ {
+ return strength;
+ }
+
+ /**
+ * This method returns a hash code value for this object.
+ *
+ * @return A hash value for this object.
+ */
+ public abstract int hashCode ();
+
+ /**
+ * This method sets the decomposition setting for this object to the
+ * specified value. This must be one of NO_DECOMPOSITION,
+ * CANONICAL_DECOMPOSITION, or FULL_DECOMPOSITION. Otherwise an
+ * exception will be thrown. See the documentation for those
+ * contants for an explanation of this setting.
+ *
+ * @param decmp The new decomposition setting.
+ *
+ * @exception IllegalArgumentException If the requested
+ * decomposition setting is not valid.
+ */
+ public synchronized void setDecomposition (int mode)
+ {
+ if (mode != NO_DECOMPOSITION
+ && mode != CANONICAL_DECOMPOSITION
+ && mode != FULL_DECOMPOSITION)
+ throw new IllegalArgumentException ();
+ decmp = mode;
+ }
+
+ /**
+ * This method sets the strength setting for this object to the specified
+ * value. This must be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL.
+ * Otherwise an exception is thrown. See the documentation for these
+ * constants for an explanation of this setting.
+ *
+ * @param strength The new strength setting.
+ *
+ * @exception IllegalArgumentException If the requested strength
+ * setting value is not valid.
+ */
+ public synchronized void setStrength (int strength)
+ {
+ if (strength != PRIMARY && strength != SECONDARY
+ && strength != TERTIARY && strength != IDENTICAL)
+ throw new IllegalArgumentException ();
+ this.strength = strength;
+ }
+
+ // Decompose a single character and append results to the buffer.
+ // FIXME: for libgcj this is a native method which handles
+ // decomposition. For Classpath, for now, it does nothing.
+ final void decomposeCharacter (char c, StringBuffer buf)
+ {
+ buf.append (c);
+ }
+
+ /**
+ * This is the current collation decomposition setting.
+ */
+ int decmp;
+
+ /**
+ * This is the current collation strength setting.
+ */
+ int strength;
+}
diff --git a/libjava/classpath/java/text/DateFormat.java b/libjava/classpath/java/text/DateFormat.java
new file mode 100644
index 00000000000..f6dfceb14e8
--- /dev/null
+++ b/libjava/classpath/java/text/DateFormat.java
@@ -0,0 +1,892 @@
+/* DateFormat.java -- Class for formatting/parsing date/times
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.io.InvalidObjectException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.TimeZone;
+
+/**
+ * @author Per Bothner (bothner@cygnus.com)
+ * @date October 25, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Mostly complete; search for FIXME to see omissions.
+ */
+
+public abstract class DateFormat extends Format implements Cloneable
+{
+ protected Calendar calendar;
+ protected NumberFormat numberFormat;
+
+ // (Values determined using a test program.)
+ public static final int FULL = 0;
+ public static final int LONG = 1;
+ public static final int MEDIUM = 2;
+ public static final int SHORT = 3;
+ public static final int DEFAULT = MEDIUM;
+
+ /* These constants need to have these exact values. They
+ * correspond to index positions within the localPatternChars
+ * string for a given locale. Each locale may specify its
+ * own character for a particular field, but the position
+ * of these characters must correspond to an appropriate field
+ * number (as listed below), in order for their meaning to
+ * be determined. For example, the US locale uses
+ * the string "GyMdkHmsSEDFwWahKzYeugAZ", where 'G' is the character
+ * for era, 'y' for year, and so on down to 'Z' for time zone.
+ */
+ /**
+ * Represents the position of the era
+ * pattern character in the array of
+ * localized pattern characters.
+ * For example, 'AD' is an era used
+ * in the Gregorian calendar system.
+ * In the U.S. locale, this is 'G'.
+ */
+ public static final int ERA_FIELD = 0;
+ /**
+ * Represents the position of the year
+ * pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'y'.
+ */
+ public static final int YEAR_FIELD = 1;
+ /**
+ * Represents the position of the month
+ * pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'M'.
+ */
+ public static final int MONTH_FIELD = 2;
+ /**
+ * Represents the position of the date
+ * or day of the month pattern character
+ * in the array of localized pattern
+ * characters. In the U.S. locale,
+ * this is 'd'.
+ */
+ public static final int DATE_FIELD = 3;
+ /**
+ * Represents the position of the 24
+ * hour pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'k'.
+ * This field numbers hours from 1 to 24.
+ */
+ public static final int HOUR_OF_DAY1_FIELD = 4;
+ /**
+ * Represents the position of the 24
+ * hour pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'H'.
+ * This field numbers hours from 0 to 23.
+ */
+ public static final int HOUR_OF_DAY0_FIELD = 5;
+ /**
+ * Represents the position of the minute
+ * pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'm'.
+ */
+ public static final int MINUTE_FIELD = 6;
+ /**
+ * Represents the position of the second
+ * pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 's'.
+ */
+ public static final int SECOND_FIELD = 7;
+ /**
+ * Represents the position of the millisecond
+ * pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'S'.
+ */
+ public static final int MILLISECOND_FIELD = 8;
+ /**
+ * Represents the position of the day of the
+ * week pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'E'.
+ */
+ public static final int DAY_OF_WEEK_FIELD = 9;
+ /**
+ * Represents the position of the day of the
+ * year pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'D'.
+ */
+ public static final int DAY_OF_YEAR_FIELD = 10;
+ /**
+ * Represents the position of the day of the
+ * week in the month pattern character in the
+ * array of localized pattern characters.
+ * In the U.S. locale, this is 'F'.
+ */
+ public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
+ /**
+ * Represents the position of the week of the
+ * year pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'w'.
+ */
+ public static final int WEEK_OF_YEAR_FIELD = 12;
+ /**
+ * Represents the position of the week of the
+ * month pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'W'.
+ */
+ public static final int WEEK_OF_MONTH_FIELD = 13;
+ /**
+ * Represents the position of the am/pm
+ * pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'a'.
+ */
+ public static final int AM_PM_FIELD = 14;
+ /**
+ * Represents the position of the 12
+ * hour pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'h'.
+ * This field numbers hours from 1 to 12.
+ */
+ public static final int HOUR1_FIELD = 15;
+ /**
+ * Represents the position of the 12
+ * hour pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'K'.
+ * This field numbers hours from 0 to 11.
+ */
+ public static final int HOUR0_FIELD = 16;
+ /**
+ * Represents the position of the generic
+ * timezone pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'z'.
+ */
+ public static final int TIMEZONE_FIELD = 17;
+ /**
+ * Represents the position of the ISO year
+ * pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'Y'.
+ * This is a GNU extension in accordance with
+ * the CLDR data used. This value may
+ * differ from the normal year value.
+ */
+ public static final int ISO_YEAR_FIELD = 18;
+ /**
+ * Represents the position of the localized
+ * day of the week pattern character in the
+ * array of localized pattern characters.
+ * In the U.S. locale, this is 'e'.
+ * This is a GNU extension in accordance with
+ * the CLDR data used. This value only
+ * differs from the day of the week with
+ * numeric formatting, in which case the
+ * locale's first day of the week is used.
+ */
+ public static final int LOCALIZED_DAY_OF_WEEK_FIELD = 19;
+ /**
+ * Represents the position of the extended year
+ * pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'u'.
+ * This is a GNU extension in accordance with
+ * the CLDR data used. This value modifies
+ * the year value, so as to incorporate the era.
+ * For example, in the Gregorian calendar system,
+ * the extended year is negative instead of being
+ * marked as BC.
+ */
+ public static final int EXTENDED_YEAR_FIELD = 20;
+ /**
+ * Represents the position of the modified Julian
+ * day pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'g'.
+ * This is a GNU extension in accordance with
+ * the CLDR data used. This value differs
+ * from the standard Julian day in that days
+ * are marked from midnight onwards rather than
+ * noon, and the local time zone affects the value.
+ * In simple terms, it can be thought of as all
+ * the date fields represented as a single number.
+ */
+ public static final int MODIFIED_JULIAN_DAY_FIELD = 21;
+ /**
+ * Represents the position of the millisecond
+ * in the day pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'A'.
+ * This is a GNU extension in accordance with
+ * the CLDR data used. This value represents
+ * all the time fields (excluding the time zone)
+ * numerically, giving the number of milliseconds
+ * into the day (e.g. 10 in the morning would
+ * be 10 * 60 * 60 * 1000). Any daylight savings
+ * offset also affects this value.
+ */
+ public static final int MILLISECOND_IN_DAY_FIELD = 22;
+ /**
+ * Represents the position of the RFC822
+ * timezone pattern character in the array of
+ * localized pattern characters.
+ * In the U.S. locale, this is 'Z'.
+ * This is a GNU extension in accordance with
+ * the CLDR data used. The value is the offset
+ * of the current time from GMT e.g. -0500 would
+ * be five hours prior to GMT.
+ */
+ public static final int RFC822_TIMEZONE_FIELD = 23;
+
+ public static class Field extends Format.Field
+ {
+ static final long serialVersionUID = 7441350119349544720L;
+
+ private int calendarField;
+
+ public static final DateFormat.Field ERA
+ = new Field("era", Calendar.ERA);
+ public static final DateFormat.Field YEAR
+ = new Field("year", Calendar.YEAR);
+ public static final DateFormat.Field MONTH
+ = new Field("month", Calendar.MONTH);
+ public static final DateFormat.Field DAY_OF_MONTH
+ = new Field("day of month", Calendar.DAY_OF_MONTH);
+ public static final DateFormat.Field HOUR_OF_DAY1
+ = new Field("hour of day 1", Calendar.HOUR_OF_DAY);
+ public static final DateFormat.Field HOUR_OF_DAY0
+ = new Field("hour of day 0", Calendar.HOUR_OF_DAY);
+ public static final DateFormat.Field MINUTE
+ = new Field("minute", Calendar.MINUTE);
+ public static final DateFormat.Field SECOND
+ = new Field("second", Calendar.SECOND);
+ public static final DateFormat.Field MILLISECOND
+ = new Field("millisecond", Calendar.MILLISECOND);
+ public static final DateFormat.Field DAY_OF_WEEK
+ = new Field("day of week", Calendar.DAY_OF_WEEK);
+ public static final DateFormat.Field DAY_OF_YEAR
+ = new Field("day of year", Calendar.DAY_OF_YEAR);
+ public static final DateFormat.Field DAY_OF_WEEK_IN_MONTH
+ = new Field("day of week in month", Calendar.DAY_OF_WEEK_IN_MONTH);
+ public static final DateFormat.Field WEEK_OF_YEAR
+ = new Field("week of year", Calendar.WEEK_OF_YEAR);
+ public static final DateFormat.Field WEEK_OF_MONTH
+ = new Field("week of month", Calendar.WEEK_OF_MONTH);
+ public static final DateFormat.Field AM_PM
+ = new Field("am/pm", Calendar.AM_PM);
+ public static final DateFormat.Field HOUR1
+ = new Field("hour1", Calendar.HOUR);
+ public static final DateFormat.Field HOUR0
+ = new Field("hour0", Calendar.HOUR);
+ public static final DateFormat.Field TIME_ZONE
+ = new Field("timezone", Calendar.ZONE_OFFSET);
+ public static final DateFormat.Field ISO_YEAR
+ = new Field("iso year", Calendar.YEAR);
+ public static final DateFormat.Field LOCALIZED_DAY_OF_WEEK
+ = new Field("localized day of week", Calendar.DAY_OF_WEEK);
+ public static final DateFormat.Field EXTENDED_YEAR
+ = new Field("extended year", Calendar.YEAR);
+ public static final DateFormat.Field MODIFIED_JULIAN_DAY
+ = new Field("julian day", -1);
+ public static final DateFormat.Field MILLISECOND_IN_DAY
+ = new Field("millisecond in day", -1);
+ public static final DateFormat.Field RFC822_TIME_ZONE
+ = new Field("rfc822 timezone", Calendar.ZONE_OFFSET);
+
+ static final DateFormat.Field[] allFields =
+ {
+ ERA, YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY1,
+ HOUR_OF_DAY0, MINUTE, SECOND, MILLISECOND,
+ DAY_OF_WEEK, DAY_OF_YEAR, DAY_OF_WEEK_IN_MONTH,
+ WEEK_OF_YEAR, WEEK_OF_MONTH, AM_PM, HOUR1, HOUR0,
+ TIME_ZONE, ISO_YEAR, LOCALIZED_DAY_OF_WEEK,
+ EXTENDED_YEAR, MODIFIED_JULIAN_DAY, MILLISECOND_IN_DAY,
+ RFC822_TIME_ZONE
+ };
+
+ // For deserialization
+ private Field()
+ {
+ super("");
+ }
+
+ protected Field(String name, int calendarField)
+ {
+ super(name);
+ this.calendarField = calendarField;
+ }
+
+ public int getCalendarField()
+ {
+ return calendarField;
+ }
+
+ public static Field ofCalendarField(int calendarField)
+ {
+ if (calendarField >= allFields.length || calendarField < 0)
+ throw new IllegalArgumentException("no such calendar field ("
+ + calendarField + ")");
+
+ return allFields[calendarField];
+ }
+
+ protected Object readResolve() throws InvalidObjectException
+ {
+ String s = getName();
+
+ for (int i=0;i<allFields.length;i++)
+ if (s.equals(allFields[i].getName()))
+ return allFields[i];
+
+ throw new InvalidObjectException("no such DateFormat field called " + s);
+ }
+ }
+
+ /**
+ * This method initializes a new instance of <code>DateFormat</code>.
+ */
+ protected DateFormat ()
+ {
+ }
+
+ /**
+ * This method tests this object for equality against the specified object.
+ * The two objects will be considered equal if an only if the specified
+ * object:
+ * <P>
+ * <ul>
+ * <li>Is not <code>null</code>.</li>
+ * <li>Is an instance of <code>DateFormat</code>.</li>
+ * <li>Has the same numberFormat field value as this object.</li>
+ * </ul>
+ *
+ * @param obj The object to test for equality against.
+ *
+ * @return <code>true</code> if the specified object is equal to this object,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (!(obj instanceof DateFormat))
+ return false;
+
+ DateFormat d = (DateFormat) obj;
+
+ return numberFormat.equals(d.numberFormat);
+ }
+
+ /**
+ * This method returns a copy of this object.
+ *
+ * @return A copy of this object.
+ */
+ public Object clone ()
+ {
+ // We know the superclass just call's Object's generic cloner.
+ return super.clone ();
+ }
+
+ /**
+ * This method formats the specified <code>Object</code> into a date string
+ * and appends it to the specified <code>StringBuffer</code>.
+ * The specified object must be an instance of <code>Number</code> or
+ * <code>Date</code> or an <code>IllegalArgumentException</code> will be
+ * thrown.
+ *
+ * @param obj The <code>Object</code> to format.
+ * @param toAppendTo The <code>StringBuffer</code> to append the resultant
+ * <code>String</code> to.
+ * @param fieldPosition Is updated to the start and end index of the
+ * specified field.
+ *
+ * @return The <code>StringBuffer</code> supplied on input, with the
+ * formatted date/time appended.
+ */
+ public final StringBuffer format (Object obj,
+ StringBuffer buf, FieldPosition pos)
+ {
+ if (obj instanceof Number)
+ obj = new Date(((Number) obj).longValue());
+ else if (! (obj instanceof Date))
+ throw new IllegalArgumentException
+ ("Cannot format given Object as a Date");
+
+ return format ((Date) obj, buf, pos);
+ }
+
+ /**
+ * Formats the date argument according to the pattern specified.
+ *
+ * @param date The formatted date.
+ */
+ public final String format (Date date)
+ {
+ StringBuffer sb = new StringBuffer ();
+ format (date, sb, new FieldPosition (MONTH_FIELD));
+ return sb.toString();
+ }
+
+ /**
+ * This method formats a <code>Date</code> into a string and appends it
+ * to the specified <code>StringBuffer</code>.
+ *
+ * @param date The <code>Date</code> value to format.
+ * @param toAppendTo The <code>StringBuffer</code> to append the resultant
+ * <code>String</code> to.
+ * @param fieldPosition Is updated to the start and end index of the
+ * specified field.
+ *
+ * @return The <code>StringBuffer</code> supplied on input, with the
+ * formatted date/time appended.
+ */
+ public abstract StringBuffer format (Date date,
+ StringBuffer buf, FieldPosition pos);
+
+ /**
+ * This method returns a list of available locales supported by this
+ * class.
+ */
+ public static Locale[] getAvailableLocales()
+ {
+ return Locale.getAvailableLocales();
+ }
+
+ /**
+ * This method returns the <code>Calendar</code> object being used by
+ * this object to parse/format datetimes.
+ *
+ * @return The <code>Calendar</code> being used by this object.
+ *
+ * @see java.util.Calendar
+ */
+ public Calendar getCalendar ()
+ {
+ return calendar;
+ }
+
+ private static DateFormat computeInstance (int style, Locale loc,
+ boolean use_date, boolean use_time)
+ {
+ return computeInstance (style, style, loc, use_date, use_time);
+ }
+
+ private static DateFormat computeInstance (int dateStyle, int timeStyle,
+ Locale loc, boolean use_date,
+ boolean use_time)
+ {
+ ResourceBundle res;
+ try
+ {
+ res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ loc, ClassLoader.getSystemClassLoader());
+ }
+ catch (MissingResourceException x)
+ {
+ res = null;
+ }
+
+ String pattern = null;
+ if (use_date)
+ {
+ String name, def;
+ switch (dateStyle)
+ {
+ case FULL:
+ name = "fullDateFormat";
+ def = "EEEE MMMM d, yyyy G";
+ break;
+ case LONG:
+ name = "longDateFormat";
+ def = "MMMM d, yyyy";
+ break;
+ case MEDIUM:
+ name = "mediumDateFormat";
+ def = "d-MMM-yy";
+ break;
+ case SHORT:
+ name = "shortDateFormat";
+ def = "M/d/yy";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+ try
+ {
+ pattern = res == null ? def : res.getString(name);
+ }
+ catch (MissingResourceException x)
+ {
+ pattern = def;
+ }
+ }
+
+ if (use_time)
+ {
+ if (pattern == null)
+ pattern = "";
+ else
+ pattern += " ";
+
+ String name, def;
+ switch (timeStyle)
+ {
+ case FULL:
+ name = "fullTimeFormat";
+ def = "h:mm:ss;S 'o''clock' a z";
+ break;
+ case LONG:
+ name = "longTimeFormat";
+ def = "h:mm:ss a z";
+ break;
+ case MEDIUM:
+ name = "mediumTimeFormat";
+ def = "h:mm:ss a";
+ break;
+ case SHORT:
+ name = "shortTimeFormat";
+ def = "h:mm a";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+
+ String s;
+ try
+ {
+ s = res == null ? def : res.getString(name);
+ }
+ catch (MissingResourceException x)
+ {
+ s = def;
+ }
+ pattern += s;
+ }
+
+ return new SimpleDateFormat (pattern, loc);
+ }
+
+ /**
+ * This method returns an instance of <code>DateFormat</code> that will
+ * format using the default formatting style for dates.
+ *
+ * @return A new <code>DateFormat</code> instance.
+ */
+ public static final DateFormat getDateInstance ()
+ {
+ return getDateInstance (DEFAULT, Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>DateFormat</code> that will
+ * format using the specified formatting style for dates.
+ *
+ * @param style The type of formatting to perform.
+ *
+ * @return A new <code>DateFormat</code> instance.
+ */
+ public static final DateFormat getDateInstance (int style)
+ {
+ return getDateInstance (style, Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>DateFormat</code> that will
+ * format using the specified formatting style for dates. The specified
+ * localed will be used in place of the default.
+ *
+ * @param style The type of formatting to perform.
+ * @param aLocale The desired locale.
+ *
+ * @return A new <code>DateFormat</code> instance.
+ */
+ public static final DateFormat getDateInstance (int style, Locale loc)
+ {
+ return computeInstance (style, loc, true, false);
+ }
+
+ /**
+ * This method returns a new instance of <code>DateFormat</code> that
+ * formats both dates and times using the <code>SHORT</code> style.
+ *
+ * @return A new <code>DateFormat</code>instance.
+ */
+ public static final DateFormat getDateTimeInstance ()
+ {
+ return getDateTimeInstance (DEFAULT, DEFAULT, Locale.getDefault());
+ }
+
+ /**
+ * This method returns a new instance of <code>DateFormat</code> that
+ * formats both dates and times using the <code>DEFAULT</code> style.
+ *
+ * @return A new <code>DateFormat</code>instance.
+ */
+ public static final DateFormat getDateTimeInstance (int dateStyle,
+ int timeStyle)
+ {
+ return getDateTimeInstance (dateStyle, timeStyle, Locale.getDefault());
+ }
+
+ /**
+ * This method returns a new instance of <code>DateFormat</code> that
+ * formats both dates and times using the specified styles.
+ *
+ * @param dateStyle The desired style for date formatting.
+ * @param timeStyle The desired style for time formatting
+ *
+ * @return A new <code>DateFormat</code>instance.
+ */
+ public static final DateFormat getDateTimeInstance (int dateStyle,
+ int timeStyle,
+ Locale loc)
+ {
+ return computeInstance (dateStyle, timeStyle, loc, true, true);
+ }
+
+ /**
+ * This method returns a new instance of <code>DateFormat</code> that
+ * formats both dates and times using the <code>SHORT</code> style.
+ *
+ * @return A new <code>DateFormat</code>instance.
+ */
+ public static final DateFormat getInstance ()
+ {
+ // JCL book says SHORT.
+ return getDateTimeInstance (SHORT, SHORT, Locale.getDefault());
+ }
+
+ /**
+ * This method returns the <code>NumberFormat</code> object being used
+ * by this object to parse/format time values.
+ *
+ * @return The <code>NumberFormat</code> in use by this object.
+ */
+ public NumberFormat getNumberFormat ()
+ {
+ return numberFormat;
+ }
+
+ /**
+ * This method returns an instance of <code>DateFormat</code> that will
+ * format using the default formatting style for times.
+ *
+ * @return A new <code>DateFormat</code> instance.
+ */
+ public static final DateFormat getTimeInstance ()
+ {
+ return getTimeInstance (DEFAULT, Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>DateFormat</code> that will
+ * format using the specified formatting style for times.
+ *
+ * @param style The type of formatting to perform.
+ *
+ * @return A new <code>DateFormat</code> instance.
+ */
+ public static final DateFormat getTimeInstance (int style)
+ {
+ return getTimeInstance (style, Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>DateFormat</code> that will
+ * format using the specified formatting style for times. The specified
+ * localed will be used in place of the default.
+ *
+ * @param style The type of formatting to perform.
+ * @param aLocale The desired locale.
+ *
+ * @return A new <code>DateFormat</code> instance.
+ */
+ public static final DateFormat getTimeInstance (int style, Locale loc)
+ {
+ return computeInstance (style, loc, false, true);
+ }
+
+ /**
+ * This method returns the <code>TimeZone</code> object being used by
+ * this instance.
+ *
+ * @return The time zone in use.
+ */
+ public TimeZone getTimeZone ()
+ {
+ return calendar.getTimeZone();
+ }
+
+ /**
+ * This method returns a hash value for this object.
+ *
+ * @return A hash value for this object.
+ */
+ public int hashCode ()
+ {
+ if (numberFormat != null)
+ return numberFormat.hashCode();
+ else
+ return 0;
+ }
+
+ /**
+ * This method indicates whether or not the parsing of date and time
+ * values should be done in a lenient value.
+ *
+ * @return <code>true</code> if date/time parsing is lenient,
+ * <code>false</code> otherwise.
+ */
+ public boolean isLenient ()
+ {
+ return calendar.isLenient();
+ }
+
+ /**
+ * This method parses the specified date/time string.
+ *
+ * @param source The string to parse.
+ * @return The resultant date.
+ *
+ * @exception ParseException If the specified string cannot be parsed.
+ */
+ public Date parse (String source) throws ParseException
+ {
+ ParsePosition pos = new ParsePosition(0);
+ Date result = parse (source, pos);
+ if (result == null)
+ {
+ int index = pos.getErrorIndex();
+ if (index < 0)
+ index = pos.getIndex();
+ throw new ParseException("invalid Date syntax in \""
+ + source + '\"', index);
+ }
+ return result;
+ }
+
+ /**
+ * This method parses the specified <code>String</code> into a
+ * <code>Date</code>. The <code>pos</code> argument contains the
+ * starting parse position on method entry and the ending parse
+ * position on method exit.
+ *
+ * @param text The string to parse.
+ * @param pos The starting parse position in entry, the ending parse
+ * position on exit.
+ *
+ * @return The parsed date, or <code>null</code> if the string cannot
+ * be parsed.
+ */
+ public abstract Date parse (String source, ParsePosition pos);
+
+ /**
+ * This method is identical to <code>parse(String, ParsePosition)</code>,
+ * but returns its result as an <code>Object</code> instead of a
+ * <code>Date</code>.
+ *
+ * @param source The string to parse.
+ * @param pos The starting parse position in entry, the ending parse
+ * position on exit.
+ *
+ * @return The parsed date, or <code>null</code> if the string cannot
+ * be parsed.
+ */
+ public Object parseObject (String source, ParsePosition pos)
+ {
+ return parse(source, pos);
+ }
+
+ /**
+ * This method specified the <code>Calendar</code> that should be used
+ * by this object to parse/format datetimes.
+ *
+ * @param The new <code>Calendar</code> for this object.
+ *
+ * @see java.util.Calendar
+ */
+ public void setCalendar (Calendar calendar)
+ {
+ this.calendar = calendar;
+ }
+
+ /**
+ * This method specifies whether or not this object should be lenient in
+ * the syntax it accepts while parsing date/time values.
+ *
+ * @param lenient <code>true</code> if parsing should be lenient,
+ * <code>false</code> otherwise.
+ */
+ public void setLenient (boolean lenient)
+ {
+ calendar.setLenient(lenient);
+ }
+
+ /**
+ * This method specifies the <code>NumberFormat</code> object that should
+ * be used by this object to parse/format times.
+ *
+ * @param The <code>NumberFormat</code> in use by this object.
+ */
+ public void setNumberFormat (NumberFormat numberFormat)
+ {
+ this.numberFormat = numberFormat;
+ }
+
+ /**
+ * This method sets the time zone that should be used by this object.
+ *
+ * @param The new time zone.
+ */
+ public void setTimeZone (TimeZone timeZone)
+ {
+ calendar.setTimeZone(timeZone);
+ }
+}
diff --git a/libjava/classpath/java/text/DateFormatSymbols.java b/libjava/classpath/java/text/DateFormatSymbols.java
new file mode 100644
index 00000000000..543a5c13a78
--- /dev/null
+++ b/libjava/classpath/java/text/DateFormatSymbols.java
@@ -0,0 +1,525 @@
+/* DateFormatSymbols.java -- Format over a range of numbers
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+/**
+ * This class acts as container for locale specific date/time formatting
+ * information such as the days of the week and the months of the year.
+ * @author Per Bothner (bothner@cygnus.com)
+ * @date October 24, 1998.
+ */
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3.
+ * Status: Believed complete and correct.
+ */
+public class DateFormatSymbols implements java.io.Serializable, Cloneable
+{
+ String[] ampms;
+ String[] eras;
+ private String localPatternChars;
+ String[] months;
+ String[] shortMonths;
+ String[] shortWeekdays;
+ String[] weekdays;
+ private String[][] zoneStrings;
+
+ private static final long serialVersionUID = -5987973545549424702L;
+
+ // The order of these prefixes must be the same as in DateFormat
+ private static final String[] formatPrefixes =
+ {
+ "full", "long", "medium", "short"
+ };
+
+ // These are each arrays with a value for SHORT, MEDIUM, LONG, FULL,
+ // and DEFAULT (constants defined in java.text.DateFormat). While
+ // not part of the official spec, we need a way to get at locale-specific
+ // default formatting patterns. They are declared package scope so
+ // as to be easily accessible where needed (DateFormat, SimpleDateFormat).
+ transient String[] dateFormats;
+ transient String[] timeFormats;
+
+ private static String[] getStringArray(ResourceBundle res, String name)
+ {
+ return res.getString(name).split("\u00ae");
+ }
+
+ private String[][] getZoneStrings(ResourceBundle res)
+ {
+ try
+ {
+ int index = 0;
+ String data = res.getString("zoneStrings");
+ String[] zones = data.split("\u00a9");
+ String[][] array = new String[zones.length][];
+ for (int a = 0; a < zones.length; ++a)
+ array[a] = zones[a].split("\u00ae");
+ return array;
+ }
+ catch (MissingResourceException e)
+ {
+ return new String[0][];
+ }
+ }
+
+ private String[] formatsForKey(ResourceBundle res, String key)
+ {
+ String[] values = new String[formatPrefixes.length];
+
+ for (int i = 0; i < formatPrefixes.length; i++)
+ values[i] = res.getString(formatPrefixes[i] + key);
+
+ return values;
+ }
+
+ /**
+ * This method initializes a new instance of <code>DateFormatSymbols</code>
+ * by loading the date format information for the specified locale.
+ *
+ * @param locale The locale for which date formatting symbols should
+ * be loaded.
+ */
+ public DateFormatSymbols (Locale locale) throws MissingResourceException
+ {
+ ResourceBundle res
+ = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", locale,
+ ClassLoader.getSystemClassLoader());
+
+ ampms = getStringArray(res, "ampms");
+ eras = getStringArray(res, "eras");
+ localPatternChars = res.getString("localPatternChars");
+ months = getStringArray(res, "months");
+ shortMonths = getStringArray(res, "shortMonths");
+ shortWeekdays = getStringArray(res, "shortWeekdays");
+ weekdays = getStringArray(res, "weekdays");
+ zoneStrings = getZoneStrings(res);
+ dateFormats = formatsForKey(res, "DateFormat");
+ timeFormats = formatsForKey(res, "TimeFormat");
+ }
+
+ /**
+ * This method loads the format symbol information for the default
+ * locale.
+ */
+ public DateFormatSymbols () throws MissingResourceException
+ {
+ this (Locale.getDefault());
+ }
+
+ /**
+ * This method returns the list of strings used for displaying AM or PM.
+ * This is a two element <code>String</code> array indexed by
+ * <code>Calendar.AM</code> and <code>Calendar.PM</code>
+ *
+ * @return The list of AM/PM display strings.
+ */
+ public String[] getAmPmStrings()
+ {
+ return ampms;
+ }
+
+ /**
+ * This method returns the list of strings used for displaying eras
+ * (e.g., "BC" and "AD"). This is a two element <code>String</code>
+ * array indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
+ *
+ * @return The list of era disply strings.
+ */
+ public String[] getEras()
+ {
+ return eras;
+ }
+
+ /**
+ * This method returns the pattern character information for this
+ * object. This is an 18 character string that contains the characters
+ * that are used in creating the date formatting strings in
+ * <code>SimpleDateFormat</code>. The following are the character
+ * positions in the string and which format character they correspond
+ * to (the character in parentheses is the default value in the US English
+ * locale):
+ * <p>
+ * <ul>
+ * <li>0 - era (G)</li>
+ * <li>1 - year (y)</li>
+ * <li>2 - month (M)</li>
+ * <li>3 - day of month (d)</li>
+ * <li>4 - hour out of 12, from 1-12 (h)</li>
+ * <li>5 - hour out of 24, from 0-23 (H)</li>
+ * <li>6 - minute (m)</li>
+ * <li>7 - second (s)</li>
+ * <li>8 - millisecond (S)</li>
+ * <li>9 - date of week (E)</li>
+ * <li>10 - date of year (D)</li>
+ * <li>11 - day of week in month, eg. "4th Thur in Nov" (F)</li>
+ * <li>12 - week in year (w)</li>
+ * <li>13 - week in month (W)</li>
+ * <li>14 - am/pm (a)</li>
+ * <li>15 - hour out of 24, from 1-24 (k)</li>
+ * <li>16 - hour out of 12, from 0-11 (K)</li>
+ * <li>17 - time zone (z)</li>
+ * </ul>
+ *
+ * @return The format patter characters
+ */
+ public String getLocalPatternChars()
+ {
+ return localPatternChars;
+ }
+
+ /**
+ * This method returns the list of strings used for displaying month
+ * names (e.g., "January" and "February"). This is a thirteen element
+ * string array indexed by <code>Calendar.JANUARY</code> through
+ * <code>Calendar.UNDECEMBER</code>. Note that there are thirteen
+ * elements because some calendars have thriteen months.
+ *
+ * @return The list of month display strings.
+ */
+ public String[] getMonths ()
+ {
+ return months;
+ }
+
+ /**
+ * This method returns the list of strings used for displaying abbreviated
+ * month names (e.g., "Jan" and "Feb"). This is a thirteen element
+ * <code>String</code> array indexed by <code>Calendar.JANUARY</code>
+ * through <code>Calendar.UNDECEMBER</code>. Note that there are thirteen
+ * elements because some calendars have thirteen months.
+ *
+ * @return The list of abbreviated month display strings.
+ */
+ public String[] getShortMonths ()
+ {
+ return shortMonths;
+ }
+
+ /**
+ * This method returns the list of strings used for displaying abbreviated
+ * weekday names (e.g., "Sun" and "Mon"). This is an eight element
+ * <code>String</code> array indexed by <code>Calendar.SUNDAY</code>
+ * through <code>Calendar.SATURDAY</code>. Note that the first element
+ * of this array is ignored.
+ *
+ * @return This list of abbreviated weekday display strings.
+ */
+ public String[] getShortWeekdays ()
+ {
+ return shortWeekdays;
+ }
+
+ /**
+ * This method returns the list of strings used for displaying weekday
+ * names (e.g., "Sunday" and "Monday"). This is an eight element
+ * <code>String</code> array indexed by <code>Calendar.SUNDAY</code>
+ * through <code>Calendar.SATURDAY</code>. Note that the first element
+ * of this array is ignored.
+ *
+ * @return This list of weekday display strings.
+ */
+ public String[] getWeekdays ()
+ {
+ return weekdays;
+ }
+
+ /**
+ * This method returns this list of localized timezone display strings.
+ * This is a two dimensional <code>String</code> array where each row in
+ * the array contains five values:
+ * <P>
+ * <ul>
+ * <li>0 - The non-localized time zone id string.</li>
+ * <li>1 - The long name of the time zone (standard time).</li>
+ * <li>2 - The short name of the time zone (standard time).</li>
+ * <li>3 - The long name of the time zone (daylight savings time).</li>
+ * <li>4 - the short name of the time zone (daylight savings time).</li>
+ * </ul>
+ *
+ * @return The list of time zone display strings.
+ */
+ public String[] [] getZoneStrings ()
+ {
+ return zoneStrings;
+ }
+
+ /**
+ * This method sets the list of strings used to display AM/PM values to
+ * the specified list.
+ * This is a two element <code>String</code> array indexed by
+ * <code>Calendar.AM</code> and <code>Calendar.PM</code>
+ *
+ * @param ampms The new list of AM/PM display strings.
+ */
+ public void setAmPmStrings (String[] value)
+ {
+ ampms = value;
+ }
+
+ /**
+ * This method sets the list of strings used to display time eras to
+ * to the specified list.
+ * This is a two element <code>String</code>
+ * array indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
+ *
+ * @param eras The new list of era disply strings.
+ */
+ public void setEras (String[] value)
+ {
+ eras = value;
+ }
+
+ /**
+ * This method sets the list of characters used to specific date/time
+ * formatting strings.
+ * This is an 18 character string that contains the characters
+ * that are used in creating the date formatting strings in
+ * <code>SimpleDateFormat</code>. The following are the character
+ * positions in the string and which format character they correspond
+ * to (the character in parentheses is the default value in the US English
+ * locale):
+ * <p>
+ * <ul>
+ * <li>0 - era (G)</li>
+ * <li>1 - year (y)</li>
+ * <li>2 - month (M)</li>
+ * <li>3 - day of month (d)</li>
+ * <li>4 - hour out of 12, from 1-12 (h)</li>
+ * <li>5 - hour out of 24, from 0-23 (H)</li>
+ * <li>6 - minute (m)</li>
+ * <li>7 - second (s)</li>
+ * <li>8 - millisecond (S)</li>
+ * <li>9 - date of week (E)</li>
+ * <li>10 - date of year (D)</li>
+ * <li>11 - day of week in month, eg. "4th Thur in Nov" (F)</li>
+ * <li>12 - week in year (w)</li>
+ * <li>13 - week in month (W)</li>
+ * <li>14 - am/pm (a)</li>
+ * <li>15 - hour out of 24, from 1-24 (k)</li>
+ * <li>16 - hour out of 12, from 0-11 (K)</li>
+ * <li>17 - time zone (z)</li>
+ * </ul>
+ *
+ * @param localPatternChars The new format patter characters
+ */
+ public void setLocalPatternChars (String value)
+ {
+ localPatternChars = value;
+ }
+
+ /**
+ * This method sets the list of strings used to display month names.
+ * This is a thirteen element
+ * string array indexed by <code>Calendar.JANUARY</code> through
+ * <code>Calendar.UNDECEMBER</code>. Note that there are thirteen
+ * elements because some calendars have thriteen months.
+ *
+ * @param months The list of month display strings.
+ */
+ public void setMonths (String[] value)
+ {
+ months = value;
+ }
+
+ /**
+ * This method sets the list of strings used to display abbreviated month
+ * names.
+ * This is a thirteen element
+ * <code>String</code> array indexed by <code>Calendar.JANUARY</code>
+ * through <code>Calendar.UNDECEMBER</code>. Note that there are thirteen
+ * elements because some calendars have thirteen months.
+ *
+ * @param shortMonths The new list of abbreviated month display strings.
+ */
+ public void setShortMonths (String[] value)
+ {
+ shortMonths = value;
+ }
+
+ /**
+ * This method sets the list of strings used to display abbreviated
+ * weekday names.
+ * This is an eight element
+ * <code>String</code> array indexed by <code>Calendar.SUNDAY</code>
+ * through <code>Calendar.SATURDAY</code>. Note that the first element
+ * of this array is ignored.
+ *
+ * @param shortWeekdays This list of abbreviated weekday display strings.
+ */
+ public void setShortWeekdays (String[] value)
+ {
+ shortWeekdays = value;
+ }
+
+ /**
+ * This method sets the list of strings used to display weekday names.
+ * This is an eight element
+ * <code>String</code> array indexed by <code>Calendar.SUNDAY</code>
+ * through <code>Calendar.SATURDAY</code>. Note that the first element
+ * of this array is ignored.
+ *
+ * @param weekdays This list of weekday display strings.
+ */
+ public void setWeekdays (String[] value)
+ {
+ weekdays = value;
+ }
+
+ /**
+ * This method sets the list of display strings for time zones.
+ * This is a two dimensional <code>String</code> array where each row in
+ * the array contains five values:
+ * <P>
+ * <ul>
+ * <li>0 - The non-localized time zone id string.</li>
+ * <li>1 - The long name of the time zone (standard time).</li>
+ * <li>2 - The short name of the time zone (standard time).</li>
+ * <li>3 - The long name of the time zone (daylight savings time).</li>
+ * <li>4 - the short name of the time zone (daylight savings time).</li>
+ * </ul>
+ *
+ * @return The list of time zone display strings.
+ */
+ public void setZoneStrings (String[][] value)
+ {
+ zoneStrings = value;
+ }
+
+ /* Does a "deep" equality test - recurses into arrays. */
+ private static boolean equals (Object x, Object y)
+ {
+ if (x == y)
+ return true;
+ if (x == null || y == null)
+ return false;
+ if (! (x instanceof Object[]) || ! (y instanceof Object[]))
+ return x.equals(y);
+ Object[] xa = (Object[]) x;
+ Object[] ya = (Object[]) y;
+ if (xa.length != ya.length)
+ return false;
+ for (int i = xa.length; --i >= 0; )
+ {
+ if (! equals(xa[i], ya[i]))
+ return false;
+ }
+ return true;
+ }
+
+ private static int hashCode (Object x)
+ {
+ if (x == null)
+ return 0;
+ if (! (x instanceof Object[]))
+ return x.hashCode();
+ Object[] xa = (Object[]) x;
+ int hash = 0;
+ for (int i = 0; i < xa.length; i++)
+ hash = 37 * hashCode(xa[i]);
+ return hash;
+ }
+
+ /**
+ * This method tests a specified object for equality against this object.
+ * This will be true if and only if the specified object:
+ * <p>
+ * <ul>
+ * <li> Is not <code>null</code>.</li>
+ * <li> Is an instance of <code>DateFormatSymbols</code>.</li>
+ * <li> Contains identical formatting symbols to this object.</li>
+ * </ul>
+ *
+ * @param obj The <code>Object</code> to test for equality against.
+ *
+ * @return <code>true</code> if the specified object is equal to this one,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof DateFormatSymbols))
+ return false;
+ DateFormatSymbols other = (DateFormatSymbols) obj;
+ return (equals(ampms, other.ampms)
+ && equals(eras, other.eras)
+ && equals(localPatternChars, other.localPatternChars)
+ && equals(months, other.months)
+ && equals(shortMonths, other.shortMonths)
+ && equals(shortWeekdays, other.shortWeekdays)
+ && equals(weekdays, other.weekdays)
+ && equals(zoneStrings, other.zoneStrings));
+ }
+
+ /**
+ * Returns a new copy of this object.
+ *
+ * @param A copy of this object
+ */
+ public Object clone ()
+ {
+ try
+ {
+ return super.clone ();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * This method returns a hash value for this object.
+ *
+ * @return A hash value for this object.
+ */
+ public int hashCode ()
+ {
+ return (hashCode(ampms)
+ ^ hashCode(eras)
+ ^ hashCode(localPatternChars)
+ ^ hashCode(months)
+ ^ hashCode(shortMonths)
+ ^ hashCode(shortWeekdays)
+ ^ hashCode(weekdays)
+ ^ hashCode(zoneStrings));
+ }
+}
diff --git a/libjava/classpath/java/text/DecimalFormat.java b/libjava/classpath/java/text/DecimalFormat.java
new file mode 100644
index 00000000000..6dadb0ce333
--- /dev/null
+++ b/libjava/classpath/java/text/DecimalFormat.java
@@ -0,0 +1,1435 @@
+/* DecimalFormat.java -- Formats and parses numbers
+ Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.text;
+
+import gnu.java.text.AttributedFormatBuffer;
+import gnu.java.text.FormatBuffer;
+import gnu.java.text.FormatCharacterIterator;
+import gnu.java.text.StringFormatBuffer;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.Currency;
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @date March 4, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.2.
+ * Note however that the docs are very unclear about how format parsing
+ * should work. No doubt there are problems here.
+ */
+public class DecimalFormat extends NumberFormat
+{
+ // This is a helper for applyPatternWithSymbols. It reads a prefix
+ // or a suffix. It can cause some side-effects.
+ private int scanFix (String pattern, int index, FormatBuffer buf,
+ String patChars, DecimalFormatSymbols syms,
+ boolean is_suffix)
+ {
+ int len = pattern.length();
+ boolean quoteStarted = false;
+ buf.clear();
+
+ boolean multiplierSet = false;
+ while (index < len)
+ {
+ char c = pattern.charAt(index);
+
+ if (quoteStarted)
+ {
+ if (c == '\'')
+ quoteStarted = false;
+ else
+ buf.append(c);
+ index++;
+ continue;
+ }
+
+ if (c == '\'' && index + 1 < len
+ && pattern.charAt(index + 1) == '\'')
+ {
+ buf.append(c);
+ index++;
+ }
+ else if (c == '\'')
+ {
+ quoteStarted = true;
+ }
+ else if (c == '\u00a4')
+ {
+ /* Currency interpreted later */
+ buf.append(c);
+ }
+ else if (c == syms.getPercent())
+ {
+ if (multiplierSet)
+ throw new IllegalArgumentException ("multiplier already set " +
+ "- index: " + index);
+ multiplierSet = true;
+ multiplier = 100;
+ buf.append(c, NumberFormat.Field.PERCENT);
+ }
+ else if (c == syms.getPerMill())
+ {
+ if (multiplierSet)
+ throw new IllegalArgumentException ("multiplier already set " +
+ "- index: " + index);
+ multiplierSet = true;
+ multiplier = 1000;
+ buf.append(c, NumberFormat.Field.PERMILLE);
+ }
+ else if (patChars.indexOf(c) != -1)
+ {
+ // This is a pattern character.
+ break;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ index++;
+ }
+
+ if (quoteStarted)
+ throw new IllegalArgumentException ("pattern is lacking a closing quote");
+
+ return index;
+ }
+
+ // A helper which reads a number format.
+ private int scanFormat (String pattern, int index, String patChars,
+ DecimalFormatSymbols syms, boolean is_positive)
+ {
+ int max = pattern.length();
+
+ int countSinceGroup = 0;
+ int zeroCount = 0;
+ boolean saw_group = false;
+
+ //
+ // Scan integer part.
+ //
+ while (index < max)
+ {
+ char c = pattern.charAt(index);
+
+ if (c == syms.getDigit())
+ {
+ if (zeroCount > 0)
+ throw new IllegalArgumentException ("digit mark following " +
+ "zero - index: " + index);
+ ++countSinceGroup;
+ }
+ else if (c == syms.getZeroDigit())
+ {
+ ++zeroCount;
+ ++countSinceGroup;
+ }
+ else if (c == syms.getGroupingSeparator())
+ {
+ countSinceGroup = 0;
+ saw_group = true;
+ }
+ else
+ break;
+
+ ++index;
+ }
+
+ // We can only side-effect when parsing the positive format.
+ if (is_positive)
+ {
+ groupingUsed = saw_group;
+ groupingSize = (byte) countSinceGroup;
+ minimumIntegerDigits = zeroCount;
+ }
+
+ // Early termination.
+ if (index == max || pattern.charAt(index) == syms.getGroupingSeparator())
+ {
+ if (is_positive)
+ decimalSeparatorAlwaysShown = false;
+ return index;
+ }
+
+ if (pattern.charAt(index) == syms.getDecimalSeparator())
+ {
+ ++index;
+
+ //
+ // Scan fractional part.
+ //
+ int hashCount = 0;
+ zeroCount = 0;
+ while (index < max)
+ {
+ char c = pattern.charAt(index);
+ if (c == syms.getZeroDigit())
+ {
+ if (hashCount > 0)
+ throw new IllegalArgumentException ("zero mark " +
+ "following digit - index: " + index);
+ ++zeroCount;
+ }
+ else if (c == syms.getDigit())
+ {
+ ++hashCount;
+ }
+ else if (c != syms.getExponential()
+ && c != syms.getPatternSeparator()
+ && c != syms.getPercent()
+ && c != syms.getPerMill()
+ && patChars.indexOf(c) != -1)
+ throw new IllegalArgumentException ("unexpected special " +
+ "character - index: " + index);
+ else
+ break;
+
+ ++index;
+ }
+
+ if (is_positive)
+ {
+ maximumFractionDigits = hashCount + zeroCount;
+ minimumFractionDigits = zeroCount;
+ }
+
+ if (index == max)
+ return index;
+ }
+
+ if (pattern.charAt(index) == syms.getExponential())
+ {
+ //
+ // Scan exponential format.
+ //
+ zeroCount = 0;
+ ++index;
+ while (index < max)
+ {
+ char c = pattern.charAt(index);
+ if (c == syms.getZeroDigit())
+ ++zeroCount;
+ else if (c == syms.getDigit())
+ {
+ if (zeroCount > 0)
+ throw new
+ IllegalArgumentException ("digit mark following zero " +
+ "in exponent - index: " +
+ index);
+ }
+ else if (patChars.indexOf(c) != -1)
+ throw new IllegalArgumentException ("unexpected special " +
+ "character - index: " +
+ index);
+ else
+ break;
+
+ ++index;
+ }
+
+ if (is_positive)
+ {
+ useExponentialNotation = true;
+ minExponentDigits = (byte) zeroCount;
+ }
+
+ maximumIntegerDigits = groupingSize;
+ groupingSize = 0;
+ if (maximumIntegerDigits > minimumIntegerDigits && maximumIntegerDigits > 0)
+ {
+ minimumIntegerDigits = 1;
+ exponentRound = maximumIntegerDigits;
+ }
+ else
+ exponentRound = 1;
+ }
+
+ return index;
+ }
+
+ // This helper function creates a string consisting of all the
+ // characters which can appear in a pattern and must be quoted.
+ private String patternChars (DecimalFormatSymbols syms)
+ {
+ StringBuffer buf = new StringBuffer ();
+ buf.append(syms.getDecimalSeparator());
+ buf.append(syms.getDigit());
+ buf.append(syms.getExponential());
+ buf.append(syms.getGroupingSeparator());
+ // Adding this one causes pattern application to fail.
+ // Of course, omitting is causes toPattern to fail.
+ // ... but we already have bugs there. FIXME.
+ // buf.append(syms.getMinusSign());
+ buf.append(syms.getPatternSeparator());
+ buf.append(syms.getPercent());
+ buf.append(syms.getPerMill());
+ buf.append(syms.getZeroDigit());
+ buf.append('\u00a4');
+ return buf.toString();
+ }
+
+ private void applyPatternWithSymbols(String pattern, DecimalFormatSymbols syms)
+ {
+ // Initialize to the state the parser expects.
+ negativePrefix = "";
+ negativeSuffix = "";
+ positivePrefix = "";
+ positiveSuffix = "";
+ decimalSeparatorAlwaysShown = false;
+ groupingSize = 0;
+ minExponentDigits = 0;
+ multiplier = 1;
+ useExponentialNotation = false;
+ groupingUsed = false;
+ maximumFractionDigits = 0;
+ maximumIntegerDigits = MAXIMUM_INTEGER_DIGITS;
+ minimumFractionDigits = 0;
+ minimumIntegerDigits = 1;
+
+ AttributedFormatBuffer buf = new AttributedFormatBuffer ();
+ String patChars = patternChars (syms);
+
+ int max = pattern.length();
+ int index = scanFix (pattern, 0, buf, patChars, syms, false);
+ buf.sync();
+ positivePrefix = buf.getBuffer().toString();
+ positivePrefixRanges = buf.getRanges();
+ positivePrefixAttrs = buf.getAttributes();
+
+ index = scanFormat (pattern, index, patChars, syms, true);
+
+ index = scanFix (pattern, index, buf, patChars, syms, true);
+ buf.sync();
+ positiveSuffix = buf.getBuffer().toString();
+ positiveSuffixRanges = buf.getRanges();
+ positiveSuffixAttrs = buf.getAttributes();
+
+ if (index == pattern.length())
+ {
+ // No negative info.
+ negativePrefix = null;
+ negativeSuffix = null;
+ }
+ else
+ {
+ if (pattern.charAt(index) != syms.getPatternSeparator())
+ throw new IllegalArgumentException ("separator character " +
+ "expected - index: " + index);
+
+ index = scanFix (pattern, index + 1, buf, patChars, syms, false);
+ buf.sync();
+ negativePrefix = buf.getBuffer().toString();
+ negativePrefixRanges = buf.getRanges();
+ negativePrefixAttrs = buf.getAttributes();
+
+ // We parse the negative format for errors but we don't let
+ // it side-effect this object.
+ index = scanFormat (pattern, index, patChars, syms, false);
+
+ index = scanFix (pattern, index, buf, patChars, syms, true);
+ buf.sync();
+ negativeSuffix = buf.getBuffer().toString();
+ negativeSuffixRanges = buf.getRanges();
+ negativeSuffixAttrs = buf.getAttributes();
+
+ if (index != pattern.length())
+ throw new IllegalArgumentException ("end of pattern expected " +
+ "- index: " + index);
+ }
+ }
+
+ public void applyLocalizedPattern (String pattern)
+ {
+ // JCL p. 638 claims this throws a ParseException but p. 629
+ // contradicts this. Empirical tests with patterns of "0,###.0"
+ // and "#.#.#" corroborate the p. 629 statement that an
+ // IllegalArgumentException is thrown.
+ applyPatternWithSymbols (pattern, symbols);
+ }
+
+ public void applyPattern (String pattern)
+ {
+ // JCL p. 638 claims this throws a ParseException but p. 629
+ // contradicts this. Empirical tests with patterns of "0,###.0"
+ // and "#.#.#" corroborate the p. 629 statement that an
+ // IllegalArgumentException is thrown.
+ applyPatternWithSymbols (pattern, nonLocalizedSymbols);
+ }
+
+ public Object clone ()
+ {
+ DecimalFormat c = (DecimalFormat) super.clone ();
+ c.symbols = (DecimalFormatSymbols) symbols.clone ();
+ return c;
+ }
+
+ /**
+ * Constructs a <code>DecimalFormat</code> which uses the default
+ * pattern and symbols.
+ */
+ public DecimalFormat ()
+ {
+ this ("#,##0.###");
+ }
+
+ /**
+ * Constructs a <code>DecimalFormat</code> which uses the given
+ * pattern and the default symbols for formatting and parsing.
+ *
+ * @param pattern the non-localized pattern to use.
+ * @throws NullPointerException if any argument is null.
+ * @throws IllegalArgumentException if the pattern is invalid.
+ */
+ public DecimalFormat (String pattern)
+ {
+ this (pattern, new DecimalFormatSymbols ());
+ }
+
+ /**
+ * Constructs a <code>DecimalFormat</code> using the given pattern
+ * and formatting symbols. This construction method is used to give
+ * complete control over the formatting process.
+ *
+ * @param pattern the non-localized pattern to use.
+ * @param symbols the set of symbols used for parsing and formatting.
+ * @throws NullPointerException if any argument is null.
+ * @throws IllegalArgumentException if the pattern is invalid.
+ */
+ public DecimalFormat(String pattern, DecimalFormatSymbols symbols)
+ {
+ this.symbols = (DecimalFormatSymbols) symbols.clone();
+ applyPattern(pattern);
+ }
+
+ private boolean equals(String s1, String s2)
+ {
+ if (s1 == null || s2 == null)
+ return s1 == s2;
+ return s1.equals(s2);
+ }
+
+ /**
+ * Tests this instance for equality with an arbitrary object. This method
+ * returns <code>true</code> if:
+ * <ul>
+ * <li><code>obj</code> is not <code>null</code>;</li>
+ * <li><code>obj</code> is an instance of <code>DecimalFormat</code>;</li>
+ * <li>this instance and <code>obj</code> have the same attributes;</li>
+ * </ul>
+ *
+ * @param obj the object (<code>null</code> permitted).
+ *
+ * @return A boolean.
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof DecimalFormat))
+ return false;
+ DecimalFormat dup = (DecimalFormat) obj;
+ return (decimalSeparatorAlwaysShown == dup.decimalSeparatorAlwaysShown
+ && groupingUsed == dup.groupingUsed
+ && groupingSize == dup.groupingSize
+ && multiplier == dup.multiplier
+ && useExponentialNotation == dup.useExponentialNotation
+ && minExponentDigits == dup.minExponentDigits
+ && minimumIntegerDigits == dup.minimumIntegerDigits
+ && maximumIntegerDigits == dup.maximumIntegerDigits
+ && minimumFractionDigits == dup.minimumFractionDigits
+ && maximumFractionDigits == dup.maximumFractionDigits
+ && equals(negativePrefix, dup.negativePrefix)
+ && equals(negativeSuffix, dup.negativeSuffix)
+ && equals(positivePrefix, dup.positivePrefix)
+ && equals(positiveSuffix, dup.positiveSuffix)
+ && symbols.equals(dup.symbols));
+ }
+
+ private void formatInternal (double number, FormatBuffer dest,
+ FieldPosition fieldPos)
+ {
+ // A very special case.
+ if (Double.isNaN(number))
+ {
+ dest.append(symbols.getNaN());
+ if (fieldPos != null &&
+ (fieldPos.getField() == INTEGER_FIELD ||
+ fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
+ {
+ int index = dest.length();
+ fieldPos.setBeginIndex(index - symbols.getNaN().length());
+ fieldPos.setEndIndex(index);
+ }
+ return;
+ }
+
+ boolean is_neg = number < 0;
+ if (is_neg)
+ {
+ if (negativePrefix != null)
+ {
+ dest.append(substituteCurrency(negativePrefix, number),
+ negativePrefixRanges, negativePrefixAttrs);
+ }
+ else
+ {
+ dest.append(symbols.getMinusSign(), NumberFormat.Field.SIGN);
+ dest.append(substituteCurrency(positivePrefix, number),
+ positivePrefixRanges, positivePrefixAttrs);
+ }
+ number = - number;
+ }
+ else
+ {
+ dest.append(substituteCurrency(positivePrefix, number),
+ positivePrefixRanges, positivePrefixAttrs);
+ }
+ int integerBeginIndex = dest.length();
+ int integerEndIndex = 0;
+ int zeroStart = symbols.getZeroDigit() - '0';
+
+ if (Double.isInfinite (number))
+ {
+ dest.append(symbols.getInfinity());
+ integerEndIndex = dest.length();
+ }
+ else
+ {
+ number *= multiplier;
+
+ // Compute exponent.
+ long exponent = 0;
+ double baseNumber;
+ if (useExponentialNotation)
+ {
+ exponent = (long) Math.floor (Math.log(number) / Math.log(10));
+ exponent = exponent - (exponent % exponentRound);
+ if (minimumIntegerDigits > 0)
+ exponent -= minimumIntegerDigits - 1;
+ baseNumber = (number / Math.pow(10.0, exponent));
+ }
+ else
+ baseNumber = number;
+
+ // Round to the correct number of digits.
+ baseNumber += 5 * Math.pow(10.0, - maximumFractionDigits - 1);
+
+ int index = dest.length();
+ //double intPart = Math.floor(baseNumber);
+ String intPart = Long.toString((long)Math.floor(baseNumber));
+ int count, groupPosition = intPart.length();
+
+ dest.setDefaultAttribute(NumberFormat.Field.INTEGER);
+
+ for (count = 0; count < minimumIntegerDigits-intPart.length(); count++)
+ dest.append(symbols.getZeroDigit());
+
+ for (count = 0;
+ count < maximumIntegerDigits && count < intPart.length();
+ count++)
+ {
+ int dig = intPart.charAt(count);
+
+ // Append group separator if required.
+ if (groupingUsed && count > 0 && groupingSize != 0 && groupPosition % groupingSize == 0)
+ {
+ dest.append(symbols.getGroupingSeparator(), NumberFormat.Field.GROUPING_SEPARATOR);
+ dest.setDefaultAttribute(NumberFormat.Field.INTEGER);
+ }
+ dest.append((char) (zeroStart + dig));
+
+ groupPosition--;
+ }
+ dest.setDefaultAttribute(null);
+
+ integerEndIndex = dest.length();
+
+ int decimal_index = integerEndIndex;
+ int consecutive_zeros = 0;
+ int total_digits = 0;
+
+ int localMaximumFractionDigits = maximumFractionDigits;
+
+ if (useExponentialNotation)
+ localMaximumFractionDigits += minimumIntegerDigits - count;
+
+ // Strip integer part from NUMBER.
+ double fracPart = baseNumber - Math.floor(baseNumber);
+
+ if ( ((fracPart != 0 || minimumFractionDigits > 0) && localMaximumFractionDigits > 0)
+ || decimalSeparatorAlwaysShown)
+ {
+ dest.append (symbols.getDecimalSeparator(), NumberFormat.Field.DECIMAL_SEPARATOR);
+ }
+
+ int fraction_begin = dest.length();
+ dest.setDefaultAttribute(NumberFormat.Field.FRACTION);
+ for (count = 0;
+ count < localMaximumFractionDigits
+ && (fracPart != 0 || count < minimumFractionDigits);
+ ++count)
+ {
+ ++total_digits;
+ fracPart *= 10;
+ long dig = (long) fracPart;
+ if (dig == 0)
+ ++consecutive_zeros;
+ else
+ consecutive_zeros = 0;
+ dest.append((char) (symbols.getZeroDigit() + dig));
+
+ // Strip integer part from FRACPART.
+ fracPart = fracPart - Math.floor (fracPart);
+ }
+
+ // Strip extraneous trailing `0's. We can't always detect
+ // these in the loop.
+ int extra_zeros = Math.min (consecutive_zeros,
+ total_digits - minimumFractionDigits);
+ if (extra_zeros > 0)
+ {
+ dest.cutTail(extra_zeros);
+ total_digits -= extra_zeros;
+ if (total_digits == 0 && !decimalSeparatorAlwaysShown)
+ dest.cutTail(1);
+ }
+
+ if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
+ {
+ fieldPos.setBeginIndex(fraction_begin);
+ fieldPos.setEndIndex(dest.length());
+ }
+
+ // Finally, print the exponent.
+ if (useExponentialNotation)
+ {
+ dest.append(symbols.getExponential(), NumberFormat.Field.EXPONENT_SYMBOL);
+ if (exponent < 0)
+ {
+ dest.append (symbols.getMinusSign (), NumberFormat.Field.EXPONENT_SIGN);
+ exponent = - exponent;
+ }
+ index = dest.length();
+ dest.setDefaultAttribute(NumberFormat.Field.EXPONENT);
+ String exponentString = Long.toString ((long) exponent);
+
+ for (count = 0; count < minExponentDigits-exponentString.length();
+ count++)
+ dest.append((char) symbols.getZeroDigit());
+
+ for (count = 0;
+ count < exponentString.length();
+ ++count)
+ {
+ int dig = exponentString.charAt(count);
+ dest.append((char) (zeroStart + dig));
+ }
+ }
+ }
+
+ if (fieldPos != null &&
+ (fieldPos.getField() == INTEGER_FIELD ||
+ fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
+ {
+ fieldPos.setBeginIndex(integerBeginIndex);
+ fieldPos.setEndIndex(integerEndIndex);
+ }
+
+ if (is_neg && negativeSuffix != null)
+ {
+ dest.append(substituteCurrency(negativeSuffix, number),
+ negativeSuffixRanges, negativeSuffixAttrs);
+ }
+ else
+ {
+ dest.append(substituteCurrency(positiveSuffix, number),
+ positiveSuffixRanges, positiveSuffixAttrs);
+ }
+ }
+
+ public StringBuffer format (double number, StringBuffer dest,
+ FieldPosition fieldPos)
+ {
+ formatInternal (number, new StringFormatBuffer(dest), fieldPos);
+ return dest;
+ }
+
+ public AttributedCharacterIterator formatToCharacterIterator (Object value)
+ {
+ AttributedFormatBuffer sbuf = new AttributedFormatBuffer();
+
+ if (value instanceof Number)
+ formatInternal(((Number) value).doubleValue(), sbuf, null);
+ else
+ throw new IllegalArgumentException
+ ("Cannot format given Object as a Number");
+
+ sbuf.sync();
+ return new FormatCharacterIterator(sbuf.getBuffer().toString(),
+ sbuf.getRanges(),
+ sbuf.getAttributes());
+ }
+
+ public StringBuffer format (long number, StringBuffer dest,
+ FieldPosition fieldPos)
+ {
+ // If using exponential notation, we just format as a double.
+ if (useExponentialNotation)
+ return format ((double) number, dest, fieldPos);
+
+ boolean is_neg = number < 0;
+ if (is_neg)
+ {
+ if (negativePrefix != null)
+ dest.append(substituteCurrency(negativePrefix, number));
+ else
+ {
+ dest.append(symbols.getMinusSign());
+ dest.append(substituteCurrency(positivePrefix, number));
+ }
+ number = - number;
+ }
+ else
+ dest.append(substituteCurrency(positivePrefix, number));
+
+ int integerBeginIndex = dest.length();
+ int index = dest.length();
+ int count = 0;
+
+ /* Handle percentages, etc. */
+ number *= multiplier;
+ while (count < maximumIntegerDigits
+ && (number > 0 || count < minimumIntegerDigits))
+ {
+ long dig = number % 10;
+ number /= 10;
+ // NUMBER and DIG will be less than 0 if the original number
+ // was the most negative long.
+ if (dig < 0)
+ {
+ dig = - dig;
+ number = - number;
+ }
+
+ // Append group separator if required.
+ if (groupingUsed && count > 0 && groupingSize != 0 && count % groupingSize == 0)
+ dest.insert(index, symbols.getGroupingSeparator());
+
+ dest.insert(index, (char) (symbols.getZeroDigit() + dig));
+
+ ++count;
+ }
+
+ if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
+ {
+ fieldPos.setBeginIndex(integerBeginIndex);
+ fieldPos.setEndIndex(dest.length());
+ }
+
+ if (decimalSeparatorAlwaysShown || minimumFractionDigits > 0)
+ {
+ dest.append(symbols.getDecimalSeparator());
+ if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
+ {
+ fieldPos.setBeginIndex(dest.length());
+ fieldPos.setEndIndex(dest.length() + minimumFractionDigits);
+ }
+ }
+
+ for (count = 0; count < minimumFractionDigits; ++count)
+ dest.append(symbols.getZeroDigit());
+
+ dest.append((is_neg && negativeSuffix != null)
+ ? substituteCurrency(negativeSuffix, number)
+ : substituteCurrency(positiveSuffix, number));
+ return dest;
+ }
+
+ /**
+ * Returns the currency corresponding to the currency symbol stored
+ * in the instance of <code>DecimalFormatSymbols</code> used by this
+ * <code>DecimalFormat</code>.
+ *
+ * @return A new instance of <code>Currency</code> if
+ * the currency code matches a known one, null otherwise.
+ */
+ public Currency getCurrency()
+ {
+ return symbols.getCurrency();
+ }
+
+ /**
+ * Returns a copy of the symbols used by this instance.
+ *
+ * @return A copy of the symbols.
+ */
+ public DecimalFormatSymbols getDecimalFormatSymbols()
+ {
+ return (DecimalFormatSymbols) symbols.clone();
+ }
+
+ public int getGroupingSize ()
+ {
+ return groupingSize;
+ }
+
+ public int getMultiplier ()
+ {
+ return multiplier;
+ }
+
+ public String getNegativePrefix ()
+ {
+ return negativePrefix;
+ }
+
+ public String getNegativeSuffix ()
+ {
+ return negativeSuffix;
+ }
+
+ public String getPositivePrefix ()
+ {
+ return positivePrefix;
+ }
+
+ public String getPositiveSuffix ()
+ {
+ return positiveSuffix;
+ }
+
+ /**
+ * Returns a hash code for this object.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ return toPattern().hashCode();
+ }
+
+ public boolean isDecimalSeparatorAlwaysShown ()
+ {
+ return decimalSeparatorAlwaysShown;
+ }
+
+ public Number parse (String str, ParsePosition pos)
+ {
+ /*
+ * Our strategy is simple: copy the text into separate buffers: one for the int part,
+ * one for the fraction part and for the exponential part.
+ * We translate or omit locale-specific information.
+ * If exponential is sufficiently big we merge the fraction and int part and
+ * remove the '.' and then we use Long to convert the number. In the other
+ * case, we use Double to convert the full number.
+ */
+
+ boolean is_neg = false;
+ int index = pos.getIndex();
+ StringBuffer int_buf = new StringBuffer ();
+
+ // We have to check both prefixes, because one might be empty. We
+ // want to pick the longest prefix that matches.
+ boolean got_pos = str.startsWith(positivePrefix, index);
+ String np = (negativePrefix != null
+ ? negativePrefix
+ : positivePrefix + symbols.getMinusSign());
+ boolean got_neg = str.startsWith(np, index);
+
+ if (got_pos && got_neg)
+ {
+ // By checking this way, we preserve ambiguity in the case
+ // where the negative format differs only in suffix. We
+ // check this again later.
+ if (np.length() > positivePrefix.length())
+ {
+ is_neg = true;
+ index += np.length();
+ }
+ else
+ index += positivePrefix.length();
+ }
+ else if (got_neg)
+ {
+ is_neg = true;
+ index += np.length();
+ }
+ else if (got_pos)
+ index += positivePrefix.length();
+ else
+ {
+ pos.setErrorIndex (index);
+ return null;
+ }
+
+ // FIXME: handle Inf and NaN.
+
+ // FIXME: do we have to respect minimum digits?
+ // What about multiplier?
+
+ StringBuffer buf = int_buf;
+ StringBuffer frac_buf = null;
+ StringBuffer exp_buf = null;
+ int start_index = index;
+ int max = str.length();
+ int exp_index = -1;
+ int last = index + maximumIntegerDigits;
+
+ if (maximumFractionDigits > 0)
+ last += maximumFractionDigits + 1;
+
+ if (useExponentialNotation)
+ last += minExponentDigits + 1;
+
+ if (last > 0 && max > last)
+ max = last;
+
+ char zero = symbols.getZeroDigit();
+ int last_group = -1;
+ boolean int_part = true;
+ boolean exp_part = false;
+ for (; index < max; ++index)
+ {
+ char c = str.charAt(index);
+
+ // FIXME: what about grouping size?
+ if (groupingUsed && c == symbols.getGroupingSeparator())
+ {
+ if (last_group != -1
+ && groupingSize != 0
+ && (index - last_group) % groupingSize != 0)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ last_group = index+1;
+ }
+ else if (c >= zero && c <= zero + 9)
+ {
+ buf.append((char) (c - zero + '0'));
+ }
+ else if (parseIntegerOnly)
+ break;
+ else if (c == symbols.getDecimalSeparator())
+ {
+ if (last_group != -1
+ && groupingSize != 0
+ && (index - last_group) % groupingSize != 0)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ buf = frac_buf = new StringBuffer();
+ frac_buf.append('.');
+ int_part = false;
+ }
+ else if (c == symbols.getExponential())
+ {
+ buf = exp_buf = new StringBuffer();
+ int_part = false;
+ exp_part = true;
+ exp_index = index+1;
+ }
+ else if (exp_part
+ && (c == '+' || c == '-' || c == symbols.getMinusSign()))
+ {
+ // For exponential notation.
+ buf.append(c);
+ }
+ else
+ break;
+ }
+
+ if (index == start_index)
+ {
+ // Didn't see any digits.
+ pos.setErrorIndex(index);
+ return null;
+ }
+
+ // Check the suffix. We must do this before converting the
+ // buffer to a number to handle the case of a number which is
+ // the most negative Long.
+ boolean got_pos_suf = str.startsWith(positiveSuffix, index);
+ String ns = (negativePrefix == null ? positiveSuffix : negativeSuffix);
+ boolean got_neg_suf = str.startsWith(ns, index);
+ if (is_neg)
+ {
+ if (! got_neg_suf)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ }
+ else if (got_pos && got_neg && got_neg_suf)
+ {
+ is_neg = true;
+ }
+ else if (got_pos != got_pos_suf && got_neg != got_neg_suf)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ else if (! got_pos_suf)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+
+ String suffix = is_neg ? ns : positiveSuffix;
+ long parsedMultiplier = 1;
+ boolean use_long;
+
+ if (is_neg)
+ int_buf.insert(0, '-');
+
+ // Now handle the exponential part if there is one.
+ if (exp_buf != null)
+ {
+ int exponent_value;
+
+ try
+ {
+ exponent_value = Integer.parseInt(exp_buf.toString());
+ }
+ catch (NumberFormatException x1)
+ {
+ pos.setErrorIndex(exp_index);
+ return null;
+ }
+
+ if (frac_buf == null)
+ {
+ // We only have to add some zeros to the int part.
+ // Build a multiplier.
+ for (int i = 0; i < exponent_value; i++)
+ int_buf.append('0');
+
+ use_long = true;
+ }
+ else
+ {
+ boolean long_sufficient;
+
+ if (exponent_value < frac_buf.length()-1)
+ {
+ int lastNonNull = -1;
+ /* We have to check the fraction buffer: it may only be full of '0'
+ * or be sufficiently filled with it to convert the number into Long.
+ */
+ for (int i = 1; i < frac_buf.length(); i++)
+ if (frac_buf.charAt(i) != '0')
+ lastNonNull = i;
+
+ long_sufficient = (lastNonNull < 0 || lastNonNull <= exponent_value);
+ }
+ else
+ long_sufficient = true;
+
+ if (long_sufficient)
+ {
+ for (int i = 1; i < frac_buf.length() && i < exponent_value; i++)
+ int_buf.append(frac_buf.charAt(i));
+ for (int i = frac_buf.length()-1; i < exponent_value; i++)
+ int_buf.append('0');
+ use_long = true;
+ }
+ else
+ {
+ /*
+ * A long type is not sufficient, we build the full buffer to
+ * be parsed by Double.
+ */
+ int_buf.append(frac_buf);
+ int_buf.append('E');
+ int_buf.append(exp_buf);
+ use_long = false;
+ }
+ }
+ }
+ else
+ {
+ if (frac_buf != null)
+ {
+ /* Check whether the fraction buffer contains only '0' */
+ int i;
+ for (i = 1; i < frac_buf.length(); i++)
+ if (frac_buf.charAt(i) != '0')
+ break;
+
+ if (i != frac_buf.length())
+ {
+ use_long = false;
+ int_buf.append(frac_buf);
+ }
+ else
+ use_long = true;
+ }
+ else
+ use_long = true;
+ }
+
+ String t = int_buf.toString();
+ Number result = null;
+ if (use_long)
+ {
+ try
+ {
+ result = new Long (t);
+ }
+ catch (NumberFormatException x1)
+ {
+ }
+ }
+ else
+ {
+ try
+ {
+ result = new Double (t);
+ }
+ catch (NumberFormatException x2)
+ {
+ }
+ }
+ if (result == null)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+
+ pos.setIndex(index + suffix.length());
+
+ return result;
+ }
+
+ /**
+ * Sets the <code>Currency</code> on the
+ * <code>DecimalFormatSymbols</code> used, which also sets the
+ * currency symbols on those symbols.
+ */
+ public void setCurrency(Currency currency)
+ {
+ symbols.setCurrency(currency);
+ }
+
+ /**
+ * Sets the symbols used by this instance. This method makes a copy of
+ * the supplied symbols.
+ *
+ * @param newSymbols the symbols (<code>null</code> not permitted).
+ */
+ public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols)
+ {
+ symbols = (DecimalFormatSymbols) newSymbols.clone();
+ }
+
+ public void setDecimalSeparatorAlwaysShown (boolean newValue)
+ {
+ decimalSeparatorAlwaysShown = newValue;
+ }
+
+ public void setGroupingSize (int groupSize)
+ {
+ groupingSize = (byte) groupSize;
+ }
+
+ public void setMaximumFractionDigits (int newValue)
+ {
+ super.setMaximumFractionDigits(Math.min(newValue, 340));
+ }
+
+ public void setMaximumIntegerDigits (int newValue)
+ {
+ super.setMaximumIntegerDigits(Math.min(newValue, 309));
+ }
+
+ public void setMinimumFractionDigits (int newValue)
+ {
+ super.setMinimumFractionDigits(Math.min(newValue, 340));
+ }
+
+ public void setMinimumIntegerDigits (int newValue)
+ {
+ super.setMinimumIntegerDigits(Math.min(newValue, 309));
+ }
+
+ public void setMultiplier (int newValue)
+ {
+ multiplier = newValue;
+ }
+
+ public void setNegativePrefix (String newValue)
+ {
+ negativePrefix = newValue;
+ }
+
+ public void setNegativeSuffix (String newValue)
+ {
+ negativeSuffix = newValue;
+ }
+
+ public void setPositivePrefix (String newValue)
+ {
+ positivePrefix = newValue;
+ }
+
+ public void setPositiveSuffix (String newValue)
+ {
+ positiveSuffix = newValue;
+ }
+
+ private void quoteFix(StringBuffer buf, String text, String patChars)
+ {
+ int len = text.length();
+ for (int index = 0; index < len; ++index)
+ {
+ char c = text.charAt(index);
+ if (patChars.indexOf(c) != -1)
+ {
+ buf.append('\'');
+ buf.append(c);
+ buf.append('\'');
+ }
+ else
+ buf.append(c);
+ }
+ }
+
+ private String computePattern(DecimalFormatSymbols syms)
+ {
+ StringBuffer mainPattern = new StringBuffer ();
+ // We have to at least emit a zero for the minimum number of
+ // digits. Past that we need hash marks up to the grouping
+ // separator (and one beyond).
+ int total_digits = Math.max(minimumIntegerDigits,
+ groupingUsed ? groupingSize + 1: groupingSize);
+ for (int i = 0; i < total_digits - minimumIntegerDigits; ++i)
+ mainPattern.append(syms.getDigit());
+ for (int i = total_digits - minimumIntegerDigits; i < total_digits; ++i)
+ mainPattern.append(syms.getZeroDigit());
+ // Inserting the gropuing operator afterwards is easier.
+ if (groupingUsed)
+ mainPattern.insert(mainPattern.length() - groupingSize,
+ syms.getGroupingSeparator());
+ // See if we need decimal info.
+ if (minimumFractionDigits > 0 || maximumFractionDigits > 0
+ || decimalSeparatorAlwaysShown)
+ mainPattern.append(syms.getDecimalSeparator());
+ for (int i = 0; i < minimumFractionDigits; ++i)
+ mainPattern.append(syms.getZeroDigit());
+ for (int i = minimumFractionDigits; i < maximumFractionDigits; ++i)
+ mainPattern.append(syms.getDigit());
+ if (useExponentialNotation)
+ {
+ mainPattern.append(syms.getExponential());
+ for (int i = 0; i < minExponentDigits; ++i)
+ mainPattern.append(syms.getZeroDigit());
+ if (minExponentDigits == 0)
+ mainPattern.append(syms.getDigit());
+ }
+
+ String main = mainPattern.toString();
+ String patChars = patternChars (syms);
+ mainPattern.setLength(0);
+
+ quoteFix (mainPattern, positivePrefix, patChars);
+ mainPattern.append(main);
+ quoteFix (mainPattern, positiveSuffix, patChars);
+
+ if (negativePrefix != null)
+ {
+ quoteFix (mainPattern, negativePrefix, patChars);
+ mainPattern.append(main);
+ quoteFix (mainPattern, negativeSuffix, patChars);
+ }
+
+ return mainPattern.toString();
+ }
+
+ public String toLocalizedPattern ()
+ {
+ return computePattern (symbols);
+ }
+
+ public String toPattern ()
+ {
+ return computePattern (nonLocalizedSymbols);
+ }
+
+ private static final int MAXIMUM_INTEGER_DIGITS = 309;
+
+ // These names are fixed by the serialization spec.
+ private boolean decimalSeparatorAlwaysShown;
+ private byte groupingSize;
+ private byte minExponentDigits;
+ private int exponentRound;
+ private int multiplier;
+ private String negativePrefix;
+ private String negativeSuffix;
+ private String positivePrefix;
+ private String positiveSuffix;
+ private int[] negativePrefixRanges, positivePrefixRanges;
+ private HashMap[] negativePrefixAttrs, positivePrefixAttrs;
+ private int[] negativeSuffixRanges, positiveSuffixRanges;
+ private HashMap[] negativeSuffixAttrs, positiveSuffixAttrs;
+ private int serialVersionOnStream = 1;
+ private DecimalFormatSymbols symbols;
+ private boolean useExponentialNotation;
+ private static final long serialVersionUID = 864413376551465018L;
+
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException
+ {
+ stream.defaultReadObject();
+ if (serialVersionOnStream < 1)
+ {
+ useExponentialNotation = false;
+ serialVersionOnStream = 1;
+ }
+ }
+
+ // The locale-independent pattern symbols happen to be the same as
+ // the US symbols.
+ private static final DecimalFormatSymbols nonLocalizedSymbols
+ = new DecimalFormatSymbols (Locale.US);
+
+ /**
+ * <p>
+ * Substitutes the currency symbol into the given string,
+ * based on the value used. Currency symbols can either
+ * be a simple series of characters (e.g. '$'), which are
+ * simply used as is, or they can be of a more complex
+ * form:
+ * </p>
+ * <p>
+ * (lower bound)|(mid value)|(upper bound)
+ * </p>
+ * <p>
+ * where each bound has the syntax '(value)(# or <)(symbol)',
+ * to indicate the bounding value and the symbol used.
+ * </p>
+ * <p>
+ * The currency symbol replaces the currency specifier, '\u00a4',
+ * an unlocalised character, which thus is used as such in all formats.
+ * If this symbol occurs twice, the international currency code is used
+ * instead.
+ * </p>
+ *
+ * @param string The string containing the currency specifier, '\u00a4'.
+ * @param number the number being formatted.
+ * @return a string formatted for the correct currency.
+ */
+ private String substituteCurrency(String string, double number)
+ {
+ int index;
+ int length;
+ char currentChar;
+ StringBuffer buf;
+
+ index = 0;
+ length = string.length();
+ buf = new StringBuffer();
+
+ while (index < length)
+ {
+ currentChar = string.charAt(index);
+ if (string.charAt(index) == '\u00a4')
+ {
+ if ((index + 1) < length && string.charAt(index + 1) == '\u00a4')
+ {
+ buf.append(symbols.getInternationalCurrencySymbol());
+ index += 2;
+ }
+ else
+ {
+ String symbol;
+
+ symbol = symbols.getCurrencySymbol();
+ if (symbol.startsWith("="))
+ {
+ String[] bounds;
+ int[] boundValues;
+ String[] boundSymbols;
+
+ bounds = symbol.substring(1).split("\\|");
+ boundValues = new int[3];
+ boundSymbols = new String[3];
+ for (int a = 0; a < 3; ++a)
+ {
+ String[] bound;
+
+ bound = bounds[a].split("[#<]");
+ boundValues[a] = Integer.parseInt(bound[0]);
+ boundSymbols[a] = bound[1];
+ }
+ if (number <= boundValues[0])
+ {
+ buf.append(boundSymbols[0]);
+ }
+ else if (number >= boundValues[2])
+ {
+ buf.append(boundSymbols[2]);
+ }
+ else
+ {
+ buf.append(boundSymbols[1]);
+ }
+ ++index;
+ }
+ else
+ {
+ buf.append(symbol);
+ ++index;
+ }
+ }
+ }
+ else
+ {
+ buf.append(string.charAt(index));
+ ++index;
+ }
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/libjava/classpath/java/text/DecimalFormatSymbols.java b/libjava/classpath/java/text/DecimalFormatSymbols.java
new file mode 100644
index 00000000000..81ea0017822
--- /dev/null
+++ b/libjava/classpath/java/text/DecimalFormatSymbols.java
@@ -0,0 +1,688 @@
+/* DecimalFormatSymbols.java -- Format symbols used by DecimalFormat
+ Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * This class is a container for the symbols used by
+ * <code>DecimalFormat</code> to format numbers and currency
+ * for a particular locale. These are
+ * normally handled automatically, but an application can override
+ * values as desired using this class.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @date February 24, 1999
+ * @see java.text.DecimalFormat
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.2.
+ */
+public final class DecimalFormatSymbols implements Cloneable, Serializable
+{
+ public Object clone ()
+ {
+ try
+ {
+ return super.clone ();
+ }
+ catch(CloneNotSupportedException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * This method initializes a new instance of
+ * <code>DecimalFormatSymbols</code> for the default locale.
+ */
+ public DecimalFormatSymbols ()
+ {
+ this (Locale.getDefault());
+ }
+
+ /**
+ * Retrieves a valid string, either using the supplied resource
+ * bundle or the default value.
+ *
+ * @param bundle the resource bundle to use to find the string.
+ * @param name key for the string in the resource bundle.
+ * @param def default value for the string.
+ */
+ private String safeGetString(ResourceBundle bundle,
+ String name, String def)
+ {
+ if (bundle != null)
+ {
+ try
+ {
+ return bundle.getString(name);
+ }
+ catch (MissingResourceException x)
+ {
+ }
+ }
+ return def;
+ }
+
+ private char safeGetChar(ResourceBundle bundle,
+ String name, char def)
+ {
+ String r = null;
+ if (bundle != null)
+ {
+ try
+ {
+ r = bundle.getString(name);
+ }
+ catch (MissingResourceException x)
+ {
+ }
+ }
+ if (r == null || r.length() < 1)
+ return def;
+ return r.charAt(0);
+ }
+
+ /**
+ * This method initializes a new instance of
+ * <code>DecimalFormatSymbols</code> for the specified locale.
+ * <strong>Note</strong>: if the locale does not have an associated
+ * <code>Currency</code> instance, the currency symbol and
+ * international currency symbol will be set to the strings "?"
+ * and "XXX" respectively. This generally happens with language
+ * locales (those with no specified country), such as
+ * <code>Locale.ENGLISH</code>.
+ *
+ * @param locale The local to load symbols for.
+ * @throws NullPointerException if the locale is null.
+ */
+ public DecimalFormatSymbols (Locale loc)
+ {
+ ResourceBundle res;
+
+ currency = Currency.getInstance("XXX");
+ currencySymbol = "?";
+ intlCurrencySymbol = "XXX";
+ try
+ {
+ res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ loc, ClassLoader.getSystemClassLoader());
+ }
+ catch (MissingResourceException x)
+ {
+ res = null;
+ }
+ try
+ {
+ Currency localeCurrency = Currency.getInstance(loc);
+ if (localeCurrency != null)
+ {
+ setCurrency(localeCurrency);
+ }
+ }
+ catch(IllegalArgumentException exception)
+ {
+ /* Locale has an invalid currency */
+ }
+ decimalSeparator = safeGetChar (res, "decimalSeparator", '.');
+ digit = safeGetChar (res, "digit", '#');
+ exponential = safeGetChar (res, "exponential", 'E');
+ groupingSeparator = safeGetChar (res, "groupingSeparator", ',');
+ infinity = safeGetString (res, "infinity", "\u221e");
+ try
+ {
+ monetarySeparator = safeGetChar (res, "monetarySeparator", '.');
+ }
+ catch (MissingResourceException x)
+ {
+ monetarySeparator = decimalSeparator;
+ }
+ minusSign = safeGetChar (res, "minusSign", '-');
+ NaN = safeGetString (res, "NaN", "\ufffd");
+ patternSeparator = safeGetChar (res, "patternSeparator", ';');
+ percent = safeGetChar (res, "percent", '%');
+ perMill = safeGetChar (res, "perMill", '\u2030');
+ zeroDigit = safeGetChar (res, "zeroDigit", '0');
+ locale = loc;
+ }
+
+ /**
+ * This method this this object for equality against the specified object.
+ * This will be true if and only if the following criteria are met with
+ * regard to the specified object:
+ * <p>
+ * <ul>
+ * <li>It is not <code>null</code>.</li>
+ * <li>It is an instance of <code>DecimalFormatSymbols</code>.</li>
+ * <li>All of its symbols are identical to the symbols in this object.</li>
+ * </ul>
+ *
+ * @return <code>true</code> if the specified object is equal to this
+ * object, <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof DecimalFormatSymbols))
+ return false;
+ DecimalFormatSymbols dfs = (DecimalFormatSymbols) obj;
+ return (currencySymbol.equals(dfs.currencySymbol)
+ && decimalSeparator == dfs.decimalSeparator
+ && digit == dfs.digit
+ && exponential == dfs.exponential
+ && groupingSeparator == dfs.groupingSeparator
+ && infinity.equals(dfs.infinity)
+ && intlCurrencySymbol.equals(dfs.intlCurrencySymbol)
+ && minusSign == dfs.minusSign
+ && monetarySeparator == dfs.monetarySeparator
+ && NaN.equals(dfs.NaN)
+ && patternSeparator == dfs.patternSeparator
+ && percent == dfs.percent
+ && perMill == dfs.perMill
+ && zeroDigit == dfs.zeroDigit);
+ }
+
+ /**
+ * Returns the currency corresponding to the currency symbol stored
+ * in this instance of <code>DecimalFormatSymbols</code>.
+ *
+ * @return An instance of <code>Currency</code> which matches
+ * the currency used, or null if there is no corresponding
+ * instance.
+ */
+ public Currency getCurrency ()
+ {
+ return currency;
+ }
+
+ /**
+ * This method returns the currency symbol in local format. For example,
+ * "$" for Canadian dollars.
+ *
+ * @return The currency symbol in local format.
+ */
+ public String getCurrencySymbol ()
+ {
+ return currencySymbol;
+ }
+
+ /**
+ * This method returns the character used as the decimal point.
+ *
+ * @return The character used as the decimal point.
+ */
+ public char getDecimalSeparator ()
+ {
+ return decimalSeparator;
+ }
+
+ /**
+ * This method returns the character used to represent a digit in a
+ * format pattern string.
+ *
+ * @return The character used to represent a digit in a format
+ * pattern string.
+ */
+ public char getDigit ()
+ {
+ return digit;
+ }
+
+ /**
+ * This method returns the character used to represent the exponential
+ * format. This is a GNU Classpath extension.
+ *
+ * @return the character used to represent an exponential in a format
+ * pattern string.
+ */
+ char getExponential ()
+ {
+ return exponential;
+ }
+
+ /**
+ * This method sets the character used to separate groups of digits. For
+ * example, the United States uses a comma (,) to separate thousands in
+ * a number.
+ *
+ * @return The character used to separate groups of digits.
+ */
+ public char getGroupingSeparator ()
+ {
+ return groupingSeparator;
+ }
+
+ /**
+ * This method returns the character used to represent infinity.
+ *
+ * @return The character used to represent infinity.
+ */
+ public String getInfinity ()
+ {
+ return infinity;
+ }
+
+ /**
+ * This method returns the ISO 4217 currency code for
+ * the currency used.
+ *
+ * @return the ISO 4217 currency code.
+ */
+ public String getInternationalCurrencySymbol ()
+ {
+ return intlCurrencySymbol;
+ }
+
+ /**
+ * This method returns the character used to represent the minus sign.
+ *
+ * @return The character used to represent the minus sign.
+ */
+ public char getMinusSign ()
+ {
+ return minusSign;
+ }
+
+ /**
+ * This method returns the character used to represent the decimal
+ * point for currency values.
+ *
+ * @return The decimal point character used in currency values.
+ */
+ public char getMonetaryDecimalSeparator ()
+ {
+ return monetarySeparator;
+ }
+
+ /**
+ * This method returns the string used to represent the NaN (not a number)
+ * value.
+ *
+ * @return The string used to represent NaN
+ */
+ public String getNaN ()
+ {
+ return NaN;
+ }
+
+ /**
+ * This method returns the character used to separate positive and negative
+ * subpatterns in a format pattern.
+ *
+ * @return The character used to separate positive and negative subpatterns
+ * in a format pattern.
+ */
+ public char getPatternSeparator ()
+ {
+ return patternSeparator;
+ }
+
+ /**
+ * This method returns the character used as the percent sign.
+ *
+ * @return The character used as the percent sign.
+ */
+ public char getPercent ()
+ {
+ return percent;
+ }
+
+ /**
+ * This method returns the character used as the per mille character.
+ *
+ * @return The per mille character.
+ */
+ public char getPerMill ()
+ {
+ return perMill;
+ }
+
+ /**
+ * This method returns the character used to represent the digit zero.
+ *
+ * @return The character used to represent the digit zero.
+ */
+ public char getZeroDigit ()
+ {
+ return zeroDigit;
+ }
+
+ /**
+ * This method returns a hash value for this object.
+ *
+ * @return A hash value for this object.
+ */
+ public int hashCode ()
+ {
+ // Compute based on zero digit, grouping separator, and decimal
+ // separator -- JCL book. This probably isn't a very good hash
+ // code.
+ return zeroDigit << 16 + groupingSeparator << 8 + decimalSeparator;
+ }
+
+ /**
+ * This method sets the currency symbol and ISO 4217 currency
+ * code to the values obtained from the supplied currency.
+ *
+ * @param currency the currency from which to obtain the values.
+ * @throws NullPointerException if the currency is null.
+ */
+ public void setCurrency (Currency currency)
+ {
+ intlCurrencySymbol = currency.getCurrencyCode();
+ currencySymbol = currency.getSymbol();
+ this.currency = currency;
+ }
+
+ /**
+ * This method sets the currency symbol to the specified value.
+ *
+ * @param currencySymbol The new currency symbol
+ */
+ public void setCurrencySymbol (String currency)
+ {
+ currencySymbol = currency;
+ }
+
+ /**
+ * This method sets the decimal point character to the specified value.
+ *
+ * @param decimalSeparator The new decimal point character
+ */
+ public void setDecimalSeparator (char decimalSep)
+ {
+ decimalSeparator = decimalSep;
+ }
+
+ /**
+ * This method sets the character used to represents a digit in a format
+ * string to the specified value.
+ *
+ * @param digit The character used to represent a digit in a format pattern.
+ */
+ public void setDigit (char digit)
+ {
+ this.digit = digit;
+ }
+
+ /**
+ * This method sets the exponential character used in the format string to
+ * the specified value. This is a GNU Classpath extension.
+ *
+ * @param exp the character used for the exponential in a format pattern.
+ */
+ void setExponential (char exp)
+ {
+ exponential = exp;
+ }
+
+ /**
+ * This method sets the character used to separate groups of digits.
+ *
+ * @param groupingSeparator The character used to separate groups of digits.
+ */
+ public void setGroupingSeparator (char groupSep)
+ {
+ groupingSeparator = groupSep;
+ }
+
+ /**
+ * This method sets the string used to represents infinity.
+ *
+ * @param infinity The string used to represent infinity.
+ */
+ public void setInfinity (String infinity)
+ {
+ this.infinity = infinity;
+ }
+
+ /**
+ * This method sets the international currency symbol to the
+ * specified value. If a valid <code>Currency</code> instance
+ * exists for the international currency code, then this is
+ * used for the currency attribute, and the currency symbol
+ * is set to the corresponding value from this instance.
+ * Otherwise, the currency attribute is set to null and the
+ * symbol is left unmodified.
+ *
+ * @param currencyCode The new international currency symbol.
+ */
+ public void setInternationalCurrencySymbol (String currencyCode)
+ {
+ intlCurrencySymbol = currencyCode;
+ try
+ {
+ currency = Currency.getInstance(currencyCode);
+ }
+ catch (IllegalArgumentException exception)
+ {
+ currency = null;
+ }
+ if (currency != null)
+ {
+ setCurrencySymbol(currency.getSymbol(locale));
+ }
+ }
+
+ /**
+ * This method sets the character used to represent the minus sign.
+ *
+ * @param minusSign The character used to represent the minus sign.
+ */
+ public void setMinusSign (char minusSign)
+ {
+ this.minusSign = minusSign;
+ }
+
+ /**
+ * This method sets the character used for the decimal point in currency
+ * values.
+ *
+ * @param monetarySeparator The decimal point character used in
+ * currency values.
+ */
+ public void setMonetaryDecimalSeparator (char decimalSep)
+ {
+ monetarySeparator = decimalSep;
+ }
+
+ /**
+ * This method sets the string used to represent the NaN (not a
+ * number) value.
+ *
+ * @param NaN The string used to represent NaN
+ */
+ public void setNaN (String nan)
+ {
+ NaN = nan;
+ }
+
+ /**
+ * This method sets the character used to separate positive and negative
+ * subpatterns in a format pattern.
+ *
+ * @param patternSeparator The character used to separate positive and
+ * negative subpatterns in a format pattern.
+ */
+ public void setPatternSeparator (char patternSep)
+ {
+ patternSeparator = patternSep;
+ }
+
+ /**
+ * This method sets the character used as the percent sign.
+ *
+ * @param percent The character used as the percent sign.
+ */
+ public void setPercent (char percent)
+ {
+ this.percent = percent;
+ }
+
+ /**
+ * This method sets the character used as the per mille character.
+ *
+ * @param perMill The per mille character.
+ */
+ public void setPerMill (char perMill)
+ {
+ this.perMill = perMill;
+ }
+
+ /**
+ * This method sets the character used to represent the digit zero.
+ *
+ * @param zeroDigit The character used to represent the digit zero.
+ */
+ public void setZeroDigit (char zeroDigit)
+ {
+ this.zeroDigit = zeroDigit;
+ }
+
+ /**
+ * @serial A string used for the local currency
+ */
+ private String currencySymbol;
+ /**
+ * @serial The <code>char</code> used to separate decimals in a number.
+ */
+ private char decimalSeparator;
+ /**
+ * @serial This is the <code>char</code> used to represent a digit in
+ * a format specification.
+ */
+ private char digit;
+ /**
+ * @serial This is the <code>char</code> used to represent the exponent
+ * separator in exponential notation.
+ */
+ private char exponential;
+ /**
+ * @serial This separates groups of thousands in numbers.
+ */
+ private char groupingSeparator;
+ /**
+ * @serial This string represents infinity.
+ */
+ private String infinity;
+ /**
+ * @serial This string represents the local currency in an international
+ * context, eg, "C$" for Canadian dollars.
+ */
+ private String intlCurrencySymbol;
+ /**
+ * @serial This is the character used to represent the minus sign.
+ */
+ private char minusSign;
+ /**
+ * @serial This character is used to separate decimals when formatting
+ * currency values.
+ */
+ private char monetarySeparator;
+ /**
+ * @serial This string is used the represent the Java NaN value for
+ * "not a number".
+ */
+ private String NaN;
+ /**
+ * @serial This is the character used to separate positive and negative
+ * subpatterns in a format pattern.
+ */
+ private char patternSeparator;
+ /**
+ * @serial This is the percent symbols
+ */
+ private char percent;
+ /**
+ * @serial This character is used for the mille percent sign.
+ */
+ private char perMill;
+ /**
+ * @serial This value represents the type of object being de-serialized.
+ * 0 indicates a pre-Java 1.1.6 version, 1 indicates 1.1.6 or later.
+ * 0 indicates a pre-Java 1.1.6 version, 1 indicates 1.1.6 or later,
+ * 2 indicates 1.4 or later
+ */
+ private int serialVersionOnStream = 2;
+ /**
+ * @serial This is the character used to represent 0.
+ */
+ private char zeroDigit;
+
+ /**
+ * @serial The locale of these currency symbols.
+ */
+ private Locale locale;
+
+ /**
+ * The currency used for the symbols in this instance.
+ * This is stored temporarily for efficiency reasons,
+ * as well as to ensure that the correct instance
+ * is restored from the currency code.
+ *
+ * @serial Ignored.
+ */
+ private transient Currency currency;
+
+ private static final long serialVersionUID = 5772796243397350300L;
+
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException
+ {
+ stream.defaultReadObject();
+ if (serialVersionOnStream < 1)
+ {
+ monetarySeparator = decimalSeparator;
+ exponential = 'E';
+ }
+ if (serialVersionOnStream < 2)
+ locale = Locale.getDefault();
+
+ serialVersionOnStream = 2;
+ }
+}
diff --git a/libjava/classpath/java/text/FieldPosition.java b/libjava/classpath/java/text/FieldPosition.java
new file mode 100644
index 00000000000..427c07e8e11
--- /dev/null
+++ b/libjava/classpath/java/text/FieldPosition.java
@@ -0,0 +1,232 @@
+/* FieldPosition.java -- Keeps track of field positions while formatting
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+/**
+ * This class is used by the java.text formatting classes to track
+ * field positions. A field position is defined by an identifier value
+ * and begin and end index positions. The formatting classes in java.text
+ * typically define constant values for the field identifiers.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public class FieldPosition
+{
+ /**
+ * This is the field identifier value.
+ */
+ private int field_id;
+
+ /**
+ * This is the beginning index of the field.
+ */
+ private int begin;
+
+ /**
+ * This is the ending index of the field.
+ */
+ private int end;
+
+ /**
+ * This is the field attribute value.
+ */
+ private Format.Field field_attribute;
+
+ /**
+ * This method initializes a new instance of <code>FieldPosition</code>
+ * to have the specified field attribute. The attribute will be used as
+ * an id. It is formally equivalent to calling FieldPosition(field, -1).
+ *
+ * @param field The field format attribute.
+ */
+ public FieldPosition (Format.Field field)
+ {
+ this(field, -1);
+ }
+
+ /**
+ * This method initializes a new instance of <code>FieldPosition</code>
+ * to have the specified field attribute. The attribute will be used as
+ * an id is non null. The integer field id is only used if the Format.Field
+ * attribute is not used by the formatter.
+ *
+ * @param field The field format attribute.
+ * @param field_id The field identifier value.
+ */
+ public FieldPosition (Format.Field field, int field_id)
+ {
+ this.field_attribute = field;
+ this.field_id = field_id;
+ }
+
+ /**
+ * This method initializes a new instance of <code>FieldPosition</code> to
+ * have the specified field id.
+ *
+ * @param field_id The field identifier value.
+ */
+ public FieldPosition (int field_id)
+ {
+ this.field_id = field_id;
+ }
+
+ /**
+ * This method returns the field identifier value for this object.
+ *
+ * @return The field identifier.
+ */
+ public int getField ()
+ {
+ return field_id;
+ }
+
+ public Format.Field getFieldAttribute ()
+ {
+ return field_attribute;
+ }
+
+ /**
+ * This method returns the beginning index for this field.
+ *
+ * @return The beginning index.
+ */
+ public int getBeginIndex ()
+ {
+ return begin;
+ }
+
+ /**
+ * This method sets the beginning index of this field to the specified value.
+ *
+ * @param begin The new beginning index.
+ */
+ public void setBeginIndex (int begin)
+ {
+ this.begin = begin;
+ }
+
+ /**
+ * This method returns the ending index for the field.
+ *
+ * @return The ending index.
+ */
+ public int getEndIndex ()
+ {
+ return end;
+ }
+
+ /**
+ * This method sets the ending index of this field to the specified value.
+ *
+ * @param end The new ending index.
+ */
+ public void setEndIndex (int end)
+ {
+ this.end = end;
+ }
+
+ /**
+ * This method tests this object for equality against the specified object.
+ * The objects will be considered equal if and only if:
+ * <p>
+ * <ul>
+ * <li>The specified object is not <code>null</code>.
+ * <li>The specified object has the same class as this object.
+ * <li>The specified object has the same field identifier, field attribute
+ * and beginning and ending index as this object.
+ * </ul>
+ *
+ * @param obj The object to test for equality to this object.
+ *
+ * @return <code>true</code> if the specified object is equal to
+ * this object, <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (this == obj)
+ return true;
+
+ if (obj == null || obj.getClass() != this.getClass())
+ return false;
+
+ FieldPosition fp = (FieldPosition) obj;
+ return (field_id == fp.field_id
+ && (field_attribute == fp.field_attribute
+ || (field_attribute != null
+ && field_attribute.equals(fp.field_attribute)))
+ && begin == fp.begin
+ && end == fp.end);
+ }
+
+
+ /**
+ * This method returns a hash value for this object
+ *
+ * @return A hash value for this object.
+ */
+ public int hashCode ()
+ {
+ int hash = 5;
+
+ hash = 31 * hash + field_id;
+ hash = 31 * hash + begin;
+ hash = 31 * hash + end;
+ hash = 31 * hash +
+ (null == field_attribute ? 0 : field_attribute.hashCode());
+
+ return hash;
+ }
+
+ /**
+ * This method returns a <code>String</code> representation of this
+ * object.
+ *
+ * @return A <code>String</code> representation of this object.
+ */
+ public String toString ()
+ {
+ return (getClass ().getName ()
+ + "[field=" + getField ()
+ + ",attribute=" + getFieldAttribute ()
+ + ",beginIndex=" + getBeginIndex ()
+ + ",endIndex=" + getEndIndex ()
+ + "]");
+ }
+}
diff --git a/libjava/classpath/java/text/Format.java b/libjava/classpath/java/text/Format.java
new file mode 100644
index 00000000000..38fda34ff64
--- /dev/null
+++ b/libjava/classpath/java/text/Format.java
@@ -0,0 +1,181 @@
+/* Format.java -- Abstract superclass for formatting/parsing strings.
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import gnu.java.text.FormatCharacterIterator;
+
+import java.io.Serializable;
+
+/**
+ * This class is the abstract superclass of classes that format and parse
+ * data to/from <code>Strings</code>. It is guaranteed that any
+ * <code>String</code> produced by a concrete subclass of <code>Format</code>
+ * will be parseable by that same subclass.
+ * <p>
+ * In addition to implementing the abstract methods in this class, subclasses
+ * should provide static factory methods of the form
+ * <code>getInstance()</code> and <code>getInstance(Locale)</code> if the
+ * subclass loads different formatting/parsing schemes based on locale.
+ * These subclasses should also implement a static method called
+ * <code>getAvailableLocales()</code> which returns an array of
+ * available locales in the current runtime environment.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public abstract class Format implements Serializable, Cloneable
+{
+ /**
+ * For compatability with Sun's JDK 1.4.2 rev. 5
+ */
+ static final long serialVersionUID = -299282585814624189L;
+
+ public static class Field extends AttributedCharacterIterator.Attribute
+ {
+ static final long serialVersionUID = 276966692217360283L;
+
+ protected Field(String name)
+ {
+ super(name);
+ }
+ }
+
+ /**
+ * This method initializes a new instance of <code>Format</code>.
+ * It performs no actions, but acts as a default constructor for
+ * subclasses.
+ */
+ public Format ()
+ {
+ }
+
+ /**
+ * This method formats an <code>Object</code> into a <code>String</code>.
+ *
+ * @param obj The <code>Object</code> to format.
+ *
+ * @return The formatted <code>String</code>.
+ *
+ * @exception IllegalArgumentException If the <code>Object</code>
+ * cannot be formatted.
+ */
+ public final String format(Object obj) throws IllegalArgumentException
+ {
+ StringBuffer sb = new StringBuffer ();
+ format (obj, sb, new FieldPosition (0));
+ return sb.toString ();
+ }
+
+ /**
+ * This method formats an <code>Object</code> into a <code>String</code> and
+ * appends the <code>String</code> to a <code>StringBuffer</code>.
+ *
+ * @param obj The <code>Object</code> to format.
+ * @param sb The <code>StringBuffer</code> to append to.
+ * @param pos The desired <code>FieldPosition</code>, which is also
+ * updated by this call.
+ *
+ * @return The updated <code>StringBuffer</code>.
+ *
+ * @exception IllegalArgumentException If the <code>Object</code>
+ * cannot be formatted.
+ */
+ public abstract StringBuffer format (Object obj, StringBuffer sb,
+ FieldPosition pos)
+ throws IllegalArgumentException;
+
+ /**
+ * This method parses a <code>String</code> and converts the parsed
+ * contents into an <code>Object</code>.
+ *
+ * @param str The <code>String</code> to parse.
+ *
+ * @return The resulting <code>Object</code>.
+ *
+ * @exception ParseException If the <code>String</code> cannot be parsed.
+ */
+ public Object parseObject (String str) throws ParseException
+ {
+ ParsePosition pos = new ParsePosition(0);
+ Object result = parseObject (str, pos);
+ if (result == null)
+ {
+ int index = pos.getErrorIndex();
+ if (index < 0)
+ index = pos.getIndex();
+ throw new ParseException("parseObject failed", index);
+ }
+ return result;
+ }
+
+ /**
+ * This method parses a <code>String</code> and converts the parsed
+ * contents into an <code>Object</code>.
+ *
+ * @param str The <code>String</code> to parse.
+ * @param pos The starting parse index on input, the ending parse
+ * index on output.
+ *
+ * @return The parsed <code>Object</code>, or <code>null</code> in
+ * case of error.
+ */
+ public abstract Object parseObject (String str, ParsePosition pos);
+
+ public AttributedCharacterIterator formatToCharacterIterator(Object obj)
+ {
+ return new FormatCharacterIterator(format(obj), null, null);
+ }
+
+ /**
+ * Creates a copy of this object.
+ *
+ * @return The copied <code>Object</code>.
+ */
+ public Object clone ()
+ {
+ try
+ {
+ return super.clone ();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ return null;
+ }
+ }
+}
diff --git a/libjava/classpath/java/text/MessageFormat.java b/libjava/classpath/java/text/MessageFormat.java
new file mode 100644
index 00000000000..f7a9f1687a6
--- /dev/null
+++ b/libjava/classpath/java/text/MessageFormat.java
@@ -0,0 +1,832 @@
+/* MessageFormat.java - Localized message formatting.
+ Copyright (C) 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import gnu.java.text.FormatCharacterIterator;
+
+import java.io.InvalidObjectException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Vector;
+
+public class MessageFormat extends Format
+{
+ /**
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Jorge Aliss (jaliss@hotmail.com)
+ * @date March 3, 1999
+ */
+ /* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.2, except serialization.
+ * and parsing.
+ */
+ private static final class MessageFormatElement
+ {
+ // Argument number.
+ int argNumber;
+ // Formatter to be used. This is the format set by setFormat.
+ Format setFormat;
+ // Formatter to be used based on the type.
+ Format format;
+
+ // Argument will be checked to make sure it is an instance of this
+ // class.
+ Class formatClass;
+
+ // Formatter type.
+ String type;
+ // Formatter style.
+ String style;
+
+ // Text to follow this element.
+ String trailer;
+
+ // Recompute the locale-based formatter.
+ void setLocale (Locale loc)
+ {
+ if (type == null)
+ ;
+ else if (type.equals("number"))
+ {
+ formatClass = java.lang.Number.class;
+
+ if (style == null)
+ format = NumberFormat.getInstance(loc);
+ else if (style.equals("currency"))
+ format = NumberFormat.getCurrencyInstance(loc);
+ else if (style.equals("percent"))
+ format = NumberFormat.getPercentInstance(loc);
+ else if (style.equals("integer"))
+ {
+ NumberFormat nf = NumberFormat.getNumberInstance(loc);
+ nf.setMaximumFractionDigits(0);
+ nf.setGroupingUsed(false);
+ format = nf;
+ }
+ else
+ {
+ format = NumberFormat.getNumberInstance(loc);
+ DecimalFormat df = (DecimalFormat) format;
+ df.applyPattern(style);
+ }
+ }
+ else if (type.equals("time") || type.equals("date"))
+ {
+ formatClass = java.util.Date.class;
+
+ int val = DateFormat.DEFAULT;
+ boolean styleIsPattern = false;
+ if (style == null)
+ ;
+ else if (style.equals("short"))
+ val = DateFormat.SHORT;
+ else if (style.equals("medium"))
+ val = DateFormat.MEDIUM;
+ else if (style.equals("long"))
+ val = DateFormat.LONG;
+ else if (style.equals("full"))
+ val = DateFormat.FULL;
+ else
+ styleIsPattern = true;
+
+ if (type.equals("time"))
+ format = DateFormat.getTimeInstance(val, loc);
+ else
+ format = DateFormat.getDateInstance(val, loc);
+
+ if (styleIsPattern)
+ {
+ SimpleDateFormat sdf = (SimpleDateFormat) format;
+ sdf.applyPattern(style);
+ }
+ }
+ else if (type.equals("choice"))
+ {
+ formatClass = java.lang.Number.class;
+
+ if (style == null)
+ throw new
+ IllegalArgumentException ("style required for choice format");
+ format = new ChoiceFormat (style);
+ }
+ }
+ }
+
+ private static final long serialVersionUID = 6479157306784022952L;
+
+ public static class Field extends Format.Field
+ {
+ static final long serialVersionUID = 7899943957617360810L;
+
+ /**
+ * This is the attribute set for all characters produced
+ * by MessageFormat during a formatting.
+ */
+ public static final MessageFormat.Field ARGUMENT = new MessageFormat.Field("argument");
+
+ // For deserialization
+ private Field()
+ {
+ super("");
+ }
+
+ protected Field(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * invoked to resolve the true static constant by
+ * comparing the deserialized object to know name.
+ *
+ * @return object constant
+ */
+ protected Object readResolve() throws InvalidObjectException
+ {
+ if (getName().equals(ARGUMENT.getName()))
+ return ARGUMENT;
+
+ throw new InvalidObjectException("no such MessageFormat field called " + getName());
+ }
+
+ }
+
+ // Helper that returns the text up to the next format opener. The
+ // text is put into BUFFER. Returns index of character after end of
+ // string. Throws IllegalArgumentException on error.
+ private static int scanString(String pat, int index, StringBuffer buffer)
+ {
+ int max = pat.length();
+ buffer.setLength(0);
+ boolean quoted = false;
+ for (; index < max; ++index)
+ {
+ char c = pat.charAt(index);
+ if (quoted)
+ {
+ // In a quoted context, a single quote ends the quoting.
+ if (c == '\'')
+ quoted = false;
+ else
+ buffer.append(c);
+ }
+ // Check for '', which is a single quote.
+ else if (c == '\'' && index + 1 < max && pat.charAt(index + 1) == '\'')
+ {
+ buffer.append(c);
+ ++index;
+ }
+ else if (c == '\'')
+ {
+ // Start quoting.
+ quoted = true;
+ }
+ else if (c == '{')
+ break;
+ else
+ buffer.append(c);
+ }
+ // Note that we explicitly allow an unterminated quote. This is
+ // done for compatibility.
+ return index;
+ }
+
+ // This helper retrieves a single part of a format element. Returns
+ // the index of the terminating character.
+ private static int scanFormatElement(String pat, int index,
+ StringBuffer buffer, char term)
+ {
+ int max = pat.length();
+ buffer.setLength(0);
+ int brace_depth = 1;
+ boolean quoted = false;
+
+ for (; index < max; ++index)
+ {
+ char c = pat.charAt(index);
+ // First see if we should turn off quoting.
+ if (quoted)
+ {
+ if (c == '\'')
+ quoted = false;
+ // In both cases we fall through to inserting the
+ // character here.
+ }
+ // See if we have just a plain quote to insert.
+ else if (c == '\'' && index + 1 < max
+ && pat.charAt(index + 1) == '\'')
+ {
+ buffer.append(c);
+ ++index;
+ }
+ // See if quoting should turn on.
+ else if (c == '\'')
+ quoted = true;
+ else if (c == '{')
+ ++brace_depth;
+ else if (c == '}')
+ {
+ if (--brace_depth == 0)
+ break;
+ }
+ // Check for TERM after braces, because TERM might be `}'.
+ else if (c == term)
+ break;
+ // All characters, including opening and closing quotes, are
+ // inserted here.
+ buffer.append(c);
+ }
+ return index;
+ }
+
+ // This is used to parse a format element and whatever non-format
+ // text might trail it.
+ private static int scanFormat(String pat, int index, StringBuffer buffer,
+ Vector elts, Locale locale)
+ {
+ MessageFormatElement mfe = new MessageFormatElement ();
+ elts.addElement(mfe);
+
+ int max = pat.length();
+
+ // Skip the opening `{'.
+ ++index;
+
+ // Fetch the argument number.
+ index = scanFormatElement (pat, index, buffer, ',');
+ try
+ {
+ mfe.argNumber = Integer.parseInt(buffer.toString());
+ }
+ catch (NumberFormatException nfx)
+ {
+ IllegalArgumentException iae = new IllegalArgumentException(pat);
+ iae.initCause(nfx);
+ throw iae;
+ }
+
+ // Extract the element format.
+ if (index < max && pat.charAt(index) == ',')
+ {
+ index = scanFormatElement (pat, index + 1, buffer, ',');
+ mfe.type = buffer.toString();
+
+ // Extract the style.
+ if (index < max && pat.charAt(index) == ',')
+ {
+ index = scanFormatElement (pat, index + 1, buffer, '}');
+ mfe.style = buffer.toString ();
+ }
+ }
+
+ // Advance past the last terminator.
+ if (index >= max || pat.charAt(index) != '}')
+ throw new IllegalArgumentException("Missing '}' at end of message format");
+ ++index;
+
+ // Now fetch trailing string.
+ index = scanString (pat, index, buffer);
+ mfe.trailer = buffer.toString ();
+
+ mfe.setLocale(locale);
+
+ return index;
+ }
+
+ /**
+ * Applies the specified pattern to this MessageFormat.
+ *
+ * @param aPattern The Pattern
+ */
+ public void applyPattern (String newPattern)
+ {
+ pattern = newPattern;
+
+ StringBuffer tempBuffer = new StringBuffer ();
+
+ int index = scanString (newPattern, 0, tempBuffer);
+ leader = tempBuffer.toString();
+
+ Vector elts = new Vector ();
+ while (index < newPattern.length())
+ index = scanFormat (newPattern, index, tempBuffer, elts, locale);
+
+ elements = new MessageFormatElement[elts.size()];
+ elts.copyInto(elements);
+ }
+
+ /**
+ * Overrides Format.clone()
+ */
+ public Object clone ()
+ {
+ MessageFormat c = (MessageFormat) super.clone ();
+ c.elements = (MessageFormatElement[]) elements.clone ();
+ return c;
+ }
+
+ /**
+ * Overrides Format.equals(Object obj)
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof MessageFormat))
+ return false;
+ MessageFormat mf = (MessageFormat) obj;
+ return (pattern.equals(mf.pattern)
+ && locale.equals(mf.locale));
+ }
+
+ /**
+ * A convinience method to format patterns.
+ *
+ * @param aPattern The pattern used when formatting.
+ * @param arguments The array containing the objects to be formatted.
+ */
+ public AttributedCharacterIterator formatToCharacterIterator (Object arguments)
+ {
+ Object[] arguments_array = (Object[])arguments;
+ FormatCharacterIterator iterator = new FormatCharacterIterator();
+
+ formatInternal(arguments_array, new StringBuffer(), null, iterator);
+
+ return iterator;
+ }
+
+ /**
+ * A convinience method to format patterns.
+ *
+ * @param aPattern The pattern used when formatting.
+ * @param arguments The array containing the objects to be formatted.
+ */
+ public static String format (String pattern, Object arguments[])
+ {
+ MessageFormat mf = new MessageFormat (pattern);
+ StringBuffer sb = new StringBuffer ();
+ FieldPosition fp = new FieldPosition (NumberFormat.INTEGER_FIELD);
+ return mf.formatInternal(arguments, sb, fp, null).toString();
+ }
+
+ /**
+ * Returns the pattern with the formatted objects.
+ *
+ * @param source The array containing the objects to be formatted.
+ * @param result The StringBuffer where the text is appened.
+ * @param fp A FieldPosition object (it is ignored).
+ */
+ public final StringBuffer format (Object arguments[], StringBuffer appendBuf,
+ FieldPosition fp)
+ {
+ return formatInternal(arguments, appendBuf, fp, null);
+ }
+
+ private StringBuffer formatInternal (Object arguments[],
+ StringBuffer appendBuf,
+ FieldPosition fp,
+ FormatCharacterIterator output_iterator)
+ {
+ appendBuf.append(leader);
+ if (output_iterator != null)
+ output_iterator.append(leader);
+
+ for (int i = 0; i < elements.length; ++i)
+ {
+ Object thisArg = null;
+ boolean unavailable = false;
+ if (arguments == null || elements[i].argNumber >= arguments.length)
+ unavailable = true;
+ else
+ thisArg = arguments[elements[i].argNumber];
+
+ AttributedCharacterIterator iterator = null;
+
+ Format formatter = null;
+
+ if (fp != null && i == fp.getField() && fp.getFieldAttribute() == Field.ARGUMENT)
+ fp.setBeginIndex(appendBuf.length());
+
+ if (unavailable)
+ appendBuf.append("{" + elements[i].argNumber + "}");
+ else
+ {
+ if (elements[i].setFormat != null)
+ formatter = elements[i].setFormat;
+ else if (elements[i].format != null)
+ {
+ if (elements[i].formatClass != null
+ && ! elements[i].formatClass.isInstance(thisArg))
+ throw new IllegalArgumentException("Wrong format class");
+
+ formatter = elements[i].format;
+ }
+ else if (thisArg instanceof Number)
+ formatter = NumberFormat.getInstance(locale);
+ else if (thisArg instanceof Date)
+ formatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
+ else
+ appendBuf.append(thisArg);
+ }
+
+ if (fp != null && fp.getField() == i && fp.getFieldAttribute() == Field.ARGUMENT)
+ fp.setEndIndex(appendBuf.length());
+
+ if (formatter != null)
+ {
+ // Special-case ChoiceFormat.
+ if (formatter instanceof ChoiceFormat)
+ {
+ StringBuffer buf = new StringBuffer ();
+ formatter.format(thisArg, buf, fp);
+ MessageFormat mf = new MessageFormat ();
+ mf.setLocale(locale);
+ mf.applyPattern(buf.toString());
+ mf.format(arguments, appendBuf, fp);
+ }
+ else
+ {
+ if (output_iterator != null)
+ iterator = formatter.formatToCharacterIterator(thisArg);
+ else
+ formatter.format(thisArg, appendBuf, fp);
+ }
+
+ elements[i].format = formatter;
+ }
+
+ if (output_iterator != null)
+ {
+ HashMap hash_argument = new HashMap();
+ int position = output_iterator.getEndIndex();
+
+ hash_argument.put (MessageFormat.Field.ARGUMENT,
+ new Integer(elements[i].argNumber));
+
+
+ if (iterator != null)
+ {
+ output_iterator.append(iterator);
+ output_iterator.addAttributes(hash_argument, position,
+ output_iterator.getEndIndex());
+ }
+ else
+ output_iterator.append(thisArg.toString(), hash_argument);
+
+ output_iterator.append(elements[i].trailer);
+ }
+
+ appendBuf.append(elements[i].trailer);
+ }
+
+ return appendBuf;
+ }
+
+ /**
+ * Returns the pattern with the formatted objects. The first argument
+ * must be a array of Objects.
+ * This is equivalent to format((Object[]) objectArray, appendBuf, fpos)
+ *
+ * @param objectArray The object array to be formatted.
+ * @param appendBuf The StringBuffer where the text is appened.
+ * @param fpos A FieldPosition object (it is ignored).
+ */
+ public final StringBuffer format (Object objectArray, StringBuffer appendBuf,
+ FieldPosition fpos)
+ {
+ return format ((Object[])objectArray, appendBuf, fpos);
+ }
+
+ /**
+ * Returns an array with the Formats for
+ * the arguments.
+ */
+ public Format[] getFormats ()
+ {
+ Format[] f = new Format[elements.length];
+ for (int i = elements.length - 1; i >= 0; --i)
+ f[i] = elements[i].setFormat;
+ return f;
+ }
+
+ /**
+ * Returns the locale.
+ */
+ public Locale getLocale ()
+ {
+ return locale;
+ }
+
+ /**
+ * Overrides Format.hashCode()
+ */
+ public int hashCode ()
+ {
+ // FIXME: not a very good hash.
+ return pattern.hashCode() + locale.hashCode();
+ }
+
+ private MessageFormat ()
+ {
+ }
+
+ /**
+ * Creates a new MessageFormat object with
+ * the specified pattern
+ *
+ * @param pattern The Pattern
+ */
+ public MessageFormat(String pattern)
+ {
+ this(pattern, Locale.getDefault());
+ }
+
+ /**
+ * Creates a new MessageFormat object with
+ * the specified pattern
+ *
+ * @param pattern The Pattern
+ * @param locale The Locale to use
+ *
+ * @since 1.4
+ */
+ public MessageFormat(String pattern, Locale locale)
+ {
+ this.locale = locale;
+ applyPattern (pattern);
+ }
+
+ /**
+ * Parse a string <code>sourceStr</code> against the pattern specified
+ * to the MessageFormat constructor.
+ *
+ * @param sourceStr the string to be parsed.
+ * @param pos the current parse position (and eventually the error position).
+ * @return the array of parsed objects sorted according to their argument number
+ * in the pattern.
+ */
+ public Object[] parse (String sourceStr, ParsePosition pos)
+ {
+ // Check initial text.
+ int index = pos.getIndex();
+ if (! sourceStr.startsWith(leader, index))
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ index += leader.length();
+
+ Vector results = new Vector (elements.length, 1);
+ // Now check each format.
+ for (int i = 0; i < elements.length; ++i)
+ {
+ Format formatter = null;
+ if (elements[i].setFormat != null)
+ formatter = elements[i].setFormat;
+ else if (elements[i].format != null)
+ formatter = elements[i].format;
+
+ Object value = null;
+ if (formatter instanceof ChoiceFormat)
+ {
+ // We must special-case a ChoiceFormat because it might
+ // have recursive formatting.
+ ChoiceFormat cf = (ChoiceFormat) formatter;
+ String[] formats = (String[]) cf.getFormats();
+ double[] limits = (double[]) cf.getLimits();
+ MessageFormat subfmt = new MessageFormat ();
+ subfmt.setLocale(locale);
+ ParsePosition subpos = new ParsePosition (index);
+
+ int j;
+ for (j = 0; value == null && j < limits.length; ++j)
+ {
+ subfmt.applyPattern(formats[j]);
+ subpos.setIndex(index);
+ value = subfmt.parse(sourceStr, subpos);
+ }
+ if (value != null)
+ {
+ index = subpos.getIndex();
+ value = new Double (limits[j]);
+ }
+ }
+ else if (formatter != null)
+ {
+ pos.setIndex(index);
+ value = formatter.parseObject(sourceStr, pos);
+ if (value != null)
+ index = pos.getIndex();
+ }
+ else
+ {
+ // We have a String format. This can lose in a number
+ // of ways, but we give it a shot.
+ int next_index;
+ if (elements[i].trailer.length() > 0)
+ next_index = sourceStr.indexOf(elements[i].trailer, index);
+ else
+ next_index = sourceStr.length();
+ if (next_index == -1)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ value = sourceStr.substring(index, next_index);
+ index = next_index;
+ }
+
+ if (value == null
+ || ! sourceStr.startsWith(elements[i].trailer, index))
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+
+ if (elements[i].argNumber >= results.size())
+ results.setSize(elements[i].argNumber + 1);
+ results.setElementAt(value, elements[i].argNumber);
+
+ index += elements[i].trailer.length();
+ }
+
+ Object[] r = new Object[results.size()];
+ results.copyInto(r);
+ return r;
+ }
+
+ public Object[] parse (String sourceStr) throws ParseException
+ {
+ ParsePosition pp = new ParsePosition (0);
+ Object[] r = parse (sourceStr, pp);
+ if (r == null)
+ throw new ParseException ("couldn't parse string", pp.getErrorIndex());
+ return r;
+ }
+
+ public Object parseObject (String sourceStr, ParsePosition pos)
+ {
+ return parse (sourceStr, pos);
+ }
+
+ /**
+ * Sets the format for the argument at an specified
+ * index.
+ *
+ * @param index The index.
+ * @format The Format object.
+ */
+ public void setFormat (int variableNum, Format newFormat)
+ {
+ elements[variableNum].setFormat = newFormat;
+ }
+
+ /**
+ * Sets the formats for the arguments.
+ *
+ * @param formats An array of Format objects.
+ */
+ public void setFormats (Format[] newFormats)
+ {
+ if (newFormats.length < elements.length)
+ throw new IllegalArgumentException("Not enough format objects");
+
+ int len = Math.min(newFormats.length, elements.length);
+ for (int i = 0; i < len; ++i)
+ elements[i].setFormat = newFormats[i];
+ }
+
+ /**
+ * Sets the locale.
+ *
+ * @param locale A Locale
+ */
+ public void setLocale (Locale loc)
+ {
+ locale = loc;
+ if (elements != null)
+ {
+ for (int i = 0; i < elements.length; ++i)
+ elements[i].setLocale(loc);
+ }
+ }
+
+ /**
+ * Returns the pattern.
+ */
+ public String toPattern ()
+ {
+ return pattern;
+ }
+
+ /**
+ * Return the formatters used sorted by argument index. It uses the
+ * internal table to fill in this array: if a format has been
+ * set using <code>setFormat</code> or <code>setFormatByArgumentIndex</code>
+ * then it returns it at the right index. If not it uses the detected
+ * formatters during a <code>format</code> call. If nothing is known
+ * about that argument index it just puts null at that position.
+ * To get useful informations you may have to call <code>format</code>
+ * at least once.
+ *
+ * @return an array of formatters sorted by argument index.
+ */
+ public Format[] getFormatsByArgumentIndex()
+ {
+ int argNumMax = 0;
+ // First, find the greatest argument number.
+ for (int i=0;i<elements.length;i++)
+ if (elements[i].argNumber > argNumMax)
+ argNumMax = elements[i].argNumber;
+
+ Format[] formats = new Format[argNumMax];
+ for (int i=0;i<elements.length;i++)
+ {
+ if (elements[i].setFormat != null)
+ formats[elements[i].argNumber] = elements[i].setFormat;
+ else if (elements[i].format != null)
+ formats[elements[i].argNumber] = elements[i].format;
+ }
+ return formats;
+ }
+
+ /**
+ * Set the format to used using the argument index number.
+ *
+ * @param argumentIndex the argument index.
+ * @param newFormat the format to use for this argument.
+ */
+ public void setFormatByArgumentIndex(int argumentIndex,
+ Format newFormat)
+ {
+ for (int i=0;i<elements.length;i++)
+ {
+ if (elements[i].argNumber == argumentIndex)
+ elements[i].setFormat = newFormat;
+ }
+ }
+
+ /**
+ * Set the format for argument using a specified array of formatters
+ * which is sorted according to the argument index. If the number of
+ * elements in the array is fewer than the number of arguments only
+ * the arguments specified by the array are touched.
+ *
+ * @param newFormats array containing the new formats to set.
+ *
+ * @throws NullPointerException if newFormats is null
+ */
+ public void setFormatsByArgumentIndex(Format[] newFormats)
+ {
+ for (int i=0;i<newFormats.length;i++)
+ {
+ // Nothing better than that can exist here.
+ setFormatByArgumentIndex(i, newFormats[i]);
+ }
+ }
+
+ // The pattern string.
+ private String pattern;
+ // The locale.
+ private Locale locale;
+ // Variables.
+ private MessageFormatElement[] elements;
+ // Leader text.
+ private String leader;
+}
diff --git a/libjava/classpath/java/text/NumberFormat.java b/libjava/classpath/java/text/NumberFormat.java
new file mode 100644
index 00000000000..a2c3997cc52
--- /dev/null
+++ b/libjava/classpath/java/text/NumberFormat.java
@@ -0,0 +1,808 @@
+/* NumberFormat.java -- Formats and parses numbers
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * This is the abstract superclass of all classes which format and
+ * parse numeric values such as decimal numbers, integers, currency values,
+ * and percentages. These classes perform their parsing and formatting
+ * in a locale specific manner, accounting for such items as differing
+ * currency symbols and thousands separators.
+ * <p>
+ * To create an instance of a concrete subclass of <code>NumberFormat</code>,
+ * do not call a class constructor directly. Instead, use one of the
+ * static factory methods in this class such as
+ * <code>getCurrencyInstance</code>.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @date March 4, 1999
+ */
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct to 1.2, except getAvailableLocales.
+ */
+public abstract class NumberFormat extends Format implements Cloneable
+{
+ /**
+ * This is a constant used to create a <code>FieldPosition</code> object
+ * that will return the integer portion of a formatted number.
+ */
+ public static final int INTEGER_FIELD = 0;
+
+ /**
+ * This is a constant used to create a <code>FieldPosition</code> object
+ * that will return the fractional portion of a formatted number.
+ */
+ public static final int FRACTION_FIELD = 1;
+
+ public static class Field extends Format.Field
+ {
+ static final long serialVersionUID = 7494728892700160890L;
+
+ /**
+ * Attribute set to all characters containing digits of the integer
+ * part.
+ */
+ public static final NumberFormat.Field INTEGER
+ = new Field("integer");
+
+ /**
+ * Attribute set to all characters containing digits of the fractional
+ * part.
+ */
+ public static final NumberFormat.Field FRACTION
+ = new Field("fraction");
+
+ /**
+ * Attribute set to all characters containing digits of the exponential
+ * part.
+ */
+ public static final NumberFormat.Field EXPONENT
+ = new Field("exponent");
+
+ /**
+ * Attribute set to all characters containing a decimal separator.
+ */
+ public static final NumberFormat.Field DECIMAL_SEPARATOR
+ = new Field("decimal separator");
+
+ /**
+ * Attribute set to all characters containing a sign (plus or minus).
+ */
+ public static final NumberFormat.Field SIGN
+ = new Field("sign");
+
+ /**
+ * Attribute set to all characters containing a grouping separator (e.g.
+ * a comma, a white space,...).
+ */
+ public static final NumberFormat.Field GROUPING_SEPARATOR
+ = new Field("grouping separator");
+
+ /**
+ * Attribute set to all characters containing an exponential symbol (e.g.
+ * 'E')
+ */
+ public static final NumberFormat.Field EXPONENT_SYMBOL
+ = new Field("exponent symbol");
+
+ /**
+ * Attribute set to all characters containing a percent symbol (e.g. '%')
+ */
+ public static final NumberFormat.Field PERCENT
+ = new Field("percent");
+
+ /**
+ * Attribute set to all characters containing a permille symbol.
+ */
+ public static final NumberFormat.Field PERMILLE
+ = new Field("permille");
+
+ /**
+ * Attribute set to all characters containing the currency unit.
+ */
+ public static final NumberFormat.Field CURRENCY
+ = new Field("currency");
+
+ /**
+ * Attribute set to all characters containing the exponent sign.
+ */
+ public static final NumberFormat.Field EXPONENT_SIGN
+ = new Field("exponent sign");
+
+ /**
+ * Private fields to register all fields contained in this descriptor.
+ */
+ private static final NumberFormat.Field[] allFields =
+ {
+ INTEGER, FRACTION, EXPONENT, DECIMAL_SEPARATOR, SIGN,
+ GROUPING_SEPARATOR, EXPONENT_SYMBOL, PERCENT,
+ PERMILLE, CURRENCY, EXPONENT_SIGN
+ };
+
+ /**
+ * This constructor is only used by the deserializer. Without it,
+ * it would fail to construct a valid object.
+ */
+ private Field()
+ {
+ super("");
+ }
+
+ /**
+ * Create a Field instance with the specified field name.
+ *
+ * @param field_name Field name for the new Field instance.
+ */
+ protected Field(String field_name)
+ {
+ super (field_name);
+ }
+
+ /**
+ * This function is used by the deserializer to know which object
+ * to use when it encounters an encoded NumberFormat.Field in a
+ * serialization stream. If the stream is valid it should return
+ * one of the above field. In the other case we throw an exception.
+ *
+ * @return a valid official NumberFormat.Field instance.
+ *
+ * @throws InvalidObjectException if the field name is invalid.
+ */
+ protected Object readResolve() throws InvalidObjectException
+ {
+ String s = getName();
+ for (int i = 0; i < allFields.length; i++)
+ if (s.equals(allFields[i].getName()))
+ return allFields[i];
+
+ throw new InvalidObjectException("no such NumberFormat field called "
+ + s);
+ }
+ }
+
+ /**
+ * This method is a specialization of the format method that performs
+ * a simple formatting of the specified <code>long</code> number.
+ *
+ * @param number The <code>long</code> to format.
+ *
+ * @return The formatted number
+ */
+ public final String format (long number)
+ {
+ StringBuffer sbuf = new StringBuffer(50);
+ format (number, sbuf, null);
+ return sbuf.toString();
+ }
+
+ public final StringBuffer format (Object obj, StringBuffer sbuf,
+ FieldPosition pos)
+ {
+ if (obj instanceof Number)
+ return format(((Number) obj).doubleValue(), sbuf, pos);
+ else
+ throw new IllegalArgumentException
+ ("Cannot format given Object as a Number");
+ }
+
+ /**
+ * This method formats the specified <code>double</code> and appends it to
+ * a <code>StringBuffer</code>.
+ *
+ * @param number The <code>double</code> to format.
+ * @param sb The <code>StringBuffer</code> to append the formatted number to.
+ * @param pos The desired <code>FieldPosition</code>.
+ *
+ * @return The <code>StringBuffer</code> with the appended number.
+ */
+ public abstract StringBuffer format (double number,
+ StringBuffer sbuf, FieldPosition pos);
+
+ /**
+ * This method formats the specified <code>long</code> and appends it to
+ * a <code>StringBuffer</code>.
+ *
+ * @param number The <code>long</code> to format.
+ * @param sb The <code>StringBuffer</code> to append the formatted number to.
+ * @param pos The desired <code>FieldPosition</code>.
+ *
+ * @return The <code>StringBuffer</code> with the appended number.
+ */
+ public abstract StringBuffer format (long number,
+ StringBuffer sbuf, FieldPosition pos);
+
+ /**
+ * This method tests the specified object for equality against this object.
+ * This will be <code>true</code> if the following conditions are met:
+ * <p>
+ * <ul>
+ * <li>The specified object is not <code>null</code>.
+ * <li>The specified object is an instance of <code>NumberFormat</code>.
+ * </ul>
+ * <p>
+ * Since this method does not test much, it is highly advised that
+ * concrete subclasses override this method.
+ *
+ * @param obj The <code>Object</code> to test against equality with
+ * this object.
+ *
+ * @return <code>true</code> if the specified object is equal to
+ * this object, <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof NumberFormat))
+ return false;
+ NumberFormat nf = (NumberFormat) obj;
+ return (groupingUsed == nf.groupingUsed
+ && maximumFractionDigits == nf.maximumFractionDigits
+ && maximumIntegerDigits == nf.maximumIntegerDigits
+ && minimumFractionDigits == nf.minimumFractionDigits
+ && minimumIntegerDigits == nf.minimumIntegerDigits
+ && parseIntegerOnly == nf.parseIntegerOnly);
+ }
+
+ /**
+ * This method returns a list of locales for which concrete instances
+ * of <code>NumberFormat</code> subclasses may be created.
+ *
+ * @return The list of available locales.
+ */
+ public static Locale[] getAvailableLocales ()
+ {
+ Locale[] list = new Locale[1];
+ list[0] = Locale.US;
+ return list;
+ }
+
+ private static NumberFormat computeInstance(Locale loc, String resource,
+ String def)
+ {
+ ResourceBundle res;
+ try
+ {
+ res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ loc, ClassLoader.getSystemClassLoader());
+ }
+ catch (MissingResourceException x)
+ {
+ res = null;
+ }
+ String fmt;
+ try
+ {
+ fmt = res == null ? def : res.getString(resource);
+ }
+ catch (MissingResourceException x)
+ {
+ fmt = def;
+ }
+ DecimalFormatSymbols dfs = new DecimalFormatSymbols (loc);
+ return new DecimalFormat (fmt, dfs);
+ }
+
+ /**
+ * This method returns an instance of <code>NumberFormat</code> suitable
+ * for formatting and parsing currency values in the default locale.
+ *
+ * @return An instance of <code>NumberFormat</code> for handling currencies.
+ */
+ public static final NumberFormat getCurrencyInstance ()
+ {
+ return getCurrencyInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>NumberFormat</code> suitable
+ * for formatting and parsing currency values in the specified locale.
+ *
+ * @return An instance of <code>NumberFormat</code> for handling currencies.
+ */
+ public static NumberFormat getCurrencyInstance (Locale loc)
+ {
+ NumberFormat format;
+
+ format = computeInstance (loc, "currencyFormat", "$#,##0.00;($#,##0.00)");
+ format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());
+ return format;
+ }
+
+ /**
+ * This method returns a default instance for the default locale. This
+ * will be a concrete subclass of <code>NumberFormat</code>, but the
+ * actual class returned is dependent on the locale.
+ *
+ * @return An instance of the default <code>NumberFormat</code> class.
+ */
+ public static final NumberFormat getInstance ()
+ {
+ return getInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns a default instance for the specified locale. This
+ * will be a concrete subclass of <code>NumberFormat</code>, but the
+ * actual class returned is dependent on the locale.
+ *
+ * @param locale The desired locale.
+ *
+ * @return An instance of the default <code>NumberFormat</code> class.
+ */
+ public static NumberFormat getInstance (Locale loc)
+ {
+ // For now always return a number instance.
+ return getNumberInstance (loc);
+ }
+
+ /**
+ * This method returns the maximum number of digits allowed in the fraction
+ * portion of a number.
+ *
+ * @return The maximum number of digits allowed in the fraction
+ * portion of a number.
+ */
+ public int getMaximumFractionDigits ()
+ {
+ return maximumFractionDigits;
+ }
+
+ /**
+ * This method returns the maximum number of digits allowed in the integer
+ * portion of a number.
+ *
+ * @return The maximum number of digits allowed in the integer
+ * portion of a number.
+ */
+ public int getMaximumIntegerDigits ()
+ {
+ return maximumIntegerDigits;
+ }
+
+ /**
+ * This method returns the minimum number of digits allowed in the fraction
+ * portion of a number.
+ *
+ * @return The minimum number of digits allowed in the fraction
+ * portion of a number.
+ */
+ public int getMinimumFractionDigits ()
+ {
+ return minimumFractionDigits;
+ }
+
+ /**
+ * This method returns the minimum number of digits allowed in the integer
+ * portion of a number.
+ *
+ * @return The minimum number of digits allowed in the integer
+ * portion of a number.
+ */
+ public int getMinimumIntegerDigits ()
+ {
+ return minimumIntegerDigits;
+ }
+
+ /**
+ * This method returns a default instance for the specified locale. This
+ * will be a concrete subclass of <code>NumberFormat</code>, but the
+ * actual class returned is dependent on the locale.
+ *
+ * @param locale The desired locale.
+ *
+ * @return An instance of the default <code>NumberFormat</code> class.
+ */
+ public static final NumberFormat getNumberInstance ()
+ {
+ return getNumberInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns a general purpose number formatting and parsing
+ * class for the default locale. This will be a concrete subclass of
+ * <code>NumberFormat</code>, but the actual class returned is dependent
+ * on the locale.
+ *
+ * @return An instance of a generic number formatter for the default locale.
+ */
+ public static NumberFormat getNumberInstance (Locale loc)
+ {
+ return computeInstance (loc, "numberFormat", "#,##0.###");
+ }
+
+ /**
+ * This method returns an integer formatting and parsing class for the
+ * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
+ * but the actual class returned is dependent on the locale.
+ *
+ * @return An instance of an integer number formatter for the default locale.
+ * @since 1.4
+ */
+ public static final NumberFormat getIntegerInstance()
+ {
+ return getIntegerInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns an integer formatting and parsing class for the
+ * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
+ * but the actual class returned is dependent on the locale.
+ *
+ * @param locale the desired locale.
+ *
+ * @return An instance of an integer number formatter for the desired locale.
+ * @since 1.4
+ */
+ public static NumberFormat getIntegerInstance(Locale locale)
+ {
+ NumberFormat format = computeInstance (locale, "numberFormat", "#,##0");
+ format.setMaximumFractionDigits(0);
+ format.setParseIntegerOnly (true);
+ return format;
+ }
+
+ /**
+ * This method returns an instance of <code>NumberFormat</code> suitable
+ * for formatting and parsing percentage values in the default locale.
+ *
+ * @return An instance of <code>NumberFormat</code> for handling percentages.
+ */
+ public static final NumberFormat getPercentInstance ()
+ {
+ return getPercentInstance (Locale.getDefault());
+ }
+
+ /**
+ * This method returns an instance of <code>NumberFormat</code> suitable
+ * for formatting and parsing percentage values in the specified locale.
+ *
+ * @param locale The desired locale.
+ *
+ * @return An instance of <code>NumberFormat</code> for handling percentages.
+ */
+ public static NumberFormat getPercentInstance (Locale loc)
+ {
+ return computeInstance (loc, "percentFormat", "#,##0%");
+ }
+
+ /**
+ * This method returns a hash value for this object.
+ *
+ * @return The hash code.
+ */
+ public int hashCode ()
+ {
+ int hash = super.hashCode();
+ hash ^= (maximumFractionDigits + maximumIntegerDigits
+ + minimumFractionDigits + minimumIntegerDigits);
+ if (groupingUsed)
+ hash ^= 0xf0f0;
+ if (parseIntegerOnly)
+ hash ^= 0x0f0f;
+ return hash;
+ }
+
+ /**
+ * This method tests whether or not grouping is in use. Grouping is
+ * a method of marking separations in numbers, such as thousand separators
+ * in the US English locale. The grouping positions and symbols are all
+ * locale specific. As an example, with grouping disabled, the number one
+ * million would appear as "1000000". With grouping enabled, this number
+ * might appear as "1,000,000". (Both of these assume the US English
+ * locale).
+ *
+ * @return <code>true</code> if grouping is enabled,
+ * <code>false</code> otherwise.
+ */
+ public boolean isGroupingUsed ()
+ {
+ return groupingUsed;
+ }
+
+ /**
+ * This method tests whether or not only integer values should be parsed.
+ * If this class is parsing only integers, parsing stops at the decimal
+ * point.
+ *
+ * @return <code>true</code> if only integers are parsed,
+ * <code>false</code> otherwise.
+ */
+ public boolean isParseIntegerOnly ()
+ {
+ return parseIntegerOnly;
+ }
+
+ /**
+ * This is a default constructor for use by subclasses.
+ */
+ public NumberFormat ()
+ {
+ }
+
+ /**
+ * This method parses the specified string into a <code>Number</code>. This
+ * will be a <code>Long</code> if possible, otherwise it will be a
+ * <code>Double</code>. If no number can be parsed, no exception is
+ * thrown. Instead, the parse position remains at its initial index.
+ *
+ * @param str The string to parse.
+ * @param pp The desired <code>ParsePosition</code>.
+ *
+ * @return The parsed <code>Number</code>
+ */
+ public abstract Number parse (String sourceStr, ParsePosition pos);
+
+ /**
+ * This method parses the specified string into a <code>Number</code>. This
+ * will be a <code>Long</code> if possible, otherwise it will be a
+ * <code>Double</code>. If no number can be parsed, an exception will be
+ * thrown.
+ *
+ * @param str The string to parse.
+ *
+ * @return The parsed <code>Number</code>
+ *
+ * @exception ParseException If no number can be parsed.
+ */
+ public Number parse (String sourceStr) throws ParseException
+ {
+ ParsePosition pp = new ParsePosition (0);
+ Number r = parse (sourceStr, pp);
+ if (r == null)
+ {
+ int index = pp.getErrorIndex();
+ if (index < 0)
+ index = pp.getIndex();
+ throw new ParseException ("couldn't parse number", index);
+ }
+ return r;
+ }
+
+ /**
+ * This method parses the specified string into an <code>Object</code>. This
+ * will be a <code>Long</code> if possible, otherwise it will be a
+ * <code>Double</code>. If no number can be parsed, no exception is
+ * thrown. Instead, the parse position remains at its initial index.
+ *
+ * @param str The string to parse.
+ * @param pp The desired <code>ParsePosition</code>.
+ *
+ * @return The parsed <code>Object</code>
+ */
+ public final Object parseObject (String sourceStr, ParsePosition pos)
+ {
+ return parse (sourceStr, pos);
+ }
+
+ /**
+ * This method sets the grouping behavior of this formatter. Grouping is
+ * a method of marking separations in numbers, such as thousand separators
+ * in the US English locale. The grouping positions and symbols are all
+ * locale specific. As an example, with grouping disabled, the number one
+ * million would appear as "1000000". With grouping enabled, this number
+ * might appear as "1,000,000". (Both of these assume the US English
+ * locale).
+ *
+ * @param groupingUsed <code>true</code> to enable grouping,
+ * <code>false</code> to disable it.
+ */
+ public void setGroupingUsed (boolean newValue)
+ {
+ groupingUsed = newValue;
+ }
+
+ /**
+ * This method sets the maximum number of digits allowed in the fraction
+ * portion of a number to the specified value. If this is less than the
+ * current minimum allowed digits, the minimum allowed digits value will
+ * be lowered to be equal to the new maximum allowed digits value.
+ *
+ * @param maximumFractionDigits The new maximum fraction digits value.
+ */
+ public void setMaximumFractionDigits (int newValue)
+ {
+ maximumFractionDigits = newValue;
+ if (getMinimumFractionDigits () > maximumFractionDigits)
+ setMinimumFractionDigits (maximumFractionDigits);
+ }
+
+ /**
+ * This method sets the maximum number of digits allowed in the integer
+ * portion of a number to the specified value. If this is less than the
+ * current minimum allowed digits, the minimum allowed digits value will
+ * be lowered to be equal to the new maximum allowed digits value.
+ *
+ * @param maximumIntegerDigits The new maximum integer digits value.
+ */
+ public void setMaximumIntegerDigits (int newValue)
+ {
+ maximumIntegerDigits = newValue;
+ if (getMinimumIntegerDigits () > maximumIntegerDigits)
+ setMinimumIntegerDigits (maximumIntegerDigits);
+ }
+
+ /**
+ * This method sets the minimum number of digits allowed in the fraction
+ * portion of a number to the specified value. If this is greater than the
+ * current maximum allowed digits, the maximum allowed digits value will
+ * be raised to be equal to the new minimum allowed digits value.
+ *
+ * @param minimumFractionDigits The new minimum fraction digits value.
+ */
+ public void setMinimumFractionDigits (int newValue)
+ {
+ minimumFractionDigits = newValue;
+ if (getMaximumFractionDigits () < minimumFractionDigits)
+ setMaximumFractionDigits (minimumFractionDigits);
+ }
+
+ /**
+ * This method sets the minimum number of digits allowed in the integer
+ * portion of a number to the specified value. If this is greater than the
+ * current maximum allowed digits, the maximum allowed digits value will
+ * be raised to be equal to the new minimum allowed digits value.
+ *
+ * @param minimumIntegerDigits The new minimum integer digits value.
+ */
+ public void setMinimumIntegerDigits (int newValue)
+ {
+ minimumIntegerDigits = newValue;
+ if (getMaximumIntegerDigits () < minimumIntegerDigits)
+ setMaximumIntegerDigits (minimumIntegerDigits);
+ }
+
+ /**
+ * This method sets the parsing behavior of this object to parse only
+ * integers or not.
+ *
+ * @param parseIntegerOnly <code>true</code> to parse only integers,
+ * <code>false</code> otherwise.
+ */
+ public void setParseIntegerOnly (boolean value)
+ {
+ parseIntegerOnly = value;
+ }
+
+ /**
+ * This method is a specialization of the format method that performs
+ * a simple formatting of the specified <code>double</code> number.
+ *
+ * @param number The <code>double</code> to format.
+ *
+ * @return The formatted number
+ */
+ public final String format (double number)
+ {
+ StringBuffer sbuf = new StringBuffer(50);
+ format (number, sbuf, null);
+ return sbuf.toString();
+ }
+
+ // These field names are fixed by the serialization spec.
+ boolean groupingUsed;
+ int maximumFractionDigits;
+ private byte maxFractionDigits;
+ int maximumIntegerDigits;
+ private byte maxIntegerDigits;
+ int minimumFractionDigits;
+ private byte minFractionDigits;
+ int minimumIntegerDigits;
+ private byte minIntegerDigits;
+ boolean parseIntegerOnly;
+ private int serialVersionOnStream;
+ private static final long serialVersionUID = -2308460125733713944L;
+
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException
+ {
+ stream.defaultReadObject();
+ if (serialVersionOnStream < 1)
+ {
+ maximumFractionDigits = maxFractionDigits;
+ maximumIntegerDigits = maxIntegerDigits;
+ minimumFractionDigits = minFractionDigits;
+ minimumIntegerDigits = minIntegerDigits;
+ serialVersionOnStream = 1;
+ }
+ }
+
+ private void writeObject(ObjectOutputStream stream) throws IOException
+ {
+ maxFractionDigits = maximumFractionDigits < Byte.MAX_VALUE ?
+ (byte) maximumFractionDigits : Byte.MAX_VALUE;
+ maxIntegerDigits = maximumIntegerDigits < Byte.MAX_VALUE ?
+ (byte) maximumIntegerDigits : Byte.MAX_VALUE;
+ minFractionDigits = minimumFractionDigits < Byte.MAX_VALUE ?
+ (byte) minimumFractionDigits : Byte.MAX_VALUE;
+ minIntegerDigits = minimumIntegerDigits < Byte.MAX_VALUE ?
+ (byte) minimumIntegerDigits : Byte.MAX_VALUE;
+ serialVersionOnStream = 1;
+ stream.defaultWriteObject();
+ }
+
+ /**
+ * Returns the currency used by this number format when formatting currency
+ * values.
+ *
+ * The default implementation throws UnsupportedOperationException.
+ *
+ * @return The used currency object, or null.
+ *
+ * @throws UnsupportedOperationException If the number format class doesn't
+ * implement currency formatting.
+ *
+ * @since 1.4
+ */
+ public Currency getCurrency()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Sets the currency used by this number format when formatting currency
+ * values.
+ *
+ * The default implementation throws UnsupportedOperationException.
+ *
+ * @param currency The new currency to be used by this number format.
+ *
+ * @throws NullPointerException If currenc is null.
+ * @throws UnsupportedOperationException If the number format class doesn't
+ * implement currency formatting.
+ *
+ * @since 1.4
+ */
+ public void setCurrency(Currency currency)
+ {
+ if (currency == null)
+ throw new NullPointerException("currency may not be null");
+
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/libjava/classpath/java/text/ParseException.java b/libjava/classpath/java/text/ParseException.java
new file mode 100644
index 00000000000..6d014effd2a
--- /dev/null
+++ b/libjava/classpath/java/text/ParseException.java
@@ -0,0 +1,86 @@
+/* ParseException.java -- an error occurred while parsing
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+/**
+ * This exception is thrown when an unexpected error occurs during parsing.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ * @see Format
+ * @see FieldPosition
+ * @status updated to 1.4
+ */
+public class ParseException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 2703218443322787634L;
+
+ /**
+ * This is the position where the error was encountered.
+ *
+ * @serial the zero-based offset in the string where the error occurred
+ */
+ private final int errorOffset;
+
+ /**
+ * This method initializes a new instance of <code>ParseException</code>
+ * with a detailed error message and a error position.
+ *
+ * @param msg the descriptive message describing the error
+ * @param offset the position where the error was encountered
+ */
+ public ParseException(String s, int offset)
+ {
+ super(s);
+ errorOffset = offset;
+ }
+
+ /**
+ * This method returns the position where the error occurred.
+ *
+ * @return the position where the error occurred
+ */
+ public int getErrorOffset()
+ {
+ return errorOffset;
+ }
+} // class ParseException
diff --git a/libjava/classpath/java/text/ParsePosition.java b/libjava/classpath/java/text/ParsePosition.java
new file mode 100644
index 00000000000..782f5e0eda2
--- /dev/null
+++ b/libjava/classpath/java/text/ParsePosition.java
@@ -0,0 +1,151 @@
+/* ParsePosition.java -- Keep track of position while parsing.
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+/**
+ * This class is used to keep track of the current position during parsing
+ * operations.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Per Bothner (bothner@cygnus.com)
+ */
+public class ParsePosition
+{
+ /**
+ * This is the index of the current parse position.
+ */
+ private int index;
+
+ /**
+ * This is the index of the position where an error occurred during parsing.
+ */
+ private int error_index;
+
+ /**
+ * This method initializes a new instance of <code>ParsePosition</code> to
+ * have the specified initial index value.
+ *
+ * @param index The initial parsing index.
+ */
+ public ParsePosition (int index)
+ {
+ this.index = index;
+ error_index = -1;
+ }
+
+ /**
+ * This method returns the current parsing index.
+ *
+ * @return The current parsing index
+ */
+ public int getIndex ()
+ {
+ return index;
+ }
+
+ /**
+ * This method sets the current parsing index to the specified value.
+ *
+ * @param index The new parsing index.
+ */
+ public void setIndex (int index)
+ {
+ this.index = index;
+ }
+
+ /**
+ * This method returns the error index value. This value defaults to -1
+ * unless explicitly set to another value.
+ *
+ * @return The error index.
+ */
+ public int getErrorIndex ()
+ {
+ return error_index;
+ }
+
+ /**
+ * This method sets the error index to the specified value.
+ *
+ * @param error_index The new error index
+ */
+ public void setErrorIndex (int error_index)
+ {
+ this.error_index = error_index;
+ }
+
+ /**
+ * This method tests the specified object for equality with this
+ * object. The two objects will be considered equal if and only if
+ * all of the following conditions are met.
+ * <p>
+ * <ul>
+ * <li>The specified object is not <code>null</code>.</li>
+ * <li>The specified object is an instance of <code>ParsePosition</code>.</li>
+ * <li>The specified object has the same index and error index as
+ * this object.</li>
+ * </ul>
+ *
+ * @param obj The <code>Object</code> to test for equality against
+ * this object.
+ *
+ * @return <code>true</code> if the specified object is equal to
+ * this object, <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof ParsePosition))
+ return false;
+
+ ParsePosition other = (ParsePosition) obj;
+ return index == other.index && error_index == other.error_index;
+ }
+
+ /**
+ * This method returns a <code>String</code> representation of this
+ * object.
+ *
+ * @return A <code>String</code> that represents this object.
+ */
+ public String toString ()
+ {
+ return (getClass ().getName () + "[index=" + getIndex ()
+ + ",errorIndex=" + getErrorIndex () + "]");
+ }
+}
diff --git a/libjava/classpath/java/text/RuleBasedCollator.java b/libjava/classpath/java/text/RuleBasedCollator.java
new file mode 100644
index 00000000000..ae84a41032d
--- /dev/null
+++ b/libjava/classpath/java/text/RuleBasedCollator.java
@@ -0,0 +1,1017 @@
+/* RuleBasedCollator.java -- Concrete Collator Class
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/* Written using "Java Class Libraries", 2nd edition, plus online
+ * API docs for JDK 1.2 from http://www.javasoft.com.
+ * Status: Believed complete and correct
+ */
+
+/**
+ * This class is a concrete subclass of <code>Collator</code> suitable
+ * for string collation in a wide variety of languages. An instance of
+ * this class is normally returned by the <code>getInstance</code> method
+ * of <code>Collator</code> with rules predefined for the requested
+ * locale. However, an instance of this class can be created manually
+ * with any desired rules.
+ * <p>
+ * Rules take the form of a <code>String</code> with the following syntax
+ * <ul>
+ * <li> Modifier: '@'</li>
+ * <li> Relation: '&lt;' | ';' | ',' | '=' : &lt;text&gt;</li>
+ * <li> Reset: '&amp;' : &lt;text&gt;</li>
+ * </ul>
+ * The modifier character indicates that accents sort backward as is the
+ * case with French. The modifier applies to all rules <b>after</b>
+ * the modifier but before the next primary sequence. If placed at the end
+ * of the sequence if applies to all unknown accented character.
+ * The relational operators specify how the text
+ * argument relates to the previous term. The relation characters have
+ * the following meanings:
+ * <ul>
+ * <li>'&lt;' - The text argument is greater than the prior term at the primary
+ * difference level.</li>
+ * <li>';' - The text argument is greater than the prior term at the secondary
+ * difference level.</li>
+ * <li>',' - The text argument is greater than the prior term at the tertiary
+ * difference level.</li>
+ * <li>'=' - The text argument is equal to the prior term</li>
+ * </ul>
+ * <p>
+ * As for the text argument itself, this is any sequence of Unicode
+ * characters not in the following ranges: 0x0009-0x000D, 0x0020-0x002F,
+ * 0x003A-0x0040, 0x005B-0x0060, and 0x007B-0x007E. If these characters are
+ * desired, they must be enclosed in single quotes. If any whitespace is
+ * encountered, it is ignored. (For example, "a b" is equal to "ab").
+ * <p>
+ * The reset operation inserts the following rule at the point where the
+ * text argument to it exists in the previously declared rule string. This
+ * makes it easy to add new rules to an existing string by simply including
+ * them in a reset sequence at the end. Note that the text argument, or
+ * at least the first character of it, must be present somewhere in the
+ * previously declared rules in order to be inserted properly. If this
+ * is not satisfied, a <code>ParseException</code> will be thrown.
+ * <p>
+ * This system of configuring <code>RuleBasedCollator</code> is needlessly
+ * complex and the people at Taligent who developed it (along with the folks
+ * at Sun who accepted it into the Java standard library) deserve a slow
+ * and agonizing death.
+ * <p>
+ * Here are a couple of example of rule strings:
+ * <p>
+ * "&lt; a &lt; b &lt; c" - This string says that a is greater than b which is
+ * greater than c, with all differences being primary differences.
+ * <p>
+ * "&lt; a,A &lt; b,B &lt; c,C" - This string says that 'A' is greater than 'a' with
+ * a tertiary strength comparison. Both 'b' and 'B' are greater than 'a' and
+ * 'A' during a primary strength comparison. But 'B' is greater than 'b'
+ * under a tertiary strength comparison.
+ * <p>
+ * "&lt; a &lt; c &amp; a &lt; b " - This sequence is identical in function to the
+ * "&lt; a &lt; b &lt; c" rule string above. The '&amp;' reset symbol indicates that
+ * the rule "&lt; b" is to be inserted after the text argument "a" in the
+ * previous rule string segment.
+ * <p>
+ * "&lt; a &lt; b &amp; y &lt; z" - This is an error. The character 'y' does not appear
+ * anywhere in the previous rule string segment so the rule following the
+ * reset rule cannot be inserted.
+ * <p>
+ * "&lt; a &amp; A @ &lt; e &amp; E &lt; f&amp; F" - This sequence is equivalent to the following
+ * "&lt; a &amp; A &lt; E &amp; e &lt; f &amp; F".
+ * <p>
+ * For a description of the various comparison strength types, see the
+ * documentation for the <code>Collator</code> class.
+ * <p>
+ * As an additional complication to this already overly complex rule scheme,
+ * if any characters precede the first rule, these characters are considered
+ * ignorable. They will be treated as if they did not exist during
+ * comparisons. For example, "- &lt; a &lt; b ..." would make '-' an ignorable
+ * character such that the strings "high-tech" and "hightech" would
+ * be considered identical.
+ * <p>
+ * A <code>ParseException</code> will be thrown for any of the following
+ * conditions:
+ * <ul>
+ * <li>Unquoted punctuation characters in a text argument.</li>
+ * <li>A relational or reset operator not followed by a text argument</li>
+ * <li>A reset operator where the text argument is not present in
+ * the previous rule string section.</li>
+ * </ul>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ */
+public class RuleBasedCollator extends Collator
+{
+ /**
+ * This class describes what rank has a character (or a sequence of characters)
+ * in the lexicographic order. Each element in a rule has a collation element.
+ */
+ static final class CollationElement
+ {
+ String key;
+ int primary;
+ short secondary;
+ short tertiary;
+ short equality;
+ boolean ignore;
+ String expansion;
+
+ CollationElement(String key, int primary, short secondary, short tertiary,
+ short equality, String expansion, boolean ignore)
+ {
+ this.key = key;
+ this.primary = primary;
+ this.secondary = secondary;
+ this.tertiary = tertiary;
+ this.equality = equality;
+ this.ignore = ignore;
+ this.expansion = expansion;
+ }
+
+ int getValue()
+ {
+ return (primary << 16) + (secondary << 8) + tertiary;
+ }
+ }
+
+ /**
+ * Basic collation instruction (internal format) to build the series of
+ * collation elements. It contains an instruction which specifies the new
+ * state of the generator. The sequence of instruction should not contain
+ * RESET (it is used by
+ * {@link #mergeRules(int,java.lang.String,java.util.ArrayList,java.util.ArrayList)})
+ * as a temporary state while merging two sets of instructions.
+ */
+ static final class CollationSorter
+ {
+ static final int GREATERP = 0;
+ static final int GREATERS = 1;
+ static final int GREATERT = 2;
+ static final int EQUAL = 3;
+ static final int RESET = 4;
+ static final int INVERSE_SECONDARY = 5;
+
+ int comparisonType;
+ String textElement;
+ int hashText;
+ int offset;
+ boolean ignore;
+
+ String expansionOrdering;
+ }
+
+ /**
+ * This the the original rule string.
+ */
+ private String rules;
+
+ /**
+ * This is the table of collation element values
+ */
+ private Object[] ce_table;
+
+ /**
+ * Quick-prefix finder.
+ */
+ HashMap prefix_tree;
+
+ /**
+ * This is the value of the last sequence entered into
+ * <code>ce_table</code>. It is used to compute the
+ * ordering value of unspecified character.
+ */
+ private int last_primary_value;
+
+ /**
+ * This is the value of the last secondary sequence of the
+ * primary 0, entered into
+ * <code>ce_table</code>. It is used to compute the
+ * ordering value of an unspecified accented character.
+ */
+ private int last_tertiary_value;
+
+ /**
+ * This variable is true if accents need to be sorted
+ * in the other direction.
+ */
+ private boolean inverseAccentComparison;
+
+ /**
+ * This collation element is special to unknown sequence.
+ * The JDK uses it to mark and sort the characters which has
+ * no collation rules.
+ */
+ static final CollationElement SPECIAL_UNKNOWN_SEQ =
+ new CollationElement("", (short) 32767, (short) 0, (short) 0,
+ (short) 0, null, false);
+
+ /**
+ * This method initializes a new instance of <code>RuleBasedCollator</code>
+ * with the specified collation rules. Note that an application normally
+ * obtains an instance of <code>RuleBasedCollator</code> by calling the
+ * <code>getInstance</code> method of <code>Collator</code>. That method
+ * automatically loads the proper set of rules for the desired locale.
+ *
+ * @param rules The collation rule string.
+ *
+ * @exception ParseException If the rule string contains syntax errors.
+ */
+ public RuleBasedCollator(String rules) throws ParseException
+ {
+ if (rules.equals(""))
+ throw new ParseException("empty rule set", 0);
+
+ this.rules = rules;
+
+ buildCollationVector(parseString(rules));
+ buildPrefixAccess();
+ }
+
+ /**
+ * This method returns the number of common characters at the beginning
+ * of the string of the two parameters.
+ *
+ * @param prefix A string considered as a prefix to test against
+ * the other string.
+ * @param s A string to test the prefix against.
+ * @return The number of common characters.
+ */
+ static int findPrefixLength(String prefix, String s)
+ {
+ int index;
+ int len = prefix.length();
+
+ for (index = 0; index < len && index < s.length(); ++index)
+ {
+ if (prefix.charAt(index) != s.charAt(index))
+ return index;
+ }
+
+
+ return index;
+ }
+
+ /**
+ * Here we are merging two sets of sorting instructions: 'patch' into 'main'. This methods
+ * checks whether it is possible to find an anchor point for the rules to be merged and
+ * then insert them at that precise point.
+ *
+ * @param offset Offset in the string containing rules of the beginning of the rules
+ * being merged in.
+ * @param starter Text of the rules being merged.
+ * @param main Repository of all already parsed rules.
+ * @param patch Rules to be merged into the repository.
+ * @throws ParseException if it is impossible to find an anchor point for the new rules.
+ */
+ private void mergeRules(int offset, String starter, ArrayList main, ArrayList patch)
+ throws ParseException
+ {
+ int insertion_point = -1;
+ int max_length = 0;
+
+ /* We must check that no rules conflict with another already present. If it
+ * is the case delete the old rule.
+ */
+
+ /* For the moment good old O(N^2) algorithm.
+ */
+ for (int i = 0; i < patch.size(); i++)
+ {
+ int j = 0;
+
+ while (j < main.size())
+ {
+ CollationSorter rule1 = (CollationSorter) patch.get(i);
+ CollationSorter rule2 = (CollationSorter) main.get(j);
+
+ if (rule1.textElement.equals(rule2.textElement))
+ main.remove(j);
+ else
+ j++;
+ }
+ }
+
+ // Find the insertion point... O(N)
+ for (int i = 0; i < main.size(); i++)
+ {
+ CollationSorter sorter = (CollationSorter) main.get(i);
+ int length = findPrefixLength(starter, sorter.textElement);
+
+ if (length > max_length)
+ {
+ max_length = length;
+ insertion_point = i+1;
+ }
+ }
+
+ if (insertion_point < 0)
+ throw new ParseException("no insertion point found for " + starter, offset);
+
+ if (max_length < starter.length())
+ {
+ /*
+ * We need to expand the first entry. It must be sorted
+ * like if it was the reference key itself (like the spec
+ * said. So the first entry is special: the element is
+ * replaced by the specified text element for the sorting.
+ * This text replace the old one for comparisons. However
+ * to preserve the behaviour we replace the first key (corresponding
+ * to the found prefix) by a new code rightly ordered in the
+ * sequence. The rest of the subsequence must be appended
+ * to the end of the sequence.
+ */
+ CollationSorter sorter = (CollationSorter) patch.get(0);
+ CollationSorter expansionPrefix =
+ (CollationSorter) main.get(insertion_point-1);
+
+ sorter.expansionOrdering = starter.substring(max_length); // Skip the first good prefix element
+
+ main.add(insertion_point, sorter);
+
+ /*
+ * This is a new set of rules. Append to the list.
+ */
+ patch.remove(0);
+ insertion_point++;
+ }
+
+ // Now insert all elements of patch at the insertion point.
+ for (int i = 0; i < patch.size(); i++)
+ main.add(i+insertion_point, patch.get(i));
+ }
+
+ /**
+ * This method parses a string and build a set of sorting instructions. The parsing
+ * may only be partial on the case the rules are to be merged sometime later.
+ *
+ * @param stop_on_reset If this parameter is true then the parser stops when it
+ * encounters a reset instruction. In the other case, it tries to parse the subrules
+ * and merged it in the same repository.
+ * @param v Output vector for the set of instructions.
+ * @param base_offset Offset in the string to begin parsing.
+ * @param rules Rules to be parsed.
+ * @return -1 if the parser reached the end of the string, an integer representing the
+ * offset in the string at which it stopped parsing.
+ * @throws ParseException if something turned wrong during the parsing. To get details
+ * decode the message.
+ */
+ private int subParseString(boolean stop_on_reset, ArrayList v,
+ int base_offset, String rules)
+ throws ParseException
+ {
+ boolean ignoreChars = (base_offset == 0);
+ int operator = -1;
+ StringBuffer sb = new StringBuffer();
+ boolean doubleQuote = false;
+ boolean eatingChars = false;
+ boolean nextIsModifier = false;
+ boolean isModifier = false;
+ int i;
+
+main_parse_loop:
+ for (i = 0; i < rules.length(); i++)
+ {
+ char c = rules.charAt(i);
+ int type = -1;
+
+ if (!eatingChars &&
+ ((c >= 0x09 && c <= 0x0D) || (c == 0x20)))
+ continue;
+
+ isModifier = nextIsModifier;
+ nextIsModifier = false;
+
+ if (eatingChars && c != '\'')
+ {
+ doubleQuote = false;
+ sb.append(c);
+ continue;
+ }
+ if (doubleQuote && eatingChars)
+ {
+ sb.append(c);
+ doubleQuote = false;
+ continue;
+ }
+
+ switch (c)
+ {
+ case '!':
+ throw new ParseException
+ ("Modifier '!' is not yet supported by Classpath", i + base_offset);
+ case '<':
+ type = CollationSorter.GREATERP;
+ break;
+ case ';':
+ type = CollationSorter.GREATERS;
+ break;
+ case ',':
+ type = CollationSorter.GREATERT;
+ break;
+ case '=':
+ type = CollationSorter.EQUAL;
+ break;
+ case '\'':
+ eatingChars = !eatingChars;
+ doubleQuote = true;
+ break;
+ case '@':
+ if (ignoreChars)
+ throw new ParseException
+ ("comparison list has not yet been started. You may only use"
+ + "(<,;=&)", i + base_offset);
+ // Inverse the order of secondaries from now on.
+ nextIsModifier = true;
+ type = CollationSorter.INVERSE_SECONDARY;
+ break;
+ case '&':
+ type = CollationSorter.RESET;
+ if (stop_on_reset)
+ break main_parse_loop;
+ break;
+ default:
+ if (operator < 0)
+ throw new ParseException
+ ("operator missing at " + (i + base_offset), i + base_offset);
+ if (! eatingChars
+ && ((c >= 0x21 && c <= 0x2F)
+ || (c >= 0x3A && c <= 0x40)
+ || (c >= 0x5B && c <= 0x60)
+ || (c >= 0x7B && c <= 0x7E)))
+ throw new ParseException
+ ("unquoted punctuation character '" + c + "'", i + base_offset);
+
+ //type = ignoreChars ? CollationSorter.IGNORE : -1;
+ sb.append(c);
+ break;
+ }
+
+ if (type < 0)
+ continue;
+
+ if (operator < 0)
+ {
+ operator = type;
+ continue;
+ }
+
+ if (sb.length() == 0 && !isModifier)
+ throw new ParseException
+ ("text element empty at " + (i+base_offset), i+base_offset);
+
+ if (operator == CollationSorter.RESET)
+ {
+ /* Reposition in the sorting list at the position
+ * indicated by the text element.
+ */
+ String subrules = rules.substring(i);
+ ArrayList sorted_rules = new ArrayList();
+ int idx;
+
+ // Parse the subrules but do not iterate through all
+ // sublist. This is the priviledge of the first call.
+ idx = subParseString(true, sorted_rules, base_offset+i, subrules);
+
+ // Merge new parsed rules into the list.
+ mergeRules(base_offset+i, sb.toString(), v, sorted_rules);
+ sb.setLength(0);
+
+ // Reset state to none.
+ operator = -1;
+ type = -1;
+ // We have found a new subrule at 'idx' but it has not been parsed.
+ if (idx >= 0)
+ {
+ i += idx-1;
+ continue main_parse_loop;
+ }
+ else
+ // No more rules.
+ break main_parse_loop;
+ }
+
+ CollationSorter sorter = new CollationSorter();
+
+ if (operator == CollationSorter.GREATERP)
+ ignoreChars = false;
+
+ sorter.comparisonType = operator;
+ sorter.textElement = sb.toString();
+ sorter.hashText = sorter.textElement.hashCode();
+ sorter.offset = base_offset+rules.length();
+ sorter.ignore = ignoreChars;
+ sb.setLength(0);
+
+ v.add(sorter);
+ operator = type;
+ }
+
+ if (operator >= 0)
+ {
+ CollationSorter sorter = new CollationSorter();
+ int pos = rules.length() + base_offset;
+
+ if ((sb.length() != 0 && nextIsModifier)
+ || (sb.length() == 0 && !nextIsModifier && !eatingChars))
+ throw new ParseException("text element empty at " + pos, pos);
+
+ if (operator == CollationSorter.GREATERP)
+ ignoreChars = false;
+
+ sorter.comparisonType = operator;
+ sorter.textElement = sb.toString();
+ sorter.hashText = sorter.textElement.hashCode();
+ sorter.offset = base_offset+pos;
+ sorter.ignore = ignoreChars;
+ v.add(sorter);
+ }
+
+ if (i == rules.length())
+ return -1;
+ else
+ return i;
+ }
+
+ /**
+ * This method creates a copy of this object.
+ *
+ * @return A copy of this object.
+ */
+ public Object clone()
+ {
+ return super.clone();
+ }
+
+ /**
+ * This method completely parses a string 'rules' containing sorting rules.
+ *
+ * @param rules String containing the rules to be parsed.
+ * @return A set of sorting instructions stored in a Vector.
+ * @throws ParseException if something turned wrong during the parsing. To get details
+ * decode the message.
+ */
+ private ArrayList parseString(String rules)
+ throws ParseException
+ {
+ ArrayList v = new ArrayList();
+
+ // result of the first subParseString is not absolute (may be -1 or a
+ // positive integer). But we do not care.
+ subParseString(false, v, 0, rules);
+
+ return v;
+ }
+
+ /**
+ * This method uses the sorting instructions built by {@link #parseString}
+ * to build collation elements which can be directly used to sort strings.
+ *
+ * @param parsedElements Parsed instructions stored in a ArrayList.
+ * @throws ParseException if the order of the instructions are not valid.
+ */
+ private void buildCollationVector(ArrayList parsedElements)
+ throws ParseException
+ {
+ int primary_seq = 0;
+ int last_tertiary_seq = 0;
+ short secondary_seq = 0;
+ short tertiary_seq = 0;
+ short equality_seq = 0;
+ boolean inverseComparisons = false;
+ final boolean DECREASING = false;
+ final boolean INCREASING = true;
+ boolean secondaryType = INCREASING;
+ ArrayList v = new ArrayList();
+
+ // elts is completely sorted.
+element_loop:
+ for (int i = 0; i < parsedElements.size(); i++)
+ {
+ CollationSorter elt = (CollationSorter) parsedElements.get(i);
+ boolean ignoreChar = false;
+
+ switch (elt.comparisonType)
+ {
+ case CollationSorter.GREATERP:
+ primary_seq++;
+ if (inverseComparisons)
+ {
+ secondary_seq = Short.MAX_VALUE;
+ secondaryType = DECREASING;
+ }
+ else
+ {
+ secondary_seq = 0;
+ secondaryType = INCREASING;
+ }
+ tertiary_seq = 0;
+ equality_seq = 0;
+ inverseComparisons = false;
+ break;
+ case CollationSorter.GREATERS:
+ if (secondaryType == DECREASING)
+ secondary_seq--;
+ else
+ secondary_seq++;
+ tertiary_seq = 0;
+ equality_seq = 0;
+ break;
+ case CollationSorter.INVERSE_SECONDARY:
+ inverseComparisons = true;
+ continue element_loop;
+ case CollationSorter.GREATERT:
+ tertiary_seq++;
+ if (primary_seq == 0)
+ last_tertiary_seq = tertiary_seq;
+ equality_seq = 0;
+ break;
+ case CollationSorter.EQUAL:
+ equality_seq++;
+ break;
+ case CollationSorter.RESET:
+ throw new ParseException
+ ("Invalid reached state 'RESET'. Internal error", elt.offset);
+ default:
+ throw new ParseException
+ ("Invalid unknown state '" + elt.comparisonType + "'", elt.offset);
+ }
+
+ v.add(new CollationElement(elt.textElement, primary_seq,
+ secondary_seq, tertiary_seq,
+ equality_seq, elt.expansionOrdering, elt.ignore));
+ }
+
+ this.inverseAccentComparison = inverseComparisons;
+
+ ce_table = v.toArray();
+
+ last_primary_value = primary_seq+1;
+ last_tertiary_value = last_tertiary_seq+1;
+ }
+
+ /**
+ * Build a tree where all keys are the texts of collation elements and data is
+ * the collation element itself. The tree is used when extracting all prefix
+ * for a given text.
+ */
+ private void buildPrefixAccess()
+ {
+ prefix_tree = new HashMap();
+
+ for (int i = 0; i < ce_table.length; i++)
+ {
+ CollationElement e = (CollationElement) ce_table[i];
+
+ prefix_tree.put(e.key, e);
+ }
+ }
+
+ /**
+ * This method returns an integer which indicates whether the first
+ * specified <code>String</code> is less than, greater than, or equal to
+ * the second. The value depends not only on the collation rules in
+ * effect, but also the strength and decomposition settings of this object.
+ *
+ * @param source The first <code>String</code> to compare.
+ * @param target A second <code>String</code> to compare to the first.
+ *
+ * @return A negative integer if source &lt; target, a positive integer
+ * if source &gt; target, or 0 if source == target.
+ */
+ public int compare(String source, String target)
+ {
+ CollationElementIterator cs, ct;
+ CollationElement ord1block = null;
+ CollationElement ord2block = null;
+ boolean advance_block_1 = true;
+ boolean advance_block_2 = true;
+
+ cs = getCollationElementIterator(source);
+ ct = getCollationElementIterator(target);
+
+ for(;;)
+ {
+ int ord1;
+ int ord2;
+
+ /*
+ * We have to check whether the characters are ignorable.
+ * If it is the case then forget them.
+ */
+ if (advance_block_1)
+ {
+ ord1block = cs.nextBlock();
+ if (ord1block != null && ord1block.ignore)
+ continue;
+ }
+
+ if (advance_block_2)
+ {
+ ord2block = ct.nextBlock();
+ if (ord2block != null && ord2block.ignore)
+ {
+ advance_block_1 = false;
+ continue;
+ }
+ }
+ else
+ advance_block_2 = true;
+
+ if (!advance_block_1)
+ advance_block_1 = true;
+
+ if (ord1block != null)
+ ord1 = ord1block.getValue();
+ else
+ {
+ if (ord2block == null)
+ return 0;
+ return -1;
+ }
+
+ if (ord2block == null)
+ return 1;
+
+ ord2 = ord2block.getValue();
+
+ // We know chars are totally equal, so skip
+ if (ord1 == ord2)
+ {
+ if (getStrength() == IDENTICAL)
+ if (!ord1block.key.equals(ord2block.key))
+ return ord1block.key.compareTo(ord2block.key);
+ continue;
+ }
+
+ // Check for primary strength differences
+ int prim1 = CollationElementIterator.primaryOrder(ord1);
+ int prim2 = CollationElementIterator.primaryOrder(ord2);
+
+ if (prim1 == 0 && getStrength() < TERTIARY)
+ {
+ advance_block_2 = false;
+ continue;
+ }
+ else if (prim2 == 0 && getStrength() < TERTIARY)
+ {
+ advance_block_1 = false;
+ continue;
+ }
+
+ if (prim1 < prim2)
+ return -1;
+ else if (prim1 > prim2)
+ return 1;
+ else if (getStrength() == PRIMARY)
+ continue;
+
+ // Check for secondary strength differences
+ int sec1 = CollationElementIterator.secondaryOrder(ord1);
+ int sec2 = CollationElementIterator.secondaryOrder(ord2);
+
+ if (sec1 < sec2)
+ return -1;
+ else if (sec1 > sec2)
+ return 1;
+ else if (getStrength() == SECONDARY)
+ continue;
+
+ // Check for tertiary differences
+ int tert1 = CollationElementIterator.tertiaryOrder(ord1);
+ int tert2 = CollationElementIterator.tertiaryOrder(ord2);
+
+ if (tert1 < tert2)
+ return -1;
+ else if (tert1 > tert2)
+ return 1;
+ else if (getStrength() == TERTIARY)
+ continue;
+
+ // Apparently JDK does this (at least for my test case).
+ return ord1block.key.compareTo(ord2block.key);
+ }
+ }
+
+ /**
+ * This method tests this object for equality against the specified
+ * object. This will be true if and only if the specified object is
+ * another reference to this object.
+ *
+ * @param obj The <code>Object</code> to compare against this object.
+ *
+ * @return <code>true</code> if the specified object is equal to this object,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * This method builds a default collation element without invoking
+ * the database created from the rules passed to the constructor.
+ *
+ * @param c Character which needs a collation element.
+ * @return A valid brand new CollationElement instance.
+ */
+ CollationElement getDefaultElement(char c)
+ {
+ int v;
+
+ // Preliminary support for generic accent sorting inversion (I don't know if all
+ // characters in the range should be sorted backward). This is the place
+ // to fix this if needed.
+ if (inverseAccentComparison && (c >= 0x02B9 && c <= 0x0361))
+ v = 0x0361 - ((int) c - 0x02B9);
+ else
+ v = (short) c;
+ return new CollationElement("" + c, last_primary_value + v,
+ (short) 0, (short) 0, (short) 0, null, false);
+ }
+
+ /**
+ * This method builds a default collation element for an accented character
+ * without invoking the database created from the rules passed to the constructor.
+ *
+ * @param c Character which needs a collation element.
+ * @return A valid brand new CollationElement instance.
+ */
+ CollationElement getDefaultAccentedElement(char c)
+ {
+ int v;
+
+ // Preliminary support for generic accent sorting inversion (I don't know if all
+ // characters in the range should be sorted backward). This is the place
+ // to fix this if needed.
+ if (inverseAccentComparison && (c >= 0x02B9 && c <= 0x0361))
+ v = 0x0361 - ((int) c - 0x02B9);
+ else
+ v = (short) c;
+ return new CollationElement("" + c, (short) 0,
+ (short) 0, (short) (last_tertiary_value + v), (short) 0, null, false);
+ }
+
+ /**
+ * This method returns an instance for <code>CollationElementIterator</code>
+ * for the specified <code>String</code> under the collation rules for this
+ * object.
+ *
+ * @param source The <code>String</code> to return the
+ * <code>CollationElementIterator</code> instance for.
+ *
+ * @return A <code>CollationElementIterator</code> for the specified
+ * <code>String</code>.
+ */
+ public CollationElementIterator getCollationElementIterator(String source)
+ {
+ return new CollationElementIterator(this, source);
+ }
+
+ /**
+ * This method returns an instance of <code>CollationElementIterator</code>
+ * for the <code>String</code> represented by the specified
+ * <code>CharacterIterator</code>.
+ *
+ * @param source The <code>CharacterIterator</code> with the desired <code>String</code>.
+ *
+ * @return A <code>CollationElementIterator</code> for the specified <code>String</code>.
+ */
+ public CollationElementIterator getCollationElementIterator(CharacterIterator source)
+ {
+ StringBuffer expand = new StringBuffer("");
+
+ // Right now we assume that we will read from the beginning of the string.
+ for (char c = source.first();
+ c != CharacterIterator.DONE;
+ c = source.next())
+ decomposeCharacter(c, expand);
+
+ return getCollationElementIterator(expand.toString());
+ }
+
+ /**
+ * This method returns an instance of <code>CollationKey</code> for the
+ * specified <code>String</code>. The object returned will have a
+ * more efficient mechanism for its comparison function that could
+ * provide speed benefits if multiple comparisons are performed, such
+ * as during a sort.
+ *
+ * @param source The <code>String</code> to create a <code>CollationKey</code> for.
+ *
+ * @return A <code>CollationKey</code> for the specified <code>String</code>.
+ */
+ public CollationKey getCollationKey(String source)
+ {
+ CollationElementIterator cei = getCollationElementIterator(source);
+ ArrayList vect = new ArrayList();
+
+ int ord = cei.next();
+ cei.reset(); //set to start of string
+
+ while (ord != CollationElementIterator.NULLORDER)
+ {
+ // If the primary order is null, it means this is an ignorable
+ // character.
+ if (CollationElementIterator.primaryOrder(ord) == 0)
+ {
+ ord = cei.next();
+ continue;
+ }
+ switch (getStrength())
+ {
+ case PRIMARY:
+ ord = CollationElementIterator.primaryOrder(ord);
+ break;
+
+ case SECONDARY:
+ ord = CollationElementIterator.primaryOrder(ord) << 8;
+ ord |= CollationElementIterator.secondaryOrder(ord);
+
+ default:
+ break;
+ }
+
+ vect.add(new Integer(ord));
+ ord = cei.next(); //increment to next key
+ }
+
+ Object[] objarr = vect.toArray();
+ byte[] key = new byte[objarr.length * 4];
+
+ for (int i = 0; i < objarr.length; i++)
+ {
+ int j = ((Integer) objarr[i]).intValue();
+ key [i * 4] = (byte) ((j & 0xFF000000) >> 24);
+ key [i * 4 + 1] = (byte) ((j & 0x00FF0000) >> 16);
+ key [i * 4 + 2] = (byte) ((j & 0x0000FF00) >> 8);
+ key [i * 4 + 3] = (byte) (j & 0x000000FF);
+ }
+
+ return new CollationKey(this, source, key);
+ }
+
+ /**
+ * This method returns a <code>String</code> containing the collation rules
+ * for this object.
+ *
+ * @return The collation rules for this object.
+ */
+ public String getRules()
+ {
+ return rules;
+ }
+
+ /**
+ * This method returns a hash value for this object.
+ *
+ * @return A hash value for this object.
+ */
+ public int hashCode()
+ {
+ return System.identityHashCode(this);
+ }
+}
diff --git a/libjava/classpath/java/text/SimpleDateFormat.java b/libjava/classpath/java/text/SimpleDateFormat.java
new file mode 100644
index 00000000000..789cb83d86d
--- /dev/null
+++ b/libjava/classpath/java/text/SimpleDateFormat.java
@@ -0,0 +1,1257 @@
+/* SimpleDateFormat.java -- A class for parsing/formating simple
+ date constructs
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+import gnu.java.text.AttributedFormatBuffer;
+import gnu.java.text.FormatBuffer;
+import gnu.java.text.FormatCharacterIterator;
+import gnu.java.text.StringFormatBuffer;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * SimpleDateFormat provides convenient methods for parsing and formatting
+ * dates using Gregorian calendars (see java.util.GregorianCalendar).
+ */
+public class SimpleDateFormat extends DateFormat
+{
+ /**
+ * This class is used by <code>SimpleDateFormat</code> as a
+ * compiled representation of a format string. The field
+ * ID, size, and character used are stored for each sequence
+ * of pattern characters.
+ */
+ private class CompiledField
+ {
+ /**
+ * The ID of the field within the local pattern characters.
+ * Package private for use in out class.
+ */
+ int field;
+
+ /**
+ * The size of the character sequence.
+ * Package private for use in out class.
+ */
+ int size;
+
+ /**
+ * The character used.
+ */
+ private char character;
+
+ /**
+ * Constructs a compiled field using the
+ * the given field ID, size and character
+ * values.
+ *
+ * @param f the field ID.
+ * @param s the size of the field.
+ * @param c the character used.
+ */
+ public CompiledField(int f, int s, char c)
+ {
+ field = f;
+ size = s;
+ character = c;
+ }
+
+ /**
+ * Retrieves the ID of the field relative to
+ * the local pattern characters.
+ */
+ public int getField()
+ {
+ return field;
+ }
+
+ /**
+ * Retrieves the size of the character sequence.
+ */
+ public int getSize()
+ {
+ return size;
+ }
+
+ /**
+ * Retrieves the character used in the sequence.
+ */
+ public char getCharacter()
+ {
+ return character;
+ }
+
+ /**
+ * Returns a <code>String</code> representation
+ * of the compiled field, primarily for debugging
+ * purposes.
+ *
+ * @return a <code>String</code> representation.
+ */
+ public String toString()
+ {
+ StringBuffer builder;
+
+ builder = new StringBuffer(getClass().getName());
+ builder.append("[field=");
+ builder.append(field);
+ builder.append(", size=");
+ builder.append(size);
+ builder.append(", character=");
+ builder.append(character);
+ builder.append("]");
+
+ return builder.toString();
+ }
+ }
+
+ /**
+ * A list of <code>CompiledField</code>s,
+ * representing the compiled version of the pattern.
+ *
+ * @see CompiledField
+ * @serial Ignored.
+ */
+ private transient ArrayList tokens;
+
+ /**
+ * The localised data used in formatting,
+ * such as the day and month names in the local
+ * language, and the localized pattern characters.
+ *
+ * @see DateFormatSymbols
+ * @serial The localisation data. May not be null.
+ */
+ private DateFormatSymbols formatData;
+
+ /**
+ * The date representing the start of the century
+ * used for interpreting two digit years. For
+ * example, 24/10/2004 would cause two digit
+ * years to be interpreted as representing
+ * the years between 2004 and 2104.
+ *
+ * @see get2DigitYearStart()
+ * @see set2DigitYearStart(java.util.Date)
+ * @see Date
+ * @serial The start date of the century for parsing two digit years.
+ * May not be null.
+ */
+ private Date defaultCenturyStart;
+
+ /**
+ * The year at which interpretation of two
+ * digit years starts.
+ *
+ * @see get2DigitYearStart()
+ * @see set2DigitYearStart(java.util.Date)
+ * @serial Ignored.
+ */
+ private transient int defaultCentury;
+
+ /**
+ * The non-localized pattern string. This
+ * only ever contains the pattern characters
+ * stored in standardChars. Localized patterns
+ * are translated to this form.
+ *
+ * @see applyPattern(String)
+ * @see applyLocalizedPattern(String)
+ * @see toPattern()
+ * @see toLocalizedPattern()
+ * @serial The non-localized pattern string. May not be null.
+ */
+ private String pattern;
+
+ /**
+ * The version of serialized data used by this class.
+ * Version 0 only includes the pattern and formatting
+ * data. Version 1 adds the start date for interpreting
+ * two digit years.
+ *
+ * @serial This specifies the version of the data being serialized.
+ * Version 0 (or no version) specifies just <code>pattern</code>
+ * and <code>formatData</code>. Version 1 adds
+ * the <code>defaultCenturyStart</code>. This implementation
+ * always writes out version 1 data.
+ */
+ private int serialVersionOnStream = 1; // 0 indicates JDK1.1.3 or earlier
+
+ /**
+ * For compatability.
+ */
+ private static final long serialVersionUID = 4774881970558875024L;
+
+ // This string is specified in the root of the CLDR. We set it here
+ // rather than doing a DateFormatSymbols(Locale.US).getLocalPatternChars()
+ // since someone could theoretically change those values (though unlikely).
+ private static final String standardChars = "GyMdkHmsSEDFwWahKzYeugAZ";
+
+ /**
+ * Reads the serialized version of this object.
+ * If the serialized data is only version 0,
+ * then the date for the start of the century
+ * for interpreting two digit years is computed.
+ * The pattern is parsed and compiled following the process
+ * of reading in the serialized data.
+ *
+ * @param stream the object stream to read the data from.
+ * @throws IOException if an I/O error occurs.
+ * @throws ClassNotFoundException if the class of the serialized data
+ * could not be found.
+ * @throws InvalidObjectException if the pattern is invalid.
+ */
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException
+ {
+ stream.defaultReadObject();
+ if (serialVersionOnStream < 1)
+ {
+ computeCenturyStart ();
+ serialVersionOnStream = 1;
+ }
+ else
+ // Ensure that defaultCentury gets set.
+ set2DigitYearStart(defaultCenturyStart);
+
+ // Set up items normally taken care of by the constructor.
+ tokens = new ArrayList();
+ try
+ {
+ compileFormat(pattern);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new InvalidObjectException("The stream pattern was invalid.");
+ }
+ }
+
+ /**
+ * Compiles the supplied non-localized pattern into a form
+ * from which formatting and parsing can be performed.
+ * This also detects errors in the pattern, which will
+ * be raised on later use of the compiled data.
+ *
+ * @param pattern the non-localized pattern to compile.
+ * @throws IllegalArgumentException if the pattern is invalid.
+ */
+ private void compileFormat(String pattern)
+ {
+ // Any alphabetical characters are treated as pattern characters
+ // unless enclosed in single quotes.
+
+ char thisChar;
+ int pos;
+ int field;
+ CompiledField current = null;
+
+ for (int i=0; i<pattern.length(); i++) {
+ thisChar = pattern.charAt(i);
+ field = standardChars.indexOf(thisChar);
+ if (field == -1) {
+ current = null;
+ if ((thisChar >= 'A' && thisChar <= 'Z')
+ || (thisChar >= 'a' && thisChar <= 'z')) {
+ // Not a valid letter
+ throw new IllegalArgumentException("Invalid letter " + thisChar +
+ "encountered at character " + i
+ + ".");
+ } else if (thisChar == '\'') {
+ // Quoted text section; skip to next single quote
+ pos = pattern.indexOf('\'',i+1);
+ if (pos == -1) {
+ throw new IllegalArgumentException("Quotes starting at character "
+ + i + " not closed.");
+ }
+ if ((pos+1 < pattern.length()) && (pattern.charAt(pos+1) == '\'')) {
+ tokens.add(pattern.substring(i+1,pos+1));
+ } else {
+ tokens.add(pattern.substring(i+1,pos));
+ }
+ i = pos;
+ } else {
+ // A special character
+ tokens.add(new Character(thisChar));
+ }
+ } else {
+ // A valid field
+ if ((current != null) && (field == current.field)) {
+ current.size++;
+ } else {
+ current = new CompiledField(field,1,thisChar);
+ tokens.add(current);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a string representation of this
+ * class.
+ *
+ * @return a string representation of the <code>SimpleDateFormat</code>
+ * instance.
+ */
+ public String toString()
+ {
+ StringBuffer output = new StringBuffer(getClass().getName());
+ output.append("[tokens=");
+ output.append(tokens);
+ output.append(", formatData=");
+ output.append(formatData);
+ output.append(", defaultCenturyStart=");
+ output.append(defaultCenturyStart);
+ output.append(", defaultCentury=");
+ output.append(defaultCentury);
+ output.append(", pattern=");
+ output.append(pattern);
+ output.append(", serialVersionOnStream=");
+ output.append(serialVersionOnStream);
+ output.append(", standardChars=");
+ output.append(standardChars);
+ output.append("]");
+ return output.toString();
+ }
+
+ /**
+ * Constructs a SimpleDateFormat using the default pattern for
+ * the default locale.
+ */
+ public SimpleDateFormat()
+ {
+ /*
+ * There does not appear to be a standard API for determining
+ * what the default pattern for a locale is, so use package-scope
+ * variables in DateFormatSymbols to encapsulate this.
+ */
+ super();
+ Locale locale = Locale.getDefault();
+ calendar = new GregorianCalendar(locale);
+ computeCenturyStart();
+ tokens = new ArrayList();
+ formatData = new DateFormatSymbols(locale);
+ pattern = (formatData.dateFormats[DEFAULT] + ' '
+ + formatData.timeFormats[DEFAULT]);
+ compileFormat(pattern);
+ numberFormat = NumberFormat.getInstance(locale);
+ numberFormat.setGroupingUsed (false);
+ numberFormat.setParseIntegerOnly (true);
+ numberFormat.setMaximumFractionDigits (0);
+ }
+
+ /**
+ * Creates a date formatter using the specified non-localized pattern,
+ * with the default DateFormatSymbols for the default locale.
+ *
+ * @param pattern the pattern to use.
+ * @throws NullPointerException if the pattern is null.
+ * @throws IllegalArgumentException if the pattern is invalid.
+ */
+ public SimpleDateFormat(String pattern)
+ {
+ this(pattern, Locale.getDefault());
+ }
+
+ /**
+ * Creates a date formatter using the specified non-localized pattern,
+ * with the default DateFormatSymbols for the given locale.
+ *
+ * @param pattern the non-localized pattern to use.
+ * @param locale the locale to use for the formatting symbols.
+ * @throws NullPointerException if the pattern is null.
+ * @throws IllegalArgumentException if the pattern is invalid.
+ */
+ public SimpleDateFormat(String pattern, Locale locale)
+ {
+ super();
+ calendar = new GregorianCalendar(locale);
+ computeCenturyStart();
+ tokens = new ArrayList();
+ formatData = new DateFormatSymbols(locale);
+ compileFormat(pattern);
+ this.pattern = pattern;
+ numberFormat = NumberFormat.getInstance(locale);
+ numberFormat.setGroupingUsed (false);
+ numberFormat.setParseIntegerOnly (true);
+ numberFormat.setMaximumFractionDigits (0);
+ }
+
+ /**
+ * Creates a date formatter using the specified non-localized
+ * pattern. The specified DateFormatSymbols will be used when
+ * formatting.
+ *
+ * @param pattern the non-localized pattern to use.
+ * @param formatData the formatting symbols to use.
+ * @throws NullPointerException if the pattern or formatData is null.
+ * @throws IllegalArgumentException if the pattern is invalid.
+ */
+ public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
+ {
+ super();
+ calendar = new GregorianCalendar();
+ computeCenturyStart ();
+ tokens = new ArrayList();
+ if (formatData == null)
+ throw new NullPointerException("formatData");
+ this.formatData = formatData;
+ compileFormat(pattern);
+ this.pattern = pattern;
+ numberFormat = NumberFormat.getInstance();
+ numberFormat.setGroupingUsed (false);
+ numberFormat.setParseIntegerOnly (true);
+ numberFormat.setMaximumFractionDigits (0);
+ }
+
+ /**
+ * This method returns a string with the formatting pattern being used
+ * by this object. This string is unlocalized.
+ *
+ * @return The format string.
+ */
+ public String toPattern()
+ {
+ return pattern;
+ }
+
+ /**
+ * This method returns a string with the formatting pattern being used
+ * by this object. This string is localized.
+ *
+ * @return The format string.
+ */
+ public String toLocalizedPattern()
+ {
+ String localChars = formatData.getLocalPatternChars();
+ return translateLocalizedPattern(pattern, standardChars, localChars);
+ }
+
+ /**
+ * This method sets the formatting pattern that should be used by this
+ * object. This string is not localized.
+ *
+ * @param pattern The new format pattern.
+ * @throws NullPointerException if the pattern is null.
+ * @throws IllegalArgumentException if the pattern is invalid.
+ */
+ public void applyPattern(String pattern)
+ {
+ tokens = new ArrayList();
+ compileFormat(pattern);
+ this.pattern = pattern;
+ }
+
+ /**
+ * This method sets the formatting pattern that should be used by this
+ * object. This string is localized.
+ *
+ * @param pattern The new format pattern.
+ * @throws NullPointerException if the pattern is null.
+ * @throws IllegalArgumentException if the pattern is invalid.
+ */
+ public void applyLocalizedPattern(String pattern)
+ {
+ String localChars = formatData.getLocalPatternChars();
+ pattern = translateLocalizedPattern(pattern, localChars, standardChars);
+ applyPattern(pattern);
+ }
+
+ /**
+ * Translates either from or to a localized variant of the pattern
+ * string. For example, in the German locale, 't' (for 'tag') is
+ * used instead of 'd' (for 'date'). This method translates
+ * a localized pattern (such as 'ttt') to a non-localized pattern
+ * (such as 'ddd'), or vice versa. Non-localized patterns use
+ * a standard set of characters, which match those of the U.S. English
+ * locale.
+ *
+ * @param pattern the pattern to translate.
+ * @param oldChars the old set of characters (used in the pattern).
+ * @param newChars the new set of characters (which will be used in the
+ * pattern).
+ * @return a version of the pattern using the characters in
+ * <code>newChars</code>.
+ */
+ private String translateLocalizedPattern(String pattern,
+ String oldChars, String newChars)
+ {
+ int len = pattern.length();
+ StringBuffer buf = new StringBuffer(len);
+ boolean quoted = false;
+ for (int i = 0; i < len; i++)
+ {
+ char ch = pattern.charAt(i);
+ if (ch == '\'')
+ quoted = ! quoted;
+ if (! quoted)
+ {
+ int j = oldChars.indexOf(ch);
+ if (j >= 0)
+ ch = newChars.charAt(j);
+ }
+ buf.append(ch);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Returns the start of the century used for two digit years.
+ *
+ * @return A <code>Date</code> representing the start of the century
+ * for two digit years.
+ */
+ public Date get2DigitYearStart()
+ {
+ return defaultCenturyStart;
+ }
+
+ /**
+ * Sets the start of the century used for two digit years.
+ *
+ * @param date A <code>Date</code> representing the start of the century for
+ * two digit years.
+ */
+ public void set2DigitYearStart(Date date)
+ {
+ defaultCenturyStart = date;
+ calendar.clear();
+ calendar.setTime(date);
+ int year = calendar.get(Calendar.YEAR);
+ defaultCentury = year - (year % 100);
+ }
+
+ /**
+ * This method returns a copy of the format symbol information used
+ * for parsing and formatting dates.
+ *
+ * @return a copy of the date format symbols.
+ */
+ public DateFormatSymbols getDateFormatSymbols()
+ {
+ return (DateFormatSymbols) formatData.clone();
+ }
+
+ /**
+ * This method sets the format symbols information used for parsing
+ * and formatting dates.
+ *
+ * @param formatData The date format symbols.
+ * @throws NullPointerException if <code>formatData</code> is null.
+ */
+ public void setDateFormatSymbols(DateFormatSymbols formatData)
+ {
+ if (formatData == null)
+ {
+ throw new
+ NullPointerException("The supplied format data was null.");
+ }
+ this.formatData = formatData;
+ }
+
+ /**
+ * This methods tests whether the specified object is equal to this
+ * object. This will be true if and only if the specified object:
+ * <p>
+ * <ul>
+ * <li>Is not <code>null</code>.</li>
+ * <li>Is an instance of <code>SimpleDateFormat</code>.</li>
+ * <li>Is equal to this object at the superclass (i.e., <code>DateFormat</code>)
+ * level.</li>
+ * <li>Has the same formatting pattern.</li>
+ * <li>Is using the same formatting symbols.</li>
+ * <li>Is using the same century for two digit years.</li>
+ * </ul>
+ *
+ * @param obj The object to compare for equality against.
+ *
+ * @return <code>true</code> if the specified object is equal to this object,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object o)
+ {
+ if (!super.equals(o))
+ return false;
+
+ if (!(o instanceof SimpleDateFormat))
+ return false;
+
+ SimpleDateFormat sdf = (SimpleDateFormat)o;
+
+ if (defaultCentury != sdf.defaultCentury)
+ return false;
+
+ if (!toPattern().equals(sdf.toPattern()))
+ return false;
+
+ if (!getDateFormatSymbols().equals(sdf.getDateFormatSymbols()))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * This method returns a hash value for this object.
+ *
+ * @return A hash value for this object.
+ */
+ public int hashCode()
+ {
+ return super.hashCode() ^ toPattern().hashCode() ^ defaultCentury ^
+ getDateFormatSymbols().hashCode();
+ }
+
+
+ /**
+ * Formats the date input according to the format string in use,
+ * appending to the specified StringBuffer. The input StringBuffer
+ * is returned as output for convenience.
+ */
+ private void formatWithAttribute(Date date, FormatBuffer buffer, FieldPosition pos)
+ {
+ String temp;
+ AttributedCharacterIterator.Attribute attribute;
+ calendar.setTime(date);
+
+ // go through vector, filling in fields where applicable, else toString
+ Iterator iter = tokens.iterator();
+ while (iter.hasNext())
+ {
+ Object o = iter.next();
+ if (o instanceof CompiledField)
+ {
+ CompiledField cf = (CompiledField) o;
+ int beginIndex = buffer.length();
+
+ switch (cf.getField())
+ {
+ case ERA_FIELD:
+ buffer.append (formatData.eras[calendar.get (Calendar.ERA)], DateFormat.Field.ERA);
+ break;
+ case YEAR_FIELD:
+ // If we have two digits, then we truncate. Otherwise, we
+ // use the size of the pattern, and zero pad.
+ buffer.setDefaultAttribute (DateFormat.Field.YEAR);
+ if (cf.getSize() == 2)
+ {
+ temp = "00"+String.valueOf (calendar.get (Calendar.YEAR));
+ buffer.append (temp.substring (temp.length() - 2));
+ }
+ else
+ withLeadingZeros (calendar.get (Calendar.YEAR), cf.getSize(), buffer);
+ break;
+ case MONTH_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.MONTH);
+ if (cf.getSize() < 3)
+ withLeadingZeros (calendar.get (Calendar.MONTH) + 1, cf.getSize(), buffer);
+ else if (cf.getSize() < 4)
+ buffer.append (formatData.shortMonths[calendar.get (Calendar.MONTH)]);
+ else
+ buffer.append (formatData.months[calendar.get (Calendar.MONTH)]);
+ break;
+ case DATE_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_MONTH);
+ withLeadingZeros (calendar.get (Calendar.DATE), cf.getSize(), buffer);
+ break;
+ case HOUR_OF_DAY1_FIELD: // 1-24
+ buffer.setDefaultAttribute(DateFormat.Field.HOUR_OF_DAY1);
+ withLeadingZeros ( ((calendar.get (Calendar.HOUR_OF_DAY) + 23) % 24) + 1,
+ cf.getSize(), buffer);
+ break;
+ case HOUR_OF_DAY0_FIELD: // 0-23
+ buffer.setDefaultAttribute (DateFormat.Field.HOUR_OF_DAY0);
+ withLeadingZeros (calendar.get (Calendar.HOUR_OF_DAY), cf.getSize(), buffer);
+ break;
+ case MINUTE_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.MINUTE);
+ withLeadingZeros (calendar.get (Calendar.MINUTE),
+ cf.getSize(), buffer);
+ break;
+ case SECOND_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.SECOND);
+ withLeadingZeros(calendar.get (Calendar.SECOND),
+ cf.getSize(), buffer);
+ break;
+ case MILLISECOND_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.MILLISECOND);
+ withLeadingZeros (calendar.get (Calendar.MILLISECOND), cf.getSize(), buffer);
+ break;
+ case DAY_OF_WEEK_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_WEEK);
+ if (cf.getSize() < 4)
+ buffer.append (formatData.shortWeekdays[calendar.get (Calendar.DAY_OF_WEEK)]);
+ else
+ buffer.append (formatData.weekdays[calendar.get (Calendar.DAY_OF_WEEK)]);
+ break;
+ case DAY_OF_YEAR_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_YEAR);
+ withLeadingZeros (calendar.get (Calendar.DAY_OF_YEAR), cf.getSize(), buffer);
+ break;
+ case DAY_OF_WEEK_IN_MONTH_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_WEEK_IN_MONTH);
+ withLeadingZeros (calendar.get (Calendar.DAY_OF_WEEK_IN_MONTH),
+ cf.getSize(), buffer);
+ break;
+ case WEEK_OF_YEAR_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.WEEK_OF_YEAR);
+ withLeadingZeros (calendar.get (Calendar.WEEK_OF_YEAR),
+ cf.getSize(), buffer);
+ break;
+ case WEEK_OF_MONTH_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.WEEK_OF_MONTH);
+ withLeadingZeros (calendar.get (Calendar.WEEK_OF_MONTH),
+ cf.getSize(), buffer);
+ break;
+ case AM_PM_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.AM_PM);
+ buffer.append (formatData.ampms[calendar.get (Calendar.AM_PM)]);
+ break;
+ case HOUR1_FIELD: // 1-12
+ buffer.setDefaultAttribute (DateFormat.Field.HOUR1);
+ withLeadingZeros (((calendar.get (Calendar.HOUR) + 11) % 12) + 1,
+ cf.getSize(), buffer);
+ break;
+ case HOUR0_FIELD: // 0-11
+ buffer.setDefaultAttribute (DateFormat.Field.HOUR0);
+ withLeadingZeros (calendar.get (Calendar.HOUR), cf.getSize(), buffer);
+ break;
+ case TIMEZONE_FIELD:
+ buffer.setDefaultAttribute (DateFormat.Field.TIME_ZONE);
+ TimeZone zone = calendar.getTimeZone();
+ boolean isDST = calendar.get (Calendar.DST_OFFSET) != 0;
+ // FIXME: XXX: This should be a localized time zone.
+ String zoneID = zone.getDisplayName
+ (isDST, cf.getSize() > 3 ? TimeZone.LONG : TimeZone.SHORT);
+ buffer.append (zoneID);
+ break;
+ case RFC822_TIMEZONE_FIELD:
+ buffer.setDefaultAttribute(DateFormat.Field.RFC822_TIME_ZONE);
+ int pureMinutes = (calendar.get(Calendar.ZONE_OFFSET) +
+ calendar.get(Calendar.DST_OFFSET)) / (1000 * 60);
+ String sign = (pureMinutes < 0) ? "-" : "+";
+ int hours = pureMinutes / 60;
+ int minutes = pureMinutes % 60;
+ buffer.append(sign);
+ withLeadingZeros(hours, 2, buffer);
+ withLeadingZeros(minutes, 2, buffer);
+ break;
+ default:
+ throw new IllegalArgumentException ("Illegal pattern character " +
+ cf.getCharacter());
+ }
+ if (pos != null && (buffer.getDefaultAttribute() == pos.getFieldAttribute()
+ || cf.getField() == pos.getField()))
+ {
+ pos.setBeginIndex(beginIndex);
+ pos.setEndIndex(buffer.length());
+ }
+ }
+ else
+ {
+ buffer.append(o.toString(), null);
+ }
+ }
+ }
+
+ public StringBuffer format(Date date, StringBuffer buffer, FieldPosition pos)
+ {
+ formatWithAttribute(date, new StringFormatBuffer (buffer), pos);
+
+ return buffer;
+ }
+
+ public AttributedCharacterIterator formatToCharacterIterator(Object date)
+ throws IllegalArgumentException
+ {
+ if (date == null)
+ throw new NullPointerException("null argument");
+ if (!(date instanceof Date))
+ throw new IllegalArgumentException("argument should be an instance of java.util.Date");
+
+ AttributedFormatBuffer buf = new AttributedFormatBuffer();
+ formatWithAttribute((Date)date, buf,
+ null);
+ buf.sync();
+
+ return new FormatCharacterIterator(buf.getBuffer().toString(),
+ buf.getRanges(),
+ buf.getAttributes());
+ }
+
+ private void withLeadingZeros(int value, int length, FormatBuffer buffer)
+ {
+ String valStr = String.valueOf(value);
+ for (length -= valStr.length(); length > 0; length--)
+ buffer.append('0');
+ buffer.append(valStr);
+ }
+
+ private boolean expect(String source, ParsePosition pos, char ch)
+ {
+ int x = pos.getIndex();
+ boolean r = x < source.length() && source.charAt(x) == ch;
+ if (r)
+ pos.setIndex(x + 1);
+ else
+ pos.setErrorIndex(x);
+ return r;
+ }
+
+ /**
+ * This method parses the specified string into a date.
+ *
+ * @param dateStr The date string to parse.
+ * @param pos The input and output parse position
+ *
+ * @return The parsed date, or <code>null</code> if the string cannot be
+ * parsed.
+ */
+ public Date parse (String dateStr, ParsePosition pos)
+ {
+ int fmt_index = 0;
+ int fmt_max = pattern.length();
+
+ calendar.clear();
+ boolean saw_timezone = false;
+ int quote_start = -1;
+ boolean is2DigitYear = false;
+ try
+ {
+ for (; fmt_index < fmt_max; ++fmt_index)
+ {
+ char ch = pattern.charAt(fmt_index);
+ if (ch == '\'')
+ {
+ int index = pos.getIndex();
+ if (fmt_index < fmt_max - 1
+ && pattern.charAt(fmt_index + 1) == '\'')
+ {
+ if (! expect (dateStr, pos, ch))
+ return null;
+ ++fmt_index;
+ }
+ else
+ quote_start = quote_start < 0 ? fmt_index : -1;
+ continue;
+ }
+
+ if (quote_start != -1
+ || ((ch < 'a' || ch > 'z')
+ && (ch < 'A' || ch > 'Z')))
+ {
+ if (! expect (dateStr, pos, ch))
+ return null;
+ continue;
+ }
+
+ // We've arrived at a potential pattern character in the
+ // pattern.
+ int fmt_count = 1;
+ while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch)
+ {
+ ++fmt_count;
+ }
+
+ // We might need to limit the number of digits to parse in
+ // some cases. We look to the next pattern character to
+ // decide.
+ boolean limit_digits = false;
+ if (fmt_index < fmt_max
+ && standardChars.indexOf(pattern.charAt(fmt_index)) >= 0)
+ limit_digits = true;
+ --fmt_index;
+
+ // We can handle most fields automatically: most either are
+ // numeric or are looked up in a string vector. In some cases
+ // we need an offset. When numeric, `offset' is added to the
+ // resulting value. When doing a string lookup, offset is the
+ // initial index into the string array.
+ int calendar_field;
+ boolean is_numeric = true;
+ int offset = 0;
+ boolean maybe2DigitYear = false;
+ boolean oneBasedHour = false;
+ boolean oneBasedHourOfDay = false;
+ Integer simpleOffset;
+ String[] set1 = null;
+ String[] set2 = null;
+ switch (ch)
+ {
+ case 'd':
+ calendar_field = Calendar.DATE;
+ break;
+ case 'D':
+ calendar_field = Calendar.DAY_OF_YEAR;
+ break;
+ case 'F':
+ calendar_field = Calendar.DAY_OF_WEEK_IN_MONTH;
+ break;
+ case 'E':
+ is_numeric = false;
+ offset = 1;
+ calendar_field = Calendar.DAY_OF_WEEK;
+ set1 = formatData.getWeekdays();
+ set2 = formatData.getShortWeekdays();
+ break;
+ case 'w':
+ calendar_field = Calendar.WEEK_OF_YEAR;
+ break;
+ case 'W':
+ calendar_field = Calendar.WEEK_OF_MONTH;
+ break;
+ case 'M':
+ calendar_field = Calendar.MONTH;
+ if (fmt_count <= 2)
+ offset = -1;
+ else
+ {
+ is_numeric = false;
+ set1 = formatData.getMonths();
+ set2 = formatData.getShortMonths();
+ }
+ break;
+ case 'y':
+ calendar_field = Calendar.YEAR;
+ if (fmt_count <= 2)
+ maybe2DigitYear = true;
+ break;
+ case 'K':
+ calendar_field = Calendar.HOUR;
+ break;
+ case 'h':
+ calendar_field = Calendar.HOUR;
+ oneBasedHour = true;
+ break;
+ case 'H':
+ calendar_field = Calendar.HOUR_OF_DAY;
+ break;
+ case 'k':
+ calendar_field = Calendar.HOUR_OF_DAY;
+ oneBasedHourOfDay = true;
+ break;
+ case 'm':
+ calendar_field = Calendar.MINUTE;
+ break;
+ case 's':
+ calendar_field = Calendar.SECOND;
+ break;
+ case 'S':
+ calendar_field = Calendar.MILLISECOND;
+ break;
+ case 'a':
+ is_numeric = false;
+ calendar_field = Calendar.AM_PM;
+ set1 = formatData.getAmPmStrings();
+ break;
+ case 'z':
+ case 'Z':
+ // We need a special case for the timezone, because it
+ // uses a different data structure than the other cases.
+ is_numeric = false;
+ calendar_field = Calendar.ZONE_OFFSET;
+ String[][] zoneStrings = formatData.getZoneStrings();
+ int zoneCount = zoneStrings.length;
+ int index = pos.getIndex();
+ boolean found_zone = false;
+ simpleOffset = computeOffset(dateStr.substring(index), pos);
+ if (simpleOffset != null)
+ {
+ found_zone = true;
+ saw_timezone = true;
+ calendar.set(Calendar.DST_OFFSET, 0);
+ offset = simpleOffset.intValue();
+ }
+ else
+ {
+ for (int j = 0; j < zoneCount; j++)
+ {
+ String[] strings = zoneStrings[j];
+ int k;
+ for (k = 0; k < strings.length; ++k)
+ {
+ if (dateStr.startsWith(strings[k], index))
+ break;
+ }
+ if (k != strings.length)
+ {
+ found_zone = true;
+ saw_timezone = true;
+ TimeZone tz = TimeZone.getTimeZone (strings[0]);
+ // Check if it's a DST zone or ordinary
+ if(k == 3 || k == 4)
+ calendar.set (Calendar.DST_OFFSET, tz.getDSTSavings());
+ else
+ calendar.set (Calendar.DST_OFFSET, 0);
+ offset = tz.getRawOffset ();
+ pos.setIndex(index + strings[k].length());
+ break;
+ }
+ }
+ }
+ if (! found_zone)
+ {
+ pos.setErrorIndex(pos.getIndex());
+ return null;
+ }
+ break;
+ default:
+ pos.setErrorIndex(pos.getIndex());
+ return null;
+ }
+
+ // Compute the value we should assign to the field.
+ int value;
+ int index = -1;
+ if (is_numeric)
+ {
+ numberFormat.setMinimumIntegerDigits(fmt_count);
+ if (limit_digits)
+ numberFormat.setMaximumIntegerDigits(fmt_count);
+ if (maybe2DigitYear)
+ index = pos.getIndex();
+ Number n = numberFormat.parse(dateStr, pos);
+ if (pos == null || ! (n instanceof Long))
+ return null;
+ value = n.intValue() + offset;
+ }
+ else if (set1 != null)
+ {
+ index = pos.getIndex();
+ int i;
+ boolean found = false;
+ for (i = offset; i < set1.length; ++i)
+ {
+ if (set1[i] != null)
+ if (dateStr.toUpperCase().startsWith(set1[i].toUpperCase(),
+ index))
+ {
+ found = true;
+ pos.setIndex(index + set1[i].length());
+ break;
+ }
+ }
+ if (!found && set2 != null)
+ {
+ for (i = offset; i < set2.length; ++i)
+ {
+ if (set2[i] != null)
+ if (dateStr.toUpperCase().startsWith(set2[i].toUpperCase(),
+ index))
+ {
+ found = true;
+ pos.setIndex(index + set2[i].length());
+ break;
+ }
+ }
+ }
+ if (!found)
+ {
+ pos.setErrorIndex(index);
+ return null;
+ }
+ value = i;
+ }
+ else
+ value = offset;
+
+ if (maybe2DigitYear)
+ {
+ // Parse into default century if the numeric year string has
+ // exactly 2 digits.
+ int digit_count = pos.getIndex() - index;
+ if (digit_count == 2)
+ {
+ is2DigitYear = true;
+ value += defaultCentury;
+ }
+ }
+
+ // Calendar uses 0-based hours.
+ // I.e. 00:00 AM is midnight, not 12 AM or 24:00
+ if (oneBasedHour && value == 12)
+ value = 0;
+
+ if (oneBasedHourOfDay && value == 24)
+ value = 0;
+
+ // Assign the value and move on.
+ calendar.set(calendar_field, value);
+ }
+
+ if (is2DigitYear)
+ {
+ // Apply the 80-20 heuristic to dermine the full year based on
+ // defaultCenturyStart.
+ int year = calendar.get(Calendar.YEAR);
+ if (calendar.getTime().compareTo(defaultCenturyStart) < 0)
+ calendar.set(Calendar.YEAR, year + 100);
+ }
+ if (! saw_timezone)
+ {
+ // Use the real rules to determine whether or not this
+ // particular time is in daylight savings.
+ calendar.clear (Calendar.DST_OFFSET);
+ calendar.clear (Calendar.ZONE_OFFSET);
+ }
+ return calendar.getTime();
+ }
+ catch (IllegalArgumentException x)
+ {
+ pos.setErrorIndex(pos.getIndex());
+ return null;
+ }
+ }
+
+ /**
+ * <p>
+ * Computes the time zone offset in milliseconds
+ * relative to GMT, based on the supplied
+ * <code>String</code> representation.
+ * </p>
+ * <p>
+ * The supplied <code>String</code> must be a three
+ * or four digit signed number, with an optional 'GMT'
+ * prefix. The first one or two digits represents the hours,
+ * while the last two represent the minutes. The
+ * two sets of digits can optionally be separated by
+ * ':'. The mandatory sign prefix (either '+' or '-')
+ * indicates the direction of the offset from GMT.
+ * </p>
+ * <p>
+ * For example, 'GMT+0200' specifies 2 hours after
+ * GMT, while '-05:00' specifies 5 hours prior to
+ * GMT. The special case of 'GMT' alone can be used
+ * to represent the offset, 0.
+ * </p>
+ * <p>
+ * If the <code>String</code> can not be parsed,
+ * the result will be null. The resulting offset
+ * is wrapped in an <code>Integer</code> object, in
+ * order to allow such failure to be represented.
+ * </p>
+ *
+ * @param zoneString a string in the form
+ * (GMT)? sign hours : minutes
+ * where sign = '+' or '-', hours
+ * is a one or two digits representing
+ * a number between 0 and 23, and
+ * minutes is two digits representing
+ * a number between 0 and 59.
+ * @return the parsed offset, or null if parsing
+ * failed.
+ */
+ private Integer computeOffset(String zoneString, ParsePosition pos)
+ {
+ Pattern pattern =
+ Pattern.compile("(GMT)?([+-])([012])?([0-9]):?([0-9]{2})");
+ Matcher matcher = pattern.matcher(zoneString);
+
+ // Match from start, but ignore trailing parts
+ boolean hasAll = matcher.lookingAt();
+ try
+ {
+ // Do we have at least the sign, hour and minute?
+ matcher.group(2);
+ matcher.group(4);
+ matcher.group(5);
+ }
+ catch (IllegalStateException ise)
+ {
+ hasAll = false;
+ }
+ if (hasAll)
+ {
+ int sign = matcher.group(2).equals("+") ? 1 : -1;
+ int hour = Integer.parseInt(matcher.group(4));
+ if (!matcher.group(3).equals(""))
+ hour += (Integer.parseInt(matcher.group(3)) * 10);
+ int minutes = Integer.parseInt(matcher.group(5));
+
+ if (hour > 23)
+ return null;
+ int offset = sign * ((hour * 60) + minutes) * 60000;
+
+ // advance the index
+ pos.setIndex(pos.getIndex() + matcher.end());
+ return new Integer(offset);
+ }
+ else if (zoneString.startsWith("GMT"))
+ {
+ pos.setIndex(pos.getIndex() + 3);
+ return new Integer(0);
+ }
+ return null;
+ }
+
+ // Compute the start of the current century as defined by
+ // get2DigitYearStart.
+ private void computeCenturyStart()
+ {
+ int year = calendar.get(Calendar.YEAR);
+ calendar.set(Calendar.YEAR, year - 80);
+ set2DigitYearStart(calendar.getTime());
+ }
+
+ /**
+ * Returns a copy of this instance of
+ * <code>SimpleDateFormat</code>. The copy contains
+ * clones of the formatting symbols and the 2-digit
+ * year century start date.
+ */
+ public Object clone()
+ {
+ SimpleDateFormat clone = (SimpleDateFormat) super.clone();
+ clone.setDateFormatSymbols((DateFormatSymbols) formatData.clone());
+ clone.set2DigitYearStart((Date) defaultCenturyStart.clone());
+ return clone;
+ }
+
+}
diff --git a/libjava/classpath/java/text/StringCharacterIterator.java b/libjava/classpath/java/text/StringCharacterIterator.java
new file mode 100644
index 00000000000..e3adc857e51
--- /dev/null
+++ b/libjava/classpath/java/text/StringCharacterIterator.java
@@ -0,0 +1,356 @@
+/* StringCharacterIterator.java -- Iterate over a character range in a string
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.text;
+
+/**
+ * This class iterates over a range of characters in a <code>String</code>.
+ * For a given range of text, a beginning and ending index,
+ * as well as a current index are defined. These values can be queried
+ * by the methods in this interface. Additionally, various methods allow
+ * the index to be set.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public final class StringCharacterIterator implements CharacterIterator
+{
+ /**
+ * This is the string to iterate over
+ */
+ private String text;
+
+ /**
+ * This is the value of the start position of the text range.
+ */
+ private int begin;
+
+ /**
+ * This is the value of the ending position of the text range.
+ */
+ private int end;
+
+ /**
+ * This is the current value of the scan index.
+ */
+ private int index;
+
+ /**
+ * This method initializes a new instance of
+ * <code>StringCharacterIterator</code> to iterate over the entire
+ * text of the specified <code>String</code>. The initial index
+ * value will be set to the first character in the string.
+ *
+ * @param text The <code>String</code> to iterate through.
+ */
+ public StringCharacterIterator (String text)
+ {
+ this (text, 0, text.length (), 0);
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method initializes a new instance of
+ * <code>StringCharacterIterator</code> to iterate over the entire
+ * text of the specified <code>String</code>. The initial index
+ * value will be set to the specified value.
+ *
+ * @param text The <code>String</code> to iterate through.
+ * @param index The initial index position.
+ */
+ public StringCharacterIterator (String text, int index)
+ {
+ this (text, 0, text.length (), index);
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method initializes a new instance of
+ * <code>StringCharacterIterator</code> that iterates over the text
+ * in a subrange of the specified <code>String</code>. The
+ * beginning and end of the range are specified by the caller, as is
+ * the initial index position.
+ *
+ * @param text The <code>String</code> to iterate through.
+ * @param begin The beginning position in the character range.
+ * @param end The ending position in the character range.
+ * @param index The initial index position.
+ *
+ * @param IllegalArgumentException If any of the range values are
+ * invalid.
+ */
+ public StringCharacterIterator (String text, int begin, int end, int index)
+ {
+ int len = text.length ();
+
+ if ((begin < 0) || (begin > len))
+ throw new IllegalArgumentException ("Bad begin position");
+
+ if ((end < begin) || (end > len))
+ throw new IllegalArgumentException ("Bad end position");
+
+ if ((index < begin) || (index > end))
+ throw new IllegalArgumentException ("Bad initial index position");
+
+ this.text = text;
+ this.begin = begin;
+ this.end = end;
+ this.index = index;
+ }
+
+ /**
+ * This is a package level constructor that copies the text out of
+ * an existing StringCharacterIterator and resets the beginning and
+ * ending index.
+ *
+ * @param scci The StringCharacterIterator to copy the info from
+ * @param begin The beginning index of the range we are interested in.
+ * @param end The ending index of the range we are interested in.
+ */
+ StringCharacterIterator (StringCharacterIterator sci, int begin, int end)
+ {
+ this (sci.text, begin, end, begin);
+ }
+
+ /**
+ * This method returns the character at the current index position
+ *
+ * @return The character at the current index position.
+ */
+ public char current ()
+ {
+ return (index < end) ? text.charAt (index) : DONE;
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method increments the current index and then returns the
+ * character at the new index value. If the index is already at
+ * <code>getEndIndex () - 1</code>, it will not be incremented.
+ *
+ * @return The character at the position of the incremented index
+ * value, or <code>DONE</code> if the index has reached
+ * getEndIndex () - 1.
+ */
+ public char next ()
+ {
+ if (index == end)
+ return DONE;
+
+ ++index;
+ return current ();
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method decrements the current index and then returns the
+ * character at the new index value. If the index value is already
+ * at the beginning index, it will not be decremented.
+ *
+ * @return The character at the position of the decremented index
+ * value, or <code>DONE</code> if index was already equal to the
+ * beginning index value.
+ */
+ public char previous ()
+ {
+ if (index == begin)
+ return DONE;
+
+ --index;
+ return current ();
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method sets the index value to the beginning of the range and returns
+ * the character there.
+ *
+ * @return The character at the beginning of the range, or
+ * <code>DONE</code> if the range is empty.
+ */
+ public char first ()
+ {
+ index = begin;
+ return current ();
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method sets the index value to <code>getEndIndex () - 1</code> and
+ * returns the character there. If the range is empty, then the index value
+ * will be set equal to the beginning index.
+ *
+ * @return The character at the end of the range, or
+ * <code>DONE</code> if the range is empty.
+ */
+ public char last ()
+ {
+ if (end == begin)
+ return DONE;
+
+ index = end - 1;
+ return current ();
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method returns the current value of the index.
+ *
+ * @return The current index value
+ */
+ public int getIndex ()
+ {
+ return index;
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method sets the value of the index to the specified value, then
+ * returns the character at that position.
+ *
+ * @param index The new index value.
+ *
+ * @return The character at the new index value or <code>DONE</code>
+ * if the index value is equal to <code>getEndIndex</code>.
+ *
+ * @exception IllegalArgumentException If the specified index is not valid
+ */
+ public char setIndex (int index)
+ {
+ if ((index < begin) || (index > end))
+ throw new IllegalArgumentException ("Bad index specified");
+
+ this.index = index;
+ return current ();
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method returns the character position of the first character in the
+ * range.
+ *
+ * @return The index of the first character in the range.
+ */
+ public int getBeginIndex ()
+ {
+ return begin;
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method returns the character position of the end of the text range.
+ * This will actually be the index of the first character following the
+ * end of the range. In the event the text range is empty, this will be
+ * equal to the first character in the range.
+ *
+ * @return The index of the end of the range.
+ */
+ public int getEndIndex ()
+ {
+ return end;
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method creates a copy of this <code>CharacterIterator</code>.
+ *
+ * @return A copy of this <code>CharacterIterator</code>.
+ */
+ public Object clone ()
+ {
+ return new StringCharacterIterator (text, begin, end, index);
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method tests this object for equality againt the specified
+ * object. This will be true if and only if the specified object:
+ * <p>
+ * <ul>
+ * <li>is not <code>null</code>.</li>
+ * <li>is an instance of <code>StringCharacterIterator</code></li>
+ * <li>has the same text as this object</li>
+ * <li>has the same beginning, ending, and current index as this object.</li>
+ * </ul>
+ *
+ * @param obj The object to test for equality against.
+ *
+ * @return <code>true</code> if the specified object is equal to this
+ * object, <code>false</code> otherwise.
+ */
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof StringCharacterIterator))
+ return false;
+
+ StringCharacterIterator sci = (StringCharacterIterator) obj;
+
+ return (begin == sci.begin
+ && end == sci.end
+ && index == sci.index
+ && text.equals (sci.text));
+ }
+
+ /*************************************************************************/
+
+ /**
+ * This method allows other classes in java.text to change the value
+ * of the underlying text being iterated through.
+ *
+ * @param text The new <code>String</code> to iterate through.
+ */
+ public void setText (String text)
+ {
+ this.text = text;
+ this.begin = 0;
+ this.end = text.length ();
+ this.index = 0;
+ }
+}
diff --git a/libjava/classpath/java/text/class-dependencies.conf b/libjava/classpath/java/text/class-dependencies.conf
new file mode 100644
index 00000000000..011b146ce10
--- /dev/null
+++ b/libjava/classpath/java/text/class-dependencies.conf
@@ -0,0 +1,220 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+# end of file
+
+# All locales supported are loaded via classes from java.text (see below)
+# from class gnu/java/locale/LocaleInformation_<locale_id>
+#
+# This introduces a dependency for all locales. To allow an easy selection
+# and addition of locales, the library variable {text_locales} can be set to
+# the set of supported locales.
+#
+
+{text_locales}: \
+ af_ZA \
+ ar_AE \
+ ar_BH \
+ ar_DZ \
+ ar_EG \
+ ar_IN \
+ ar_IQ \
+ ar_JO \
+ ar_KW \
+ ar_LB \
+ ar_LY \
+ ar_MA \
+ ar_OM \
+ ar_QA \
+ ar_SD \
+ ar_SY \
+ ar_TN \
+ ar_YE \
+ be_BY \
+ bn_IN \
+ br_FR \
+ bs_BA \
+ ca_ES \
+ cs_CZ \
+ cy_GB \
+ da_DK \
+ de \
+ de_AT \
+ de_BE \
+ de_CH \
+ de_DE \
+ de_LU \
+ el_GR \
+ en \
+ en_AU \
+ en_BW \
+ en_CA \
+ en_DK \
+ en_GB \
+ en_HK \
+ en_IE \
+ en_IN \
+ en_NZ \
+ en_PH \
+ en_SG \
+ en_US \
+ en_ZA \
+ en_ZW \
+ es_AR \
+ es_BO \
+ es_CL \
+ es_CO \
+ es_CR \
+ es_DO \
+ es_EC \
+ es_ES \
+ es_GT \
+ es_HN \
+ es_MX \
+ es_NI \
+ es_PA \
+ es_PE \
+ es_PR \
+ es_PY \
+ es_SV \
+ es_US \
+ es_UY \
+ es_VE \
+ et_EE \
+ eu_ES \
+ fa_IR \
+ fi_FI \
+ fo_FO \
+ fr_BE \
+ fr_CA \
+ fr_CH \
+ fr_FR \
+ fr_LU \
+ ga_IE \
+ gd_GB \
+ gl_ES \
+ gv_GB \
+ he_IL \
+ hi_IN \
+ hr_HR \
+ hu_HU \
+ id_ID \
+ it_CH \
+ it_IT \
+ iw_IL \
+ ja_JP \
+ ka_GE \
+ kl_GL \
+ ko_KR \
+ kw_GB \
+ lt_LT \
+ lv_LV \
+ mi_NZ \
+ mk_MK \
+ mr_IN \
+ mt_MT \
+ nl \
+ nl_BE \
+ nl_NL \
+ nn_NO \
+ no_NO \
+ oc_FR \
+ pl_PL \
+ pt_BR \
+ pt_PT \
+ ro_RO \
+ ru_RU \
+ ru_UA \
+ se_NO \
+ sk_SK \
+ sl_SI \
+ sq_AL \
+ sr_YU \
+ sv_FI \
+ sv_SE \
+ ta_IN \
+ te_IN \
+ tg_TJ \
+ tl_PH \
+ tr_TR \
+ uk_UA \
+ ur_PK \
+ uz_UZ \
+ vi_VN \
+ yi_US \
+ zh_CN \
+ zh_HK \
+ zh_SG \
+ zh_TW
+
+java/text/Collator.getInstance(Ljava/util/Locale;)Ljava/text/Collator;: \
+ gnu/java/locale/LocaleInformation_{text_locales}.*
+
+java/text/DateFormatSymbols.<init>(Ljava/util/Locale;)V: \
+ gnu/java/locale/LocaleInformation_{text_locales}.*
+
+java/text/DecimalFormatSymbols.<init>(Ljava/util/Locale;)V: \
+ gnu/java/locale/LocaleInformation_{text_locales}.*
+
+java/text/BreakIterator.getInstance(Ljava/lang/String;Ljava/util/Locale;)Ljava/text/BreakIterator;: \
+ gnu/java/locale/LocaleInformation_{text_locales}.*
+
+java/text/NumberFormat.computeInstance(Ljava/util/Locale;Ljava/lang/String;Ljava/lang/String;)Ljava/text/NumberFormat;: \
+ gnu/java/locale/LocaleInformation_{text_locales}.*
+
+java/text/DateFormat.computeInstance(IILjava/util/Locale;ZZ)Ljava/text/DateFormat;: \
+ gnu/java/locale/LocaleInformation_{text_locales}.*
diff --git a/libjava/classpath/java/text/package.html b/libjava/classpath/java/text/package.html
new file mode 100644
index 00000000000..3c2e22ba5e4
--- /dev/null
+++ b/libjava/classpath/java/text/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.text package.
+ Copyright (C) 2002 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 - java.text</title></head>
+
+<body>
+<p>Classes to iterate over strings and to format texts according to a
+specific locale.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/util/.cvsignore b/libjava/classpath/java/util/.cvsignore
new file mode 100644
index 00000000000..d41ae8d8147
--- /dev/null
+++ b/libjava/classpath/java/util/.cvsignore
@@ -0,0 +1 @@
+LocaleData.java
diff --git a/libjava/classpath/java/util/AbstractCollection.java b/libjava/classpath/java/util/AbstractCollection.java
new file mode 100644
index 00000000000..00ee23ebd43
--- /dev/null
+++ b/libjava/classpath/java/util/AbstractCollection.java
@@ -0,0 +1,470 @@
+/* AbstractCollection.java -- Abstract implementation of most of Collection
+ Copyright (C) 1998, 2000, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.lang.reflect.Array;
+
+/**
+ * A basic implementation of most of the methods in the Collection interface to
+ * make it easier to create a collection. To create an unmodifiable Collection,
+ * just subclass AbstractCollection and provide implementations of the
+ * iterator() and size() methods. The Iterator returned by iterator() need only
+ * provide implementations of hasNext() and next() (that is, it may throw an
+ * UnsupportedOperationException if remove() is called). To create a modifiable
+ * Collection, you must in addition provide an implementation of the
+ * add(Object) method and the Iterator returned by iterator() must provide an
+ * implementation of remove(). Other methods should be overridden if the
+ * backing data structure allows for a more efficient implementation. The
+ * precise implementation used by AbstractCollection is documented, so that
+ * subclasses can tell which methods could be implemented more efficiently.
+ * <p>
+ *
+ * The programmer should provide a no-argument constructor, and one that
+ * accepts another Collection, as recommended by the Collection interface.
+ * Unfortunately, there is no way to enforce this in Java.
+ *
+ * @author Original author unknown
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see AbstractSet
+ * @see AbstractList
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class AbstractCollection implements Collection
+{
+ /**
+ * The main constructor, for use by subclasses.
+ */
+ protected AbstractCollection()
+ {
+ }
+
+ /**
+ * Return an Iterator over this collection. The iterator must provide the
+ * hasNext and next methods and should in addition provide remove if the
+ * collection is modifiable.
+ *
+ * @return an iterator
+ */
+ public abstract Iterator iterator();
+
+ /**
+ * Return the number of elements in this collection. If there are more than
+ * Integer.MAX_VALUE elements, return Integer.MAX_VALUE.
+ *
+ * @return the size
+ */
+ public abstract int size();
+
+ /**
+ * Add an object to the collection (optional operation). This implementation
+ * always throws an UnsupportedOperationException - it should be
+ * overridden if the collection is to be modifiable. If the collection
+ * does not accept duplicates, simply return false. Collections may specify
+ * limitations on what may be added.
+ *
+ * @param o the object to add
+ * @return true if the add operation caused the Collection to change
+ * @throws UnsupportedOperationException if the add operation is not
+ * supported on this collection
+ * @throws NullPointerException if the collection does not support null
+ * @throws ClassCastException if the object is of the wrong type
+ * @throws IllegalArgumentException if some aspect of the object prevents
+ * it from being added
+ */
+ public boolean add(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Add all the elements of a given collection to this collection (optional
+ * operation). This implementation obtains an Iterator over the given
+ * collection and iterates over it, adding each element with the
+ * add(Object) method (thus this method will fail with an
+ * UnsupportedOperationException if the add method does). The behavior is
+ * unspecified if the specified collection is modified during the iteration,
+ * including the special case of trying addAll(this) on a non-empty
+ * collection.
+ *
+ * @param c the collection to add the elements of to this collection
+ * @return true if the add operation caused the Collection to change
+ * @throws UnsupportedOperationException if the add operation is not
+ * supported on this collection
+ * @throws NullPointerException if the specified collection is null
+ * @throws ClassCastException if the type of any element in c is
+ * not a valid type for addition.
+ * @throws IllegalArgumentException if some aspect of any element
+ * in c prevents it being added.
+ * @throws NullPointerException if any element in c is null and this
+ * collection doesn't allow null values.
+ * @see #add(Object)
+ */
+ public boolean addAll(Collection c)
+ {
+ Iterator itr = c.iterator();
+ boolean modified = false;
+ int pos = c.size();
+ while (--pos >= 0)
+ modified |= add(itr.next());
+ return modified;
+ }
+
+ /**
+ * Remove all elements from the collection (optional operation). This
+ * implementation obtains an iterator over the collection and calls next
+ * and remove on it repeatedly (thus this method will fail with an
+ * UnsupportedOperationException if the Iterator's remove method does)
+ * until there are no more elements to remove.
+ * Many implementations will have a faster way of doing this.
+ *
+ * @throws UnsupportedOperationException if the Iterator returned by
+ * iterator does not provide an implementation of remove
+ * @see Iterator#remove()
+ */
+ public void clear()
+ {
+ Iterator itr = iterator();
+ int pos = size();
+ while (--pos >= 0)
+ {
+ itr.next();
+ itr.remove();
+ }
+ }
+
+ /**
+ * Test whether this collection contains a given object. That is, if the
+ * collection has an element e such that (o == null ? e == null :
+ * o.equals(e)). This implementation obtains an iterator over the collection
+ * and iterates over it, testing each element for equality with the given
+ * object. If it is equal, true is returned. Otherwise false is returned when
+ * the end of the collection is reached.
+ *
+ * @param o the object to remove from this collection
+ * @return true if this collection contains an object equal to o
+ */
+ public boolean contains(Object o)
+ {
+ Iterator itr = iterator();
+ int pos = size();
+ while (--pos >= 0)
+ if (equals(o, itr.next()))
+ return true;
+ return false;
+ }
+
+ /**
+ * Tests whether this collection contains all the elements in a given
+ * collection. This implementation iterates over the given collection,
+ * testing whether each element is contained in this collection. If any one
+ * is not, false is returned. Otherwise true is returned.
+ *
+ * @param c the collection to test against
+ * @return true if this collection contains all the elements in the given
+ * collection
+ * @throws NullPointerException if the given collection is null
+ * @see #contains(Object)
+ */
+ public boolean containsAll(Collection c)
+ {
+ Iterator itr = c.iterator();
+ int pos = c.size();
+ while (--pos >= 0)
+ if (!contains(itr.next()))
+ return false;
+ return true;
+ }
+
+ /**
+ * Test whether this collection is empty. This implementation returns
+ * size() == 0.
+ *
+ * @return true if this collection is empty.
+ * @see #size()
+ */
+ public boolean isEmpty()
+ {
+ return size() == 0;
+ }
+
+ /**
+ * Remove a single instance of an object from this collection (optional
+ * operation). That is, remove one element e such that
+ * <code>(o == null ? e == null : o.equals(e))</code>, if such an element
+ * exists. This implementation obtains an iterator over the collection
+ * and iterates over it, testing each element for equality with the given
+ * object. If it is equal, it is removed by the iterator's remove method
+ * (thus this method will fail with an UnsupportedOperationException if
+ * the Iterator's remove method does). After the first element has been
+ * removed, true is returned; if the end of the collection is reached, false
+ * is returned.
+ *
+ * @param o the object to remove from this collection
+ * @return true if the remove operation caused the Collection to change, or
+ * equivalently if the collection did contain o.
+ * @throws UnsupportedOperationException if this collection's Iterator
+ * does not support the remove method
+ * @see Iterator#remove()
+ */
+ public boolean remove(Object o)
+ {
+ Iterator itr = iterator();
+ int pos = size();
+ while (--pos >= 0)
+ if (equals(o, itr.next()))
+ {
+ itr.remove();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Remove from this collection all its elements that are contained in a given
+ * collection (optional operation). This implementation iterates over this
+ * collection, and for each element tests if it is contained in the given
+ * collection. If so, it is removed by the Iterator's remove method (thus
+ * this method will fail with an UnsupportedOperationException if the
+ * Iterator's remove method does).
+ *
+ * @param c the collection to remove the elements of
+ * @return true if the remove operation caused the Collection to change
+ * @throws UnsupportedOperationException if this collection's Iterator
+ * does not support the remove method
+ * @throws NullPointerException if the collection, c, is null.
+ * @see Iterator#remove()
+ */
+ public boolean removeAll(Collection c)
+ {
+ return removeAllInternal(c);
+ }
+
+ /**
+ * Remove from this collection all its elements that are contained in a given
+ * collection (optional operation). This implementation iterates over this
+ * collection, and for each element tests if it is contained in the given
+ * collection. If so, it is removed by the Iterator's remove method (thus
+ * this method will fail with an UnsupportedOperationException if the
+ * Iterator's remove method does). This method is necessary for ArrayList,
+ * which cannot publicly override removeAll but can optimize this call.
+ *
+ * @param c the collection to remove the elements of
+ * @return true if the remove operation caused the Collection to change
+ * @throws UnsupportedOperationException if this collection's Iterator
+ * does not support the remove method
+ * @throws NullPointerException if the collection, c, is null.
+ * @see Iterator#remove()
+ */
+ // Package visible for use throughout java.util.
+ boolean removeAllInternal(Collection c)
+ {
+ Iterator itr = iterator();
+ boolean modified = false;
+ int pos = size();
+ while (--pos >= 0)
+ if (c.contains(itr.next()))
+ {
+ itr.remove();
+ modified = true;
+ }
+ return modified;
+ }
+
+ /**
+ * Remove from this collection all its elements that are not contained in a
+ * given collection (optional operation). This implementation iterates over
+ * this collection, and for each element tests if it is contained in the
+ * given collection. If not, it is removed by the Iterator's remove method
+ * (thus this method will fail with an UnsupportedOperationException if
+ * the Iterator's remove method does).
+ *
+ * @param c the collection to retain the elements of
+ * @return true if the remove operation caused the Collection to change
+ * @throws UnsupportedOperationException if this collection's Iterator
+ * does not support the remove method
+ * @throws NullPointerException if the collection, c, is null.
+ * @see Iterator#remove()
+ */
+ public boolean retainAll(Collection c)
+ {
+ return retainAllInternal(c);
+ }
+
+ /**
+ * Remove from this collection all its elements that are not contained in a
+ * given collection (optional operation). This implementation iterates over
+ * this collection, and for each element tests if it is contained in the
+ * given collection. If not, it is removed by the Iterator's remove method
+ * (thus this method will fail with an UnsupportedOperationException if
+ * the Iterator's remove method does). This method is necessary for
+ * ArrayList, which cannot publicly override retainAll but can optimize
+ * this call.
+ *
+ * @param c the collection to retain the elements of
+ * @return true if the remove operation caused the Collection to change
+ * @throws UnsupportedOperationException if this collection's Iterator
+ * does not support the remove method
+ * @throws NullPointerException if the collection, c, is null.
+ * @see Iterator#remove()
+ */
+ // Package visible for use throughout java.util.
+ boolean retainAllInternal(Collection c)
+ {
+ Iterator itr = iterator();
+ boolean modified = false;
+ int pos = size();
+ while (--pos >= 0)
+ if (!c.contains(itr.next()))
+ {
+ itr.remove();
+ modified = true;
+ }
+ return modified;
+ }
+
+ /**
+ * Return an array containing the elements of this collection. This
+ * implementation creates an Object array of size size() and then iterates
+ * over the collection, setting each element of the array from the value
+ * returned by the iterator. The returned array is safe, and is not backed
+ * by the collection.
+ *
+ * @return an array containing the elements of this collection
+ */
+ public Object[] toArray()
+ {
+ Iterator itr = iterator();
+ int size = size();
+ Object[] a = new Object[size];
+ for (int pos = 0; pos < size; pos++)
+ a[pos] = itr.next();
+ return a;
+ }
+
+ /**
+ * Copy the collection into a given array if it will fit, or into a
+ * dynamically created array of the same run-time type as the given array if
+ * not. If there is space remaining in the array, the first element after the
+ * end of the collection is set to null (this is only useful if the
+ * collection is known to contain no null elements, however). This
+ * implementation first tests whether the given array is large enough to hold
+ * all the elements of the collection. If not, the reflection API is used to
+ * allocate a new array of the same run-time type. Next an iterator is
+ * obtained over the collection and the elements are placed in the array as
+ * they are returned by the iterator. Finally the first spare element, if
+ * any, of the array is set to null, and the created array is returned.
+ * The returned array is safe; it is not backed by the collection. Note that
+ * null may not mark the last element, if the collection allows null
+ * elements.
+ *
+ * @param a the array to copy into, or of the correct run-time type
+ * @return the array that was produced
+ * @throws NullPointerException if the given array is null
+ * @throws ArrayStoreException if the type of the array precludes holding
+ * one of the elements of the Collection
+ */
+ public Object[] toArray(Object[] a)
+ {
+ int size = size();
+ if (a.length < size)
+ a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
+ size);
+ else if (a.length > size)
+ a[size] = null;
+
+ Iterator itr = iterator();
+ for (int pos = 0; pos < size; pos++)
+ a[pos] = itr.next();
+
+ return a;
+ }
+
+ /**
+ * Creates a String representation of the Collection. The string returned is
+ * of the form "[a, b, ...]" where a and b etc are the results of calling
+ * toString on the elements of the collection. This implementation obtains an
+ * Iterator over the Collection and adds each element to a StringBuffer as it
+ * is returned by the iterator.
+ *
+ * @return a String representation of the Collection
+ */
+ public String toString()
+ {
+ Iterator itr = iterator();
+ StringBuffer r = new StringBuffer("[");
+ for (int pos = size(); pos > 0; pos--)
+ {
+ r.append(itr.next());
+ if (pos > 1)
+ r.append(", ");
+ }
+ r.append("]");
+ return r.toString();
+ }
+
+ /**
+ * Compare two objects according to Collection semantics.
+ *
+ * @param o1 the first object
+ * @param o2 the second object
+ * @return o1 == null ? o2 == null : o1.equals(o2)
+ */
+ // Package visible for use throughout java.util.
+ // It may be inlined since it is final.
+ static final boolean equals(Object o1, Object o2)
+ {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ /**
+ * Hash an object according to Collection semantics.
+ *
+ * @param o the object to hash
+ * @return o1 == null ? 0 : o1.hashCode()
+ */
+ // Package visible for use throughout java.util.
+ // It may be inlined since it is final.
+ static final int hashCode(Object o)
+ {
+ return o == null ? 0 : o.hashCode();
+ }
+}
diff --git a/libjava/classpath/java/util/AbstractList.java b/libjava/classpath/java/util/AbstractList.java
new file mode 100644
index 00000000000..8a9b6f10d7a
--- /dev/null
+++ b/libjava/classpath/java/util/AbstractList.java
@@ -0,0 +1,1225 @@
+/* AbstractList.java -- Abstract implementation of most of List
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A basic implementation of most of the methods in the List interface to make
+ * it easier to create a List based on a random-access data structure. If
+ * the list is sequential (such as a linked list), use AbstractSequentialList.
+ * To create an unmodifiable list, it is only necessary to override the
+ * size() and get(int) methods (this contrasts with all other abstract
+ * collection classes which require an iterator to be provided). To make the
+ * list modifiable, the set(int, Object) method should also be overridden, and
+ * to make the list resizable, the add(int, Object) and remove(int) methods
+ * should be overridden too. Other methods should be overridden if the
+ * backing data structure allows for a more efficient implementation.
+ * The precise implementation used by AbstractList is documented, so that
+ * subclasses can tell which methods could be implemented more efficiently.
+ * <p>
+ *
+ * As recommended by Collection and List, the subclass should provide at
+ * least a no-argument and a Collection constructor. This class is not
+ * synchronized.
+ *
+ * @author Original author unknown
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see List
+ * @see AbstractSequentialList
+ * @see AbstractCollection
+ * @see ListIterator
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class AbstractList extends AbstractCollection implements List
+{
+ /**
+ * A count of the number of structural modifications that have been made to
+ * the list (that is, insertions and removals). Structural modifications
+ * are ones which change the list size or affect how iterations would
+ * behave. This field is available for use by Iterator and ListIterator,
+ * in order to throw a {@link ConcurrentModificationException} in response
+ * to the next operation on the iterator. This <i>fail-fast</i> behavior
+ * saves the user from many subtle bugs otherwise possible from concurrent
+ * modification during iteration.
+ * <p>
+ *
+ * To make lists fail-fast, increment this field by just 1 in the
+ * <code>add(int, Object)</code> and <code>remove(int)</code> methods.
+ * Otherwise, this field may be ignored.
+ */
+ protected transient int modCount;
+
+ /**
+ * The main constructor, for use by subclasses.
+ */
+ protected AbstractList()
+ {
+ }
+
+ /**
+ * Returns the elements at the specified position in the list.
+ *
+ * @param index the element to return
+ * @return the element at that position
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public abstract Object get(int index);
+
+ /**
+ * Insert an element into the list at a given position (optional operation).
+ * This shifts all existing elements from that position to the end one
+ * index to the right. This version of add has no return, since it is
+ * assumed to always succeed if there is no exception. This implementation
+ * always throws UnsupportedOperationException, and must be overridden to
+ * make a modifiable List. If you want fail-fast iterators, be sure to
+ * increment modCount when overriding this.
+ *
+ * @param index the location to insert the item
+ * @param o the object to insert
+ * @throws UnsupportedOperationException if this list does not support the
+ * add operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @see #modCount
+ */
+ public void add(int index, Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Add an element to the end of the list (optional operation). If the list
+ * imposes restraints on what can be inserted, such as no null elements,
+ * this should be documented. This implementation calls
+ * <code>add(size(), o);</code>, and will fail if that version does.
+ *
+ * @param o the object to add
+ * @return true, as defined by Collection for a modified list
+ * @throws UnsupportedOperationException if this list does not support the
+ * add operation
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @see #add(int, Object)
+ */
+ public boolean add(Object o)
+ {
+ add(size(), o);
+ return true;
+ }
+
+ /**
+ * Insert the contents of a collection into the list at a given position
+ * (optional operation). Shift all elements at that position to the right
+ * by the number of elements inserted. This operation is undefined if
+ * this list is modified during the operation (for example, if you try
+ * to insert a list into itself). This implementation uses the iterator of
+ * the collection, repeatedly calling add(int, Object); this will fail
+ * if add does. This can often be made more efficient.
+ *
+ * @param index the location to insert the collection
+ * @param c the collection to insert
+ * @return true if the list was modified by this action, that is, if c is
+ * non-empty
+ * @throws UnsupportedOperationException if this list does not support the
+ * addAll operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws ClassCastException if some element of c cannot be added to this
+ * list due to its type
+ * @throws IllegalArgumentException if some element of c cannot be added
+ * to this list for some other reason
+ * @throws NullPointerException if the specified collection is null
+ * @see #add(int, Object)
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ Iterator itr = c.iterator();
+ int size = c.size();
+ for (int pos = size; pos > 0; pos--)
+ add(index++, itr.next());
+ return size > 0;
+ }
+
+ /**
+ * Clear the list, such that a subsequent call to isEmpty() would return
+ * true (optional operation). This implementation calls
+ * <code>removeRange(0, size())</code>, so it will fail unless remove
+ * or removeRange is overridden.
+ *
+ * @throws UnsupportedOperationException if this list does not support the
+ * clear operation
+ * @see #remove(int)
+ * @see #removeRange(int, int)
+ */
+ public void clear()
+ {
+ removeRange(0, size());
+ }
+
+ /**
+ * Test whether this list is equal to another object. A List is defined to be
+ * equal to an object if and only if that object is also a List, and the two
+ * lists have the same sequence. Two lists l1 and l2 are equal if and only
+ * if <code>l1.size() == l2.size()</code>, and for every integer n between 0
+ * and <code>l1.size() - 1</code> inclusive, <code>l1.get(n) == null ?
+ * l2.get(n) == null : l1.get(n).equals(l2.get(n))</code>.
+ * <p>
+ *
+ * This implementation returns true if the object is this, or false if the
+ * object is not a List. Otherwise, it iterates over both lists (with
+ * iterator()), returning false if two elements compare false or one list
+ * is shorter, and true if the iteration completes successfully.
+ *
+ * @param o the object to test for equality with this list
+ * @return true if o is equal to this list
+ * @see Object#equals(Object)
+ * @see #hashCode()
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ return true;
+ if (! (o instanceof List))
+ return false;
+ int size = size();
+ if (size != ((List) o).size())
+ return false;
+
+ Iterator itr1 = iterator();
+ Iterator itr2 = ((List) o).iterator();
+
+ while (--size >= 0)
+ if (! equals(itr1.next(), itr2.next()))
+ return false;
+ return true;
+ }
+
+ /**
+ * Obtains a hash code for this list. In order to obey the general
+ * contract of the hashCode method of class Object, this value is
+ * calculated as follows:
+ *
+<pre>hashCode = 1;
+Iterator i = list.iterator();
+while (i.hasNext())
+{
+ Object obj = i.next();
+ hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
+}</pre>
+ *
+ * This ensures that the general contract of Object.hashCode() is adhered to.
+ *
+ * @return the hash code of this list
+ *
+ * @see Object#hashCode()
+ * @see #equals(Object)
+ */
+ public int hashCode()
+ {
+ int hashCode = 1;
+ Iterator itr = iterator();
+ int pos = size();
+ while (--pos >= 0)
+ hashCode = 31 * hashCode + hashCode(itr.next());
+ return hashCode;
+ }
+
+ /**
+ * Obtain the first index at which a given object is to be found in this
+ * list. This implementation follows a listIterator() until a match is found,
+ * or returns -1 if the list end is reached.
+ *
+ * @param o the object to search for
+ * @return the least integer n such that <code>o == null ? get(n) == null :
+ * o.equals(get(n))</code>, or -1 if there is no such index
+ */
+ public int indexOf(Object o)
+ {
+ ListIterator itr = listIterator();
+ int size = size();
+ for (int pos = 0; pos < size; pos++)
+ if (equals(o, itr.next()))
+ return pos;
+ return -1;
+ }
+
+ /**
+ * Obtain an Iterator over this list, whose sequence is the list order.
+ * This implementation uses size(), get(int), and remove(int) of the
+ * backing list, and does not support remove unless the list does. This
+ * implementation is fail-fast if you correctly maintain modCount.
+ * Also, this implementation is specified by Sun to be distinct from
+ * listIterator, although you could easily implement it as
+ * <code>return listIterator(0)</code>.
+ *
+ * @return an Iterator over the elements of this list, in order
+ * @see #modCount
+ */
+ public Iterator iterator()
+ {
+ // Bah, Sun's implementation forbids using listIterator(0).
+ return new Iterator()
+ {
+ private int pos = 0;
+ private int size = size();
+ private int last = -1;
+ private int knownMod = modCount;
+
+ // This will get inlined, since it is private.
+ /**
+ * Checks for modifications made to the list from
+ * elsewhere while iteration is in progress.
+ *
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ private void checkMod()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ }
+
+ /**
+ * Tests to see if there are any more objects to
+ * return.
+ *
+ * @return True if the end of the list has not yet been
+ * reached.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public boolean hasNext()
+ {
+ checkMod();
+ return pos < size;
+ }
+
+ /**
+ * Retrieves the next object from the list.
+ *
+ * @return The next object.
+ * @throws NoSuchElementException if there are
+ * no more objects to retrieve.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public Object next()
+ {
+ checkMod();
+ if (pos == size)
+ throw new NoSuchElementException();
+ last = pos;
+ return get(pos++);
+ }
+
+ /**
+ * Removes the last object retrieved by <code>next()</code>
+ * from the list, if the list supports object removal.
+ *
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ * @throws IllegalStateException if the iterator is positioned
+ * before the start of the list or the last object has already
+ * been removed.
+ * @throws UnsupportedOperationException if the list does
+ * not support removing elements.
+ */
+ public void remove()
+ {
+ checkMod();
+ if (last < 0)
+ throw new IllegalStateException();
+ AbstractList.this.remove(last);
+ pos--;
+ size--;
+ last = -1;
+ knownMod = modCount;
+ }
+ };
+ }
+
+ /**
+ * Obtain the last index at which a given object is to be found in this
+ * list. This implementation grabs listIterator(size()), then searches
+ * backwards for a match or returns -1.
+ *
+ * @return the greatest integer n such that <code>o == null ? get(n) == null
+ * : o.equals(get(n))</code>, or -1 if there is no such index
+ */
+ public int lastIndexOf(Object o)
+ {
+ int pos = size();
+ ListIterator itr = listIterator(pos);
+ while (--pos >= 0)
+ if (equals(o, itr.previous()))
+ return pos;
+ return -1;
+ }
+
+ /**
+ * Obtain a ListIterator over this list, starting at the beginning. This
+ * implementation returns listIterator(0).
+ *
+ * @return a ListIterator over the elements of this list, in order, starting
+ * at the beginning
+ */
+ public ListIterator listIterator()
+ {
+ return listIterator(0);
+ }
+
+ /**
+ * Obtain a ListIterator over this list, starting at a given position.
+ * A first call to next() would return the same as get(index), and a
+ * first call to previous() would return the same as get(index - 1).
+ * <p>
+ *
+ * This implementation uses size(), get(int), set(int, Object),
+ * add(int, Object), and remove(int) of the backing list, and does not
+ * support remove, set, or add unless the list does. This implementation
+ * is fail-fast if you correctly maintain modCount.
+ *
+ * @param index the position, between 0 and size() inclusive, to begin the
+ * iteration from
+ * @return a ListIterator over the elements of this list, in order, starting
+ * at index
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @see #modCount
+ */
+ public ListIterator listIterator(final int index)
+ {
+ if (index < 0 || index > size())
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size());
+
+ return new ListIterator()
+ {
+ private int knownMod = modCount;
+ private int position = index;
+ private int lastReturned = -1;
+ private int size = size();
+
+ // This will get inlined, since it is private.
+ /**
+ * Checks for modifications made to the list from
+ * elsewhere while iteration is in progress.
+ *
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ private void checkMod()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ }
+
+ /**
+ * Tests to see if there are any more objects to
+ * return.
+ *
+ * @return True if the end of the list has not yet been
+ * reached.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public boolean hasNext()
+ {
+ checkMod();
+ return position < size;
+ }
+
+ /**
+ * Tests to see if there are objects prior to the
+ * current position in the list.
+ *
+ * @return True if objects exist prior to the current
+ * position of the iterator.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public boolean hasPrevious()
+ {
+ checkMod();
+ return position > 0;
+ }
+
+ /**
+ * Retrieves the next object from the list.
+ *
+ * @return The next object.
+ * @throws NoSuchElementException if there are no
+ * more objects to retrieve.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public Object next()
+ {
+ checkMod();
+ if (position == size)
+ throw new NoSuchElementException();
+ lastReturned = position;
+ return get(position++);
+ }
+
+ /**
+ * Retrieves the previous object from the list.
+ *
+ * @return The next object.
+ * @throws NoSuchElementException if there are no
+ * previous objects to retrieve.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public Object previous()
+ {
+ checkMod();
+ if (position == 0)
+ throw new NoSuchElementException();
+ lastReturned = --position;
+ return get(lastReturned);
+ }
+
+ /**
+ * Returns the index of the next element in the
+ * list, which will be retrieved by <code>next()</code>
+ *
+ * @return The index of the next element.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public int nextIndex()
+ {
+ checkMod();
+ return position;
+ }
+
+ /**
+ * Returns the index of the previous element in the
+ * list, which will be retrieved by <code>previous()</code>
+ *
+ * @return The index of the previous element.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public int previousIndex()
+ {
+ checkMod();
+ return position - 1;
+ }
+
+ /**
+ * Removes the last object retrieved by <code>next()</code>
+ * or <code>previous()</code> from the list, if the list
+ * supports object removal.
+ *
+ * @throws IllegalStateException if the iterator is positioned
+ * before the start of the list or the last object has already
+ * been removed.
+ * @throws UnsupportedOperationException if the list does
+ * not support removing elements.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public void remove()
+ {
+ checkMod();
+ if (lastReturned < 0)
+ throw new IllegalStateException();
+ AbstractList.this.remove(lastReturned);
+ size--;
+ position = lastReturned;
+ lastReturned = -1;
+ knownMod = modCount;
+ }
+
+ /**
+ * Replaces the last object retrieved by <code>next()</code>
+ * or <code>previous</code> with o, if the list supports object
+ * replacement and an add or remove operation has not already
+ * been performed.
+ *
+ * @throws IllegalStateException if the iterator is positioned
+ * before the start of the list or the last object has already
+ * been removed.
+ * @throws UnsupportedOperationException if the list doesn't support
+ * the addition or removal of elements.
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this list.
+ * @throws IllegalArgumentException if something else related to o
+ * prevents its addition.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public void set(Object o)
+ {
+ checkMod();
+ if (lastReturned < 0)
+ throw new IllegalStateException();
+ AbstractList.this.set(lastReturned, o);
+ }
+
+ /**
+ * Adds the supplied object before the element that would be returned
+ * by a call to <code>next()</code>, if the list supports addition.
+ *
+ * @param o The object to add to the list.
+ * @throws UnsupportedOperationException if the list doesn't support
+ * the addition of new elements.
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this list.
+ * @throws IllegalArgumentException if something else related to o
+ * prevents its addition.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public void add(Object o)
+ {
+ checkMod();
+ AbstractList.this.add(position++, o);
+ size++;
+ lastReturned = -1;
+ knownMod = modCount;
+ }
+ };
+ }
+
+ /**
+ * Remove the element at a given position in this list (optional operation).
+ * Shifts all remaining elements to the left to fill the gap. This
+ * implementation always throws an UnsupportedOperationException.
+ * If you want fail-fast iterators, be sure to increment modCount when
+ * overriding this.
+ *
+ * @param index the position within the list of the object to remove
+ * @return the object that was removed
+ * @throws UnsupportedOperationException if this list does not support the
+ * remove operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ * @see #modCount
+ */
+ public Object remove(int index)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Remove a subsection of the list. This is called by the clear and
+ * removeRange methods of the class which implements subList, which are
+ * difficult for subclasses to override directly. Therefore, this method
+ * should be overridden instead by the more efficient implementation, if one
+ * exists. Overriding this can reduce quadratic efforts to constant time
+ * in some cases!
+ * <p>
+ *
+ * This implementation first checks for illegal or out of range arguments. It
+ * then obtains a ListIterator over the list using listIterator(fromIndex).
+ * It then calls next() and remove() on this iterator repeatedly, toIndex -
+ * fromIndex times.
+ *
+ * @param fromIndex the index, inclusive, to remove from.
+ * @param toIndex the index, exclusive, to remove to.
+ * @throws UnsupportedOperationException if the list does
+ * not support removing elements.
+ */
+ protected void removeRange(int fromIndex, int toIndex)
+ {
+ ListIterator itr = listIterator(fromIndex);
+ for (int index = fromIndex; index < toIndex; index++)
+ {
+ itr.next();
+ itr.remove();
+ }
+ }
+
+ /**
+ * Replace an element of this list with another object (optional operation).
+ * This implementation always throws an UnsupportedOperationException.
+ *
+ * @param index the position within this list of the element to be replaced
+ * @param o the object to replace it with
+ * @return the object that was replaced
+ * @throws UnsupportedOperationException if this list does not support the
+ * set operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ */
+ public Object set(int index, Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Obtain a List view of a subsection of this list, from fromIndex
+ * (inclusive) to toIndex (exclusive). If the two indices are equal, the
+ * sublist is empty. The returned list should be modifiable if and only
+ * if this list is modifiable. Changes to the returned list should be
+ * reflected in this list. If this list is structurally modified in
+ * any way other than through the returned list, the result of any subsequent
+ * operations on the returned list is undefined.
+ * <p>
+ *
+ * This implementation returns a subclass of AbstractList. It stores, in
+ * private fields, the offset and size of the sublist, and the expected
+ * modCount of the backing list. If the backing list implements RandomAccess,
+ * the sublist will also.
+ * <p>
+ *
+ * The subclass's <code>set(int, Object)</code>, <code>get(int)</code>,
+ * <code>add(int, Object)</code>, <code>remove(int)</code>,
+ * <code>addAll(int, Collection)</code> and
+ * <code>removeRange(int, int)</code> methods all delegate to the
+ * corresponding methods on the backing abstract list, after
+ * bounds-checking the index and adjusting for the offset. The
+ * <code>addAll(Collection c)</code> method merely returns addAll(size, c).
+ * The <code>listIterator(int)</code> method returns a "wrapper object"
+ * over a list iterator on the backing list, which is created with the
+ * corresponding method on the backing list. The <code>iterator()</code>
+ * method merely returns listIterator(), and the <code>size()</code> method
+ * merely returns the subclass's size field.
+ * <p>
+ *
+ * All methods first check to see if the actual modCount of the backing
+ * list is equal to its expected value, and throw a
+ * ConcurrentModificationException if it is not.
+ *
+ * @param fromIndex the index that the returned list should start from
+ * (inclusive)
+ * @param toIndex the index that the returned list should go to (exclusive)
+ * @return a List backed by a subsection of this list
+ * @throws IndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; size()
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @see ConcurrentModificationException
+ * @see RandomAccess
+ */
+ public List subList(int fromIndex, int toIndex)
+ {
+ // This follows the specification of AbstractList, but is inconsistent
+ // with the one in List. Don't you love Sun's inconsistencies?
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException(fromIndex + " > " + toIndex);
+ if (fromIndex < 0 || toIndex > size())
+ throw new IndexOutOfBoundsException();
+
+ if (this instanceof RandomAccess)
+ return new RandomAccessSubList(this, fromIndex, toIndex);
+ return new SubList(this, fromIndex, toIndex);
+ }
+
+ /**
+ * This class follows the implementation requirements set forth in
+ * {@link AbstractList#subList(int, int)}. It matches Sun's implementation
+ * by using a non-public top-level class in the same package.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class SubList extends AbstractList
+ {
+ // Package visible, for use by iterator.
+ /** The original list. */
+ final AbstractList backingList;
+ /** The index of the first element of the sublist. */
+ final int offset;
+ /** The size of the sublist. */
+ int size;
+
+ /**
+ * Construct the sublist.
+ *
+ * @param backing the list this comes from
+ * @param fromIndex the lower bound, inclusive
+ * @param toIndex the upper bound, exclusive
+ */
+ SubList(AbstractList backing, int fromIndex, int toIndex)
+ {
+ backingList = backing;
+ modCount = backing.modCount;
+ offset = fromIndex;
+ size = toIndex - fromIndex;
+ }
+
+ /**
+ * This method checks the two modCount fields to ensure that there has
+ * not been a concurrent modification, returning if all is okay.
+ *
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ */
+ // This can be inlined. Package visible, for use by iterator.
+ void checkMod()
+ {
+ if (modCount != backingList.modCount)
+ throw new ConcurrentModificationException();
+ }
+
+ /**
+ * This method checks that a value is between 0 and size (inclusive). If
+ * it is not, an exception is thrown.
+ *
+ * @param index the value to check
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ // This will get inlined, since it is private.
+ private void checkBoundsInclusive(int index)
+ {
+ if (index < 0 || index > size)
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size);
+ }
+
+ /**
+ * This method checks that a value is between 0 (inclusive) and size
+ * (exclusive). If it is not, an exception is thrown.
+ *
+ * @param index the value to check
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ // This will get inlined, since it is private.
+ private void checkBoundsExclusive(int index)
+ {
+ if (index < 0 || index >= size)
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size);
+ }
+
+ /**
+ * Specified by AbstractList.subList to return the private field size.
+ *
+ * @return the sublist size
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ */
+ public int size()
+ {
+ checkMod();
+ return size;
+ }
+
+ /**
+ * Specified by AbstractList.subList to delegate to the backing list.
+ *
+ * @param index the location to modify
+ * @param o the new value
+ * @return the old value
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ * @throws UnsupportedOperationException if the backing list does not
+ * support the set operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ * @throws ClassCastException if o cannot be added to the backing list due
+ * to its type
+ * @throws IllegalArgumentException if o cannot be added to the backing list
+ * for some other reason
+ */
+ public Object set(int index, Object o)
+ {
+ checkMod();
+ checkBoundsExclusive(index);
+ return backingList.set(index + offset, o);
+ }
+
+ /**
+ * Specified by AbstractList.subList to delegate to the backing list.
+ *
+ * @param index the location to get from
+ * @return the object at that location
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object get(int index)
+ {
+ checkMod();
+ checkBoundsExclusive(index);
+ return backingList.get(index + offset);
+ }
+
+ /**
+ * Specified by AbstractList.subList to delegate to the backing list.
+ *
+ * @param index the index to insert at
+ * @param o the object to add
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws UnsupportedOperationException if the backing list does not
+ * support the add operation.
+ * @throws ClassCastException if o cannot be added to the backing list due
+ * to its type.
+ * @throws IllegalArgumentException if o cannot be added to the backing
+ * list for some other reason.
+ */
+ public void add(int index, Object o)
+ {
+ checkMod();
+ checkBoundsInclusive(index);
+ backingList.add(index + offset, o);
+ size++;
+ modCount = backingList.modCount;
+ }
+
+ /**
+ * Specified by AbstractList.subList to delegate to the backing list.
+ *
+ * @param index the index to remove
+ * @return the removed object
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ * @throws UnsupportedOperationException if the backing list does not
+ * support the remove operation
+ */
+ public Object remove(int index)
+ {
+ checkMod();
+ checkBoundsExclusive(index);
+ Object o = backingList.remove(index + offset);
+ size--;
+ modCount = backingList.modCount;
+ return o;
+ }
+
+ /**
+ * Specified by AbstractList.subList to delegate to the backing list.
+ * This does no bounds checking, as it assumes it will only be called
+ * by trusted code like clear() which has already checked the bounds.
+ *
+ * @param fromIndex the lower bound, inclusive
+ * @param toIndex the upper bound, exclusive
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ * @throws UnsupportedOperationException if the backing list does
+ * not support removing elements.
+ */
+ protected void removeRange(int fromIndex, int toIndex)
+ {
+ checkMod();
+
+ backingList.removeRange(offset + fromIndex, offset + toIndex);
+ size -= toIndex - fromIndex;
+ modCount = backingList.modCount;
+ }
+
+ /**
+ * Specified by AbstractList.subList to delegate to the backing list.
+ *
+ * @param index the location to insert at
+ * @param c the collection to insert
+ * @return true if this list was modified, in other words, c is non-empty
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws UnsupportedOperationException if this list does not support the
+ * addAll operation
+ * @throws ClassCastException if some element of c cannot be added to this
+ * list due to its type
+ * @throws IllegalArgumentException if some element of c cannot be added
+ * to this list for some other reason
+ * @throws NullPointerException if the specified collection is null
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ checkMod();
+ checkBoundsInclusive(index);
+ int csize = c.size();
+ boolean result = backingList.addAll(offset + index, c);
+ size += csize;
+ modCount = backingList.modCount;
+ return result;
+ }
+
+ /**
+ * Specified by AbstractList.subList to return addAll(size, c).
+ *
+ * @param c the collection to insert
+ * @return true if this list was modified, in other words, c is non-empty
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ * @throws UnsupportedOperationException if this list does not support the
+ * addAll operation
+ * @throws ClassCastException if some element of c cannot be added to this
+ * list due to its type
+ * @throws IllegalArgumentException if some element of c cannot be added
+ * to this list for some other reason
+ * @throws NullPointerException if the specified collection is null
+ */
+ public boolean addAll(Collection c)
+ {
+ return addAll(size, c);
+ }
+
+ /**
+ * Specified by AbstractList.subList to return listIterator().
+ *
+ * @return an iterator over the sublist
+ */
+ public Iterator iterator()
+ {
+ return listIterator();
+ }
+
+ /**
+ * Specified by AbstractList.subList to return a wrapper around the
+ * backing list's iterator.
+ *
+ * @param index the start location of the iterator
+ * @return a list iterator over the sublist
+ * @throws ConcurrentModificationException if the backing list has been
+ * modified externally to this sublist
+ * @throws IndexOutOfBoundsException if the value is out of range
+ */
+ public ListIterator listIterator(final int index)
+ {
+ checkMod();
+ checkBoundsInclusive(index);
+
+ return new ListIterator()
+ {
+ private final ListIterator i = backingList.listIterator(index + offset);
+ private int position = index;
+
+ /**
+ * Tests to see if there are any more objects to
+ * return.
+ *
+ * @return True if the end of the list has not yet been
+ * reached.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public boolean hasNext()
+ {
+ checkMod();
+ return position < size;
+ }
+
+ /**
+ * Tests to see if there are objects prior to the
+ * current position in the list.
+ *
+ * @return True if objects exist prior to the current
+ * position of the iterator.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public boolean hasPrevious()
+ {
+ checkMod();
+ return position > 0;
+ }
+
+ /**
+ * Retrieves the next object from the list.
+ *
+ * @return The next object.
+ * @throws NoSuchElementException if there are no
+ * more objects to retrieve.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public Object next()
+ {
+ if (position == size)
+ throw new NoSuchElementException();
+ position++;
+ return i.next();
+ }
+
+ /**
+ * Retrieves the previous object from the list.
+ *
+ * @return The next object.
+ * @throws NoSuchElementException if there are no
+ * previous objects to retrieve.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public Object previous()
+ {
+ if (position == 0)
+ throw new NoSuchElementException();
+ position--;
+ return i.previous();
+ }
+
+ /**
+ * Returns the index of the next element in the
+ * list, which will be retrieved by <code>next()</code>
+ *
+ * @return The index of the next element.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public int nextIndex()
+ {
+ return i.nextIndex() - offset;
+ }
+
+ /**
+ * Returns the index of the previous element in the
+ * list, which will be retrieved by <code>previous()</code>
+ *
+ * @return The index of the previous element.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public int previousIndex()
+ {
+ return i.previousIndex() - offset;
+ }
+
+ /**
+ * Removes the last object retrieved by <code>next()</code>
+ * from the list, if the list supports object removal.
+ *
+ * @throws IllegalStateException if the iterator is positioned
+ * before the start of the list or the last object has already
+ * been removed.
+ * @throws UnsupportedOperationException if the list does
+ * not support removing elements.
+ */
+ public void remove()
+ {
+ i.remove();
+ size--;
+ position = nextIndex();
+ modCount = backingList.modCount;
+ }
+
+
+ /**
+ * Replaces the last object retrieved by <code>next()</code>
+ * or <code>previous</code> with o, if the list supports object
+ * replacement and an add or remove operation has not already
+ * been performed.
+ *
+ * @throws IllegalStateException if the iterator is positioned
+ * before the start of the list or the last object has already
+ * been removed.
+ * @throws UnsupportedOperationException if the list doesn't support
+ * the addition or removal of elements.
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this list.
+ * @throws IllegalArgumentException if something else related to o
+ * prevents its addition.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public void set(Object o)
+ {
+ i.set(o);
+ }
+
+ /**
+ * Adds the supplied object before the element that would be returned
+ * by a call to <code>next()</code>, if the list supports addition.
+ *
+ * @param o The object to add to the list.
+ * @throws UnsupportedOperationException if the list doesn't support
+ * the addition of new elements.
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this list.
+ * @throws IllegalArgumentException if something else related to o
+ * prevents its addition.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public void add(Object o)
+ {
+ i.add(o);
+ size++;
+ position++;
+ modCount = backingList.modCount;
+ }
+
+ // Here is the reason why the various modCount fields are mostly
+ // ignored in this wrapper listIterator.
+ // If the backing listIterator is failfast, then the following holds:
+ // Using any other method on this list will call a corresponding
+ // method on the backing list *after* the backing listIterator
+ // is created, which will in turn cause a ConcurrentModException
+ // when this listIterator comes to use the backing one. So it is
+ // implicitly failfast.
+ // If the backing listIterator is NOT failfast, then the whole of
+ // this list isn't failfast, because the modCount field of the
+ // backing list is not valid. It would still be *possible* to
+ // make the iterator failfast wrt modifications of the sublist
+ // only, but somewhat pointless when the list can be changed under
+ // us.
+ // Either way, no explicit handling of modCount is needed.
+ // However modCount = backingList.modCount must be executed in add
+ // and remove, and size must also be updated in these two methods,
+ // since they do not go through the corresponding methods of the subList.
+ };
+ }
+ } // class SubList
+
+ /**
+ * This class is a RandomAccess version of SubList, as required by
+ * {@link AbstractList#subList(int, int)}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class RandomAccessSubList extends SubList
+ implements RandomAccess
+ {
+ /**
+ * Construct the sublist.
+ *
+ * @param backing the list this comes from
+ * @param fromIndex the lower bound, inclusive
+ * @param toIndex the upper bound, exclusive
+ */
+ RandomAccessSubList(AbstractList backing, int fromIndex, int toIndex)
+ {
+ super(backing, fromIndex, toIndex);
+ }
+ } // class RandomAccessSubList
+
+} // class AbstractList
diff --git a/libjava/classpath/java/util/AbstractMap.java b/libjava/classpath/java/util/AbstractMap.java
new file mode 100644
index 00000000000..7cd6436a308
--- /dev/null
+++ b/libjava/classpath/java/util/AbstractMap.java
@@ -0,0 +1,749 @@
+/* AbstractMap.java -- Abstract implementation of most of Map
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An abstract implementation of Map to make it easier to create your own
+ * implementations. In order to create an unmodifiable Map, subclass
+ * AbstractMap and implement the <code>entrySet</code> (usually via an
+ * AbstractSet). To make it modifiable, also implement <code>put</code>,
+ * and have <code>entrySet().iterator()</code> support <code>remove</code>.
+ * <p>
+ *
+ * It is recommended that classes which extend this support at least the
+ * no-argument constructor, and a constructor which accepts another Map.
+ * Further methods in this class may be overridden if you have a more
+ * efficient implementation.
+ *
+ * @author Original author unknown
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Map
+ * @see Collection
+ * @see HashMap
+ * @see LinkedHashMap
+ * @see TreeMap
+ * @see WeakHashMap
+ * @see IdentityHashMap
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class AbstractMap implements Map
+{
+ /** An "enum" of iterator types. */
+ // Package visible for use by subclasses.
+ static final int KEYS = 0,
+ VALUES = 1,
+ ENTRIES = 2;
+
+ /**
+ * The cache for {@link #keySet()}.
+ */
+ // Package visible for use by subclasses.
+ Set keys;
+
+ /**
+ * The cache for {@link #values()}.
+ */
+ // Package visible for use by subclasses.
+ Collection values;
+
+ /**
+ * The main constructor, for use by subclasses.
+ */
+ protected AbstractMap()
+ {
+ }
+
+ /**
+ * Returns a set view of the mappings in this Map. Each element in the
+ * set must be an implementation of 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 must be valid:
+ * <code>Iterator.remove</code>, <code>Set.remove</code>,
+ * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
+ * Element addition is not supported via this set.
+ *
+ * @return the entry set
+ * @see Map.Entry
+ */
+ public abstract Set entrySet();
+
+ /**
+ * Remove all entries from this Map (optional operation). This default
+ * implementation calls entrySet().clear(). NOTE: If the entry set does
+ * not permit clearing, then this will fail, too. Subclasses often
+ * override this for efficiency. Your implementation of entrySet() should
+ * not call <code>AbstractMap.clear</code> unless you want an infinite loop.
+ *
+ * @throws UnsupportedOperationException if <code>entrySet().clear()</code>
+ * does not support clearing.
+ * @see Set#clear()
+ */
+ public void clear()
+ {
+ entrySet().clear();
+ }
+
+ /**
+ * Create a shallow copy of this Map, no keys or values are copied. The
+ * default implementation simply calls <code>super.clone()</code>.
+ *
+ * @return the shallow clone
+ * @throws CloneNotSupportedException if a subclass is not Cloneable
+ * @see Cloneable
+ * @see Object#clone()
+ */
+ protected Object clone() throws CloneNotSupportedException
+ {
+ AbstractMap copy = (AbstractMap) super.clone();
+ // Clear out the caches; they are stale.
+ copy.keys = null;
+ copy.values = null;
+ return copy;
+ }
+
+ /**
+ * Returns true if this contains a mapping for the given key. This
+ * implementation does a linear search, O(n), over the
+ * <code>entrySet()</code>, returning <code>true</code> if a match
+ * is found, <code>false</code> if the iteration ends. Many subclasses
+ * can implement this more efficiently.
+ *
+ * @param key the key to search for
+ * @return true if the map contains the key
+ * @throws NullPointerException if key is <code>null</code> but the map
+ * does not permit null keys
+ * @see #containsValue(Object)
+ */
+ public boolean containsKey(Object key)
+ {
+ Iterator entries = entrySet().iterator();
+ int pos = size();
+ while (--pos >= 0)
+ if (equals(key, ((Map.Entry) entries.next()).getKey()))
+ return true;
+ return false;
+ }
+
+ /**
+ * Returns true if this contains at least one mapping with the given value.
+ * This implementation does a linear search, O(n), over the
+ * <code>entrySet()</code>, returning <code>true</code> if a match
+ * is found, <code>false</code> if the iteration ends. A match is
+ * defined as a value, v, where <code>(value == null ? v == null :
+ * value.equals(v))</code>. Subclasses are unlikely to implement
+ * this more efficiently.
+ *
+ * @param value the value to search for
+ * @return true if the map contains the value
+ * @see #containsKey(Object)
+ */
+ public boolean containsValue(Object value)
+ {
+ Iterator entries = entrySet().iterator();
+ int pos = size();
+ while (--pos >= 0)
+ if (equals(value, ((Map.Entry) entries.next()).getValue()))
+ return true;
+ return false;
+ }
+
+ /**
+ * Compares the specified object with this map for equality. Returns
+ * <code>true</code> if the other object is a Map with the same mappings,
+ * that is,<br>
+ * <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
+ *
+ * @param o the object to be compared
+ * @return true if the object equals this map
+ * @see Set#equals(Object)
+ */
+ public boolean equals(Object o)
+ {
+ return (o == this ||
+ (o instanceof Map &&
+ entrySet().equals(((Map) o).entrySet())));
+ }
+
+ /**
+ * Returns the value mapped by the given key. Returns <code>null</code> if
+ * there is no mapping. However, in Maps that accept null values, you
+ * must rely on <code>containsKey</code> to determine if a mapping exists.
+ * This iteration takes linear time, searching entrySet().iterator() of
+ * the key. Many implementations override this method.
+ *
+ * @param key the key to look up
+ * @return the value associated with the key, or null if key not in map
+ * @throws NullPointerException if this map does not accept null keys
+ * @see #containsKey(Object)
+ */
+ public Object get(Object key)
+ {
+ Iterator entries = entrySet().iterator();
+ int pos = size();
+ while (--pos >= 0)
+ {
+ Map.Entry entry = (Map.Entry) entries.next();
+ if (equals(key, entry.getKey()))
+ return entry.getValue();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the hash code for this map. As defined in Map, this is the sum
+ * of all hashcodes for each Map.Entry object in entrySet, or basically
+ * entrySet().hashCode().
+ *
+ * @return the hash code
+ * @see Map.Entry#hashCode()
+ * @see Set#hashCode()
+ */
+ public int hashCode()
+ {
+ return entrySet().hashCode();
+ }
+
+ /**
+ * Returns true if the map contains no mappings. This is implemented by
+ * <code>size() == 0</code>.
+ *
+ * @return true if the map is empty
+ * @see #size()
+ */
+ public boolean isEmpty()
+ {
+ return size() == 0;
+ }
+
+ /**
+ * Returns a set view of this map's keys. The set is backed by the map,
+ * so changes in one show up in the other. Modifications while an iteration
+ * is in progress produce undefined behavior. The set supports removal
+ * if entrySet() does, but does not support element addition.
+ * <p>
+ *
+ * This implementation creates an AbstractSet, where the iterator wraps
+ * the entrySet iterator, size defers to the Map's size, and contains
+ * defers to the Map's containsKey. The set is created on first use, and
+ * returned on subsequent uses, although since no synchronization occurs,
+ * there is a slight possibility of creating two sets.
+ *
+ * @return a Set view of the keys
+ * @see Set#iterator()
+ * @see #size()
+ * @see #containsKey(Object)
+ * @see #values()
+ */
+ public Set keySet()
+ {
+ if (keys == null)
+ keys = new AbstractSet()
+ {
+ /**
+ * Retrieves the number of keys in the backing map.
+ *
+ * @return The number of keys.
+ */
+ public int size()
+ {
+ return AbstractMap.this.size();
+ }
+
+ /**
+ * Returns true if the backing map contains the
+ * supplied key.
+ *
+ * @param key The key to search for.
+ * @return True if the key was found, false otherwise.
+ */
+ public boolean contains(Object key)
+ {
+ return containsKey(key);
+ }
+
+ /**
+ * Returns an iterator which iterates over the keys
+ * in the backing map, using a wrapper around the
+ * iterator returned by <code>entrySet()</code>.
+ *
+ * @return An iterator over the keys.
+ */
+ public Iterator iterator()
+ {
+ return new Iterator()
+ {
+ /**
+ * The iterator returned by <code>entrySet()</code>.
+ */
+ private final Iterator map_iterator = entrySet().iterator();
+
+ /**
+ * Returns true if a call to <code>next()</code> will
+ * return another key.
+ *
+ * @return True if the iterator has not yet reached
+ * the last key.
+ */
+ public boolean hasNext()
+ {
+ return map_iterator.hasNext();
+ }
+
+ /**
+ * Returns the key from the next entry retrieved
+ * by the underlying <code>entrySet()</code> iterator.
+ *
+ * @return The next key.
+ */
+ public Object next()
+ {
+ return ((Map.Entry) map_iterator.next()).getKey();
+ }
+
+ /**
+ * Removes the map entry which has a key equal
+ * to that returned by the last call to
+ * <code>next()</code>.
+ *
+ * @throws UnsupportedOperationException if the
+ * map doesn't support removal.
+ */
+ public void remove()
+ {
+ map_iterator.remove();
+ }
+ };
+ }
+ };
+ return keys;
+ }
+
+ /**
+ * Associates the given key to the given value (optional operation). If the
+ * map already contains the key, its value is replaced. This implementation
+ * simply throws an UnsupportedOperationException. Be aware that in a map
+ * that permits <code>null</code> values, a null return does not always
+ * imply that the mapping was created.
+ *
+ * @param key the key to map
+ * @param value the value to be mapped
+ * @return the previous value of the key, or null if there was no mapping
+ * @throws UnsupportedOperationException if the operation is not supported
+ * @throws ClassCastException if the key or value is of the wrong type
+ * @throws IllegalArgumentException if something about this key or value
+ * prevents it from existing in this map
+ * @throws NullPointerException if the map forbids null keys or values
+ * @see #containsKey(Object)
+ */
+ public Object put(Object key, Object value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Copies all entries of the given map to this one (optional operation). If
+ * the map already contains a key, its value is replaced. This implementation
+ * simply iterates over the map's entrySet(), calling <code>put</code>,
+ * so it is not supported if puts are not.
+ *
+ * @param m the mapping to load into this map
+ * @throws UnsupportedOperationException if the operation is not supported
+ * by this map.
+ * @throws ClassCastException if a key or value is of the wrong type for
+ * adding to this map.
+ * @throws IllegalArgumentException if something about a key or value
+ * prevents it from existing in this map.
+ * @throws NullPointerException if the map forbids null keys or values.
+ * @throws NullPointerException if <code>m</code> is null.
+ * @see #put(Object, Object)
+ */
+ public void putAll(Map m)
+ {
+ Iterator entries = m.entrySet().iterator();
+ int pos = m.size();
+ while (--pos >= 0)
+ {
+ Map.Entry entry = (Map.Entry) entries.next();
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * Removes the mapping for this key if present (optional operation). This
+ * implementation iterates over the entrySet searching for a matching
+ * key, at which point it calls the iterator's <code>remove</code> method.
+ * It returns the result of <code>getValue()</code> on the entry, if found,
+ * or null if no entry is found. Note that maps which permit null values
+ * may also return null if the key was removed. If the entrySet does not
+ * support removal, this will also fail. This is O(n), so many
+ * implementations override it for efficiency.
+ *
+ * @param key the key to remove
+ * @return the value the key mapped to, or null if not present.
+ * Null may also be returned if null values are allowed
+ * in the map and the value of this mapping is null.
+ * @throws UnsupportedOperationException if deletion is unsupported
+ * @see Iterator#remove()
+ */
+ public Object remove(Object key)
+ {
+ Iterator entries = entrySet().iterator();
+ int pos = size();
+ while (--pos >= 0)
+ {
+ Map.Entry entry = (Map.Entry) entries.next();
+ if (equals(key, entry.getKey()))
+ {
+ // Must get the value before we remove it from iterator.
+ Object r = entry.getValue();
+ entries.remove();
+ return r;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the number of key-value mappings in the map. If there are more
+ * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
+ * implemented as <code>entrySet().size()</code>.
+ *
+ * @return the number of mappings
+ * @see Set#size()
+ */
+ public int size()
+ {
+ return entrySet().size();
+ }
+
+ /**
+ * Returns a String representation of this map. This is a listing of the
+ * map entries (which are specified in Map.Entry as being
+ * <code>getKey() + "=" + getValue()</code>), separated by a comma and
+ * space (", "), and surrounded by braces ('{' and '}'). This implementation
+ * uses a StringBuffer and iterates over the entrySet to build the String.
+ * Note that this can fail with an exception if underlying keys or
+ * values complete abruptly in toString().
+ *
+ * @return a String representation
+ * @see Map.Entry#toString()
+ */
+ public String toString()
+ {
+ Iterator entries = entrySet().iterator();
+ StringBuffer r = new StringBuffer("{");
+ for (int pos = size(); pos > 0; pos--)
+ {
+ Map.Entry entry = (Map.Entry) entries.next();
+ r.append(entry.getKey());
+ r.append('=');
+ r.append(entry.getValue());
+ if (pos > 1)
+ r.append(", ");
+ }
+ r.append("}");
+ return r.toString();
+ }
+
+ /**
+ * Returns a collection or bag view of this map's values. The collection
+ * is backed by the map, so changes in one show up in the other.
+ * Modifications while an iteration is in progress produce undefined
+ * behavior. The collection supports removal if entrySet() does, but
+ * does not support element addition.
+ * <p>
+ *
+ * This implementation creates an AbstractCollection, where the iterator
+ * wraps the entrySet iterator, size defers to the Map's size, and contains
+ * defers to the Map's containsValue. The collection is created on first
+ * use, and returned on subsequent uses, although since no synchronization
+ * occurs, there is a slight possibility of creating two collections.
+ *
+ * @return a Collection view of the values
+ * @see Collection#iterator()
+ * @see #size()
+ * @see #containsValue(Object)
+ * @see #keySet()
+ */
+ public Collection values()
+ {
+ if (values == null)
+ values = new AbstractCollection()
+ {
+ /**
+ * Returns the number of values stored in
+ * the backing map.
+ *
+ * @return The number of values.
+ */
+ public int size()
+ {
+ return AbstractMap.this.size();
+ }
+
+ /**
+ * Returns true if the backing map contains
+ * the supplied value.
+ *
+ * @param value The value to search for.
+ * @return True if the value was found, false otherwise.
+ */
+ public boolean contains(Object value)
+ {
+ return containsValue(value);
+ }
+
+ /**
+ * Returns an iterator which iterates over the
+ * values in the backing map, by using a wrapper
+ * around the iterator returned by <code>entrySet()</code>.
+ *
+ * @return An iterator over the values.
+ */
+ public Iterator iterator()
+ {
+ return new Iterator()
+ {
+ /**
+ * The iterator returned by <code>entrySet()</code>.
+ */
+ private final Iterator map_iterator = entrySet().iterator();
+
+ /**
+ * Returns true if a call to <code>next()</call> will
+ * return another value.
+ *
+ * @return True if the iterator has not yet reached
+ * the last value.
+ */
+ public boolean hasNext()
+ {
+ return map_iterator.hasNext();
+ }
+
+ /**
+ * Returns the value from the next entry retrieved
+ * by the underlying <code>entrySet()</code> iterator.
+ *
+ * @return The next value.
+ */
+ public Object next()
+ {
+ return ((Map.Entry) map_iterator.next()).getValue();
+ }
+
+ /**
+ * Removes the map entry which has a key equal
+ * to that returned by the last call to
+ * <code>next()</code>.
+ *
+ * @throws UnsupportedOperationException if the
+ * map doesn't support removal.
+ */
+ public void remove()
+ {
+ map_iterator.remove();
+ }
+ };
+ }
+ };
+ return values;
+ }
+
+ /**
+ * Compare two objects according to Collection semantics.
+ *
+ * @param o1 the first object
+ * @param o2 the second object
+ * @return o1 == null ? o2 == null : o1.equals(o2)
+ */
+ // Package visible for use throughout java.util.
+ // It may be inlined since it is final.
+ static final boolean equals(Object o1, Object o2)
+ {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ /**
+ * Hash an object according to Collection semantics.
+ *
+ * @param o the object to hash
+ * @return o1 == null ? 0 : o1.hashCode()
+ */
+ // Package visible for use throughout java.util.
+ // It may be inlined since it is final.
+ static final int hashCode(Object o)
+ {
+ return o == null ? 0 : o.hashCode();
+ }
+
+ /**
+ * A class which implements Map.Entry. It is shared by HashMap, TreeMap,
+ * Hashtable, and Collections. It is not specified by the JDK, but makes
+ * life much easier.
+ *
+ * @author Jon Zeppieri
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ // XXX - FIXME Use fully qualified implements as gcj 3.1 workaround.
+ // Bug still exists in 3.4.1
+ static class BasicMapEntry implements Map.Entry
+ {
+ /**
+ * The key. Package visible for direct manipulation.
+ */
+ Object key;
+
+ /**
+ * The value. Package visible for direct manipulation.
+ */
+ Object value;
+
+ /**
+ * Basic constructor initializes the fields.
+ * @param newKey the key
+ * @param newValue the value
+ */
+ BasicMapEntry(Object newKey, Object newValue)
+ {
+ key = newKey;
+ value = newValue;
+ }
+
+ /**
+ * Compares the specified object with this entry. Returns true only if
+ * the object is a mapping of identical key and value. In other words,
+ * this must be:<br>
+ * <pre>(o instanceof Map.Entry)
+ * && (getKey() == null ? ((HashMap) o).getKey() == null
+ * : getKey().equals(((HashMap) o).getKey()))
+ * && (getValue() == null ? ((HashMap) o).getValue() == null
+ * : getValue().equals(((HashMap) o).getValue()))</pre>
+ *
+ * @param o the object to compare
+ * @return <code>true</code> if it is equal
+ */
+ public final boolean equals(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ // Optimize for our own entries.
+ if (o instanceof BasicMapEntry)
+ {
+ BasicMapEntry e = (BasicMapEntry) o;
+ return (AbstractMap.equals(key, e.key)
+ && AbstractMap.equals(value, e.value));
+ }
+ Map.Entry e = (Map.Entry) o;
+ return (AbstractMap.equals(key, e.getKey())
+ && AbstractMap.equals(value, e.getValue()));
+ }
+
+ /**
+ * Get the key corresponding to this entry.
+ *
+ * @return the key
+ */
+ public final Object getKey()
+ {
+ return key;
+ }
+
+ /**
+ * Get the value corresponding to this entry. If you already called
+ * Iterator.remove(), the behavior undefined, but in this case it works.
+ *
+ * @return the value
+ */
+ public final Object getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the hash code of the entry. This is defined as the exclusive-or
+ * of the hashcodes of the key and value (using 0 for null). In other
+ * words, this must be:<br>
+ * <pre>(getKey() == null ? 0 : getKey().hashCode())
+ * ^ (getValue() == null ? 0 : getValue().hashCode())</pre>
+ *
+ * @return the hash code
+ */
+ public final int hashCode()
+ {
+ return (AbstractMap.hashCode(key) ^ AbstractMap.hashCode(value));
+ }
+
+ /**
+ * Replaces the value with the specified object. This writes through
+ * to the map, unless you have already called Iterator.remove(). It
+ * may be overridden to restrict a null value.
+ *
+ * @param newVal the new value to store
+ * @return the old value
+ * @throws NullPointerException if the map forbids null values.
+ * @throws UnsupportedOperationException if the map doesn't support
+ * <code>put()</code>.
+ * @throws ClassCastException if the value is of a type unsupported
+ * by the map.
+ * @throws IllegalArgumentException if something else about this
+ * value prevents it being stored in the map.
+ */
+ public Object setValue(Object newVal)
+ {
+ Object r = value;
+ value = newVal;
+ return r;
+ }
+
+ /**
+ * This provides a string representation of the entry. It is of the form
+ * "key=value", where string concatenation is used on key and value.
+ *
+ * @return the string representation
+ */
+ public final String toString()
+ {
+ return key + "=" + value;
+ }
+ } // class BasicMapEntry
+}
diff --git a/libjava/classpath/java/util/AbstractSequentialList.java b/libjava/classpath/java/util/AbstractSequentialList.java
new file mode 100644
index 00000000000..79583228d96
--- /dev/null
+++ b/libjava/classpath/java/util/AbstractSequentialList.java
@@ -0,0 +1,235 @@
+/* AbstractSequentialList.java -- List implementation for sequential access
+ Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Abstract superclass to make it easier to implement the List interface when
+ * backed by a sequential-access store, such as a linked list. For random
+ * access data, use AbstractList. This class implements the random access
+ * methods (<code>get</code>, <code>set</code>, <code>add</code>, and
+ * <code>remove</code>) atop the list iterator, opposite of AbstractList's
+ * approach of implementing the iterator atop random access.
+ * <p>
+ *
+ * To implement a list, you need an implementation for <code>size()</code>
+ * and <code>listIterator</code>. With just <code>hasNext</code>,
+ * <code>next</code>, <code>hasPrevious</code>, <code>previous</code>,
+ * <code>nextIndex</code>, and <code>previousIndex</code>, you have an
+ * unmodifiable list. For a modifiable one, add <code>set</code>, and for
+ * a variable-size list, add <code>add</code> and <code>remove</code>.
+ * <p>
+ *
+ * The programmer should provide a no-argument constructor, and one that
+ * accepts another Collection, as recommended by the Collection interface.
+ * Unfortunately, there is no way to enforce this in Java.
+ *
+ * @author Original author unknown
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see List
+ * @see AbstractList
+ * @see AbstractCollection
+ * @see ListIterator
+ * @see LinkedList
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class AbstractSequentialList extends AbstractList
+{
+ /**
+ * The main constructor, for use by subclasses.
+ */
+ protected AbstractSequentialList()
+ {
+ }
+
+ /**
+ * Returns a ListIterator over the list, starting from position index.
+ * Subclasses must provide an implementation of this method.
+ *
+ * @param index the starting position of the list
+ * @return the list iterator
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public abstract ListIterator listIterator(int index);
+
+ /**
+ * Insert an element into the list at a given position (optional operation).
+ * This shifts all existing elements from that position to the end one
+ * index to the right. This version of add has no return, since it is
+ * assumed to always succeed if there is no exception. This iteration
+ * uses listIterator(index).add(o).
+ *
+ * @param index the location to insert the item
+ * @param o the object to insert
+ * @throws UnsupportedOperationException if this list does not support the
+ * add operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason.
+ * @throws NullPointerException if o is null and the list does not permit
+ * the addition of null values.
+ */
+ public void add(int index, Object o)
+ {
+ listIterator(index).add(o);
+ }
+
+ /**
+ * Insert the contents of a collection into the list at a given position
+ * (optional operation). Shift all elements at that position to the right
+ * by the number of elements inserted. This operation is undefined if
+ * this list is modified during the operation (for example, if you try
+ * to insert a list into itself).
+ * <p>
+ *
+ * This implementation grabs listIterator(index), then proceeds to use add
+ * for each element returned by c's iterator. Sun's online specs are wrong,
+ * claiming that this also calls next(): listIterator.add() correctly
+ * skips the added element.
+ *
+ * @param index the location to insert the collection
+ * @param c the collection to insert
+ * @return true if the list was modified by this action, that is, if c is
+ * non-empty
+ * @throws UnsupportedOperationException if this list does not support the
+ * addAll operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws ClassCastException if some element of c cannot be added to this
+ * list due to its type
+ * @throws IllegalArgumentException if some element of c cannot be added
+ * to this list for some other reason
+ * @throws NullPointerException if the specified collection is null
+ * @throws NullPointerException if an object, o, in c is null and the list
+ * does not permit the addition of null values.
+ * @see #add(int, Object)
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ Iterator ci = c.iterator();
+ int size = c.size();
+ ListIterator i = listIterator(index);
+ for (int pos = size; pos > 0; pos--)
+ i.add(ci.next());
+ return size > 0;
+ }
+
+ /**
+ * Get the element at a given index in this list. This implementation
+ * returns listIterator(index).next().
+ *
+ * @param index the index of the element to be returned
+ * @return the element at index index in this list
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object get(int index)
+ {
+ // This is a legal listIterator position, but an illegal get.
+ if (index == size())
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size());
+ return listIterator(index).next();
+ }
+
+ /**
+ * Obtain an Iterator over this list, whose sequence is the list order. This
+ * implementation returns listIterator().
+ *
+ * @return an Iterator over the elements of this list, in order
+ */
+ public Iterator iterator()
+ {
+ return listIterator();
+ }
+
+ /**
+ * Remove the element at a given position in this list (optional operation).
+ * Shifts all remaining elements to the left to fill the gap. This
+ * implementation uses listIterator(index) and ListIterator.remove().
+ *
+ * @param index the position within the list of the object to remove
+ * @return the object that was removed
+ * @throws UnsupportedOperationException if this list does not support the
+ * remove operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object remove(int index)
+ {
+ // This is a legal listIterator position, but an illegal remove.
+ if (index == size())
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size());
+ ListIterator i = listIterator(index);
+ Object removed = i.next();
+ i.remove();
+ return removed;
+ }
+
+ /**
+ * Replace an element of this list with another object (optional operation).
+ * This implementation uses listIterator(index) and ListIterator.set(o).
+ *
+ * @param index the position within this list of the element to be replaced
+ * @param o the object to replace it with
+ * @return the object that was replaced
+ * @throws UnsupportedOperationException if this list does not support the
+ * set operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @throws NullPointerException if o is null and the list does not allow
+ * a value to be set to null.
+ */
+ public Object set(int index, Object o)
+ {
+ // This is a legal listIterator position, but an illegal set.
+ if (index == size())
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size());
+ ListIterator i = listIterator(index);
+ Object old = i.next();
+ i.set(o);
+ return old;
+ }
+}
diff --git a/libjava/classpath/java/util/AbstractSet.java b/libjava/classpath/java/util/AbstractSet.java
new file mode 100644
index 00000000000..f0d7cb19908
--- /dev/null
+++ b/libjava/classpath/java/util/AbstractSet.java
@@ -0,0 +1,139 @@
+/* AbstractSet.java -- Abstract implementation of most of Set
+ Copyright (C) 1998, 2000, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An abstract implementation of Set to make it easier to create your own
+ * implementations. In order to create a Set, subclass AbstractSet and
+ * implement the same methods that are required for AbstractCollection
+ * (although these methods must of course meet the requirements that Set puts
+ * on them - specifically, no element may be in the set more than once). This
+ * class simply provides implementations of equals() and hashCode() to fulfil
+ * the requirements placed on them by the Set interface.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see AbstractCollection
+ * @see Set
+ * @see HashSet
+ * @see TreeSet
+ * @see LinkedHashSet
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class AbstractSet extends AbstractCollection implements Set
+{
+ /**
+ * The main constructor, for use by subclasses.
+ */
+ protected AbstractSet()
+ {
+ }
+
+ /**
+ * Tests whether the given object is equal to this Set. This implementation
+ * first checks whether this set <em>is</em> the given object, and returns
+ * true if so. Otherwise, if o is a Set and is the same size as this one, it
+ * returns the result of calling containsAll on the given Set. Otherwise, it
+ * returns false.
+ *
+ * @param o the Object to be tested for equality with this Set
+ * @return true if the given object is equal to this Set
+ */
+ public boolean equals(Object o)
+ {
+ return (o == this ||
+ (o instanceof Set && ((Set) o).size() == size()
+ && containsAll((Collection) o)));
+ }
+
+ /**
+ * Returns a hash code for this Set. The hash code of a Set is the sum of the
+ * hash codes of all its elements, except that the hash code of null is
+ * defined to be zero. This implementation obtains an Iterator over the Set,
+ * and sums the results.
+ *
+ * @return a hash code for this Set
+ */
+ public int hashCode()
+ {
+ Iterator itr = iterator();
+ int hash = 0;
+ int pos = size();
+ while (--pos >= 0)
+ hash += hashCode(itr.next());
+ return hash;
+ }
+
+ /**
+ * Removes from this set all elements in the given collection (optional
+ * operation). This implementation uses <code>size()</code> to determine
+ * the smaller collection. Then, if this set is smaller, it iterates
+ * over the set, calling Iterator.remove if the collection contains
+ * the element. If this set is larger, it iterates over the collection,
+ * calling Set.remove for all elements in the collection. Note that
+ * this operation will fail if a remove methods is not supported.
+ *
+ * @param c the collection of elements to remove
+ * @return true if the set was modified as a result
+ * @throws UnsupportedOperationException if remove is not supported
+ * @throws NullPointerException if the collection is null
+ * @see AbstractCollection#remove(Object)
+ * @see Collection#contains(Object)
+ * @see Iterator#remove()
+ */
+ public boolean removeAll(Collection c)
+ {
+ int oldsize = size();
+ int count = c.size();
+ Iterator i;
+ if (oldsize < count)
+ {
+ for (i = iterator(), count = oldsize; count > 0; count--)
+ if (c.contains(i.next()))
+ i.remove();
+ }
+ else
+ for (i = c.iterator(); count > 0; count--)
+ remove(i.next());
+ return oldsize != size();
+ }
+
+}
diff --git a/libjava/classpath/java/util/ArrayList.java b/libjava/classpath/java/util/ArrayList.java
new file mode 100644
index 00000000000..82bcca8c3e0
--- /dev/null
+++ b/libjava/classpath/java/util/ArrayList.java
@@ -0,0 +1,591 @@
+/* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed
+ implementation of the List interface
+ Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+
+/**
+ * An array-backed implementation of the List interface. This implements
+ * all optional list operations, and permits null elements, so that it is
+ * better than Vector, which it replaces. Random access is roughly constant
+ * time, and iteration is roughly linear time, so it is nice and fast, with
+ * less overhead than a LinkedList.
+ * <p>
+ *
+ * Each list has a capacity, and as the array reaches that capacity it
+ * is automatically transferred to a larger array. You also have access to
+ * ensureCapacity and trimToSize to control the backing array's size, avoiding
+ * reallocation or wasted memory.
+ * <p>
+ *
+ * ArrayList is not synchronized, so if you need multi-threaded access,
+ * consider using:<br>
+ * <code>List l = Collections.synchronizedList(new ArrayList(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon A. Zeppieri
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see List
+ * @see LinkedList
+ * @see Vector
+ * @see Collections#synchronizedList(List)
+ * @see AbstractList
+ * @status updated to 1.4
+ */
+public class ArrayList extends AbstractList
+ implements List, RandomAccess, Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.2
+ */
+ private static final long serialVersionUID = 8683452581122892189L;
+
+ /**
+ * The default capacity for new ArrayLists.
+ */
+ private static final int DEFAULT_CAPACITY = 16;
+
+ /**
+ * The number of elements in this list.
+ * @serial the list size
+ */
+ private int size;
+
+ /**
+ * Where the data is stored.
+ */
+ private transient Object[] data;
+
+ /**
+ * Construct a new ArrayList with the supplied initial capacity.
+ *
+ * @param capacity initial capacity of this ArrayList
+ * @throws IllegalArgumentException if capacity is negative
+ */
+ public ArrayList(int capacity)
+ {
+ // Must explicitly check, to get correct exception.
+ if (capacity < 0)
+ throw new IllegalArgumentException();
+ data = new Object[capacity];
+ }
+
+ /**
+ * Construct a new ArrayList with the default capacity (16).
+ */
+ public ArrayList()
+ {
+ this(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * Construct a new ArrayList, and initialize it with the elements
+ * in the supplied Collection. The initial capacity is 110% of the
+ * Collection's size.
+ *
+ * @param c the collection whose elements will initialize this list
+ * @throws NullPointerException if c is null
+ */
+ public ArrayList(Collection c)
+ {
+ this((int) (c.size() * 1.1f));
+ addAll(c);
+ }
+
+ /**
+ * Trims the capacity of this List to be equal to its size;
+ * a memory saver.
+ */
+ public void trimToSize()
+ {
+ // Not a structural change from the perspective of iterators on this list,
+ // so don't update modCount.
+ if (size != data.length)
+ {
+ Object[] newData = new Object[size];
+ System.arraycopy(data, 0, newData, 0, size);
+ data = newData;
+ }
+ }
+
+ /**
+ * Guarantees that this list will have at least enough capacity to
+ * hold minCapacity elements. This implementation will grow the list to
+ * max(current * 2, minCapacity) if (minCapacity &gt; current). The JCL says
+ * explictly that "this method increases its capacity to minCap", while
+ * the JDK 1.3 online docs specify that the list will grow to at least the
+ * size specified.
+ *
+ * @param minCapacity the minimum guaranteed capacity
+ */
+ public void ensureCapacity(int minCapacity)
+ {
+ int current = data.length;
+
+ if (minCapacity > current)
+ {
+ Object[] newData = new Object[Math.max(current * 2, minCapacity)];
+ System.arraycopy(data, 0, newData, 0, size);
+ data = newData;
+ }
+ }
+
+ /**
+ * Returns the number of elements in this list.
+ *
+ * @return the list size
+ */
+ public int size()
+ {
+ return size;
+ }
+
+ /**
+ * Checks if the list is empty.
+ *
+ * @return true if there are no elements
+ */
+ public boolean isEmpty()
+ {
+ return size == 0;
+ }
+
+ /**
+ * Returns true iff element is in this ArrayList.
+ *
+ * @param e the element whose inclusion in the List is being tested
+ * @return true if the list contains e
+ */
+ public boolean contains(Object e)
+ {
+ return indexOf(e) != -1;
+ }
+
+ /**
+ * Returns the lowest index at which element appears in this List, or
+ * -1 if it does not appear.
+ *
+ * @param e the element whose inclusion in the List is being tested
+ * @return the index where e was found
+ */
+ public int indexOf(Object e)
+ {
+ for (int i = 0; i < size; i++)
+ if (equals(e, data[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the highest index at which element appears in this List, or
+ * -1 if it does not appear.
+ *
+ * @param e the element whose inclusion in the List is being tested
+ * @return the index where e was found
+ */
+ public int lastIndexOf(Object e)
+ {
+ for (int i = size - 1; i >= 0; i--)
+ if (equals(e, data[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Creates a shallow copy of this ArrayList (elements are not cloned).
+ *
+ * @return the cloned object
+ */
+ public Object clone()
+ {
+ ArrayList clone = null;
+ try
+ {
+ clone = (ArrayList) super.clone();
+ clone.data = (Object[]) data.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // Impossible to get here.
+ }
+ return clone;
+ }
+
+ /**
+ * Returns an Object array containing all of the elements in this ArrayList.
+ * The array is independent of this list.
+ *
+ * @return an array representation of this list
+ */
+ public Object[] toArray()
+ {
+ Object[] array = new Object[size];
+ System.arraycopy(data, 0, array, 0, size);
+ return array;
+ }
+
+ /**
+ * Returns an Array whose component type is the runtime component type of
+ * the passed-in Array. The returned Array is populated with all of the
+ * elements in this ArrayList. If the passed-in Array is not large enough
+ * to store all of the elements in this List, a new Array will be created
+ * and returned; if the passed-in Array is <i>larger</i> than the size
+ * of this List, then size() index will be set to null.
+ *
+ * @param a the passed-in Array
+ * @return an array representation of this list
+ * @throws ArrayStoreException if the runtime type of a does not allow
+ * an element in this list
+ * @throws NullPointerException if a is null
+ */
+ public Object[] toArray(Object[] a)
+ {
+ if (a.length < size)
+ a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
+ size);
+ else if (a.length > size)
+ a[size] = null;
+ System.arraycopy(data, 0, a, 0, size);
+ return a;
+ }
+
+ /**
+ * Retrieves the element at the user-supplied index.
+ *
+ * @param index the index of the element we are fetching
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object get(int index)
+ {
+ checkBoundExclusive(index);
+ return data[index];
+ }
+
+ /**
+ * Sets the element at the specified index. The new element, e,
+ * can be an object of any type or null.
+ *
+ * @param index the index at which the element is being set
+ * @param e the element to be set
+ * @return the element previously at the specified index
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= 0
+ */
+ public Object set(int index, Object e)
+ {
+ checkBoundExclusive(index);
+ Object result = data[index];
+ data[index] = e;
+ return result;
+ }
+
+ /**
+ * Appends the supplied element to the end of this list.
+ * The element, e, can be an object of any type or null.
+ *
+ * @param e the element to be appended to this list
+ * @return true, the add will always succeed
+ */
+ public boolean add(Object e)
+ {
+ modCount++;
+ if (size == data.length)
+ ensureCapacity(size + 1);
+ data[size++] = e;
+ return true;
+ }
+
+ /**
+ * Adds the supplied element at the specified index, shifting all
+ * elements currently at that index or higher one to the right.
+ * The element, e, can be an object of any type or null.
+ *
+ * @param index the index at which the element is being added
+ * @param e the item being added
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public void add(int index, Object e)
+ {
+ checkBoundInclusive(index);
+ modCount++;
+ if (size == data.length)
+ ensureCapacity(size + 1);
+ if (index != size)
+ System.arraycopy(data, index, data, index + 1, size - index);
+ data[index] = e;
+ size++;
+ }
+
+ /**
+ * Removes the element at the user-supplied index.
+ *
+ * @param index the index of the element to be removed
+ * @return the removed Object
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object remove(int index)
+ {
+ checkBoundExclusive(index);
+ Object r = data[index];
+ modCount++;
+ if (index != --size)
+ System.arraycopy(data, index + 1, data, index, size - index);
+ // Aid for garbage collection by releasing this pointer.
+ data[size] = null;
+ return r;
+ }
+
+ /**
+ * Removes all elements from this List
+ */
+ public void clear()
+ {
+ if (size > 0)
+ {
+ modCount++;
+ // Allow for garbage collection.
+ Arrays.fill(data, 0, size, null);
+ size = 0;
+ }
+ }
+
+ /**
+ * Add each element in the supplied Collection to this List. It is undefined
+ * what happens if you modify the list while this is taking place; for
+ * example, if the collection contains this list. c can contain objects
+ * of any type, as well as null values.
+ *
+ * @param c a Collection containing elements to be added to this List
+ * @return true if the list was modified, in other words c is not empty
+ * @throws NullPointerException if c is null
+ */
+ public boolean addAll(Collection c)
+ {
+ return addAll(size, c);
+ }
+
+ /**
+ * Add all elements in the supplied collection, inserting them beginning
+ * at the specified index. c can contain objects of any type, as well
+ * as null values.
+ *
+ * @param index the index at which the elements will be inserted
+ * @param c the Collection containing the elements to be inserted
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; 0
+ * @throws NullPointerException if c is null
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ checkBoundInclusive(index);
+ Iterator itr = c.iterator();
+ int csize = c.size();
+
+ modCount++;
+ if (csize + size > data.length)
+ ensureCapacity(size + csize);
+ int end = index + csize;
+ if (size > 0 && index != size)
+ System.arraycopy(data, index, data, end, size - index);
+ size += csize;
+ for ( ; index < end; index++)
+ data[index] = itr.next();
+ return csize > 0;
+ }
+
+ /**
+ * Removes all elements in the half-open interval [fromIndex, toIndex).
+ * Does nothing when toIndex is equal to fromIndex.
+ *
+ * @param fromIndex the first index which will be removed
+ * @param toIndex one greater than the last index which will be removed
+ * @throws IndexOutOfBoundsException if fromIndex &gt; toIndex
+ */
+ protected void removeRange(int fromIndex, int toIndex)
+ {
+ int change = toIndex - fromIndex;
+ if (change > 0)
+ {
+ modCount++;
+ System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
+ size -= change;
+ }
+ else if (change < 0)
+ throw new IndexOutOfBoundsException();
+ }
+
+ /**
+ * Checks that the index is in the range of possible elements (inclusive).
+ *
+ * @param index the index to check
+ * @throws IndexOutOfBoundsException if index &gt; size
+ */
+ private void checkBoundInclusive(int index)
+ {
+ // Implementation note: we do not check for negative ranges here, since
+ // use of a negative index will cause an ArrayIndexOutOfBoundsException,
+ // a subclass of the required exception, with no effort on our part.
+ if (index > size)
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ + size);
+ }
+
+ /**
+ * Checks that the index is in the range of existing elements (exclusive).
+ *
+ * @param index the index to check
+ * @throws IndexOutOfBoundsException if index &gt;= size
+ */
+ private void checkBoundExclusive(int index)
+ {
+ // Implementation note: we do not check for negative ranges here, since
+ // use of a negative index will cause an ArrayIndexOutOfBoundsException,
+ // a subclass of the required exception, with no effort on our part.
+ if (index >= size)
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ + size);
+ }
+
+ /**
+ * Remove from this list all elements contained in the given collection.
+ * This is not public, due to Sun's API, but this performs in linear
+ * time while the default behavior of AbstractList would be quadratic.
+ *
+ * @param c the collection to filter out
+ * @return true if this list changed
+ * @throws NullPointerException if c is null
+ */
+ boolean removeAllInternal(Collection c)
+ {
+ int i;
+ int j;
+ for (i = 0; i < size; i++)
+ if (c.contains(data[i]))
+ break;
+ if (i == size)
+ return false;
+
+ modCount++;
+ for (j = i++; i < size; i++)
+ if (! c.contains(data[i]))
+ data[j++] = data[i];
+ size -= i - j;
+ return true;
+ }
+
+ /**
+ * Retain in this vector only the elements contained in the given collection.
+ * This is not public, due to Sun's API, but this performs in linear
+ * time while the default behavior of AbstractList would be quadratic.
+ *
+ * @param c the collection to filter by
+ * @return true if this vector changed
+ * @throws NullPointerException if c is null
+ * @since 1.2
+ */
+ boolean retainAllInternal(Collection c)
+ {
+ int i;
+ int j;
+ for (i = 0; i < size; i++)
+ if (! c.contains(data[i]))
+ break;
+ if (i == size)
+ return false;
+
+ modCount++;
+ for (j = i++; i < size; i++)
+ if (c.contains(data[i]))
+ data[j++] = data[i];
+ size -= i - j;
+ return true;
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param out the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData the size field (int), the length of the backing array
+ * (int), followed by its elements (Objects) in proper order.
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ // The 'size' field.
+ s.defaultWriteObject();
+ // We serialize unused list entries to preserve capacity.
+ int len = data.length;
+ s.writeInt(len);
+ // it would be more efficient to just write "size" items,
+ // this need readObject read "size" items too.
+ for (int i = 0; i < size; i++)
+ s.writeObject(data[i]);
+ }
+
+ /**
+ * Deserializes this object from the given stream.
+ *
+ * @param in the stream to read from
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @serialData the size field (int), the length of the backing array
+ * (int), followed by its elements (Objects) in proper order.
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ // the `size' field.
+ s.defaultReadObject();
+ int capacity = s.readInt();
+ data = new Object[capacity];
+ for (int i = 0; i < size; i++)
+ data[i] = s.readObject();
+ }
+}
diff --git a/libjava/classpath/java/util/Arrays.java b/libjava/classpath/java/util/Arrays.java
new file mode 100644
index 00000000000..15c1a5f33bf
--- /dev/null
+++ b/libjava/classpath/java/util/Arrays.java
@@ -0,0 +1,2510 @@
+/* Arrays.java -- Utility class with methods to operate on arrays
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+
+/**
+ * This class contains various static utility methods performing operations on
+ * arrays, and a method to provide a List "view" of an array to facilitate
+ * using arrays with Collection-based APIs. All methods throw a
+ * {@link NullPointerException} if the parameter array is null.
+ * <p>
+ *
+ * Implementations may use their own algorithms, but must obey the general
+ * properties; for example, the sort must be stable and n*log(n) complexity.
+ * Sun's implementation of sort, and therefore ours, is a tuned quicksort,
+ * adapted from Jon L. Bentley and M. Douglas McIlroy's "Engineering a Sort
+ * Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265
+ * (November 1993). This algorithm offers n*log(n) performance on many data
+ * sets that cause other quicksorts to degrade to quadratic performance.
+ *
+ * @author Original author unknown
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Comparable
+ * @see Comparator
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class Arrays
+{
+ /**
+ * This class is non-instantiable.
+ */
+ private Arrays()
+ {
+ }
+
+
+// binarySearch
+ /**
+ * Perform a binary search of a byte array for a key. The array must be
+ * sorted (as by the sort() method) - if it is not, the behaviour of this
+ * method is undefined, and may be an infinite loop. If the array contains
+ * the key more than once, any one of them may be found. Note: although the
+ * specification allows for an infinite loop if the array is unsorted, it
+ * will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ */
+ public static int binarySearch(byte[] a, byte key)
+ {
+ int low = 0;
+ int hi = a.length - 1;
+ int mid = 0;
+ while (low <= hi)
+ {
+ mid = (low + hi) >> 1;
+ final byte d = a[mid];
+ if (d == key)
+ return mid;
+ else if (d > key)
+ hi = mid - 1;
+ else
+ // This gets the insertion point right on the last loop.
+ low = ++mid;
+ }
+ return -mid - 1;
+ }
+
+ /**
+ * Perform a binary search of a char array for a key. The array must be
+ * sorted (as by the sort() method) - if it is not, the behaviour of this
+ * method is undefined, and may be an infinite loop. If the array contains
+ * the key more than once, any one of them may be found. Note: although the
+ * specification allows for an infinite loop if the array is unsorted, it
+ * will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ */
+ public static int binarySearch(char[] a, char key)
+ {
+ int low = 0;
+ int hi = a.length - 1;
+ int mid = 0;
+ while (low <= hi)
+ {
+ mid = (low + hi) >> 1;
+ final char d = a[mid];
+ if (d == key)
+ return mid;
+ else if (d > key)
+ hi = mid - 1;
+ else
+ // This gets the insertion point right on the last loop.
+ low = ++mid;
+ }
+ return -mid - 1;
+ }
+
+ /**
+ * Perform a binary search of a short array for a key. The array must be
+ * sorted (as by the sort() method) - if it is not, the behaviour of this
+ * method is undefined, and may be an infinite loop. If the array contains
+ * the key more than once, any one of them may be found. Note: although the
+ * specification allows for an infinite loop if the array is unsorted, it
+ * will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ */
+ public static int binarySearch(short[] a, short key)
+ {
+ int low = 0;
+ int hi = a.length - 1;
+ int mid = 0;
+ while (low <= hi)
+ {
+ mid = (low + hi) >> 1;
+ final short d = a[mid];
+ if (d == key)
+ return mid;
+ else if (d > key)
+ hi = mid - 1;
+ else
+ // This gets the insertion point right on the last loop.
+ low = ++mid;
+ }
+ return -mid - 1;
+ }
+
+ /**
+ * Perform a binary search of an int array for a key. The array must be
+ * sorted (as by the sort() method) - if it is not, the behaviour of this
+ * method is undefined, and may be an infinite loop. If the array contains
+ * the key more than once, any one of them may be found. Note: although the
+ * specification allows for an infinite loop if the array is unsorted, it
+ * will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ */
+ public static int binarySearch(int[] a, int key)
+ {
+ int low = 0;
+ int hi = a.length - 1;
+ int mid = 0;
+ while (low <= hi)
+ {
+ mid = (low + hi) >> 1;
+ final int d = a[mid];
+ if (d == key)
+ return mid;
+ else if (d > key)
+ hi = mid - 1;
+ else
+ // This gets the insertion point right on the last loop.
+ low = ++mid;
+ }
+ return -mid - 1;
+ }
+
+ /**
+ * Perform a binary search of a long array for a key. The array must be
+ * sorted (as by the sort() method) - if it is not, the behaviour of this
+ * method is undefined, and may be an infinite loop. If the array contains
+ * the key more than once, any one of them may be found. Note: although the
+ * specification allows for an infinite loop if the array is unsorted, it
+ * will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ */
+ public static int binarySearch(long[] a, long key)
+ {
+ int low = 0;
+ int hi = a.length - 1;
+ int mid = 0;
+ while (low <= hi)
+ {
+ mid = (low + hi) >> 1;
+ final long d = a[mid];
+ if (d == key)
+ return mid;
+ else if (d > key)
+ hi = mid - 1;
+ else
+ // This gets the insertion point right on the last loop.
+ low = ++mid;
+ }
+ return -mid - 1;
+ }
+
+ /**
+ * Perform a binary search of a float array for a key. The array must be
+ * sorted (as by the sort() method) - if it is not, the behaviour of this
+ * method is undefined, and may be an infinite loop. If the array contains
+ * the key more than once, any one of them may be found. Note: although the
+ * specification allows for an infinite loop if the array is unsorted, it
+ * will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ */
+ public static int binarySearch(float[] a, float key)
+ {
+ // Must use Float.compare to take into account NaN, +-0.
+ int low = 0;
+ int hi = a.length - 1;
+ int mid = 0;
+ while (low <= hi)
+ {
+ mid = (low + hi) >> 1;
+ final int r = Float.compare(a[mid], key);
+ if (r == 0)
+ return mid;
+ else if (r > 0)
+ hi = mid - 1;
+ else
+ // This gets the insertion point right on the last loop
+ low = ++mid;
+ }
+ return -mid - 1;
+ }
+
+ /**
+ * Perform a binary search of a double array for a key. The array must be
+ * sorted (as by the sort() method) - if it is not, the behaviour of this
+ * method is undefined, and may be an infinite loop. If the array contains
+ * the key more than once, any one of them may be found. Note: although the
+ * specification allows for an infinite loop if the array is unsorted, it
+ * will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ */
+ public static int binarySearch(double[] a, double key)
+ {
+ // Must use Double.compare to take into account NaN, +-0.
+ int low = 0;
+ int hi = a.length - 1;
+ int mid = 0;
+ while (low <= hi)
+ {
+ mid = (low + hi) >> 1;
+ final int r = Double.compare(a[mid], key);
+ if (r == 0)
+ return mid;
+ else if (r > 0)
+ hi = mid - 1;
+ else
+ // This gets the insertion point right on the last loop
+ low = ++mid;
+ }
+ return -mid - 1;
+ }
+
+ /**
+ * Perform a binary search of an Object array for a key, using the natural
+ * ordering of the elements. The array must be sorted (as by the sort()
+ * method) - if it is not, the behaviour of this method is undefined, and may
+ * be an infinite loop. Further, the key must be comparable with every item
+ * in the array. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this (JCL)
+ * implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws ClassCastException if key could not be compared with one of the
+ * elements of a
+ * @throws NullPointerException if a null element in a is compared
+ */
+ public static int binarySearch(Object[] a, Object key)
+ {
+ return binarySearch(a, key, null);
+ }
+
+ /**
+ * Perform a binary search of an Object array for a key, using a supplied
+ * Comparator. The array must be sorted (as by the sort() method with the
+ * same Comparator) - if it is not, the behaviour of this method is
+ * undefined, and may be an infinite loop. Further, the key must be
+ * comparable with every item in the array. If the array contains the key
+ * more than once, any one of them may be found. Note: although the
+ * specification allows for an infinite loop if the array is unsorted, it
+ * will not happen in this (JCL) implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param key the value to search for
+ * @param c the comparator by which the array is sorted; or null to
+ * use the elements' natural order
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws ClassCastException if key could not be compared with one of the
+ * elements of a
+ * @throws NullPointerException if a null element is compared with natural
+ * ordering (only possible when c is null)
+ */
+ public static int binarySearch(Object[] a, Object key, Comparator c)
+ {
+ int low = 0;
+ int hi = a.length - 1;
+ int mid = 0;
+ while (low <= hi)
+ {
+ mid = (low + hi) >> 1;
+ final int d = Collections.compare(key, a[mid], c);
+ if (d == 0)
+ return mid;
+ else if (d < 0)
+ hi = mid - 1;
+ else
+ // This gets the insertion point right on the last loop
+ low = ++mid;
+ }
+ return -mid - 1;
+ }
+
+
+// equals
+ /**
+ * Compare two boolean arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a2 is of the same length
+ * as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+ */
+ public static boolean equals(boolean[] a1, boolean[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (a1[i] != a2[i])
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two byte arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a2 is of the same length
+ * as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+ */
+ public static boolean equals(byte[] a1, byte[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (a1[i] != a2[i])
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two char arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a2 is of the same length
+ * as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+ */
+ public static boolean equals(char[] a1, char[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (a1[i] != a2[i])
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two short arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a2 is of the same length
+ * as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+ */
+ public static boolean equals(short[] a1, short[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (a1[i] != a2[i])
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two int arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a2 is of the same length
+ * as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+ */
+ public static boolean equals(int[] a1, int[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (a1[i] != a2[i])
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two long arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a2 is of the same length
+ * as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+ */
+ public static boolean equals(long[] a1, long[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (a1[i] != a2[i])
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two float arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a2 is of the same length
+ * as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+ */
+ public static boolean equals(float[] a1, float[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // Must use Float.compare to take into account NaN, +-0.
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (Float.compare(a1[i], a2[i]) != 0)
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two double arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a2 is of the same length
+ * as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+ */
+ public static boolean equals(double[] a1, double[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // Must use Double.compare to take into account NaN, +-0.
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (Double.compare(a1[i], a2[i]) != 0)
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two Object arrays for equality.
+ *
+ * @param a1 the first array to compare
+ * @param a2 the second array to compare
+ * @return true if a1 and a2 are both null, or if a1 is of the same length
+ * as a2, and for each 0 <= i < a.length, a1[i] == null ?
+ * a2[i] == null : a1[i].equals(a2[i]).
+ */
+ public static boolean equals(Object[] a1, Object[] a2)
+ {
+ // Quick test which saves comparing elements of the same array, and also
+ // catches the case that both are null.
+ if (a1 == a2)
+ return true;
+
+ if (null == a1 || null == a2)
+ return false;
+
+ // If they're the same length, test each element
+ if (a1.length == a2.length)
+ {
+ int i = a1.length;
+ while (--i >= 0)
+ if (! AbstractCollection.equals(a1[i], a2[i]))
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+
+// fill
+ /**
+ * Fill an array with a boolean value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ */
+ public static void fill(boolean[] a, boolean val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with a boolean value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(boolean[] a, int fromIndex, int toIndex, boolean val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+ /**
+ * Fill an array with a byte value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ */
+ public static void fill(byte[] a, byte val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with a byte value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(byte[] a, int fromIndex, int toIndex, byte val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+ /**
+ * Fill an array with a char value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ */
+ public static void fill(char[] a, char val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with a char value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(char[] a, int fromIndex, int toIndex, char val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+ /**
+ * Fill an array with a short value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ */
+ public static void fill(short[] a, short val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with a short value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(short[] a, int fromIndex, int toIndex, short val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+ /**
+ * Fill an array with an int value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ */
+ public static void fill(int[] a, int val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with an int value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(int[] a, int fromIndex, int toIndex, int val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+ /**
+ * Fill an array with a long value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ */
+ public static void fill(long[] a, long val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with a long value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(long[] a, int fromIndex, int toIndex, long val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+ /**
+ * Fill an array with a float value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ */
+ public static void fill(float[] a, float val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with a float value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(float[] a, int fromIndex, int toIndex, float val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+ /**
+ * Fill an array with a double value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ */
+ public static void fill(double[] a, double val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with a double value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(double[] a, int fromIndex, int toIndex, double val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+ /**
+ * Fill an array with an Object value.
+ *
+ * @param a the array to fill
+ * @param val the value to fill it with
+ * @throws ClassCastException if val is not an instance of the element
+ * type of a.
+ */
+ public static void fill(Object[] a, Object val)
+ {
+ fill(a, 0, a.length, val);
+ }
+
+ /**
+ * Fill a range of an array with an Object value.
+ *
+ * @param a the array to fill
+ * @param fromIndex the index to fill from, inclusive
+ * @param toIndex the index to fill to, exclusive
+ * @param val the value to fill with
+ * @throws ClassCastException if val is not an instance of the element
+ * type of a.
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void fill(Object[] a, int fromIndex, int toIndex, Object val)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ for (int i = fromIndex; i < toIndex; i++)
+ a[i] = val;
+ }
+
+
+// sort
+ // Thanks to Paul Fisher (rao@gnu.org) for finding this quicksort algorithm
+ // as specified by Sun and porting it to Java. The algorithm is an optimised
+ // quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
+ // "Engineering a Sort Function", Software-Practice and Experience, Vol.
+ // 23(11) P. 1249-1265 (November 1993). This algorithm gives n*log(n)
+ // performance on many arrays that would take quadratic time with a standard
+ // quicksort.
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the byte array to sort
+ */
+ public static void sort(byte[] a)
+ {
+ qsort(a, 0, a.length);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the byte array to sort
+ * @param fromIndex the first index to sort (inclusive)
+ * @param toIndex the last index to sort (exclusive)
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void sort(byte[] a, int fromIndex, int toIndex)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ if (fromIndex < 0)
+ throw new ArrayIndexOutOfBoundsException();
+ qsort(a, fromIndex, toIndex - fromIndex);
+ }
+
+ /**
+ * Finds the index of the median of three array elements.
+ *
+ * @param a the first index
+ * @param b the second index
+ * @param c the third index
+ * @param d the array
+ * @return the index (a, b, or c) which has the middle value of the three
+ */
+ private static int med3(int a, int b, int c, byte[] d)
+ {
+ return (d[a] < d[b]
+ ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
+ : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
+ }
+
+ /**
+ * Swaps the elements at two locations of an array
+ *
+ * @param i the first index
+ * @param j the second index
+ * @param a the array
+ */
+ private static void swap(int i, int j, byte[] a)
+ {
+ byte c = a[i];
+ a[i] = a[j];
+ a[j] = c;
+ }
+
+ /**
+ * Swaps two ranges of an array.
+ *
+ * @param i the first range start
+ * @param j the second range start
+ * @param n the element count
+ * @param a the array
+ */
+ private static void vecswap(int i, int j, int n, byte[] a)
+ {
+ for ( ; n > 0; i++, j++, n--)
+ swap(i, j, a);
+ }
+
+ /**
+ * Performs a recursive modified quicksort.
+ *
+ * @param array the array to sort
+ * @param from the start index (inclusive)
+ * @param count the number of elements to sort
+ */
+ private static void qsort(byte[] array, int from, int count)
+ {
+ // Use an insertion sort on small arrays.
+ if (count <= 7)
+ {
+ for (int i = from + 1; i < from + count; i++)
+ for (int j = i; j > from && array[j - 1] > array[j]; j--)
+ swap(j, j - 1, array);
+ return;
+ }
+
+ // Determine a good median element.
+ int mid = count / 2;
+ int lo = from;
+ int hi = from + count - 1;
+
+ if (count > 40)
+ { // big arrays, pseudomedian of 9
+ int s = count / 8;
+ lo = med3(lo, lo + s, lo + 2 * s, array);
+ mid = med3(mid - s, mid, mid + s, array);
+ hi = med3(hi - 2 * s, hi - s, hi, array);
+ }
+ mid = med3(lo, mid, hi, array);
+
+ int a, b, c, d;
+ int comp;
+
+ // Pull the median element out of the fray, and use it as a pivot.
+ swap(from, mid, array);
+ a = b = from;
+ c = d = from + count - 1;
+
+ // Repeatedly move b and c to each other, swapping elements so
+ // that all elements before index b are less than the pivot, and all
+ // elements after index c are greater than the pivot. a and b track
+ // the elements equal to the pivot.
+ while (true)
+ {
+ while (b <= c && (comp = array[b] - array[from]) <= 0)
+ {
+ if (comp == 0)
+ {
+ swap(a, b, array);
+ a++;
+ }
+ b++;
+ }
+ while (c >= b && (comp = array[c] - array[from]) >= 0)
+ {
+ if (comp == 0)
+ {
+ swap(c, d, array);
+ d--;
+ }
+ c--;
+ }
+ if (b > c)
+ break;
+ swap(b, c, array);
+ b++;
+ c--;
+ }
+
+ // Swap pivot(s) back in place, the recurse on left and right sections.
+ hi = from + count;
+ int span;
+ span = Math.min(a - from, b - a);
+ vecswap(from, b - span, span, array);
+
+ span = Math.min(d - c, hi - d - 1);
+ vecswap(b, hi - span, span, array);
+
+ span = b - a;
+ if (span > 1)
+ qsort(array, from, span);
+
+ span = d - c;
+ if (span > 1)
+ qsort(array, hi - span, span);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the char array to sort
+ */
+ public static void sort(char[] a)
+ {
+ qsort(a, 0, a.length);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the char array to sort
+ * @param fromIndex the first index to sort (inclusive)
+ * @param toIndex the last index to sort (exclusive)
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void sort(char[] a, int fromIndex, int toIndex)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ if (fromIndex < 0)
+ throw new ArrayIndexOutOfBoundsException();
+ qsort(a, fromIndex, toIndex - fromIndex);
+ }
+
+ /**
+ * Finds the index of the median of three array elements.
+ *
+ * @param a the first index
+ * @param b the second index
+ * @param c the third index
+ * @param d the array
+ * @return the index (a, b, or c) which has the middle value of the three
+ */
+ private static int med3(int a, int b, int c, char[] d)
+ {
+ return (d[a] < d[b]
+ ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
+ : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
+ }
+
+ /**
+ * Swaps the elements at two locations of an array
+ *
+ * @param i the first index
+ * @param j the second index
+ * @param a the array
+ */
+ private static void swap(int i, int j, char[] a)
+ {
+ char c = a[i];
+ a[i] = a[j];
+ a[j] = c;
+ }
+
+ /**
+ * Swaps two ranges of an array.
+ *
+ * @param i the first range start
+ * @param j the second range start
+ * @param n the element count
+ * @param a the array
+ */
+ private static void vecswap(int i, int j, int n, char[] a)
+ {
+ for ( ; n > 0; i++, j++, n--)
+ swap(i, j, a);
+ }
+
+ /**
+ * Performs a recursive modified quicksort.
+ *
+ * @param array the array to sort
+ * @param from the start index (inclusive)
+ * @param count the number of elements to sort
+ */
+ private static void qsort(char[] array, int from, int count)
+ {
+ // Use an insertion sort on small arrays.
+ if (count <= 7)
+ {
+ for (int i = from + 1; i < from + count; i++)
+ for (int j = i; j > from && array[j - 1] > array[j]; j--)
+ swap(j, j - 1, array);
+ return;
+ }
+
+ // Determine a good median element.
+ int mid = count / 2;
+ int lo = from;
+ int hi = from + count - 1;
+
+ if (count > 40)
+ { // big arrays, pseudomedian of 9
+ int s = count / 8;
+ lo = med3(lo, lo + s, lo + 2 * s, array);
+ mid = med3(mid - s, mid, mid + s, array);
+ hi = med3(hi - 2 * s, hi - s, hi, array);
+ }
+ mid = med3(lo, mid, hi, array);
+
+ int a, b, c, d;
+ int comp;
+
+ // Pull the median element out of the fray, and use it as a pivot.
+ swap(from, mid, array);
+ a = b = from;
+ c = d = from + count - 1;
+
+ // Repeatedly move b and c to each other, swapping elements so
+ // that all elements before index b are less than the pivot, and all
+ // elements after index c are greater than the pivot. a and b track
+ // the elements equal to the pivot.
+ while (true)
+ {
+ while (b <= c && (comp = array[b] - array[from]) <= 0)
+ {
+ if (comp == 0)
+ {
+ swap(a, b, array);
+ a++;
+ }
+ b++;
+ }
+ while (c >= b && (comp = array[c] - array[from]) >= 0)
+ {
+ if (comp == 0)
+ {
+ swap(c, d, array);
+ d--;
+ }
+ c--;
+ }
+ if (b > c)
+ break;
+ swap(b, c, array);
+ b++;
+ c--;
+ }
+
+ // Swap pivot(s) back in place, the recurse on left and right sections.
+ hi = from + count;
+ int span;
+ span = Math.min(a - from, b - a);
+ vecswap(from, b - span, span, array);
+
+ span = Math.min(d - c, hi - d - 1);
+ vecswap(b, hi - span, span, array);
+
+ span = b - a;
+ if (span > 1)
+ qsort(array, from, span);
+
+ span = d - c;
+ if (span > 1)
+ qsort(array, hi - span, span);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the short array to sort
+ */
+ public static void sort(short[] a)
+ {
+ qsort(a, 0, a.length);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the short array to sort
+ * @param fromIndex the first index to sort (inclusive)
+ * @param toIndex the last index to sort (exclusive)
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void sort(short[] a, int fromIndex, int toIndex)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ if (fromIndex < 0)
+ throw new ArrayIndexOutOfBoundsException();
+ qsort(a, fromIndex, toIndex - fromIndex);
+ }
+
+ /**
+ * Finds the index of the median of three array elements.
+ *
+ * @param a the first index
+ * @param b the second index
+ * @param c the third index
+ * @param d the array
+ * @return the index (a, b, or c) which has the middle value of the three
+ */
+ private static int med3(int a, int b, int c, short[] d)
+ {
+ return (d[a] < d[b]
+ ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
+ : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
+ }
+
+ /**
+ * Swaps the elements at two locations of an array
+ *
+ * @param i the first index
+ * @param j the second index
+ * @param a the array
+ */
+ private static void swap(int i, int j, short[] a)
+ {
+ short c = a[i];
+ a[i] = a[j];
+ a[j] = c;
+ }
+
+ /**
+ * Swaps two ranges of an array.
+ *
+ * @param i the first range start
+ * @param j the second range start
+ * @param n the element count
+ * @param a the array
+ */
+ private static void vecswap(int i, int j, int n, short[] a)
+ {
+ for ( ; n > 0; i++, j++, n--)
+ swap(i, j, a);
+ }
+
+ /**
+ * Performs a recursive modified quicksort.
+ *
+ * @param array the array to sort
+ * @param from the start index (inclusive)
+ * @param count the number of elements to sort
+ */
+ private static void qsort(short[] array, int from, int count)
+ {
+ // Use an insertion sort on small arrays.
+ if (count <= 7)
+ {
+ for (int i = from + 1; i < from + count; i++)
+ for (int j = i; j > from && array[j - 1] > array[j]; j--)
+ swap(j, j - 1, array);
+ return;
+ }
+
+ // Determine a good median element.
+ int mid = count / 2;
+ int lo = from;
+ int hi = from + count - 1;
+
+ if (count > 40)
+ { // big arrays, pseudomedian of 9
+ int s = count / 8;
+ lo = med3(lo, lo + s, lo + 2 * s, array);
+ mid = med3(mid - s, mid, mid + s, array);
+ hi = med3(hi - 2 * s, hi - s, hi, array);
+ }
+ mid = med3(lo, mid, hi, array);
+
+ int a, b, c, d;
+ int comp;
+
+ // Pull the median element out of the fray, and use it as a pivot.
+ swap(from, mid, array);
+ a = b = from;
+ c = d = from + count - 1;
+
+ // Repeatedly move b and c to each other, swapping elements so
+ // that all elements before index b are less than the pivot, and all
+ // elements after index c are greater than the pivot. a and b track
+ // the elements equal to the pivot.
+ while (true)
+ {
+ while (b <= c && (comp = array[b] - array[from]) <= 0)
+ {
+ if (comp == 0)
+ {
+ swap(a, b, array);
+ a++;
+ }
+ b++;
+ }
+ while (c >= b && (comp = array[c] - array[from]) >= 0)
+ {
+ if (comp == 0)
+ {
+ swap(c, d, array);
+ d--;
+ }
+ c--;
+ }
+ if (b > c)
+ break;
+ swap(b, c, array);
+ b++;
+ c--;
+ }
+
+ // Swap pivot(s) back in place, the recurse on left and right sections.
+ hi = from + count;
+ int span;
+ span = Math.min(a - from, b - a);
+ vecswap(from, b - span, span, array);
+
+ span = Math.min(d - c, hi - d - 1);
+ vecswap(b, hi - span, span, array);
+
+ span = b - a;
+ if (span > 1)
+ qsort(array, from, span);
+
+ span = d - c;
+ if (span > 1)
+ qsort(array, hi - span, span);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the int array to sort
+ */
+ public static void sort(int[] a)
+ {
+ qsort(a, 0, a.length);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the int array to sort
+ * @param fromIndex the first index to sort (inclusive)
+ * @param toIndex the last index to sort (exclusive)
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void sort(int[] a, int fromIndex, int toIndex)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ if (fromIndex < 0)
+ throw new ArrayIndexOutOfBoundsException();
+ qsort(a, fromIndex, toIndex - fromIndex);
+ }
+
+ /**
+ * Finds the index of the median of three array elements.
+ *
+ * @param a the first index
+ * @param b the second index
+ * @param c the third index
+ * @param d the array
+ * @return the index (a, b, or c) which has the middle value of the three
+ */
+ private static int med3(int a, int b, int c, int[] d)
+ {
+ return (d[a] < d[b]
+ ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
+ : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
+ }
+
+ /**
+ * Swaps the elements at two locations of an array
+ *
+ * @param i the first index
+ * @param j the second index
+ * @param a the array
+ */
+ private static void swap(int i, int j, int[] a)
+ {
+ int c = a[i];
+ a[i] = a[j];
+ a[j] = c;
+ }
+
+ /**
+ * Swaps two ranges of an array.
+ *
+ * @param i the first range start
+ * @param j the second range start
+ * @param n the element count
+ * @param a the array
+ */
+ private static void vecswap(int i, int j, int n, int[] a)
+ {
+ for ( ; n > 0; i++, j++, n--)
+ swap(i, j, a);
+ }
+
+ /**
+ * Compares two integers in natural order, since a - b is inadequate.
+ *
+ * @param a the first int
+ * @param b the second int
+ * @return &lt; 0, 0, or &gt; 0 accorting to the comparison
+ */
+ private static int compare(int a, int b)
+ {
+ return a < b ? -1 : a == b ? 0 : 1;
+ }
+
+ /**
+ * Performs a recursive modified quicksort.
+ *
+ * @param array the array to sort
+ * @param from the start index (inclusive)
+ * @param count the number of elements to sort
+ */
+ private static void qsort(int[] array, int from, int count)
+ {
+ // Use an insertion sort on small arrays.
+ if (count <= 7)
+ {
+ for (int i = from + 1; i < from + count; i++)
+ for (int j = i; j > from && array[j - 1] > array[j]; j--)
+ swap(j, j - 1, array);
+ return;
+ }
+
+ // Determine a good median element.
+ int mid = count / 2;
+ int lo = from;
+ int hi = from + count - 1;
+
+ if (count > 40)
+ { // big arrays, pseudomedian of 9
+ int s = count / 8;
+ lo = med3(lo, lo + s, lo + 2 * s, array);
+ mid = med3(mid - s, mid, mid + s, array);
+ hi = med3(hi - 2 * s, hi - s, hi, array);
+ }
+ mid = med3(lo, mid, hi, array);
+
+ int a, b, c, d;
+ int comp;
+
+ // Pull the median element out of the fray, and use it as a pivot.
+ swap(from, mid, array);
+ a = b = from;
+ c = d = from + count - 1;
+
+ // Repeatedly move b and c to each other, swapping elements so
+ // that all elements before index b are less than the pivot, and all
+ // elements after index c are greater than the pivot. a and b track
+ // the elements equal to the pivot.
+ while (true)
+ {
+ while (b <= c && (comp = compare(array[b], array[from])) <= 0)
+ {
+ if (comp == 0)
+ {
+ swap(a, b, array);
+ a++;
+ }
+ b++;
+ }
+ while (c >= b && (comp = compare(array[c], array[from])) >= 0)
+ {
+ if (comp == 0)
+ {
+ swap(c, d, array);
+ d--;
+ }
+ c--;
+ }
+ if (b > c)
+ break;
+ swap(b, c, array);
+ b++;
+ c--;
+ }
+
+ // Swap pivot(s) back in place, the recurse on left and right sections.
+ hi = from + count;
+ int span;
+ span = Math.min(a - from, b - a);
+ vecswap(from, b - span, span, array);
+
+ span = Math.min(d - c, hi - d - 1);
+ vecswap(b, hi - span, span, array);
+
+ span = b - a;
+ if (span > 1)
+ qsort(array, from, span);
+
+ span = d - c;
+ if (span > 1)
+ qsort(array, hi - span, span);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the long array to sort
+ */
+ public static void sort(long[] a)
+ {
+ qsort(a, 0, a.length);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the long array to sort
+ * @param fromIndex the first index to sort (inclusive)
+ * @param toIndex the last index to sort (exclusive)
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void sort(long[] a, int fromIndex, int toIndex)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ if (fromIndex < 0)
+ throw new ArrayIndexOutOfBoundsException();
+ qsort(a, fromIndex, toIndex - fromIndex);
+ }
+
+ /**
+ * Finds the index of the median of three array elements.
+ *
+ * @param a the first index
+ * @param b the second index
+ * @param c the third index
+ * @param d the array
+ * @return the index (a, b, or c) which has the middle value of the three
+ */
+ private static int med3(int a, int b, int c, long[] d)
+ {
+ return (d[a] < d[b]
+ ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
+ : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
+ }
+
+ /**
+ * Swaps the elements at two locations of an array
+ *
+ * @param i the first index
+ * @param j the second index
+ * @param a the array
+ */
+ private static void swap(int i, int j, long[] a)
+ {
+ long c = a[i];
+ a[i] = a[j];
+ a[j] = c;
+ }
+
+ /**
+ * Swaps two ranges of an array.
+ *
+ * @param i the first range start
+ * @param j the second range start
+ * @param n the element count
+ * @param a the array
+ */
+ private static void vecswap(int i, int j, int n, long[] a)
+ {
+ for ( ; n > 0; i++, j++, n--)
+ swap(i, j, a);
+ }
+
+ /**
+ * Compares two longs in natural order, since a - b is inadequate.
+ *
+ * @param a the first long
+ * @param b the second long
+ * @return &lt; 0, 0, or &gt; 0 accorting to the comparison
+ */
+ private static int compare(long a, long b)
+ {
+ return a < b ? -1 : a == b ? 0 : 1;
+ }
+
+ /**
+ * Performs a recursive modified quicksort.
+ *
+ * @param array the array to sort
+ * @param from the start index (inclusive)
+ * @param count the number of elements to sort
+ */
+ private static void qsort(long[] array, int from, int count)
+ {
+ // Use an insertion sort on small arrays.
+ if (count <= 7)
+ {
+ for (int i = from + 1; i < from + count; i++)
+ for (int j = i; j > from && array[j - 1] > array[j]; j--)
+ swap(j, j - 1, array);
+ return;
+ }
+
+ // Determine a good median element.
+ int mid = count / 2;
+ int lo = from;
+ int hi = from + count - 1;
+
+ if (count > 40)
+ { // big arrays, pseudomedian of 9
+ int s = count / 8;
+ lo = med3(lo, lo + s, lo + 2 * s, array);
+ mid = med3(mid - s, mid, mid + s, array);
+ hi = med3(hi - 2 * s, hi - s, hi, array);
+ }
+ mid = med3(lo, mid, hi, array);
+
+ int a, b, c, d;
+ int comp;
+
+ // Pull the median element out of the fray, and use it as a pivot.
+ swap(from, mid, array);
+ a = b = from;
+ c = d = from + count - 1;
+
+ // Repeatedly move b and c to each other, swapping elements so
+ // that all elements before index b are less than the pivot, and all
+ // elements after index c are greater than the pivot. a and b track
+ // the elements equal to the pivot.
+ while (true)
+ {
+ while (b <= c && (comp = compare(array[b], array[from])) <= 0)
+ {
+ if (comp == 0)
+ {
+ swap(a, b, array);
+ a++;
+ }
+ b++;
+ }
+ while (c >= b && (comp = compare(array[c], array[from])) >= 0)
+ {
+ if (comp == 0)
+ {
+ swap(c, d, array);
+ d--;
+ }
+ c--;
+ }
+ if (b > c)
+ break;
+ swap(b, c, array);
+ b++;
+ c--;
+ }
+
+ // Swap pivot(s) back in place, the recurse on left and right sections.
+ hi = from + count;
+ int span;
+ span = Math.min(a - from, b - a);
+ vecswap(from, b - span, span, array);
+
+ span = Math.min(d - c, hi - d - 1);
+ vecswap(b, hi - span, span, array);
+
+ span = b - a;
+ if (span > 1)
+ qsort(array, from, span);
+
+ span = d - c;
+ if (span > 1)
+ qsort(array, hi - span, span);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the float array to sort
+ */
+ public static void sort(float[] a)
+ {
+ qsort(a, 0, a.length);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the float array to sort
+ * @param fromIndex the first index to sort (inclusive)
+ * @param toIndex the last index to sort (exclusive)
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void sort(float[] a, int fromIndex, int toIndex)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ if (fromIndex < 0)
+ throw new ArrayIndexOutOfBoundsException();
+ qsort(a, fromIndex, toIndex - fromIndex);
+ }
+
+ /**
+ * Finds the index of the median of three array elements.
+ *
+ * @param a the first index
+ * @param b the second index
+ * @param c the third index
+ * @param d the array
+ * @return the index (a, b, or c) which has the middle value of the three
+ */
+ private static int med3(int a, int b, int c, float[] d)
+ {
+ return (Float.compare(d[a], d[b]) < 0
+ ? (Float.compare(d[b], d[c]) < 0 ? b
+ : Float.compare(d[a], d[c]) < 0 ? c : a)
+ : (Float.compare(d[b], d[c]) > 0 ? b
+ : Float.compare(d[a], d[c]) > 0 ? c : a));
+ }
+
+ /**
+ * Swaps the elements at two locations of an array
+ *
+ * @param i the first index
+ * @param j the second index
+ * @param a the array
+ */
+ private static void swap(int i, int j, float[] a)
+ {
+ float c = a[i];
+ a[i] = a[j];
+ a[j] = c;
+ }
+
+ /**
+ * Swaps two ranges of an array.
+ *
+ * @param i the first range start
+ * @param j the second range start
+ * @param n the element count
+ * @param a the array
+ */
+ private static void vecswap(int i, int j, int n, float[] a)
+ {
+ for ( ; n > 0; i++, j++, n--)
+ swap(i, j, a);
+ }
+
+ /**
+ * Performs a recursive modified quicksort.
+ *
+ * @param array the array to sort
+ * @param from the start index (inclusive)
+ * @param count the number of elements to sort
+ */
+ private static void qsort(float[] array, int from, int count)
+ {
+ // Use an insertion sort on small arrays.
+ if (count <= 7)
+ {
+ for (int i = from + 1; i < from + count; i++)
+ for (int j = i;
+ j > from && Float.compare(array[j - 1], array[j]) > 0;
+ j--)
+ {
+ swap(j, j - 1, array);
+ }
+ return;
+ }
+
+ // Determine a good median element.
+ int mid = count / 2;
+ int lo = from;
+ int hi = from + count - 1;
+
+ if (count > 40)
+ { // big arrays, pseudomedian of 9
+ int s = count / 8;
+ lo = med3(lo, lo + s, lo + 2 * s, array);
+ mid = med3(mid - s, mid, mid + s, array);
+ hi = med3(hi - 2 * s, hi - s, hi, array);
+ }
+ mid = med3(lo, mid, hi, array);
+
+ int a, b, c, d;
+ int comp;
+
+ // Pull the median element out of the fray, and use it as a pivot.
+ swap(from, mid, array);
+ a = b = from;
+ c = d = from + count - 1;
+
+ // Repeatedly move b and c to each other, swapping elements so
+ // that all elements before index b are less than the pivot, and all
+ // elements after index c are greater than the pivot. a and b track
+ // the elements equal to the pivot.
+ while (true)
+ {
+ while (b <= c && (comp = Float.compare(array[b], array[from])) <= 0)
+ {
+ if (comp == 0)
+ {
+ swap(a, b, array);
+ a++;
+ }
+ b++;
+ }
+ while (c >= b && (comp = Float.compare(array[c], array[from])) >= 0)
+ {
+ if (comp == 0)
+ {
+ swap(c, d, array);
+ d--;
+ }
+ c--;
+ }
+ if (b > c)
+ break;
+ swap(b, c, array);
+ b++;
+ c--;
+ }
+
+ // Swap pivot(s) back in place, the recurse on left and right sections.
+ hi = from + count;
+ int span;
+ span = Math.min(a - from, b - a);
+ vecswap(from, b - span, span, array);
+
+ span = Math.min(d - c, hi - d - 1);
+ vecswap(b, hi - span, span, array);
+
+ span = b - a;
+ if (span > 1)
+ qsort(array, from, span);
+
+ span = d - c;
+ if (span > 1)
+ qsort(array, hi - span, span);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the double array to sort
+ */
+ public static void sort(double[] a)
+ {
+ qsort(a, 0, a.length);
+ }
+
+ /**
+ * Performs a stable sort on the elements, arranging them according to their
+ * natural order.
+ *
+ * @param a the double array to sort
+ * @param fromIndex the first index to sort (inclusive)
+ * @param toIndex the last index to sort (exclusive)
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; a.length
+ */
+ public static void sort(double[] a, int fromIndex, int toIndex)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException();
+ if (fromIndex < 0)
+ throw new ArrayIndexOutOfBoundsException();
+ qsort(a, fromIndex, toIndex - fromIndex);
+ }
+
+ /**
+ * Finds the index of the median of three array elements.
+ *
+ * @param a the first index
+ * @param b the second index
+ * @param c the third index
+ * @param d the array
+ * @return the index (a, b, or c) which has the middle value of the three
+ */
+ private static int med3(int a, int b, int c, double[] d)
+ {
+ return (Double.compare(d[a], d[b]) < 0
+ ? (Double.compare(d[b], d[c]) < 0 ? b
+ : Double.compare(d[a], d[c]) < 0 ? c : a)
+ : (Double.compare(d[b], d[c]) > 0 ? b
+ : Double.compare(d[a], d[c]) > 0 ? c : a));
+ }
+
+ /**
+ * Swaps the elements at two locations of an array
+ *
+ * @param i the first index
+ * @param j the second index
+ * @param a the array
+ */
+ private static void swap(int i, int j, double[] a)
+ {
+ double c = a[i];
+ a[i] = a[j];
+ a[j] = c;
+ }
+
+ /**
+ * Swaps two ranges of an array.
+ *
+ * @param i the first range start
+ * @param j the second range start
+ * @param n the element count
+ * @param a the array
+ */
+ private static void vecswap(int i, int j, int n, double[] a)
+ {
+ for ( ; n > 0; i++, j++, n--)
+ swap(i, j, a);
+ }
+
+ /**
+ * Performs a recursive modified quicksort.
+ *
+ * @param array the array to sort
+ * @param from the start index (inclusive)
+ * @param count the number of elements to sort
+ */
+ private static void qsort(double[] array, int from, int count)
+ {
+ // Use an insertion sort on small arrays.
+ if (count <= 7)
+ {
+ for (int i = from + 1; i < from + count; i++)
+ for (int j = i;
+ j > from && Double.compare(array[j - 1], array[j]) > 0;
+ j--)
+ {
+ swap(j, j - 1, array);
+ }
+ return;
+ }
+
+ // Determine a good median element.
+ int mid = count / 2;
+ int lo = from;
+ int hi = from + count - 1;
+
+ if (count > 40)
+ { // big arrays, pseudomedian of 9
+ int s = count / 8;
+ lo = med3(lo, lo + s, lo + 2 * s, array);
+ mid = med3(mid - s, mid, mid + s, array);
+ hi = med3(hi - 2 * s, hi - s, hi, array);
+ }
+ mid = med3(lo, mid, hi, array);
+
+ int a, b, c, d;
+ int comp;
+
+ // Pull the median element out of the fray, and use it as a pivot.
+ swap(from, mid, array);
+ a = b = from;
+ c = d = from + count - 1;
+
+ // Repeatedly move b and c to each other, swapping elements so
+ // that all elements before index b are less than the pivot, and all
+ // elements after index c are greater than the pivot. a and b track
+ // the elements equal to the pivot.
+ while (true)
+ {
+ while (b <= c && (comp = Double.compare(array[b], array[from])) <= 0)
+ {
+ if (comp == 0)
+ {
+ swap(a, b, array);
+ a++;
+ }
+ b++;
+ }
+ while (c >= b && (comp = Double.compare(array[c], array[from])) >= 0)
+ {
+ if (comp == 0)
+ {
+ swap(c, d, array);
+ d--;
+ }
+ c--;
+ }
+ if (b > c)
+ break;
+ swap(b, c, array);
+ b++;
+ c--;
+ }
+
+ // Swap pivot(s) back in place, the recurse on left and right sections.
+ hi = from + count;
+ int span;
+ span = Math.min(a - from, b - a);
+ vecswap(from, b - span, span, array);
+
+ span = Math.min(d - c, hi - d - 1);
+ vecswap(b, hi - span, span, array);
+
+ span = b - a;
+ if (span > 1)
+ qsort(array, from, span);
+
+ span = d - c;
+ if (span > 1)
+ qsort(array, hi - span, span);
+ }
+
+ /**
+ * Sort an array of Objects according to their natural ordering. The sort is
+ * guaranteed to be stable, that is, equal elements will not be reordered.
+ * The sort algorithm is a mergesort with the merge omitted if the last
+ * element of one half comes before the first element of the other half. This
+ * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
+ * copy of the array.
+ *
+ * @param a the array to be sorted
+ * @throws ClassCastException if any two elements are not mutually
+ * comparable
+ * @throws NullPointerException if an element is null (since
+ * null.compareTo cannot work)
+ * @see Comparable
+ */
+ public static void sort(Object[] a)
+ {
+ sort(a, 0, a.length, null);
+ }
+
+ /**
+ * Sort an array of Objects according to a Comparator. The sort is
+ * guaranteed to be stable, that is, equal elements will not be reordered.
+ * The sort algorithm is a mergesort with the merge omitted if the last
+ * element of one half comes before the first element of the other half. This
+ * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
+ * copy of the array.
+ *
+ * @param a the array to be sorted
+ * @param c a Comparator to use in sorting the array; or null to indicate
+ * the elements' natural order
+ * @throws ClassCastException if any two elements are not mutually
+ * comparable by the Comparator provided
+ * @throws NullPointerException if a null element is compared with natural
+ * ordering (only possible when c is null)
+ */
+ public static void sort(Object[] a, Comparator c)
+ {
+ sort(a, 0, a.length, c);
+ }
+
+ /**
+ * Sort an array of Objects according to their natural ordering. The sort is
+ * guaranteed to be stable, that is, equal elements will not be reordered.
+ * The sort algorithm is a mergesort with the merge omitted if the last
+ * element of one half comes before the first element of the other half. This
+ * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
+ * copy of the array.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element to be sorted
+ * @param toIndex the index of the last element to be sorted plus one
+ * @throws ClassCastException if any two elements are not mutually
+ * comparable
+ * @throws NullPointerException if an element is null (since
+ * null.compareTo cannot work)
+ * @throws ArrayIndexOutOfBoundsException if fromIndex and toIndex
+ * are not in range.
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ */
+ public static void sort(Object[] a, int fromIndex, int toIndex)
+ {
+ sort(a, fromIndex, toIndex, null);
+ }
+
+ /**
+ * Sort an array of Objects according to a Comparator. The sort is
+ * guaranteed to be stable, that is, equal elements will not be reordered.
+ * The sort algorithm is a mergesort with the merge omitted if the last
+ * element of one half comes before the first element of the other half. This
+ * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
+ * copy of the array.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element to be sorted
+ * @param toIndex the index of the last element to be sorted plus one
+ * @param c a Comparator to use in sorting the array; or null to indicate
+ * the elements' natural order
+ * @throws ClassCastException if any two elements are not mutually
+ * comparable by the Comparator provided
+ * @throws ArrayIndexOutOfBoundsException if fromIndex and toIndex
+ * are not in range.
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @throws NullPointerException if a null element is compared with natural
+ * ordering (only possible when c is null)
+ */
+ public static void sort(Object[] a, int fromIndex, int toIndex, Comparator c)
+ {
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException("fromIndex " + fromIndex
+ + " > toIndex " + toIndex);
+ if (fromIndex < 0)
+ throw new ArrayIndexOutOfBoundsException();
+
+ // In general, the code attempts to be simple rather than fast, the
+ // idea being that a good optimising JIT will be able to optimise it
+ // better than I can, and if I try it will make it more confusing for
+ // the JIT. First presort the array in chunks of length 6 with insertion
+ // sort. A mergesort would give too much overhead for this length.
+ for (int chunk = fromIndex; chunk < toIndex; chunk += 6)
+ {
+ int end = Math.min(chunk + 6, toIndex);
+ for (int i = chunk + 1; i < end; i++)
+ {
+ if (Collections.compare(a[i - 1], a[i], c) > 0)
+ {
+ // not already sorted
+ int j = i;
+ Object elem = a[j];
+ do
+ {
+ a[j] = a[j - 1];
+ j--;
+ }
+ while (j > chunk
+ && Collections.compare(a[j - 1], elem, c) > 0);
+ a[j] = elem;
+ }
+ }
+ }
+
+ int len = toIndex - fromIndex;
+ // If length is smaller or equal 6 we are done.
+ if (len <= 6)
+ return;
+
+ Object[] src = a;
+ Object[] dest = new Object[len];
+ Object[] t = null; // t is used for swapping src and dest
+
+ // The difference of the fromIndex of the src and dest array.
+ int srcDestDiff = -fromIndex;
+
+ // The merges are done in this loop
+ for (int size = 6; size < len; size <<= 1)
+ {
+ for (int start = fromIndex; start < toIndex; start += size << 1)
+ {
+ // mid is the start of the second sublist;
+ // end the start of the next sublist (or end of array).
+ int mid = start + size;
+ int end = Math.min(toIndex, mid + size);
+
+ // The second list is empty or the elements are already in
+ // order - no need to merge
+ if (mid >= end
+ || Collections.compare(src[mid - 1], src[mid], c) <= 0)
+ {
+ System.arraycopy(src, start,
+ dest, start + srcDestDiff, end - start);
+
+ // The two halves just need swapping - no need to merge
+ }
+ else if (Collections.compare(src[start], src[end - 1], c) > 0)
+ {
+ System.arraycopy(src, start,
+ dest, end - size + srcDestDiff, size);
+ System.arraycopy(src, mid,
+ dest, start + srcDestDiff, end - mid);
+
+ }
+ else
+ {
+ // Declare a lot of variables to save repeating
+ // calculations. Hopefully a decent JIT will put these
+ // in registers and make this fast
+ int p1 = start;
+ int p2 = mid;
+ int i = start + srcDestDiff;
+
+ // The main merge loop; terminates as soon as either
+ // half is ended
+ while (p1 < mid && p2 < end)
+ {
+ dest[i++] =
+ src[(Collections.compare(src[p1], src[p2], c) <= 0
+ ? p1++ : p2++)];
+ }
+
+ // Finish up by copying the remainder of whichever half
+ // wasn't finished.
+ if (p1 < mid)
+ System.arraycopy(src, p1, dest, i, mid - p1);
+ else
+ System.arraycopy(src, p2, dest, i, end - p2);
+ }
+ }
+ // swap src and dest ready for the next merge
+ t = src;
+ src = dest;
+ dest = t;
+ fromIndex += srcDestDiff;
+ toIndex += srcDestDiff;
+ srcDestDiff = -srcDestDiff;
+ }
+
+ // make sure the result ends up back in the right place. Note
+ // that src and dest may have been swapped above, so src
+ // contains the sorted array.
+ if (src != a)
+ {
+ // Note that fromIndex == 0.
+ System.arraycopy(src, 0, a, srcDestDiff, toIndex);
+ }
+ }
+
+ /**
+ * Returns a list "view" of the specified array. This method is intended to
+ * make it easy to use the Collections API with existing array-based APIs and
+ * programs. Changes in the list or the array show up in both places. The
+ * list does not support element addition or removal, but does permit
+ * value modification. The returned list implements both Serializable and
+ * RandomAccess.
+ *
+ * @param a the array to return a view of
+ * @return a fixed-size list, changes to which "write through" to the array
+ * @see Serializable
+ * @see RandomAccess
+ * @see Arrays.ArrayList
+ */
+ public static List asList(final Object[] a)
+ {
+ return new Arrays.ArrayList(a);
+ }
+
+ /**
+ * Inner class used by {@link #asList(Object[])} to provide a list interface
+ * to an array. The name, though it clashes with java.util.ArrayList, is
+ * Sun's choice for Serialization purposes. Element addition and removal
+ * is prohibited, but values can be modified.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+ private static final class ArrayList extends AbstractList
+ implements Serializable, RandomAccess
+ {
+ // We override the necessary methods, plus others which will be much
+ // more efficient with direct iteration rather than relying on iterator().
+
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -2764017481108945198L;
+
+ /**
+ * The array we are viewing.
+ * @serial the array
+ */
+ private final Object[] a;
+
+ /**
+ * Construct a list view of the array.
+ * @param a the array to view
+ * @throws NullPointerException if a is null
+ */
+ ArrayList(Object[] a)
+ {
+ // We have to explicitly check.
+ if (a == null)
+ throw new NullPointerException();
+ this.a = a;
+ }
+
+ /**
+ * Returns the object at the specified index in
+ * the array.
+ *
+ * @param index The index to retrieve an object from.
+ * @return The object at the array index specified.
+ */
+ public Object get(int index)
+ {
+ return a[index];
+ }
+
+ /**
+ * Returns the size of the array.
+ *
+ * @return The size.
+ */
+ public int size()
+ {
+ return a.length;
+ }
+
+ /**
+ * Replaces the object at the specified index
+ * with the supplied element.
+ *
+ * @param index The index at which to place the new object.
+ * @param element The new object.
+ * @return The object replaced by this operation.
+ */
+ public Object set(int index, Object element)
+ {
+ Object old = a[index];
+ a[index] = element;
+ return old;
+ }
+
+ /**
+ * Returns true if the array contains the
+ * supplied object.
+ *
+ * @param o The object to look for.
+ * @return True if the object was found.
+ */
+ public boolean contains(Object o)
+ {
+ return lastIndexOf(o) >= 0;
+ }
+
+ /**
+ * Returns the first index at which the
+ * object, o, occurs in the array.
+ *
+ * @param o The object to search for.
+ * @return The first relevant index.
+ */
+ public int indexOf(Object o)
+ {
+ int size = a.length;
+ for (int i = 0; i < size; i++)
+ if (ArrayList.equals(o, a[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the last index at which the
+ * object, o, occurs in the array.
+ *
+ * @param o The object to search for.
+ * @return The last relevant index.
+ */
+ public int lastIndexOf(Object o)
+ {
+ int i = a.length;
+ while (--i >= 0)
+ if (ArrayList.equals(o, a[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Transforms the list into an array of
+ * objects, by simplying cloning the array
+ * wrapped by this list.
+ *
+ * @return A clone of the internal array.
+ */
+ public Object[] toArray()
+ {
+ return (Object[]) a.clone();
+ }
+
+ /**
+ * Copies the objects from this list into
+ * the supplied array. The supplied array
+ * is shrunk or enlarged to the size of the
+ * internal array, and filled with its objects.
+ *
+ * @param array The array to fill with the objects in this list.
+ * @return The array containing the objects in this list,
+ * which may or may not be == to array.
+ */
+ public Object[] toArray(Object[] array)
+ {
+ int size = a.length;
+ if (array.length < size)
+ array = (Object[])
+ Array.newInstance(array.getClass().getComponentType(), size);
+ else if (array.length > size)
+ array[size] = null;
+
+ System.arraycopy(a, 0, array, 0, size);
+ return array;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/BitSet.java b/libjava/classpath/java/util/BitSet.java
new file mode 100644
index 00000000000..ce88794f52b
--- /dev/null
+++ b/libjava/classpath/java/util/BitSet.java
@@ -0,0 +1,744 @@
+/* BitSet.java -- A vector of bits.
+ Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+import java.io.Serializable;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * hashCode algorithm taken from JDK 1.2 docs.
+ */
+
+/**
+ * This class can be thought of in two ways. You can see it as a
+ * vector of bits or as a set of non-negative integers. The name
+ * <code>BitSet</code> is a bit misleading.
+ *
+ * It is implemented by a bit vector, but its equally possible to see
+ * it as set of non-negative integer; each integer in the set is
+ * represented by a set bit at the corresponding index. The size of
+ * this structure is determined by the highest integer in the set.
+ *
+ * You can union, intersect and build (symmetric) remainders, by
+ * invoking the logical operations and, or, andNot, resp. xor.
+ *
+ * This implementation is NOT synchronized against concurrent access from
+ * multiple threads. Specifically, if one thread is reading from a bitset
+ * while another thread is simultaneously modifying it, the results are
+ * undefined.
+ *
+ * @author Jochen Hoenicke
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class BitSet implements Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.0.
+ */
+ private static final long serialVersionUID = 7997698588986878753L;
+
+ /**
+ * A common mask.
+ */
+ private static final int LONG_MASK = 0x3f;
+
+ /**
+ * The actual bits.
+ * @serial the i'th bit is in bits[i/64] at position i%64 (where position
+ * 0 is the least significant).
+ */
+ private long[] bits;
+
+ /**
+ * Create a new empty bit set. All bits are initially false.
+ */
+ public BitSet()
+ {
+ this(64);
+ }
+
+ /**
+ * Create a new empty bit set, with a given size. This
+ * constructor reserves enough space to represent the integers
+ * from <code>0</code> to <code>nbits-1</code>.
+ *
+ * @param nbits the initial size of the bit set
+ * @throws NegativeArraySizeException if nbits &lt; 0
+ */
+ public BitSet(int nbits)
+ {
+ if (nbits < 0)
+ throw new NegativeArraySizeException();
+
+ int length = nbits >>> 6;
+ if ((nbits & LONG_MASK) != 0)
+ ++length;
+ bits = new long[length];
+ }
+
+ /**
+ * Performs the logical AND operation on this bit set and the
+ * given <code>set</code>. This means it builds the intersection
+ * of the two sets. The result is stored into this bit set.
+ *
+ * @param bs the second bit set
+ * @throws NullPointerException if bs is null
+ */
+ public void and(BitSet bs)
+ {
+ int max = Math.min(bits.length, bs.bits.length);
+ int i;
+ for (i = 0; i < max; ++i)
+ bits[i] &= bs.bits[i];
+ while (i < bits.length)
+ bits[i++] = 0;
+ }
+
+ /**
+ * Performs the logical AND operation on this bit set and the
+ * complement of the given <code>bs</code>. This means it
+ * selects every element in the first set, that isn't in the
+ * second set. The result is stored into this bit set and is
+ * effectively the set difference of the two.
+ *
+ * @param bs the second bit set
+ * @throws NullPointerException if bs is null
+ * @since 1.2
+ */
+ public void andNot(BitSet bs)
+ {
+ int i = Math.min(bits.length, bs.bits.length);
+ while (--i >= 0)
+ bits[i] &= ~bs.bits[i];
+ }
+
+ /**
+ * Returns the number of bits set to true.
+ *
+ * @return the number of true bits
+ * @since 1.4
+ */
+ public int cardinality()
+ {
+ int card = 0;
+ for (int i = bits.length - 1; i >= 0; i--)
+ {
+ long a = bits[i];
+ // Take care of common cases.
+ if (a == 0)
+ continue;
+ if (a == -1)
+ {
+ card += 64;
+ continue;
+ }
+
+ // Successively collapse alternating bit groups into a sum.
+ a = ((a >> 1) & 0x5555555555555555L) + (a & 0x5555555555555555L);
+ a = ((a >> 2) & 0x3333333333333333L) + (a & 0x3333333333333333L);
+ int b = (int) ((a >>> 32) + a);
+ b = ((b >> 4) & 0x0f0f0f0f) + (b & 0x0f0f0f0f);
+ b = ((b >> 8) & 0x00ff00ff) + (b & 0x00ff00ff);
+ card += ((b >> 16) & 0x0000ffff) + (b & 0x0000ffff);
+ }
+ return card;
+ }
+
+ /**
+ * Sets all bits in the set to false.
+ *
+ * @since 1.4
+ */
+ public void clear()
+ {
+ Arrays.fill(bits, 0);
+ }
+
+ /**
+ * Removes the integer <code>pos</code> from this set. That is
+ * the corresponding bit is cleared. If the index is not in the set,
+ * this method does nothing.
+ *
+ * @param pos a non-negative integer
+ * @throws IndexOutOfBoundsException if pos &lt; 0
+ */
+ public void clear(int pos)
+ {
+ int offset = pos >> 6;
+ ensure(offset);
+ // ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
+ // so we'll just let that be our exception.
+ bits[offset] &= ~(1L << pos);
+ }
+
+ /**
+ * Sets the bits between from (inclusive) and to (exclusive) to false.
+ *
+ * @param from the start range (inclusive)
+ * @param to the end range (exclusive)
+ * @throws IndexOutOfBoundsException if from &lt; 0 || to &lt; 0 ||
+ * from &gt; to
+ * @since 1.4
+ */
+ public void clear(int from, int to)
+ {
+ if (from < 0 || from > to)
+ throw new IndexOutOfBoundsException();
+ if (from == to)
+ return;
+ int lo_offset = from >>> 6;
+ int hi_offset = to >>> 6;
+ ensure(hi_offset);
+ if (lo_offset == hi_offset)
+ {
+ bits[hi_offset] &= ((1L << from) - 1) | (-1L << to);
+ return;
+ }
+
+ bits[lo_offset] &= (1L << from) - 1;
+ bits[hi_offset] &= -1L << to;
+ for (int i = lo_offset + 1; i < hi_offset; i++)
+ bits[i] = 0;
+ }
+
+ /**
+ * Create a clone of this bit set, that is an instance of the same
+ * class and contains the same elements. But it doesn't change when
+ * this bit set changes.
+ *
+ * @return the clone of this object.
+ */
+ public Object clone()
+ {
+ try
+ {
+ BitSet bs = (BitSet) super.clone();
+ bs.bits = (long[]) bits.clone();
+ return bs;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // Impossible to get here.
+ return null;
+ }
+ }
+
+ /**
+ * Returns true if the <code>obj</code> is a bit set that contains
+ * exactly the same elements as this bit set, otherwise false.
+ *
+ * @param obj the object to compare to
+ * @return true if obj equals this bit set
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof BitSet))
+ return false;
+ BitSet bs = (BitSet) obj;
+ int max = Math.min(bits.length, bs.bits.length);
+ int i;
+ for (i = 0; i < max; ++i)
+ if (bits[i] != bs.bits[i])
+ return false;
+ // If one is larger, check to make sure all extra bits are 0.
+ for (int j = i; j < bits.length; ++j)
+ if (bits[j] != 0)
+ return false;
+ for (int j = i; j < bs.bits.length; ++j)
+ if (bs.bits[j] != 0)
+ return false;
+ return true;
+ }
+
+ /**
+ * Sets the bit at the index to the opposite value.
+ *
+ * @param index the index of the bit
+ * @throws IndexOutOfBoundsException if index is negative
+ * @since 1.4
+ */
+ public void flip(int index)
+ {
+ int offset = index >> 6;
+ ensure(offset);
+ // ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
+ // so we'll just let that be our exception.
+ bits[offset] ^= 1L << index;
+ }
+
+ /**
+ * Sets a range of bits to the opposite value.
+ *
+ * @param from the low index (inclusive)
+ * @param to the high index (exclusive)
+ * @throws IndexOutOfBoundsException if from &gt; to || from &lt; 0 ||
+ * to &lt; 0
+ * @since 1.4
+ */
+ public void flip(int from, int to)
+ {
+ if (from < 0 || from > to)
+ throw new IndexOutOfBoundsException();
+ if (from == to)
+ return;
+ int lo_offset = from >>> 6;
+ int hi_offset = to >>> 6;
+ ensure(hi_offset);
+ if (lo_offset == hi_offset)
+ {
+ bits[hi_offset] ^= (-1L << from) & ((1L << to) - 1);
+ return;
+ }
+
+ bits[lo_offset] ^= -1L << from;
+ bits[hi_offset] ^= (1L << to) - 1;
+ for (int i = lo_offset + 1; i < hi_offset; i++)
+ bits[i] ^= -1;
+ }
+
+ /**
+ * Returns true if the integer <code>bitIndex</code> is in this bit
+ * set, otherwise false.
+ *
+ * @param pos a non-negative integer
+ * @return the value of the bit at the specified position
+ * @throws IndexOutOfBoundsException if the pos is negative
+ */
+ public boolean get(int pos)
+ {
+ int offset = pos >> 6;
+ if (offset >= bits.length)
+ return false;
+ // ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
+ // so we'll just let that be our exception.
+ return (bits[offset] & (1L << pos)) != 0;
+ }
+
+ /**
+ * Returns a new <code>BitSet</code> composed of a range of bits from
+ * this one.
+ *
+ * @param from the low index (inclusive)
+ * @param to the high index (exclusive)
+ * @throws IndexOutOfBoundsException if from &gt; to || from &lt; 0 ||
+ * to &lt; 0
+ * @since 1.4
+ */
+ public BitSet get(int from, int to)
+ {
+ if (from < 0 || from > to)
+ throw new IndexOutOfBoundsException();
+ BitSet bs = new BitSet(to - from);
+ int lo_offset = from >>> 6;
+ if (lo_offset >= bits.length)
+ return bs;
+
+ int lo_bit = from & LONG_MASK;
+ int hi_offset = to >>> 6;
+ if (lo_bit == 0)
+ {
+ int len = Math.min(hi_offset - lo_offset + 1, bits.length - lo_offset);
+ System.arraycopy(bits, lo_offset, bs.bits, 0, len);
+ if (hi_offset < bits.length)
+ bs.bits[hi_offset - lo_offset] &= (1L << to) - 1;
+ return bs;
+ }
+
+ int len = Math.min(hi_offset, bits.length - 1);
+ int reverse = 64 - lo_bit;
+ int i;
+ for (i = 0; lo_offset < len; lo_offset++, i++)
+ bs.bits[i] = ((bits[lo_offset] >>> lo_bit)
+ | (bits[lo_offset + 1] << reverse));
+ if ((to & LONG_MASK) > lo_bit)
+ bs.bits[i++] = bits[lo_offset] >>> lo_bit;
+ if (hi_offset < bits.length)
+ bs.bits[i - 1] &= (1L << (to - from)) - 1;
+ return bs;
+ }
+
+ /**
+ * Returns a hash code value for this bit set. The hash code of
+ * two bit sets containing the same integers is identical. The algorithm
+ * used to compute it is as follows:
+ *
+ * Suppose the bits in the BitSet were to be stored in an array of
+ * long integers called <code>bits</code>, in such a manner that
+ * bit <code>k</code> is set in the BitSet (for non-negative values
+ * of <code>k</code>) if and only if
+ *
+ * <code>((k/64) &lt; bits.length)
+ * && ((bits[k/64] & (1L &lt;&lt; (bit % 64))) != 0)
+ * </code>
+ *
+ * Then the following definition of the hashCode method
+ * would be a correct implementation of the actual algorithm:
+ *
+ *
+<pre>public int hashCode()
+{
+ long h = 1234;
+ for (int i = bits.length-1; i &gt;= 0; i--)
+ {
+ h ^= bits[i] * (i + 1);
+ }
+
+ return (int)((h >> 32) ^ h);
+}</pre>
+ *
+ * Note that the hash code values changes, if the set is changed.
+ *
+ * @return the hash code value for this bit set.
+ */
+ public int hashCode()
+ {
+ long h = 1234;
+ for (int i = bits.length; i > 0; )
+ h ^= i * bits[--i];
+ return (int) ((h >> 32) ^ h);
+ }
+
+ /**
+ * Returns true if the specified BitSet and this one share at least one
+ * common true bit.
+ *
+ * @param set the set to check for intersection
+ * @return true if the sets intersect
+ * @throws NullPointerException if set is null
+ * @since 1.4
+ */
+ public boolean intersects(BitSet set)
+ {
+ int i = Math.min(bits.length, set.bits.length);
+ while (--i >= 0)
+ if ((bits[i] & set.bits[i]) != 0)
+ return true;
+ return false;
+ }
+
+ /**
+ * Returns true if this set contains no true bits.
+ *
+ * @return true if all bits are false
+ * @since 1.4
+ */
+ public boolean isEmpty()
+ {
+ for (int i = bits.length - 1; i >= 0; i--)
+ if (bits[i] != 0)
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns the logical number of bits actually used by this bit
+ * set. It returns the index of the highest set bit plus one.
+ * Note that this method doesn't return the number of set bits.
+ *
+ * @return the index of the highest set bit plus one.
+ */
+ public int length()
+ {
+ // Set i to highest index that contains a non-zero value.
+ int i;
+ for (i = bits.length - 1; i >= 0 && bits[i] == 0; --i)
+ ;
+
+ // if i < 0 all bits are cleared.
+ if (i < 0)
+ return 0;
+
+ // Now determine the exact length.
+ long b = bits[i];
+ int len = (i + 1) * 64;
+ // b >= 0 checks if the highest bit is zero.
+ while (b >= 0)
+ {
+ --len;
+ b <<= 1;
+ }
+
+ return len;
+ }
+
+ /**
+ * Returns the index of the next false bit, from the specified bit
+ * (inclusive).
+ *
+ * @param from the start location
+ * @return the first false bit
+ * @throws IndexOutOfBoundsException if from is negative
+ * @since 1.4
+ */
+ public int nextClearBit(int from)
+ {
+ int offset = from >> 6;
+ long mask = 1L << from;
+ while (offset < bits.length)
+ {
+ // ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
+ // so we'll just let that be our exception.
+ long h = bits[offset];
+ do
+ {
+ if ((h & mask) == 0)
+ return from;
+ mask <<= 1;
+ from++;
+ }
+ while (mask != 0);
+ mask = 1;
+ offset++;
+ }
+ return from;
+ }
+
+ /**
+ * Returns the index of the next true bit, from the specified bit
+ * (inclusive). If there is none, -1 is returned. You can iterate over
+ * all true bits with this loop:<br>
+ *
+<pre>for (int i = bs.nextSetBit(0); i &gt;= 0; i = bs.nextSetBit(i + 1))
+{
+ // operate on i here
+}</pre>
+ *
+ * @param from the start location
+ * @return the first true bit, or -1
+ * @throws IndexOutOfBoundsException if from is negative
+ * @since 1.4
+ */
+ public int nextSetBit(int from)
+ {
+ int offset = from >> 6;
+ long mask = 1L << from;
+ while (offset < bits.length)
+ {
+ // ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
+ // so we'll just let that be our exception.
+ long h = bits[offset];
+ do
+ {
+ if ((h & mask) != 0)
+ return from;
+ mask <<= 1;
+ from++;
+ }
+ while (mask != 0);
+ mask = 1;
+ offset++;
+ }
+ return -1;
+ }
+
+ /**
+ * Performs the logical OR operation on this bit set and the
+ * given <code>set</code>. This means it builds the union
+ * of the two sets. The result is stored into this bit set, which
+ * grows as necessary.
+ *
+ * @param bs the second bit set
+ * @throws NullPointerException if bs is null
+ */
+ public void or(BitSet bs)
+ {
+ ensure(bs.bits.length - 1);
+ for (int i = bs.bits.length - 1; i >= 0; i--)
+ bits[i] |= bs.bits[i];
+ }
+
+ /**
+ * Add the integer <code>bitIndex</code> to this set. That is
+ * the corresponding bit is set to true. If the index was already in
+ * the set, this method does nothing. The size of this structure
+ * is automatically increased as necessary.
+ *
+ * @param pos a non-negative integer.
+ * @throws IndexOutOfBoundsException if pos is negative
+ */
+ public void set(int pos)
+ {
+ int offset = pos >> 6;
+ ensure(offset);
+ // ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
+ // so we'll just let that be our exception.
+ bits[offset] |= 1L << pos;
+ }
+
+ /**
+ * Sets the bit at the given index to the specified value. The size of
+ * this structure is automatically increased as necessary.
+ *
+ * @param index the position to set
+ * @param value the value to set it to
+ * @throws IndexOutOfBoundsException if index is negative
+ * @since 1.4
+ */
+ public void set(int index, boolean value)
+ {
+ if (value)
+ set(index);
+ else
+ clear(index);
+ }
+
+ /**
+ * Sets the bits between from (inclusive) and to (exclusive) to true.
+ *
+ * @param from the start range (inclusive)
+ * @param to the end range (exclusive)
+ * @throws IndexOutOfBoundsException if from &lt; 0 || from &gt; to ||
+ * to &lt; 0
+ * @since 1.4
+ */
+ public void set(int from, int to)
+ {
+ if (from < 0 || from > to)
+ throw new IndexOutOfBoundsException();
+ if (from == to)
+ return;
+ int lo_offset = from >>> 6;
+ int hi_offset = to >>> 6;
+ ensure(hi_offset);
+ if (lo_offset == hi_offset)
+ {
+ bits[hi_offset] |= (-1L << from) & ((1L << to) - 1);
+ return;
+ }
+
+ bits[lo_offset] |= -1L << from;
+ bits[hi_offset] |= (1L << to) - 1;
+ for (int i = lo_offset + 1; i < hi_offset; i++)
+ bits[i] = -1;
+ }
+
+ /**
+ * Sets the bits between from (inclusive) and to (exclusive) to the
+ * specified value.
+ *
+ * @param from the start range (inclusive)
+ * @param to the end range (exclusive)
+ * @param value the value to set it to
+ * @throws IndexOutOfBoundsException if from &lt; 0 || from &gt; to ||
+ * to &lt; 0
+ * @since 1.4
+ */
+ public void set(int from, int to, boolean value)
+ {
+ if (value)
+ set(from, to);
+ else
+ clear(from, to);
+ }
+
+ /**
+ * Returns the number of bits actually used by this bit set. Note
+ * that this method doesn't return the number of set bits, and that
+ * future requests for larger bits will make this automatically grow.
+ *
+ * @return the number of bits currently used.
+ */
+ public int size()
+ {
+ return bits.length * 64;
+ }
+
+ /**
+ * Returns the string representation of this bit set. This
+ * consists of a comma separated list of the integers in this set
+ * surrounded by curly braces. There is a space after each comma.
+ * A sample string is thus "{1, 3, 53}".
+ * @return the string representation.
+ */
+ public String toString()
+ {
+ StringBuffer r = new StringBuffer("{");
+ boolean first = true;
+ for (int i = 0; i < bits.length; ++i)
+ {
+ long bit = 1;
+ long word = bits[i];
+ if (word == 0)
+ continue;
+ for (int j = 0; j < 64; ++j)
+ {
+ if ((word & bit) != 0)
+ {
+ if (! first)
+ r.append(", ");
+ r.append(64 * i + j);
+ first = false;
+ }
+ bit <<= 1;
+ }
+ }
+ return r.append("}").toString();
+ }
+
+ /**
+ * Performs the logical XOR operation on this bit set and the
+ * given <code>set</code>. This means it builds the symmetric
+ * remainder of the two sets (the elements that are in one set,
+ * but not in the other). The result is stored into this bit set,
+ * which grows as necessary.
+ *
+ * @param bs the second bit set
+ * @throws NullPointerException if bs is null
+ */
+ public void xor(BitSet bs)
+ {
+ ensure(bs.bits.length - 1);
+ for (int i = bs.bits.length - 1; i >= 0; i--)
+ bits[i] ^= bs.bits[i];
+ }
+
+ /**
+ * Make sure the vector is big enough.
+ *
+ * @param lastElt the size needed for the bits array
+ */
+ private void ensure(int lastElt)
+ {
+ if (lastElt >= bits.length)
+ {
+ long[] nd = new long[lastElt + 1];
+ System.arraycopy(bits, 0, nd, 0, bits.length);
+ bits = nd;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/Calendar.java b/libjava/classpath/java/util/Calendar.java
new file mode 100644
index 00000000000..88bd76bcadc
--- /dev/null
+++ b/libjava/classpath/java/util/Calendar.java
@@ -0,0 +1,1277 @@
+/* Calendar.java --
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * This class is an abstract base class for Calendars, which can be
+ * used to convert between <code>Date</code> objects and a set of
+ * integer fields which represent <code>YEAR</code>,
+ * <code>MONTH</code>, <code>DAY</code>, etc. The <code>Date</code>
+ * object represents a time in milliseconds since the Epoch. <br>
+ *
+ * This class is locale sensitive. To get the Object matching the
+ * current locale you can use <code>getInstance</code>. You can even provide
+ * a locale or a timezone. <code>getInstance</code> returns currently
+ * a <code>GregorianCalendar</code> for the current date. <br>
+ *
+ * If you want to convert a date from the Year, Month, Day, DayOfWeek,
+ * etc. Representation to a <code>Date</code>-Object, you can create
+ * a new Calendar with <code>getInstance()</code>,
+ * <code>clear()</code> all fields, <code>set(int,int)</code> the
+ * fields you need and convert it with <code>getTime()</code>. <br>
+ *
+ * If you want to convert a <code>Date</code>-object to the Calendar
+ * representation, create a new Calendar, assign the
+ * <code>Date</code>-Object with <code>setTime()</code>, and read the
+ * fields with <code>get(int)</code>. <br>
+ *
+ * When computing the date from time fields, it may happen, that there
+ * are either two few fields set, or some fields are inconsistent. This
+ * cases will handled in a calendar specific way. Missing fields are
+ * replaced by the fields of the epoch: 1970 January 1 00:00. <br>
+ *
+ * To understand, how the day of year is computed out of the fields
+ * look at the following table. It is traversed from top to bottom,
+ * and for the first line all fields are set, that line is used to
+ * compute the day. <br>
+ *
+ *
+<pre>month + day_of_month
+month + week_of_month + day_of_week
+month + day_of_week_of_month + day_of_week
+day_of_year
+day_of_week + week_of_year</pre>
+ *
+ * The hour_of_day-field takes precedence over the ampm and
+ * hour_of_ampm fields. <br>
+ *
+ * <STRONG>Note:</STRONG> This can differ for non-Gregorian calendar. <br>
+ *
+ * To convert a calendar to a human readable form and vice versa, use
+ * the <code>java.text.DateFormat</code> class. <br>
+ *
+ * Other useful things you can do with an calendar, is
+ * <code>roll</code>ing fields (that means increase/decrease a
+ * specific field by one, propagating overflows), or
+ * <code>add</code>ing/substracting a fixed amount to a field.
+ *
+ * @see Date
+ * @see GregorianCalendar
+ * @see TimeZone
+ * @see java.text.DateFormat
+ */
+public abstract class Calendar implements Serializable, Cloneable
+{
+ /**
+ * Constant representing the era time field.
+ */
+ public static final int ERA = 0;
+
+ /**
+ * Constant representing the year time field.
+ */
+ public static final int YEAR = 1;
+
+ /**
+ * Constant representing the month time field. This field
+ * should contain one of the JANUARY,...,DECEMBER constants below.
+ */
+ public static final int MONTH = 2;
+
+ /**
+ * Constant representing the week of the year field.
+ * @see #setFirstDayOfWeek(int)
+ */
+ public static final int WEEK_OF_YEAR = 3;
+
+ /**
+ * Constant representing the week of the month time field.
+ * @see #setFirstDayOfWeek(int)
+ */
+ public static final int WEEK_OF_MONTH = 4;
+
+ /**
+ * Constant representing the day time field, synonym for DAY_OF_MONTH.
+ */
+ public static final int DATE = 5;
+
+ /**
+ * Constant representing the day time field.
+ */
+ public static final int DAY_OF_MONTH = 5;
+
+ /**
+ * Constant representing the day of year time field. This is
+ * 1 for the first day in month.
+ */
+ public static final int DAY_OF_YEAR = 6;
+
+ /**
+ * Constant representing the day of week time field. This field
+ * should contain one of the SUNDAY,...,SATURDAY constants below.
+ */
+ public static final int DAY_OF_WEEK = 7;
+
+ /**
+ * Constant representing the day-of-week-in-month field. For
+ * instance this field contains 2 for the second thursday in a
+ * month. If you give a negative number here, the day will count
+ * from the end of the month.
+ */
+ public static final int DAY_OF_WEEK_IN_MONTH = 8;
+
+ /**
+ * Constant representing the part of the day for 12-hour clock. This
+ * should be one of AM or PM.
+ */
+ public static final int AM_PM = 9;
+
+ /**
+ * Constant representing the hour time field for 12-hour clock.
+ */
+ public static final int HOUR = 10;
+
+ /**
+ * Constant representing the hour of day time field for 24-hour clock.
+ */
+ public static final int HOUR_OF_DAY = 11;
+
+ /**
+ * Constant representing the minute of hour time field.
+ */
+ public static final int MINUTE = 12;
+
+ /**
+ * Constant representing the second time field.
+ */
+ public static final int SECOND = 13;
+
+ /**
+ * Constant representing the millisecond time field.
+ */
+ public static final int MILLISECOND = 14;
+
+ /**
+ * Constant representing the time zone offset time field for the
+ * time given in the other fields. It is measured in
+ * milliseconds. The default is the offset of the time zone.
+ */
+ public static final int ZONE_OFFSET = 15;
+
+ /**
+ * Constant representing the daylight saving time offset in
+ * milliseconds. The default is the value given by the time zone.
+ */
+ public static final int DST_OFFSET = 16;
+
+ /**
+ * Number of time fields.
+ */
+ public static final int FIELD_COUNT = 17;
+
+ /**
+ * Constant representing Sunday.
+ */
+ public static final int SUNDAY = 1;
+
+ /**
+ * Constant representing Monday.
+ */
+ public static final int MONDAY = 2;
+
+ /**
+ * Constant representing Tuesday.
+ */
+ public static final int TUESDAY = 3;
+
+ /**
+ * Constant representing Wednesday.
+ */
+ public static final int WEDNESDAY = 4;
+
+ /**
+ * Constant representing Thursday.
+ */
+ public static final int THURSDAY = 5;
+
+ /**
+ * Constant representing Friday.
+ */
+ public static final int FRIDAY = 6;
+
+ /**
+ * Constant representing Saturday.
+ */
+ public static final int SATURDAY = 7;
+
+ /**
+ * Constant representing January.
+ */
+ public static final int JANUARY = 0;
+
+ /**
+ * Constant representing February.
+ */
+ public static final int FEBRUARY = 1;
+
+ /**
+ * Constant representing March.
+ */
+ public static final int MARCH = 2;
+
+ /**
+ * Constant representing April.
+ */
+ public static final int APRIL = 3;
+
+ /**
+ * Constant representing May.
+ */
+ public static final int MAY = 4;
+
+ /**
+ * Constant representing June.
+ */
+ public static final int JUNE = 5;
+
+ /**
+ * Constant representing July.
+ */
+ public static final int JULY = 6;
+
+ /**
+ * Constant representing August.
+ */
+ public static final int AUGUST = 7;
+
+ /**
+ * Constant representing September.
+ */
+ public static final int SEPTEMBER = 8;
+
+ /**
+ * Constant representing October.
+ */
+ public static final int OCTOBER = 9;
+
+ /**
+ * Constant representing November.
+ */
+ public static final int NOVEMBER = 10;
+
+ /**
+ * Constant representing December.
+ */
+ public static final int DECEMBER = 11;
+
+ /**
+ * Constant representing Undecimber. This is an artificial name useful
+ * for lunar calendars.
+ */
+ public static final int UNDECIMBER = 12;
+
+ /**
+ * Useful constant for 12-hour clock.
+ */
+ public static final int AM = 0;
+
+ /**
+ * Useful constant for 12-hour clock.
+ */
+ public static final int PM = 1;
+
+ /**
+ * The time fields. The array is indexed by the constants YEAR to
+ * DST_OFFSET.
+ * @serial
+ */
+ protected int[] fields = new int[FIELD_COUNT];
+
+ /**
+ * The flags which tell if the fields above have a value.
+ * @serial
+ */
+ protected boolean[] isSet = new boolean[FIELD_COUNT];
+
+ /**
+ * The time in milliseconds since the epoch.
+ * @serial
+ */
+ protected long time;
+
+ /**
+ * Tells if the above field has a valid value.
+ * @serial
+ */
+ protected boolean isTimeSet;
+
+ /**
+ * Tells if the fields have a valid value. This superseeds the isSet
+ * array.
+ * @serial
+ */
+ protected boolean areFieldsSet;
+
+ /**
+ * The time zone of this calendar. Used by sub classes to do UTC / local
+ * time conversion. Sub classes can access this field with getTimeZone().
+ * @serial
+ */
+ private TimeZone zone;
+
+ /**
+ * This is the default calendar class, that is returned on
+ * java.util.Calendar.getInstance().
+ * XXX - this isn't localized anywhere, is it?
+ * @see java.util.Calendar#getInstance()
+ */
+ private static final String calendarClassName = "java.util.GregorianCalendar";
+
+ /**
+ * Specifies if the date/time interpretation should be lenient.
+ * If the flag is set, a date such as "February 30, 1996" will be
+ * treated as the 29th day after the February 1. If this flag
+ * is false, such dates will cause an exception.
+ * @serial
+ */
+ private boolean lenient;
+
+ /**
+ * Sets what the first day of week is. This is used for
+ * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
+ * @serial
+ */
+ private int firstDayOfWeek;
+
+ /**
+ * Sets how many days are required in the first week of the year.
+ * If the first day of the year should be the first week you should
+ * set this value to 1. If the first week must be a full week, set
+ * it to 7.
+ * @serial
+ */
+ private int minimalDaysInFirstWeek;
+
+ /**
+ * Is set to true if DST_OFFSET is explicitly set. In that case
+ * it's value overrides the value computed from the current
+ * time and the timezone.
+ */
+ private boolean explicitDSTOffset = false;
+
+ /**
+ * The version of the serialized data on the stream.
+ * <dl><dt>0 or not present</dt>
+ * <dd> JDK 1.1.5 or later.</dd>
+ * <dt>1</dt>
+ * <dd>JDK 1.1.6 or later. This always writes a correct `time' value
+ * on the stream, as well as the other fields, to be compatible with
+ * earlier versions</dd></dl>
+ * @since JDK1.1.6
+ * @serial
+ */
+ private int serialVersionOnStream = 1;
+
+ /**
+ * XXX - I have not checked the compatibility. The documentation of
+ * the serialized-form is quite hairy...
+ */
+ static final long serialVersionUID = -1807547505821590642L;
+
+ /**
+ * The name of the resource bundle. Used only by getBundle()
+ */
+ private static final String bundleName = "gnu.java.locale.LocaleInformation";
+
+ /**
+ * get resource bundle:
+ * The resources should be loaded via this method only. Iff an application
+ * uses this method, the resourcebundle is required.
+ */
+ private static ResourceBundle getBundle(Locale locale)
+ {
+ return ResourceBundle.getBundle(bundleName, locale,
+ ClassLoader.getSystemClassLoader());
+ }
+
+ /**
+ * Constructs a new Calendar with the default time zone and the default
+ * locale.
+ */
+ protected Calendar()
+ {
+ this(TimeZone.getDefault(), Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new Calendar with the given time zone and the given
+ * locale.
+ * @param zone a time zone.
+ * @param locale a locale.
+ */
+ protected Calendar(TimeZone zone, Locale locale)
+ {
+ this.zone = zone;
+ lenient = true;
+ String[] days = { "", "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
+
+ ResourceBundle rb = getBundle(locale);
+ String min = (String) rb.getObject("minNumberOfDaysInFirstWeek");
+ String first = (String) rb.getObject("firstDayOfWeek");
+ try
+ {
+ if (min != null)
+ minimalDaysInFirstWeek = Integer.parseInt(min);
+ }
+ catch (NumberFormatException ex)
+ {
+ minimalDaysInFirstWeek = 1;
+ }
+
+ firstDayOfWeek = 1;
+ if (first != null)
+ for (int i = 0; i < 8; i++)
+ if (days[i].equals(first))
+ firstDayOfWeek = i;
+
+ clear();
+ }
+
+ /**
+ * Creates a calendar representing the actual time, using the default
+ * time zone and locale.
+ */
+ public static synchronized Calendar getInstance()
+ {
+ return getInstance(TimeZone.getDefault(), Locale.getDefault());
+ }
+
+ /**
+ * Creates a calendar representing the actual time, using the given
+ * time zone and the default locale.
+ * @param zone a time zone.
+ */
+ public static synchronized Calendar getInstance(TimeZone zone)
+ {
+ return getInstance(zone, Locale.getDefault());
+ }
+
+ /**
+ * Creates a calendar representing the actual time, using the default
+ * time zone and the given locale.
+ * @param locale a locale.
+ */
+ public static synchronized Calendar getInstance(Locale locale)
+ {
+ return getInstance(TimeZone.getDefault(), locale);
+ }
+
+ /**
+ * Cache of locale->calendar-class mappings. This avoids having to do a ResourceBundle
+ * lookup for every getInstance call.
+ */
+ private static HashMap cache = new HashMap();
+
+ /** Preset argument types for calendar-class constructor lookup. */
+ private static Class[] ctorArgTypes = new Class[]
+ {
+ TimeZone.class, Locale.class
+ };
+
+ /**
+ * Creates a calendar representing the actual time, using the given
+ * time zone and locale.
+ * @param zone a time zone.
+ * @param locale a locale.
+ */
+ public static synchronized Calendar getInstance(TimeZone zone, Locale locale)
+ {
+ Class calendarClass = (Class) cache.get(locale);
+ Throwable exception = null;
+
+ try
+ {
+ if (calendarClass == null)
+ {
+ calendarClass = Class.forName(calendarClassName);
+ if (Calendar.class.isAssignableFrom(calendarClass))
+ cache.put(locale, calendarClass);
+ }
+
+ // GregorianCalendar is by far the most common case. Optimize by
+ // avoiding reflection.
+ if (calendarClass == GregorianCalendar.class)
+ return new GregorianCalendar(zone, locale);
+
+ if (Calendar.class.isAssignableFrom(calendarClass))
+ {
+ Constructor ctor = calendarClass.getConstructor(ctorArgTypes);
+ return (Calendar) ctor.newInstance(new Object[] { zone, locale });
+ }
+ }
+ catch (ClassNotFoundException ex)
+ {
+ exception = ex;
+ }
+ catch (IllegalAccessException ex)
+ {
+ exception = ex;
+ }
+ catch (NoSuchMethodException ex)
+ {
+ exception = ex;
+ }
+ catch (InstantiationException ex)
+ {
+ exception = ex;
+ }
+ catch (InvocationTargetException ex)
+ {
+ exception = ex;
+ }
+
+ throw new RuntimeException("Error instantiating calendar for locale "
+ + locale, exception);
+ }
+
+ /**
+ * Gets the set of locales for which a Calendar is available.
+ * @exception MissingResourceException if locale data couldn't be found.
+ * @return the set of locales.
+ */
+ public static synchronized Locale[] getAvailableLocales()
+ {
+ ResourceBundle rb = getBundle(new Locale("", ""));
+ return (Locale[]) rb.getObject("availableLocales");
+ }
+
+ /**
+ * Converts the time field values (<code>fields</code>) to
+ * milliseconds since the epoch UTC (<code>time</code>). Override
+ * this method if you write your own Calendar. */
+ protected abstract void computeTime();
+
+ /**
+ * Converts the milliseconds since the epoch UTC
+ * (<code>time</code>) to time fields
+ * (<code>fields</code>). Override this method if you write your
+ * own Calendar.
+ */
+ protected abstract void computeFields();
+
+ /**
+ * Converts the time represented by this object to a
+ * <code>Date</code>-Object.
+ * @return the Date.
+ */
+ public final Date getTime()
+ {
+ if (! isTimeSet)
+ computeTime();
+ return new Date(time);
+ }
+
+ /**
+ * Sets this Calendar's time to the given Date. All time fields
+ * are invalidated by this method.
+ */
+ public final void setTime(Date date)
+ {
+ setTimeInMillis(date.getTime());
+ }
+
+ /**
+ * Returns the time represented by this Calendar.
+ * @return the time in milliseconds since the epoch.
+ * @specnote This was made public in 1.4.
+ */
+ public long getTimeInMillis()
+ {
+ if (! isTimeSet)
+ computeTime();
+ return time;
+ }
+
+ /**
+ * Sets this Calendar's time to the given Time. All time fields
+ * are invalidated by this method.
+ * @param time the time in milliseconds since the epoch
+ * @specnote This was made public in 1.4.
+ */
+ public void setTimeInMillis(long time)
+ {
+ clear();
+ this.time = time;
+ isTimeSet = true;
+ computeFields();
+ }
+
+ /**
+ * Gets the value of the specified field. They are recomputed
+ * if they are invalid.
+ * @param field the time field. One of the time field constants.
+ * @return the value of the specified field
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @specnote Not final since JDK 1.4
+ */
+ public int get(int field)
+ {
+ // If the requested field is invalid, force all fields to be recomputed.
+ if (! isSet[field])
+ areFieldsSet = false;
+ complete();
+ return fields[field];
+ }
+
+ /**
+ * Gets the value of the specified field. This method doesn't
+ * recompute the fields, if they are invalid.
+ * @param field the time field. One of the time field constants.
+ * @return the value of the specified field, undefined if
+ * <code>areFieldsSet</code> or <code>isSet[field]</code> is false.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ protected final int internalGet(int field)
+ {
+ return fields[field];
+ }
+
+ /**
+ * Sets the time field with the given value. This does invalidate
+ * the time in milliseconds.
+ * @param field the time field. One of the time field constants
+ * @param value the value to be set.
+ * @throws ArrayIndexOutOfBoundsException if field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @specnote Not final since JDK 1.4
+ */
+ public void set(int field, int value)
+ {
+ if (isTimeSet)
+ for (int i = 0; i < FIELD_COUNT; i++)
+ isSet[i] = false;
+ isTimeSet = false;
+ fields[field] = value;
+ isSet[field] = true;
+
+ // The five valid date patterns, in order of priority
+ // 1 YEAR + MONTH + DAY_OF_MONTH
+ // 2 YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
+ // 3 YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
+ // 4 YEAR + DAY_OF_YEAR
+ // 5 YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
+ switch (field)
+ {
+ case MONTH: // pattern 1,2 or 3
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case DAY_OF_MONTH: // pattern 1
+ isSet[YEAR] = true;
+ isSet[MONTH] = true;
+ isSet[WEEK_OF_MONTH] = true;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case WEEK_OF_MONTH: // pattern 2
+ if (! isSet[DAY_OF_WEEK])
+ fields[DAY_OF_WEEK] = getFirstDayOfWeek();
+ isSet[YEAR] = true;
+ isSet[MONTH] = true;
+ isSet[DAY_OF_WEEK] = true;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case DAY_OF_WEEK_IN_MONTH: // pattern 3
+ if (! isSet[DAY_OF_WEEK])
+ fields[DAY_OF_WEEK] = getFirstDayOfWeek();
+ isSet[YEAR] = true;
+ isSet[MONTH] = true;
+ isSet[DAY_OF_WEEK] = true;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case DAY_OF_YEAR: // pattern 4
+ isSet[YEAR] = true;
+ isSet[MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ break;
+ case WEEK_OF_YEAR: // pattern 5
+ if (! isSet[DAY_OF_WEEK])
+ fields[DAY_OF_WEEK] = getFirstDayOfWeek();
+ isSet[YEAR] = true;
+ isSet[DAY_OF_WEEK] = true;
+ isSet[MONTH] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ break;
+ case AM_PM:
+ isSet[HOUR] = true;
+ isSet[HOUR_OF_DAY] = false;
+ break;
+ case HOUR_OF_DAY:
+ isSet[AM_PM] = false;
+ isSet[HOUR] = false;
+ break;
+ case HOUR:
+ isSet[AM_PM] = true;
+ isSet[HOUR_OF_DAY] = false;
+ break;
+ case DST_OFFSET:
+ explicitDSTOffset = true;
+ }
+
+ // May have crossed over a DST boundary.
+ if (! explicitDSTOffset && (field != DST_OFFSET && field != ZONE_OFFSET))
+ isSet[DST_OFFSET] = false;
+ }
+
+ /**
+ * Sets the fields for year, month, and date
+ * @param year the year.
+ * @param month the month, one of the constants JANUARY..UNDICEMBER.
+ * @param date the day of the month
+ */
+ public final void set(int year, int month, int date)
+ {
+ isTimeSet = false;
+ fields[YEAR] = year;
+ fields[MONTH] = month;
+ fields[DATE] = date;
+ isSet[YEAR] = isSet[MONTH] = isSet[DATE] = true;
+ isSet[WEEK_OF_YEAR] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[ERA] = false;
+
+ if (! explicitDSTOffset)
+ isSet[DST_OFFSET] = false; // May have crossed a DST boundary.
+ }
+
+ /**
+ * Sets the fields for year, month, date, hour, and minute
+ * @param year the year.
+ * @param month the month, one of the constants JANUARY..UNDICEMBER.
+ * @param date the day of the month
+ * @param hour the hour of day.
+ * @param minute the minute.
+ */
+ public final void set(int year, int month, int date, int hour, int minute)
+ {
+ set(year, month, date);
+ fields[HOUR_OF_DAY] = hour;
+ fields[MINUTE] = minute;
+ isSet[HOUR_OF_DAY] = isSet[MINUTE] = true;
+ isSet[AM_PM] = false;
+ isSet[HOUR] = false;
+ }
+
+ /**
+ * Sets the fields for year, month, date, hour, and minute
+ * @param year the year.
+ * @param month the month, one of the constants JANUARY..UNDICEMBER.
+ * @param date the day of the month
+ * @param hour the hour of day.
+ * @param minute the minute.
+ * @param second the second.
+ */
+ public final void set(int year, int month, int date, int hour, int minute,
+ int second)
+ {
+ set(year, month, date, hour, minute);
+ fields[SECOND] = second;
+ isSet[SECOND] = true;
+ }
+
+ /**
+ * Clears the values of all the time fields.
+ */
+ public final void clear()
+ {
+ isTimeSet = false;
+ areFieldsSet = false;
+ int zoneOffs = zone.getRawOffset();
+ int[] tempFields =
+ {
+ 1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
+ 0, 0, zoneOffs, 0
+ };
+ fields = tempFields;
+ for (int i = 0; i < FIELD_COUNT; i++)
+ isSet[i] = false;
+ }
+
+ /**
+ * Clears the values of the specified time field.
+ * @param field the time field. One of the time field constants.
+ * @throws ArrayIndexOutOfBoundsException if field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ public final void clear(int field)
+ {
+ int[] tempFields =
+ {
+ 1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
+ 0, 0, zone.getRawOffset(), 0
+ };
+ isTimeSet = false;
+ areFieldsSet = false;
+ isSet[field] = false;
+ fields[field] = tempFields[field];
+ }
+
+ /**
+ * Determines if the specified field has a valid value.
+ * @return true if the specified field has a value.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ public final boolean isSet(int field)
+ {
+ return isSet[field];
+ }
+
+ /**
+ * Fills any unset fields in the time field list
+ */
+ protected void complete()
+ {
+ if (! isTimeSet)
+ computeTime();
+ if (! areFieldsSet)
+ computeFields();
+ }
+
+ /**
+ * Compares the given calendar with this.
+ * @param o the object to that we should compare.
+ * @return true, if the given object is a calendar, that represents
+ * the same time (but doesn't necessary have the same fields).
+ */
+ public boolean equals(Object o)
+ {
+ return (o instanceof Calendar)
+ && getTimeInMillis() == ((Calendar) o).getTimeInMillis();
+ }
+
+ /**
+ * Returns a hash code for this calendar.
+ * @return a hash code, which fullfits the general contract of
+ * <code>hashCode()</code>
+ */
+ public int hashCode()
+ {
+ long time = getTimeInMillis();
+ return (int) ((time & 0xffffffffL) ^ (time >> 32));
+ }
+
+ /**
+ * Compares the given calendar with this.
+ * @param o the object to that we should compare.
+ * @return true, if the given object is a calendar, and this calendar
+ * represents a smaller time than the calendar o.
+ * @exception ClassCastException if o is not an calendar.
+ * @since JDK1.2 you don't need to override this method
+ */
+ public boolean before(Object o)
+ {
+ return getTimeInMillis() < ((Calendar) o).getTimeInMillis();
+ }
+
+ /**
+ * Compares the given calendar with this.
+ * @param o the object to that we should compare.
+ * @return true, if the given object is a calendar, and this calendar
+ * represents a bigger time than the calendar o.
+ * @exception ClassCastException if o is not an calendar.
+ * @since JDK1.2 you don't need to override this method
+ */
+ public boolean after(Object o)
+ {
+ return getTimeInMillis() > ((Calendar) o).getTimeInMillis();
+ }
+
+ /**
+ * Adds the specified amount of time to the given time field. The
+ * amount may be negative to subtract the time. If the field overflows
+ * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
+ * @param field the time field. One of the time field constants.
+ * @param amount the amount of time.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ public abstract void add(int field, int amount);
+
+ /**
+ * Rolls the specified time field up or down. This means add one
+ * to the specified field, but don't change the other fields. If
+ * the maximum for this field is reached, start over with the
+ * minimum value. <br>
+ *
+ * <strong>Note:</strong> There may be situation, where the other
+ * fields must be changed, e.g rolling the month on May, 31.
+ * The date June, 31 is automatically converted to July, 1.
+ * @param field the time field. One of the time field constants.
+ * @param up the direction, true for up, false for down.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ public abstract void roll(int field, boolean up);
+
+ /**
+ * Rolls up or down the specified time field by the given amount.
+ * A negative amount rolls down. The default implementation is
+ * call <code>roll(int, boolean)</code> for the specified amount.
+ *
+ * Subclasses should override this method to do more intuitiv things.
+ *
+ * @param field the time field. One of the time field constants.
+ * @param amount the amount to roll by, positive for rolling up,
+ * negative for rolling down.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @since JDK1.2
+ */
+ public void roll(int field, int amount)
+ {
+ while (amount > 0)
+ {
+ roll(field, true);
+ amount--;
+ }
+ while (amount < 0)
+ {
+ roll(field, false);
+ amount++;
+ }
+ }
+
+ /**
+ * Sets the time zone to the specified value.
+ * @param zone the new time zone
+ */
+ public void setTimeZone(TimeZone zone)
+ {
+ this.zone = zone;
+ }
+
+ /**
+ * Gets the time zone of this calendar
+ * @return the current time zone.
+ */
+ public TimeZone getTimeZone()
+ {
+ return zone;
+ }
+
+ /**
+ * Specifies if the date/time interpretation should be lenient.
+ * If the flag is set, a date such as "February 30, 1996" will be
+ * treated as the 29th day after the February 1. If this flag
+ * is false, such dates will cause an exception.
+ * @param lenient true, if the date should be interpreted linient,
+ * false if it should be interpreted strict.
+ */
+ public void setLenient(boolean lenient)
+ {
+ this.lenient = lenient;
+ }
+
+ /**
+ * Tells if the date/time interpretation is lenient.
+ * @return true, if the date should be interpreted linient,
+ * false if it should be interpreted strict.
+ */
+ public boolean isLenient()
+ {
+ return lenient;
+ }
+
+ /**
+ * Sets what the first day of week is. This is used for
+ * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
+ * @param value the first day of week. One of SUNDAY to SATURDAY.
+ */
+ public void setFirstDayOfWeek(int value)
+ {
+ firstDayOfWeek = value;
+ }
+
+ /**
+ * Gets what the first day of week is. This is used for
+ * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
+ * @return the first day of week. One of SUNDAY to SATURDAY.
+ */
+ public int getFirstDayOfWeek()
+ {
+ return firstDayOfWeek;
+ }
+
+ /**
+ * Sets how many days are required in the first week of the year.
+ * If the first day of the year should be the first week you should
+ * set this value to 1. If the first week must be a full week, set
+ * it to 7.
+ * @param value the minimal days required in the first week.
+ */
+ public void setMinimalDaysInFirstWeek(int value)
+ {
+ minimalDaysInFirstWeek = value;
+ }
+
+ /**
+ * Gets how many days are required in the first week of the year.
+ * @return the minimal days required in the first week.
+ * @see #setMinimalDaysInFirstWeek
+ */
+ public int getMinimalDaysInFirstWeek()
+ {
+ return minimalDaysInFirstWeek;
+ }
+
+ /**
+ * Gets the smallest value that is allowed for the specified field.
+ * @param field the time field. One of the time field constants.
+ * @return the smallest value.
+ */
+ public abstract int getMinimum(int field);
+
+ /**
+ * Gets the biggest value that is allowed for the specified field.
+ * @param field the time field. One of the time field constants.
+ * @return the biggest value.
+ */
+ public abstract int getMaximum(int field);
+
+ /**
+ * Gets the greatest minimum value that is allowed for the specified field.
+ * @param field the time field. One of the time field constants.
+ * @return the greatest minimum value.
+ */
+ public abstract int getGreatestMinimum(int field);
+
+ /**
+ * Gets the smallest maximum value that is allowed for the
+ * specified field. For example this is 28 for DAY_OF_MONTH.
+ * @param field the time field. One of the time field constants.
+ * @return the least maximum value.
+ */
+ public abstract int getLeastMaximum(int field);
+
+ /**
+ * Gets the actual minimum value that is allowed for the specified field.
+ * This value is dependent on the values of the other fields.
+ * @param field the time field. One of the time field constants.
+ * @return the actual minimum value.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @since jdk1.2
+ */
+ public int getActualMinimum(int field)
+ {
+ Calendar tmp = (Calendar) clone(); // To avoid restoring state
+ int min = tmp.getGreatestMinimum(field);
+ int end = tmp.getMinimum(field);
+ tmp.set(field, min);
+ for (; min > end; min--)
+ {
+ tmp.add(field, -1); // Try to get smaller
+ if (tmp.get(field) != min - 1)
+ break; // Done if not successful
+ }
+ return min;
+ }
+
+ /**
+ * Gets the actual maximum value that is allowed for the specified field.
+ * This value is dependent on the values of the other fields.
+ * @param field the time field. One of the time field constants.
+ * @return the actual maximum value.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @since jdk1.2
+ */
+ public int getActualMaximum(int field)
+ {
+ Calendar tmp = (Calendar) clone(); // To avoid restoring state
+ int max = tmp.getLeastMaximum(field);
+ int end = tmp.getMaximum(field);
+ tmp.set(field, max);
+ for (; max < end; max++)
+ {
+ tmp.add(field, 1);
+ if (tmp.get(field) != max + 1)
+ break;
+ }
+ return max;
+ }
+
+ /**
+ * Return a clone of this object.
+ */
+ public Object clone()
+ {
+ try
+ {
+ Calendar cal = (Calendar) super.clone();
+ cal.fields = (int[]) fields.clone();
+ cal.isSet = (boolean[]) isSet.clone();
+ return cal;
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ return null;
+ }
+ }
+
+ private static final String[] fieldNames =
+ {
+ ",ERA=", ",YEAR=", ",MONTH=",
+ ",WEEK_OF_YEAR=",
+ ",WEEK_OF_MONTH=",
+ ",DAY_OF_MONTH=",
+ ",DAY_OF_YEAR=", ",DAY_OF_WEEK=",
+ ",DAY_OF_WEEK_IN_MONTH=",
+ ",AM_PM=", ",HOUR=",
+ ",HOUR_OF_DAY=", ",MINUTE=",
+ ",SECOND=", ",MILLISECOND=",
+ ",ZONE_OFFSET=", ",DST_OFFSET="
+ };
+
+ /**
+ * Returns a string representation of this object. It is mainly
+ * for debugging purposes and its content is implementation
+ * specific.
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(getClass().getName()).append('[');
+ sb.append("time=");
+ if (isTimeSet)
+ sb.append(time);
+ else
+ sb.append("?");
+ sb.append(",zone=" + zone);
+ sb.append(",areFieldsSet=" + areFieldsSet);
+ for (int i = 0; i < FIELD_COUNT; i++)
+ {
+ sb.append(fieldNames[i]);
+ if (isSet[i])
+ sb.append(fields[i]);
+ else
+ sb.append("?");
+ }
+ sb.append(",lenient=").append(lenient);
+ sb.append(",firstDayOfWeek=").append(firstDayOfWeek);
+ sb.append(",minimalDaysInFirstWeek=").append(minimalDaysInFirstWeek);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ /**
+ * Saves the state of the object to the stream. Ideally we would
+ * only write the time field, but we need to be compatible with
+ * earlier versions. <br>
+ *
+ * This doesn't write the JDK1.1 field nextStamp to the stream, as
+ * I don't know what it is good for, and because the documentation
+ * says, that it could be omitted. */
+ private void writeObject(ObjectOutputStream stream) throws IOException
+ {
+ if (! isTimeSet)
+ computeTime();
+ stream.defaultWriteObject();
+ }
+
+ /**
+ * Reads the object back from stream (deserialization).
+ */
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException
+ {
+ stream.defaultReadObject();
+ if (! isTimeSet)
+ computeTime();
+
+ if (serialVersionOnStream > 1)
+ {
+ // This is my interpretation of the serial number:
+ // Sun wants to remove all fields from the stream someday
+ // and will then increase the serialVersion number again.
+ // We prepare to be compatible.
+ fields = new int[FIELD_COUNT];
+ isSet = new boolean[FIELD_COUNT];
+ areFieldsSet = false;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/Collection.java b/libjava/classpath/java/util/Collection.java
new file mode 100644
index 00000000000..29e1b3786b4
--- /dev/null
+++ b/libjava/classpath/java/util/Collection.java
@@ -0,0 +1,288 @@
+/* Collection.java -- Interface that represents a collection of objects
+ Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Interface that represents a collection of objects. This interface is the
+ * root of the collection hierarchy, and does not provide any guarantees about
+ * the order of its elements or whether or not duplicate elements are
+ * permitted.
+ * <p>
+ * All methods of this interface that are defined to modify the collection are
+ * defined as <dfn>optional</dfn>. An optional operation may throw an
+ * UnsupportedOperationException if the data backing this collection does not
+ * support such a modification. This may mean that the data structure is
+ * immutable, or that it is read-only but may change ("unmodifiable"), or
+ * that it is modifiable but of fixed size (such as an array), or any number
+ * of other combinations.
+ * <p>
+ * A class that wishes to implement this interface should consider subclassing
+ * AbstractCollection, which provides basic implementations of most of the
+ * methods of this interface. Classes that are prepared to make guarantees
+ * about ordering or about absence of duplicate elements should consider
+ * implementing List or Set respectively, both of which are subinterfaces of
+ * Collection.
+ * <p>
+ * A general-purpose implementation of the Collection interface should in most
+ * cases provide at least two constructors: One which takes no arguments and
+ * creates an empty collection, and one which takes a Collection as an argument
+ * and returns a collection containing the same elements (that is, creates a
+ * copy of the argument using its own implementation).
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see List
+ * @see Set
+ * @see Map
+ * @see SortedSet
+ * @see SortedMap
+ * @see HashSet
+ * @see TreeSet
+ * @see ArrayList
+ * @see LinkedList
+ * @see Vector
+ * @see Collections
+ * @see Arrays
+ * @see AbstractCollection
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Collection
+{
+ /**
+ * Add an element to this collection.
+ *
+ * @param o the object to add.
+ * @return true if the collection was modified as a result of this action.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the add operation.
+ * @throws ClassCastException if o cannot be added to this collection due
+ * to its type.
+ * @throws NullPointerException if o is null and this collection doesn't
+ * support the addition of null values.
+ * @throws IllegalArgumentException if o cannot be added to this
+ * collection for some other reason.
+ */
+ boolean add(Object o);
+
+ /**
+ * Add the contents of a given collection to this collection.
+ *
+ * @param c the collection to add.
+ * @return true if the collection was modified as a result of this action.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the addAll operation.
+ * @throws ClassCastException if some element of c cannot be added to this
+ * collection due to its type.
+ * @throws NullPointerException if some element of c is null and this
+ * collection does not support the addition of null values.
+ * @throws NullPointerException if c itself is null.
+ * @throws IllegalArgumentException if some element of c cannot be added
+ * to this collection for some other reason.
+ */
+ boolean addAll(Collection c);
+
+ /**
+ * Clear the collection, such that a subsequent call to isEmpty() would
+ * return true.
+ *
+ * @throws UnsupportedOperationException if this collection does not
+ * support the clear operation.
+ */
+ void clear();
+
+ /**
+ * Test whether this collection contains a given object as one of its
+ * elements.
+ *
+ * @param o the element to look for.
+ * @return true if this collection contains at least one element e such that
+ * <code>o == null ? e == null : o.equals(e)</code>.
+ * @throws ClassCastException if the type of o is not a valid type for this
+ * collection.
+ * @throws NullPointerException if o is null and this collection doesn't
+ * support null values.
+ */
+ boolean contains(Object o);
+
+ /**
+ * Test whether this collection contains every element in a given collection.
+ *
+ * @param c the collection to test for.
+ * @return true if for every element o in c, contains(o) would return true.
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for this collection.
+ * @throws NullPointerException if some element of c is null and this
+ * collection does not support null values.
+ * @throws NullPointerException if c itself is null.
+ */
+ boolean containsAll(Collection c);
+
+ /**
+ * Test whether this collection is equal to some object. The Collection
+ * interface does not explicitly require any behaviour from this method, and
+ * it may be left to the default implementation provided by Object. The Set
+ * and List interfaces do, however, require specific behaviour from this
+ * method.
+ * <p>
+ * If an implementation of Collection, which is not also an implementation of
+ * Set or List, should choose to implement this method, it should take care
+ * to obey the contract of the equals method of Object. In particular, care
+ * should be taken to return false when o is a Set or a List, in order to
+ * preserve the symmetry of the relation.
+ *
+ * @param o the object to compare to this collection.
+ * @return true if the o is equal to this collection.
+ */
+ boolean equals(Object o);
+
+ /**
+ * Obtain a hash code for this collection. The Collection interface does not
+ * explicitly require any behaviour from this method, and it may be left to
+ * the default implementation provided by Object. The Set and List interfaces
+ * do, however, require specific behaviour from this method.
+ * <p>
+ * If an implementation of Collection, which is not also an implementation of
+ * Set or List, should choose to implement this method, it should take care
+ * to obey the contract of the hashCode method of Object. Note that this
+ * method renders it impossible to correctly implement both Set and List, as
+ * the required implementations are mutually exclusive.
+ *
+ * @return a hash code for this collection.
+ */
+ int hashCode();
+
+ /**
+ * Test whether this collection is empty, that is, if size() == 0.
+ *
+ * @return true if this collection contains no elements.
+ */
+ boolean isEmpty();
+
+ /**
+ * Obtain an Iterator over this collection.
+ *
+ * @return an Iterator over the elements of this collection, in any order.
+ */
+ Iterator iterator();
+
+ /**
+ * Remove a single occurrence of an object from this collection. That is,
+ * remove an element e, if one exists, such that <code>o == null ? e == null
+ * : o.equals(e)</code>.
+ *
+ * @param o the object to remove.
+ * @return true if the collection changed as a result of this call, that is,
+ * if the collection contained at least one occurrence of o.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the remove operation.
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this collection.
+ * @throws NullPointerException if o is null and the collection doesn't
+ * support null values.
+ */
+ boolean remove(Object o);
+
+ /**
+ * Remove all elements of a given collection from this collection. That is,
+ * remove every element e such that c.contains(e).
+ *
+ * @param c The collection of objects to be removed.
+ * @return true if this collection was modified as a result of this call.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the removeAll operation.
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for this collection.
+ * @throws NullPointerException if some element of c is null and this
+ * collection does not support removing null values.
+ * @throws NullPointerException if c itself is null.
+ */
+ boolean removeAll(Collection c);
+
+ /**
+ * Remove all elements of this collection that are not contained in a given
+ * collection. That is, remove every element e such that !c.contains(e).
+ *
+ * @param c The collection of objects to be retained.
+ * @return true if this collection was modified as a result of this call.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the retainAll operation.
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for this collection.
+ * @throws NullPointerException if some element of c is null and this
+ * collection does not support retaining null values.
+ * @throws NullPointerException if c itself is null.
+ */
+ boolean retainAll(Collection c);
+
+ /**
+ * Get the number of elements in this collection.
+ *
+ * @return the number of elements in the collection.
+ */
+ int size();
+
+ /**
+ * Copy the current contents of this collection into an array.
+ *
+ * @return an array of type Object[] and length equal to the size of this
+ * collection, containing the elements currently in this collection, in
+ * any order.
+ */
+ Object[] toArray();
+
+ /**
+ * Copy the current contents of this collection into an array. If the array
+ * passed as an argument has length less than the size of this collection, an
+ * array of the same run-time type as a, and length equal to the size of this
+ * collection, is allocated using Reflection. Otherwise, a itself is used.
+ * The elements of this collection are copied into it, and if there is space
+ * in the array, the following element is set to null. The resultant array is
+ * returned.
+ * Note: The fact that the following element is set to null is only useful
+ * if it is known that this collection does not contain any null elements.
+ *
+ * @param a the array to copy this collection into.
+ * @return an array containing the elements currently in this collection, in
+ * any order.
+ * @throws ArrayStoreException if the type of any element of the
+ * collection is not a subtype of the element type of a.
+ */
+ Object[] toArray(Object[] a);
+}
diff --git a/libjava/classpath/java/util/Collections.java b/libjava/classpath/java/util/Collections.java
new file mode 100644
index 00000000000..ed8a00500c6
--- /dev/null
+++ b/libjava/classpath/java/util/Collections.java
@@ -0,0 +1,5493 @@
+/* Collections.java -- Utility class with methods to operate on collections
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * Utility class consisting of static methods that operate on, or return
+ * Collections. Contains methods to sort, search, reverse, fill and shuffle
+ * Collections, methods to facilitate interoperability with legacy APIs that
+ * are unaware of collections, a method to return a list which consists of
+ * multiple copies of one element, and methods which "wrap" collections to give
+ * them extra properties, such as thread-safety and unmodifiability.
+ * <p>
+ *
+ * All methods which take a collection throw a {@link NullPointerException} if
+ * that collection is null. Algorithms which can change a collection may, but
+ * are not required, to throw the {@link UnsupportedOperationException} that
+ * the underlying collection would throw during an attempt at modification.
+ * For example,
+ * <code>Collections.singleton("").addAll(Collections.EMPTY_SET)</code>
+ * does not throw a exception, even though addAll is an unsupported operation
+ * on a singleton; the reason for this is that addAll did not attempt to
+ * modify the set.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see Set
+ * @see List
+ * @see Map
+ * @see Arrays
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class Collections
+{
+ /**
+ * Constant used to decide cutoff for when a non-RandomAccess list should
+ * be treated as sequential-access. Basically, quadratic behavior is
+ * acceptable for small lists when the overhead is so small in the first
+ * place. I arbitrarily set it to 16, so it may need some tuning.
+ */
+ private static final int LARGE_LIST_SIZE = 16;
+
+ /**
+ * Determines if a list should be treated as a sequential-access one.
+ * Rather than the old method of JDK 1.3 of assuming only instanceof
+ * AbstractSequentialList should be sequential, this uses the new method
+ * of JDK 1.4 of assuming anything that does NOT implement RandomAccess
+ * and exceeds a large (unspecified) size should be sequential.
+ *
+ * @param l the list to check
+ * @return <code>true</code> if it should be treated as sequential-access
+ */
+ private static boolean isSequential(List l)
+ {
+ return ! (l instanceof RandomAccess) && l.size() > LARGE_LIST_SIZE;
+ }
+
+ /**
+ * This class is non-instantiable.
+ */
+ private Collections()
+ {
+ }
+
+ /**
+ * An immutable, serializable, empty Set.
+ * @see Serializable
+ */
+ public static final Set EMPTY_SET = new EmptySet();
+
+ /**
+ * The implementation of {@link #EMPTY_SET}. This class name is required
+ * for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class EmptySet extends AbstractSet
+ implements Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 1582296315990362920L;
+
+ /**
+ * A private constructor adds overhead.
+ */
+ EmptySet()
+ {
+ }
+
+ /**
+ * The size: always 0!
+ * @return 0.
+ */
+ public int size()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns an iterator that does not iterate.
+ * @return A non-iterating iterator.
+ */
+ // This is really cheating! I think it's perfectly valid, though.
+ public Iterator iterator()
+ {
+ return EMPTY_LIST.iterator();
+ }
+
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractSet.
+ /**
+ * The empty set never contains anything.
+ * @param o The object to search for.
+ * @return <code>false</code>.
+ */
+ public boolean contains(Object o)
+ {
+ return false;
+ }
+
+ /**
+ * This is true only if the given collection is also empty.
+ * @param c The collection of objects which are to be compared
+ * against the members of this set.
+ * @return <code>true</code> if c is empty.
+ */
+ public boolean containsAll(Collection c)
+ {
+ return c.isEmpty();
+ }
+
+ /**
+ * Equal only if the other set is empty.
+ * @param o The object to compare with this set.
+ * @return <code>true</code> if o is an empty instance of <code>Set</code>.
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof Set && ((Set) o).isEmpty();
+ }
+
+ /**
+ * The hashcode is always 0.
+ * @return 0.
+ */
+ public int hashCode()
+ {
+ return 0;
+ }
+
+ /**
+ * Always succeeds with a <code>false</code> result.
+ * @param o The object to remove.
+ * @return <code>false</code>.
+ */
+ public boolean remove(Object o)
+ {
+ return false;
+ }
+
+ /**
+ * Always succeeds with a <code>false</code> result.
+ * @param c The collection of objects which should
+ * all be removed from this set.
+ * @return <code>false</code>.
+ */
+ public boolean removeAll(Collection c)
+ {
+ return false;
+ }
+
+ /**
+ * Always succeeds with a <code>false</code> result.
+ * @param c The collection of objects which should
+ * all be retained within this set.
+ * @return <code>false</code>.
+ */
+ public boolean retainAll(Collection c)
+ {
+ return false;
+ }
+
+ /**
+ * The array is always empty.
+ * @return A new array with a size of 0.
+ */
+ public Object[] toArray()
+ {
+ return new Object[0];
+ }
+
+ /**
+ * We don't even need to use reflection!
+ * @param a An existing array, which can be empty.
+ * @return The original array with any existing
+ * initial element set to null.
+ */
+ public Object[] toArray(Object[] a)
+ {
+ if (a.length > 0)
+ a[0] = null;
+ return a;
+ }
+
+ /**
+ * The string never changes.
+ *
+ * @return the string "[]".
+ */
+ public String toString()
+ {
+ return "[]";
+ }
+ } // class EmptySet
+
+ /**
+ * An immutable, serializable, empty List, which implements RandomAccess.
+ * @see Serializable
+ * @see RandomAccess
+ */
+ public static final List EMPTY_LIST = new EmptyList();
+
+ /**
+ * The implementation of {@link #EMPTY_LIST}. This class name is required
+ * for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class EmptyList extends AbstractList
+ implements Serializable, RandomAccess
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 8842843931221139166L;
+
+ /**
+ * A private constructor adds overhead.
+ */
+ EmptyList()
+ {
+ }
+
+ /**
+ * The size is always 0.
+ * @return 0.
+ */
+ public int size()
+ {
+ return 0;
+ }
+
+ /**
+ * No matter the index, it is out of bounds. This
+ * method never returns, throwing an exception instead.
+ *
+ * @param index The index of the element to retrieve.
+ * @return the object at the specified index.
+ * @throws IndexOutOfBoundsException as any given index
+ * is outside the bounds of an empty array.
+ */
+ public Object get(int index)
+ {
+ throw new IndexOutOfBoundsException();
+ }
+
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractList.
+ /**
+ * Never contains anything.
+ * @param o The object to search for.
+ * @return <code>false</code>.
+ */
+ public boolean contains(Object o)
+ {
+ return false;
+ }
+
+ /**
+ * This is true only if the given collection is also empty.
+ * @param c The collection of objects, which should be compared
+ * against the members of this list.
+ * @return <code>true</code> if c is also empty.
+ */
+ public boolean containsAll(Collection c)
+ {
+ return c.isEmpty();
+ }
+
+ /**
+ * Equal only if the other list is empty.
+ * @param o The object to compare against this list.
+ * @return <code>true</code> if o is also an empty instance of
+ * <code>List</code>.
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof List && ((List) o).isEmpty();
+ }
+
+ /**
+ * The hashcode is always 1.
+ * @return 1.
+ */
+ public int hashCode()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns -1.
+ * @param o The object to search for.
+ * @return -1.
+ */
+ public int indexOf(Object o)
+ {
+ return -1;
+ }
+
+ /**
+ * Returns -1.
+ * @param o The object to search for.
+ * @return -1.
+ */
+ public int lastIndexOf(Object o)
+ {
+ return -1;
+ }
+
+ /**
+ * Always succeeds with <code>false</code> result.
+ * @param o The object to remove.
+ * @return -1.
+ */
+ public boolean remove(Object o)
+ {
+ return false;
+ }
+
+ /**
+ * Always succeeds with <code>false</code> result.
+ * @param c The collection of objects which should
+ * all be removed from this list.
+ * @return <code>false</code>.
+ */
+ public boolean removeAll(Collection c)
+ {
+ return false;
+ }
+
+ /**
+ * Always succeeds with <code>false</code> result.
+ * @param c The collection of objects which should
+ * all be retained within this list.
+ * @return <code>false</code>.
+ */
+ public boolean retainAll(Collection c)
+ {
+ return false;
+ }
+
+ /**
+ * The array is always empty.
+ * @return A new array with a size of 0.
+ */
+ public Object[] toArray()
+ {
+ return new Object[0];
+ }
+
+ /**
+ * We don't even need to use reflection!
+ * @param a An existing array, which can be empty.
+ * @return The original array with any existing
+ * initial element set to null.
+ */
+ public Object[] toArray(Object[] a)
+ {
+ if (a.length > 0)
+ a[0] = null;
+ return a;
+ }
+
+ /**
+ * The string never changes.
+ *
+ * @return the string "[]".
+ */
+ public String toString()
+ {
+ return "[]";
+ }
+ } // class EmptyList
+
+ /**
+ * An immutable, serializable, empty Map.
+ * @see Serializable
+ */
+ public static final Map EMPTY_MAP = new EmptyMap();
+
+ /**
+ * The implementation of {@link #EMPTY_MAP}. This class name is required
+ * for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class EmptyMap extends AbstractMap
+ implements Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 6428348081105594320L;
+
+ /**
+ * A private constructor adds overhead.
+ */
+ EmptyMap()
+ {
+ }
+
+ /**
+ * There are no entries.
+ * @return The empty set.
+ */
+ public Set entrySet()
+ {
+ return EMPTY_SET;
+ }
+
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractMap.
+ /**
+ * No entries!
+ * @param key The key to search for.
+ * @return <code>false</code>.
+ */
+ public boolean containsKey(Object key)
+ {
+ return false;
+ }
+
+ /**
+ * No entries!
+ * @param value The value to search for.
+ * @return <code>false</code>.
+ */
+ public boolean containsValue(Object value)
+ {
+ return false;
+ }
+
+ /**
+ * Equal to all empty maps.
+ * @param o The object o to compare against this map.
+ * @return <code>true</code> if o is also an empty instance of
+ * <code>Map</code>.
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof Map && ((Map) o).isEmpty();
+ }
+
+ /**
+ * No mappings, so this returns null.
+ * @param o The key of the object to retrieve.
+ * @return null.
+ */
+ public Object get(Object o)
+ {
+ return null;
+ }
+
+ /**
+ * The hashcode is always 0.
+ * @return 0.
+ */
+ public int hashCode()
+ {
+ return 0;
+ }
+
+ /**
+ * No entries.
+ * @return The empty set.
+ */
+ public Set keySet()
+ {
+ return EMPTY_SET;
+ }
+
+ /**
+ * Remove always succeeds, with null result.
+ * @param o The key of the mapping to remove.
+ * @return null, as there is never a mapping for o.
+ */
+ public Object remove(Object o)
+ {
+ return null;
+ }
+
+ /**
+ * Size is always 0.
+ * @return 0.
+ */
+ public int size()
+ {
+ return 0;
+ }
+
+ /**
+ * No entries. Technically, EMPTY_SET, while more specific than a general
+ * Collection, will work. Besides, that's what the JDK uses!
+ * @return The empty set.
+ */
+ public Collection values()
+ {
+ return EMPTY_SET;
+ }
+
+ /**
+ * The string never changes.
+ *
+ * @return the string "[]".
+ */
+ public String toString()
+ {
+ return "[]";
+ }
+ } // class EmptyMap
+
+
+ /**
+ * Compare two objects with or without a Comparator. If c is null, uses the
+ * natural ordering. Slightly slower than doing it inline if the JVM isn't
+ * clever, but worth it for removing a duplicate of the search code.
+ * Note: This code is also used in Arrays (for sort as well as search).
+ */
+ static final int compare(Object o1, Object o2, Comparator c)
+ {
+ return c == null ? ((Comparable) o1).compareTo(o2) : c.compare(o1, o2);
+ }
+
+ /**
+ * Perform a binary search of a List for a key, using the natural ordering of
+ * the elements. The list must be sorted (as by the sort() method) - if it is
+ * not, the behavior of this method is undefined, and may be an infinite
+ * loop. Further, the key must be comparable with every item in the list. If
+ * the list contains the key more than once, any one of them may be found.
+ * <p>
+ *
+ * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
+ * and uses a linear search with O(n) link traversals and log(n) comparisons
+ * with {@link AbstractSequentialList} lists. Note: although the
+ * specification allows for an infinite loop if the list is unsorted, it will
+ * not happen in this (Classpath) implementation.
+ *
+ * @param l the list to search (must be sorted)
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value
+ * @throws ClassCastException if key could not be compared with one of the
+ * elements of l
+ * @throws NullPointerException if a null element has compareTo called
+ * @see #sort(List)
+ */
+ public static int binarySearch(List l, Object key)
+ {
+ return binarySearch(l, key, null);
+ }
+
+ /**
+ * Perform a binary search of a List for a key, using a supplied Comparator.
+ * The list must be sorted (as by the sort() method with the same Comparator)
+ * - if it is not, the behavior of this method is undefined, and may be an
+ * infinite loop. Further, the key must be comparable with every item in the
+ * list. If the list contains the key more than once, any one of them may be
+ * found. If the comparator is null, the elements' natural ordering is used.
+ * <p>
+ *
+ * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
+ * and uses a linear search with O(n) link traversals and log(n) comparisons
+ * with {@link AbstractSequentialList} lists. Note: although the
+ * specification allows for an infinite loop if the list is unsorted, it will
+ * not happen in this (Classpath) implementation.
+ *
+ * @param l the list to search (must be sorted)
+ * @param key the value to search for
+ * @param c the comparator by which the list is sorted
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value
+ * @throws ClassCastException if key could not be compared with one of the
+ * elements of l
+ * @throws NullPointerException if a null element is compared with natural
+ * ordering (only possible when c is null)
+ * @see #sort(List, Comparator)
+ */
+ public static int binarySearch(List l, Object key, Comparator c)
+ {
+ int pos = 0;
+ int low = 0;
+ int hi = l.size() - 1;
+
+ // We use a linear search with log(n) comparisons using an iterator
+ // if the list is sequential-access.
+ if (isSequential(l))
+ {
+ ListIterator itr = l.listIterator();
+ int i = 0;
+ Object o = itr.next(); // Assumes list is not empty (see isSequential)
+ boolean forward = true;
+ while (low <= hi)
+ {
+ pos = (low + hi) >> 1;
+ if (i < pos)
+ {
+ if (!forward)
+ itr.next(); // Changing direction first.
+ for ( ; i != pos; i++, o = itr.next());
+ forward = true;
+ }
+ else
+ {
+ if (forward)
+ itr.previous(); // Changing direction first.
+ for ( ; i != pos; i--, o = itr.previous());
+ forward = false;
+ }
+ final int d = compare(key, o, c);
+ if (d == 0)
+ return pos;
+ else if (d < 0)
+ hi = pos - 1;
+ else
+ // This gets the insertion point right on the last loop
+ low = ++pos;
+ }
+ }
+ else
+ {
+ while (low <= hi)
+ {
+ pos = (low + hi) >> 1;
+ final int d = compare(key, l.get(pos), c);
+ if (d == 0)
+ return pos;
+ else if (d < 0)
+ hi = pos - 1;
+ else
+ // This gets the insertion point right on the last loop
+ low = ++pos;
+ }
+ }
+
+ // If we failed to find it, we do the same whichever search we did.
+ return -pos - 1;
+ }
+
+ /**
+ * Copy one list to another. If the destination list is longer than the
+ * source list, the remaining elements are unaffected. This method runs in
+ * linear time.
+ *
+ * @param dest the destination list
+ * @param source the source list
+ * @throws IndexOutOfBoundsException if the destination list is shorter
+ * than the source list (the destination will be unmodified)
+ * @throws UnsupportedOperationException if dest.listIterator() does not
+ * support the set operation
+ */
+ public static void copy(List dest, List source)
+ {
+ int pos = source.size();
+ if (dest.size() < pos)
+ throw new IndexOutOfBoundsException("Source does not fit in dest");
+
+ Iterator i1 = source.iterator();
+ ListIterator i2 = dest.listIterator();
+
+ while (--pos >= 0)
+ {
+ i2.next();
+ i2.set(i1.next());
+ }
+ }
+
+ /**
+ * Returns an Enumeration over a collection. This allows interoperability
+ * with legacy APIs that require an Enumeration as input.
+ *
+ * @param c the Collection to iterate over
+ * @return an Enumeration backed by an Iterator over c
+ */
+ public static Enumeration enumeration(Collection c)
+ {
+ final Iterator i = c.iterator();
+ return new Enumeration()
+ {
+ /**
+ * Returns <code>true</code> if there are more elements to
+ * be enumerated.
+ *
+ * @return The result of <code>hasNext()</code>
+ * called on the underlying iterator.
+ */
+ public final boolean hasMoreElements()
+ {
+ return i.hasNext();
+ }
+
+ /**
+ * Returns the next element to be enumerated.
+ *
+ * @return The result of <code>next()</code>
+ * called on the underlying iterator.
+ */
+ public final Object nextElement()
+ {
+ return i.next();
+ }
+ };
+ }
+
+ /**
+ * Replace every element of a list with a given value. This method runs in
+ * linear time.
+ *
+ * @param l the list to fill.
+ * @param val the object to vill the list with.
+ * @throws UnsupportedOperationException if l.listIterator() does not
+ * support the set operation.
+ */
+ public static void fill(List l, Object val)
+ {
+ ListIterator itr = l.listIterator();
+ for (int i = l.size() - 1; i >= 0; --i)
+ {
+ itr.next();
+ itr.set(val);
+ }
+ }
+
+ /**
+ * Returns the starting index where the specified sublist first occurs
+ * in a larger list, or -1 if there is no matching position. If
+ * <code>target.size() &gt; source.size()</code>, this returns -1,
+ * otherwise this implementation uses brute force, checking for
+ * <code>source.sublist(i, i + target.size()).equals(target)</code>
+ * for all possible i.
+ *
+ * @param source the list to search
+ * @param target the sublist to search for
+ * @return the index where found, or -1
+ * @since 1.4
+ */
+ public static int indexOfSubList(List source, List target)
+ {
+ int ssize = source.size();
+ for (int i = 0, j = target.size(); j <= ssize; i++, j++)
+ if (source.subList(i, j).equals(target))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the starting index where the specified sublist last occurs
+ * in a larger list, or -1 if there is no matching position. If
+ * <code>target.size() &gt; source.size()</code>, this returns -1,
+ * otherwise this implementation uses brute force, checking for
+ * <code>source.sublist(i, i + target.size()).equals(target)</code>
+ * for all possible i.
+ *
+ * @param source the list to search
+ * @param target the sublist to search for
+ * @return the index where found, or -1
+ * @since 1.4
+ */
+ public static int lastIndexOfSubList(List source, List target)
+ {
+ int ssize = source.size();
+ for (int i = ssize - target.size(), j = ssize; i >= 0; i--, j--)
+ if (source.subList(i, j).equals(target))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns an ArrayList holding the elements visited by a given
+ * Enumeration. This method exists for interoperability between legacy
+ * APIs and the new Collection API.
+ *
+ * @param e the enumeration to put in a list
+ * @return a list containing the enumeration elements
+ * @see ArrayList
+ * @since 1.4
+ */
+ public static ArrayList list(Enumeration e)
+ {
+ ArrayList l = new ArrayList();
+ while (e.hasMoreElements())
+ l.add(e.nextElement());
+ return l;
+ }
+
+ /**
+ * Find the maximum element in a Collection, according to the natural
+ * ordering of the elements. This implementation iterates over the
+ * Collection, so it works in linear time.
+ *
+ * @param c the Collection to find the maximum element of
+ * @return the maximum element of c
+ * @exception NoSuchElementException if c is empty
+ * @exception ClassCastException if elements in c are not mutually comparable
+ * @exception NullPointerException if null.compareTo is called
+ */
+ public static Object max(Collection c)
+ {
+ return max(c, null);
+ }
+
+ /**
+ * Find the maximum element in a Collection, according to a specified
+ * Comparator. This implementation iterates over the Collection, so it
+ * works in linear time.
+ *
+ * @param c the Collection to find the maximum element of
+ * @param order the Comparator to order the elements by, or null for natural
+ * ordering
+ * @return the maximum element of c
+ * @throws NoSuchElementException if c is empty
+ * @throws ClassCastException if elements in c are not mutually comparable
+ * @throws NullPointerException if null is compared by natural ordering
+ * (only possible when order is null)
+ */
+ public static Object max(Collection c, Comparator order)
+ {
+ Iterator itr = c.iterator();
+ Object max = itr.next(); // throws NoSuchElementException
+ int csize = c.size();
+ for (int i = 1; i < csize; i++)
+ {
+ Object o = itr.next();
+ if (compare(max, o, order) < 0)
+ max = o;
+ }
+ return max;
+ }
+
+ /**
+ * Find the minimum element in a Collection, according to the natural
+ * ordering of the elements. This implementation iterates over the
+ * Collection, so it works in linear time.
+ *
+ * @param c the Collection to find the minimum element of
+ * @return the minimum element of c
+ * @throws NoSuchElementException if c is empty
+ * @throws ClassCastException if elements in c are not mutually comparable
+ * @throws NullPointerException if null.compareTo is called
+ */
+ public static Object min(Collection c)
+ {
+ return min(c, null);
+ }
+
+ /**
+ * Find the minimum element in a Collection, according to a specified
+ * Comparator. This implementation iterates over the Collection, so it
+ * works in linear time.
+ *
+ * @param c the Collection to find the minimum element of
+ * @param order the Comparator to order the elements by, or null for natural
+ * ordering
+ * @return the minimum element of c
+ * @throws NoSuchElementException if c is empty
+ * @throws ClassCastException if elements in c are not mutually comparable
+ * @throws NullPointerException if null is compared by natural ordering
+ * (only possible when order is null)
+ */
+ public static Object min(Collection c, Comparator order)
+ {
+ Iterator itr = c.iterator();
+ Object min = itr.next(); // throws NoSuchElementExcception
+ int csize = c.size();
+ for (int i = 1; i < csize; i++)
+ {
+ Object o = itr.next();
+ if (compare(min, o, order) > 0)
+ min = o;
+ }
+ return min;
+ }
+
+ /**
+ * Creates an immutable list consisting of the same object repeated n times.
+ * The returned object is tiny, consisting of only a single reference to the
+ * object and a count of the number of elements. It is Serializable, and
+ * implements RandomAccess. You can use it in tandem with List.addAll for
+ * fast list construction.
+ *
+ * @param n the number of times to repeat the object
+ * @param o the object to repeat
+ * @return a List consisting of n copies of o
+ * @throws IllegalArgumentException if n &lt; 0
+ * @see List#addAll(Collection)
+ * @see Serializable
+ * @see RandomAccess
+ */
+ public static List nCopies(final int n, final Object o)
+ {
+ return new CopiesList(n, o);
+ }
+
+ /**
+ * The implementation of {@link #nCopies(int, Object)}. This class name
+ * is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class CopiesList extends AbstractList
+ implements Serializable, RandomAccess
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 2739099268398711800L;
+
+ /**
+ * The count of elements in this list.
+ * @serial the list size
+ */
+ private final int n;
+
+ /**
+ * The repeated list element.
+ * @serial the list contents
+ */
+ private final Object element;
+
+ /**
+ * Constructs the list.
+ *
+ * @param n the count
+ * @param o the object
+ * @throws IllegalArgumentException if n &lt; 0
+ */
+ CopiesList(int n, Object o)
+ {
+ if (n < 0)
+ throw new IllegalArgumentException();
+ this.n = n;
+ element = o;
+ }
+
+ /**
+ * The size is fixed.
+ * @return The size of the list.
+ */
+ public int size()
+ {
+ return n;
+ }
+
+ /**
+ * The same element is returned.
+ * @param index The index of the element to be returned (irrelevant
+ * as the list contains only copies of <code>element</code>).
+ * @return The element used by this list.
+ */
+ public Object get(int index)
+ {
+ if (index < 0 || index >= n)
+ throw new IndexOutOfBoundsException();
+ return element;
+ }
+
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractList.
+ /**
+ * This list only contains one element.
+ * @param o The object to search for.
+ * @return <code>true</code> if o is the element used by this list.
+ */
+ public boolean contains(Object o)
+ {
+ return n > 0 && equals(o, element);
+ }
+
+ /**
+ * The index is either 0 or -1.
+ * @param o The object to find the index of.
+ * @return 0 if <code>o == element</code>, -1 if not.
+ */
+ public int indexOf(Object o)
+ {
+ return (n > 0 && equals(o, element)) ? 0 : -1;
+ }
+
+ /**
+ * The index is either n-1 or -1.
+ * @param o The object to find the last index of.
+ * @return The last index in the list if <code>o == element</code>,
+ * -1 if not.
+ */
+ public int lastIndexOf(Object o)
+ {
+ return equals(o, element) ? n - 1 : -1;
+ }
+
+ /**
+ * A subList is just another CopiesList.
+ * @param from The starting bound of the sublist.
+ * @param to The ending bound of the sublist.
+ * @return A list of copies containing <code>from - to</code>
+ * elements, all of which are equal to the element
+ * used by this list.
+ */
+ public List subList(int from, int to)
+ {
+ if (from < 0 || to > n)
+ throw new IndexOutOfBoundsException();
+ return new CopiesList(to - from, element);
+ }
+
+ /**
+ * The array is easy.
+ * @return An array of size n filled with copies of
+ * the element used by this list.
+ */
+ public Object[] toArray()
+ {
+ Object[] a = new Object[n];
+ Arrays.fill(a, element);
+ return a;
+ }
+
+ /**
+ * The string is easy to generate.
+ * @return A string representation of the list.
+ */
+ public String toString()
+ {
+ StringBuffer r = new StringBuffer("{");
+ for (int i = n - 1; --i > 0; )
+ r.append(element).append(", ");
+ r.append(element).append("}");
+ return r.toString();
+ }
+ } // class CopiesList
+
+ /**
+ * Replace all instances of one object with another in the specified list.
+ * The list does not change size. An element e is replaced if
+ * <code>oldval == null ? e == null : oldval.equals(e)</code>.
+ *
+ * @param list the list to iterate over
+ * @param oldval the element to replace
+ * @param newval the new value for the element
+ * @return <code>true</code> if a replacement occurred.
+ * @throws UnsupportedOperationException if the list iterator does not allow
+ * for the set operation
+ * @throws ClassCastException if newval is of a type which cannot be added
+ * to the list
+ * @throws IllegalArgumentException if some other aspect of newval stops
+ * it being added to the list
+ * @since 1.4
+ */
+ public static boolean replaceAll(List list, Object oldval, Object newval)
+ {
+ ListIterator itr = list.listIterator();
+ boolean replace_occured = false;
+ for (int i = list.size(); --i >= 0; )
+ if (AbstractCollection.equals(oldval, itr.next()))
+ {
+ itr.set(newval);
+ replace_occured = true;
+ }
+ return replace_occured;
+ }
+
+ /**
+ * Reverse a given list. This method works in linear time.
+ *
+ * @param l the list to reverse
+ * @throws UnsupportedOperationException if l.listIterator() does not
+ * support the set operation
+ */
+ public static void reverse(List l)
+ {
+ ListIterator i1 = l.listIterator();
+ int pos1 = 1;
+ int pos2 = l.size();
+ ListIterator i2 = l.listIterator(pos2);
+ while (pos1 < pos2)
+ {
+ Object o = i1.next();
+ i1.set(i2.previous());
+ i2.set(o);
+ ++pos1;
+ --pos2;
+ }
+ }
+
+ /**
+ * Get a comparator that implements the reverse of natural ordering. In
+ * other words, this sorts Comparable objects opposite of how their
+ * compareTo method would sort. This makes it easy to sort into reverse
+ * order, by simply passing Collections.reverseOrder() to the sort method.
+ * The return value of this method is Serializable.
+ *
+ * @return a comparator that imposes reverse natural ordering
+ * @see Comparable
+ * @see Serializable
+ */
+ public static Comparator reverseOrder()
+ {
+ return rcInstance;
+ }
+
+ /**
+ * The object for {@link #reverseOrder()}.
+ */
+ private static final ReverseComparator rcInstance = new ReverseComparator();
+
+ /**
+ * The implementation of {@link #reverseOrder()}. This class name
+ * is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ReverseComparator
+ implements Comparator, Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 7207038068494060240L;
+
+ /**
+ * A private constructor adds overhead.
+ */
+ ReverseComparator()
+ {
+ }
+
+ /**
+ * Compare two objects in reverse natural order.
+ *
+ * @param a the first object
+ * @param b the second object
+ * @return &lt;, ==, or &gt; 0 according to b.compareTo(a)
+ */
+ public int compare(Object a, Object b)
+ {
+ return ((Comparable) b).compareTo(a);
+ }
+ }
+
+ /**
+ * Rotate the elements in a list by a specified distance. After calling this
+ * method, the element now at index <code>i</code> was formerly at index
+ * <code>(i - distance) mod list.size()</code>. The list size is unchanged.
+ * <p>
+ *
+ * For example, suppose a list contains <code>[t, a, n, k, s]</code>. After
+ * either <code>Collections.rotate(l, 4)</code> or
+ * <code>Collections.rotate(l, -1)</code>, the new contents are
+ * <code>[s, t, a, n, k]</code>. This can be applied to sublists to rotate
+ * just a portion of the list. For example, to move element <code>a</code>
+ * forward two positions in the original example, use
+ * <code>Collections.rotate(l.subList(1, 3+1), -1)</code>, which will
+ * result in <code>[t, n, k, a, s]</code>.
+ * <p>
+ *
+ * If the list is small or implements {@link RandomAccess}, the
+ * implementation exchanges the first element to its destination, then the
+ * displaced element, and so on until a circuit has been completed. The
+ * process is repeated if needed on the second element, and so forth, until
+ * all elements have been swapped. For large non-random lists, the
+ * implementation breaks the list into two sublists at index
+ * <code>-distance mod size</code>, calls {@link #reverse(List)} on the
+ * pieces, then reverses the overall list.
+ *
+ * @param list the list to rotate
+ * @param distance the distance to rotate by; unrestricted in value
+ * @throws UnsupportedOperationException if the list does not support set
+ * @since 1.4
+ */
+ public static void rotate(List list, int distance)
+ {
+ int size = list.size();
+ if (size == 0)
+ return;
+ distance %= size;
+ if (distance == 0)
+ return;
+ if (distance < 0)
+ distance += size;
+
+ if (isSequential(list))
+ {
+ reverse(list);
+ reverse(list.subList(0, distance));
+ reverse(list.subList(distance, size));
+ }
+ else
+ {
+ // Determine the least common multiple of distance and size, as there
+ // are (distance / LCM) loops to cycle through.
+ int a = size;
+ int lcm = distance;
+ int b = a % lcm;
+ while (b != 0)
+ {
+ a = lcm;
+ lcm = b;
+ b = a % lcm;
+ }
+
+ // Now, make the swaps. We must take the remainder every time through
+ // the inner loop so that we don't overflow i to negative values.
+ while (--lcm >= 0)
+ {
+ Object o = list.get(lcm);
+ for (int i = lcm + distance; i != lcm; i = (i + distance) % size)
+ o = list.set(i, o);
+ list.set(lcm, o);
+ }
+ }
+ }
+
+ /**
+ * Shuffle a list according to a default source of randomness. The algorithm
+ * used iterates backwards over the list, swapping each element with an
+ * element randomly selected from the elements in positions less than or
+ * equal to it (using r.nextInt(int)).
+ * <p>
+ *
+ * This algorithm would result in a perfectly fair shuffle (that is, each
+ * element would have an equal chance of ending up in any position) if r were
+ * a perfect source of randomness. In practice the results are merely very
+ * close to perfect.
+ * <p>
+ *
+ * This method operates in linear time. To do this on large lists which do
+ * not implement {@link RandomAccess}, a temporary array is used to acheive
+ * this speed, since it would be quadratic access otherwise.
+ *
+ * @param l the list to shuffle
+ * @throws UnsupportedOperationException if l.listIterator() does not
+ * support the set operation
+ */
+ public static void shuffle(List l)
+ {
+ if (defaultRandom == null)
+ {
+ synchronized (Collections.class)
+ {
+ if (defaultRandom == null)
+ defaultRandom = new Random();
+ }
+ }
+ shuffle(l, defaultRandom);
+ }
+
+ /**
+ * Cache a single Random object for use by shuffle(List). This improves
+ * performance as well as ensuring that sequential calls to shuffle() will
+ * not result in the same shuffle order occurring: the resolution of
+ * System.currentTimeMillis() is not sufficient to guarantee a unique seed.
+ */
+ private static Random defaultRandom = null;
+
+ /**
+ * Shuffle a list according to a given source of randomness. The algorithm
+ * used iterates backwards over the list, swapping each element with an
+ * element randomly selected from the elements in positions less than or
+ * equal to it (using r.nextInt(int)).
+ * <p>
+ *
+ * This algorithm would result in a perfectly fair shuffle (that is, each
+ * element would have an equal chance of ending up in any position) if r were
+ * a perfect source of randomness. In practise (eg if r = new Random()) the
+ * results are merely very close to perfect.
+ * <p>
+ *
+ * This method operates in linear time. To do this on large lists which do
+ * not implement {@link RandomAccess}, a temporary array is used to acheive
+ * this speed, since it would be quadratic access otherwise.
+ *
+ * @param l the list to shuffle
+ * @param r the source of randomness to use for the shuffle
+ * @throws UnsupportedOperationException if l.listIterator() does not
+ * support the set operation
+ */
+ public static void shuffle(List l, Random r)
+ {
+ int lsize = l.size();
+ ListIterator i = l.listIterator(lsize);
+ boolean sequential = isSequential(l);
+ Object[] a = null; // stores a copy of the list for the sequential case
+
+ if (sequential)
+ a = l.toArray();
+
+ for (int pos = lsize - 1; pos > 0; --pos)
+ {
+ // Obtain a random position to swap with. pos + 1 is used so that the
+ // range of the random number includes the current position.
+ int swap = r.nextInt(pos + 1);
+
+ // Swap the desired element.
+ Object o;
+ if (sequential)
+ {
+ o = a[swap];
+ a[swap] = i.previous();
+ }
+ else
+ o = l.set(swap, i.previous());
+
+ i.set(o);
+ }
+ }
+
+
+ /**
+ * Obtain an immutable Set consisting of a single element. The return value
+ * of this method is Serializable.
+ *
+ * @param o the single element
+ * @return an immutable Set containing only o
+ * @see Serializable
+ */
+ public static Set singleton(Object o)
+ {
+ return new SingletonSet(o);
+ }
+
+ /**
+ * The implementation of {@link #singleton(Object)}. This class name
+ * is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class SingletonSet extends AbstractSet
+ implements Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 3193687207550431679L;
+
+
+ /**
+ * The single element; package visible for use in nested class.
+ * @serial the singleton
+ */
+ final Object element;
+
+ /**
+ * Construct a singleton.
+ * @param o the element
+ */
+ SingletonSet(Object o)
+ {
+ element = o;
+ }
+
+ /**
+ * The size: always 1!
+ * @return 1.
+ */
+ public int size()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns an iterator over the lone element.
+ */
+ public Iterator iterator()
+ {
+ return new Iterator()
+ {
+ /**
+ * Flag to indicate whether or not the element has
+ * been retrieved.
+ */
+ private boolean hasNext = true;
+
+ /**
+ * Returns <code>true</code> if elements still remain to be
+ * iterated through.
+ *
+ * @return <code>true</code> if the element has not yet been returned.
+ */
+ public boolean hasNext()
+ {
+ return hasNext;
+ }
+
+ /**
+ * Returns the element.
+ *
+ * @return The element used by this singleton.
+ * @throws NoSuchElementException if the object
+ * has already been retrieved.
+ */
+ public Object next()
+ {
+ if (hasNext)
+ {
+ hasNext = false;
+ return element;
+ }
+ else
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Removes the element from the singleton.
+ * As this set is immutable, this will always
+ * throw an exception.
+ *
+ * @throws UnsupportedOperationException as the
+ * singleton set doesn't support
+ * <code>remove()</code>.
+ */
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractSet.
+ /**
+ * The set only contains one element.
+ *
+ * @param o The object to search for.
+ * @return <code>true</code> if o == the element of the singleton.
+ */
+ public boolean contains(Object o)
+ {
+ return equals(o, element);
+ }
+
+ /**
+ * This is true if the other collection only contains the element.
+ *
+ * @param c A collection to compare against this singleton.
+ * @return <code>true</code> if c only contains either no elements or
+ * elements equal to the element in this singleton.
+ */
+ public boolean containsAll(Collection c)
+ {
+ Iterator i = c.iterator();
+ int pos = c.size();
+ while (--pos >= 0)
+ if (! equals(i.next(), element))
+ return false;
+ return true;
+ }
+
+ /**
+ * The hash is just that of the element.
+ *
+ * @return The hashcode of the element.
+ */
+ public int hashCode()
+ {
+ return hashCode(element);
+ }
+
+ /**
+ * Returning an array is simple.
+ *
+ * @return An array containing the element.
+ */
+ public Object[] toArray()
+ {
+ return new Object[] {element};
+ }
+
+ /**
+ * Obvious string.
+ *
+ * @return The string surrounded by enclosing
+ * square brackets.
+ */
+ public String toString()
+ {
+ return "[" + element + "]";
+ }
+ } // class SingletonSet
+
+ /**
+ * Obtain an immutable List consisting of a single element. The return value
+ * of this method is Serializable, and implements RandomAccess.
+ *
+ * @param o the single element
+ * @return an immutable List containing only o
+ * @see Serializable
+ * @see RandomAccess
+ * @since 1.3
+ */
+ public static List singletonList(Object o)
+ {
+ return new SingletonList(o);
+ }
+
+ /**
+ * The implementation of {@link #singletonList(Object)}. This class name
+ * is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class SingletonList extends AbstractList
+ implements Serializable, RandomAccess
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 3093736618740652951L;
+
+ /**
+ * The single element.
+ * @serial the singleton
+ */
+ private final Object element;
+
+ /**
+ * Construct a singleton.
+ * @param o the element
+ */
+ SingletonList(Object o)
+ {
+ element = o;
+ }
+
+ /**
+ * The size: always 1!
+ * @return 1.
+ */
+ public int size()
+ {
+ return 1;
+ }
+
+ /**
+ * Only index 0 is valid.
+ * @param index The index of the element
+ * to retrieve.
+ * @return The singleton's element if the
+ * index is 0.
+ * @throws IndexOutOfBoundsException if
+ * index is not 0.
+ */
+ public Object get(int index)
+ {
+ if (index == 0)
+ return element;
+ throw new IndexOutOfBoundsException();
+ }
+
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractList.
+ /**
+ * The set only contains one element.
+ *
+ * @param o The object to search for.
+ * @return <code>true</code> if o == the singleton element.
+ */
+ public boolean contains(Object o)
+ {
+ return equals(o, element);
+ }
+
+ /**
+ * This is true if the other collection only contains the element.
+ *
+ * @param c A collection to compare against this singleton.
+ * @return <code>true</code> if c only contains either no elements or
+ * elements equal to the element in this singleton.
+ */
+ public boolean containsAll(Collection c)
+ {
+ Iterator i = c.iterator();
+ int pos = c.size();
+ while (--pos >= 0)
+ if (! equals(i.next(), element))
+ return false;
+ return true;
+ }
+
+ /**
+ * Speed up the hashcode computation.
+ *
+ * @return The hashcode of the list, based
+ * on the hashcode of the singleton element.
+ */
+ public int hashCode()
+ {
+ return 31 + hashCode(element);
+ }
+
+ /**
+ * Either the list has it or not.
+ *
+ * @param o The object to find the first index of.
+ * @return 0 if o is the singleton element, -1 if not.
+ */
+ public int indexOf(Object o)
+ {
+ return equals(o, element) ? 0 : -1;
+ }
+
+ /**
+ * Either the list has it or not.
+ *
+ * @param o The object to find the last index of.
+ * @return 0 if o is the singleton element, -1 if not.
+ */
+ public int lastIndexOf(Object o)
+ {
+ return equals(o, element) ? 0 : -1;
+ }
+
+ /**
+ * Sublists are limited in scope.
+ *
+ * @param from The starting bound for the sublist.
+ * @param to The ending bound for the sublist.
+ * @return Either an empty list if both bounds are
+ * 0 or 1, or this list if the bounds are 0 and 1.
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws IndexOutOfBoundsException if either bound is greater
+ * than 1.
+ */
+ public List subList(int from, int to)
+ {
+ if (from == to && (to == 0 || to == 1))
+ return EMPTY_LIST;
+ if (from == 0 && to == 1)
+ return this;
+ if (from > to)
+ throw new IllegalArgumentException();
+ throw new IndexOutOfBoundsException();
+ }
+
+ /**
+ * Returning an array is simple.
+ *
+ * @return An array containing the element.
+ */
+ public Object[] toArray()
+ {
+ return new Object[] {element};
+ }
+
+ /**
+ * Obvious string.
+ *
+ * @return The string surrounded by enclosing
+ * square brackets.
+ */
+ public String toString()
+ {
+ return "[" + element + "]";
+ }
+ } // class SingletonList
+
+ /**
+ * Obtain an immutable Map consisting of a single key-value pair.
+ * The return value of this method is Serializable.
+ *
+ * @param key the single key
+ * @param value the single value
+ * @return an immutable Map containing only the single key-value pair
+ * @see Serializable
+ * @since 1.3
+ */
+ public static Map singletonMap(Object key, Object value)
+ {
+ return new SingletonMap(key, value);
+ }
+
+ /**
+ * The implementation of {@link #singletonMap(Object)}. This class name
+ * is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class SingletonMap extends AbstractMap
+ implements Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -6979724477215052911L;
+
+ /**
+ * The single key.
+ * @serial the singleton key
+ */
+ private final Object k;
+
+ /**
+ * The corresponding value.
+ * @serial the singleton value
+ */
+ private final Object v;
+
+ /**
+ * Cache the entry set.
+ */
+ private transient Set entries;
+
+ /**
+ * Construct a singleton.
+ * @param key the key
+ * @param value the value
+ */
+ SingletonMap(Object key, Object value)
+ {
+ k = key;
+ v = value;
+ }
+
+ /**
+ * There is a single immutable entry.
+ *
+ * @return A singleton containing the map entry.
+ */
+ public Set entrySet()
+ {
+ if (entries == null)
+ entries = singleton(new AbstractMap.BasicMapEntry(k, v)
+ {
+ /**
+ * Sets the value of the map entry to the supplied value.
+ * An exception is always thrown, as the map is immutable.
+ *
+ * @param o The new value.
+ * @return The old value.
+ * @throws UnsupportedOperationException as setting the value
+ * is not supported.
+ */
+ public Object setValue(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+ });
+ return entries;
+ }
+
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractMap.
+ /**
+ * Single entry.
+ *
+ * @param key The key to look for.
+ * @return <code>true</code> if the key is the same as the one used by
+ * this map.
+ */
+ public boolean containsKey(Object key)
+ {
+ return equals(key, k);
+ }
+
+ /**
+ * Single entry.
+ *
+ * @param value The value to look for.
+ * @return <code>true</code> if the value is the same as the one used by
+ * this map.
+ */
+ public boolean containsValue(Object value)
+ {
+ return equals(value, v);
+ }
+
+ /**
+ * Single entry.
+ *
+ * @param key The key of the value to be retrieved.
+ * @return The singleton value if the key is the same as the
+ * singleton key, null otherwise.
+ */
+ public Object get(Object key)
+ {
+ return equals(key, k) ? v : null;
+ }
+
+ /**
+ * Calculate the hashcode directly.
+ *
+ * @return The hashcode computed from the singleton key
+ * and the singleton value.
+ */
+ public int hashCode()
+ {
+ return hashCode(k) ^ hashCode(v);
+ }
+
+ /**
+ * Return the keyset.
+ *
+ * @return A singleton containing the key.
+ */
+ public Set keySet()
+ {
+ if (keys == null)
+ keys = singleton(k);
+ return keys;
+ }
+
+ /**
+ * The size: always 1!
+ *
+ * @return 1.
+ */
+ public int size()
+ {
+ return 1;
+ }
+
+ /**
+ * Return the values. Technically, a singleton, while more specific than
+ * a general Collection, will work. Besides, that's what the JDK uses!
+ *
+ * @return A singleton containing the value.
+ */
+ public Collection values()
+ {
+ if (values == null)
+ values = singleton(v);
+ return values;
+ }
+
+ /**
+ * Obvious string.
+ *
+ * @return A string containing the string representations of the key
+ * and its associated value.
+ */
+ public String toString()
+ {
+ return "{" + k + "=" + v + "}";
+ }
+ } // class SingletonMap
+
+ /**
+ * Sort a list according to the natural ordering of its elements. The list
+ * must be modifiable, but can be of fixed size. The sort algorithm is
+ * precisely that used by Arrays.sort(Object[]), which offers guaranteed
+ * nlog(n) performance. This implementation dumps the list into an array,
+ * sorts the array, and then iterates over the list setting each element from
+ * the array.
+ *
+ * @param l the List to sort
+ * @throws ClassCastException if some items are not mutually comparable
+ * @throws UnsupportedOperationException if the List is not modifiable
+ * @throws NullPointerException if some element is null
+ * @see Arrays#sort(Object[])
+ */
+ public static void sort(List l)
+ {
+ sort(l, null);
+ }
+
+ /**
+ * Sort a list according to a specified Comparator. The list must be
+ * modifiable, but can be of fixed size. The sort algorithm is precisely that
+ * used by Arrays.sort(Object[], Comparator), which offers guaranteed
+ * nlog(n) performance. This implementation dumps the list into an array,
+ * sorts the array, and then iterates over the list setting each element from
+ * the array.
+ *
+ * @param l the List to sort
+ * @param c the Comparator specifying the ordering for the elements, or
+ * null for natural ordering
+ * @throws ClassCastException if c will not compare some pair of items
+ * @throws UnsupportedOperationException if the List is not modifiable
+ * @throws NullPointerException if null is compared by natural ordering
+ * (only possible when c is null)
+ * @see Arrays#sort(Object[], Comparator)
+ */
+ public static void sort(List l, Comparator c)
+ {
+ Object[] a = l.toArray();
+ Arrays.sort(a, c);
+ ListIterator i = l.listIterator();
+ for (int pos = 0, alen = a.length; pos < alen; pos++)
+ {
+ i.next();
+ i.set(a[pos]);
+ }
+ }
+
+ /**
+ * Swaps the elements at the specified positions within the list. Equal
+ * positions have no effect.
+ *
+ * @param l the list to work on
+ * @param i the first index to swap
+ * @param j the second index
+ * @throws UnsupportedOperationException if list.set is not supported
+ * @throws IndexOutOfBoundsException if either i or j is &lt; 0 or &gt;=
+ * list.size()
+ * @since 1.4
+ */
+ public static void swap(List l, int i, int j)
+ {
+ l.set(i, l.set(j, l.get(i)));
+ }
+
+
+ /**
+ * Returns a synchronized (thread-safe) collection wrapper backed by the
+ * given collection. Notice that element access through the iterators
+ * is thread-safe, but if the collection can be structurally modified
+ * (adding or removing elements) then you should synchronize around the
+ * iteration to avoid non-deterministic behavior:<br>
+ * <pre>
+ * Collection c = Collections.synchronizedCollection(new Collection(...));
+ * ...
+ * synchronized (c)
+ * {
+ * Iterator i = c.iterator();
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre><p>
+ *
+ * Since the collection might be a List or a Set, and those have incompatible
+ * equals and hashCode requirements, this relies on Object's implementation
+ * rather than passing those calls on to the wrapped collection. The returned
+ * Collection implements Serializable, but can only be serialized if
+ * the collection it wraps is likewise Serializable.
+ *
+ * @param c the collection to wrap
+ * @return a synchronized view of the collection
+ * @see Serializable
+ */
+ public static Collection synchronizedCollection(Collection c)
+ {
+ return new SynchronizedCollection(c);
+ }
+
+ /**
+ * The implementation of {@link #synchronizedCollection(Collection)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ * Package visible, so that collections such as the one for
+ * Hashtable.values() can specify which object to synchronize on.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ static class SynchronizedCollection
+ implements Collection, Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 3053995032091335093L;
+
+ /**
+ * The wrapped collection. Package visible for use by subclasses.
+ * @serial the real collection
+ */
+ final Collection c;
+
+ /**
+ * The object to synchronize on. When an instance is created via public
+ * methods, it will be this; but other uses like SynchronizedMap.values()
+ * must specify another mutex. Package visible for use by subclasses.
+ * @serial the lock
+ */
+ final Object mutex;
+
+ /**
+ * Wrap a given collection.
+ * @param c the collection to wrap
+ * @throws NullPointerException if c is null
+ */
+ SynchronizedCollection(Collection c)
+ {
+ this.c = c;
+ mutex = this;
+ if (c == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Called only by trusted code to specify the mutex as well as the
+ * collection.
+ * @param sync the mutex
+ * @param c the collection
+ */
+ SynchronizedCollection(Object sync, Collection c)
+ {
+ this.c = c;
+ mutex = sync;
+ }
+
+ /**
+ * Adds the object to the underlying collection, first
+ * obtaining a lock on the mutex.
+ *
+ * @param o The object to add.
+ * @return <code>true</code> if the collection was modified as a result
+ * of this action.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the add operation.
+ * @throws ClassCastException if o cannot be added to this collection due
+ * to its type.
+ * @throws NullPointerException if o is null and this collection doesn't
+ * support the addition of null values.
+ * @throws IllegalArgumentException if o cannot be added to this
+ * collection for some other reason.
+ */
+ public boolean add(Object o)
+ {
+ synchronized (mutex)
+ {
+ return c.add(o);
+ }
+ }
+
+ /**
+ * Adds the objects in col to the underlying collection, first
+ * obtaining a lock on the mutex.
+ *
+ * @param col The collection to take the new objects from.
+ * @return <code>true</code> if the collection was modified as a result
+ * of this action.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the addAll operation.
+ * @throws ClassCastException if some element of col cannot be added to this
+ * collection due to its type.
+ * @throws NullPointerException if some element of col is null and this
+ * collection does not support the addition of null values.
+ * @throws NullPointerException if col itself is null.
+ * @throws IllegalArgumentException if some element of col cannot be added
+ * to this collection for some other reason.
+ */
+ public boolean addAll(Collection col)
+ {
+ synchronized (mutex)
+ {
+ return c.addAll(col);
+ }
+ }
+
+ /**
+ * Removes all objects from the underlying collection,
+ * first obtaining a lock on the mutex.
+ *
+ * @throws UnsupportedOperationException if this collection does not
+ * support the clear operation.
+ */
+ public void clear()
+ {
+ synchronized (mutex)
+ {
+ c.clear();
+ }
+ }
+
+ /**
+ * Checks for the existence of o within the underlying
+ * collection, first obtaining a lock on the mutex.
+ *
+ * @param o the element to look for.
+ * @return <code>true</code> if this collection contains at least one
+ * element e such that <code>o == null ? e == null : o.equals(e)</code>.
+ * @throws ClassCastException if the type of o is not a valid type for this
+ * collection.
+ * @throws NullPointerException if o is null and this collection doesn't
+ * support null values.
+ */
+ public boolean contains(Object o)
+ {
+ synchronized (mutex)
+ {
+ return c.contains(o);
+ }
+ }
+
+ /**
+ * Checks for the existence of each object in cl
+ * within the underlying collection, first obtaining
+ * a lock on the mutex.
+ *
+ * @param c1 the collection to test for.
+ * @return <code>true</code> if for every element o in c, contains(o)
+ * would return <code>true</code>.
+ * @throws ClassCastException if the type of any element in cl is not a valid
+ * type for this collection.
+ * @throws NullPointerException if some element of cl is null and this
+ * collection does not support null values.
+ * @throws NullPointerException if cl itself is null.
+ */
+ public boolean containsAll(Collection c1)
+ {
+ synchronized (mutex)
+ {
+ return c.containsAll(c1);
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if there are no objects in the underlying
+ * collection. A lock on the mutex is obtained before the
+ * check is performed.
+ *
+ * @return <code>true</code> if this collection contains no elements.
+ */
+ public boolean isEmpty()
+ {
+ synchronized (mutex)
+ {
+ return c.isEmpty();
+ }
+ }
+
+ /**
+ * Returns a synchronized iterator wrapper around the underlying
+ * collection's iterator. A lock on the mutex is obtained before
+ * retrieving the collection's iterator.
+ *
+ * @return An iterator over the elements in the underlying collection,
+ * which returns each element in any order.
+ */
+ public Iterator iterator()
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedIterator(mutex, c.iterator());
+ }
+ }
+
+ /**
+ * Removes the specified object from the underlying collection,
+ * first obtaining a lock on the mutex.
+ *
+ * @param o The object to remove.
+ * @return <code>true</code> if the collection changed as a result of this call, that is,
+ * if the collection contained at least one occurrence of o.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the remove operation.
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this collection.
+ * @throws NullPointerException if o is null and the collection doesn't
+ * support null values.
+ */
+ public boolean remove(Object o)
+ {
+ synchronized (mutex)
+ {
+ return c.remove(o);
+ }
+ }
+
+ /**
+ * Removes all elements, e, of the underlying
+ * collection for which <code>col.contains(e)</code>
+ * returns <code>true</code>. A lock on the mutex is obtained
+ * before the operation proceeds.
+ *
+ * @param col The collection of objects to be removed.
+ * @return <code>true</code> if this collection was modified as a result of this call.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the removeAll operation.
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for this collection.
+ * @throws NullPointerException if some element of c is null and this
+ * collection does not support removing null values.
+ * @throws NullPointerException if c itself is null.
+ */
+ public boolean removeAll(Collection col)
+ {
+ synchronized (mutex)
+ {
+ return c.removeAll(col);
+ }
+ }
+
+ /**
+ * Retains all elements, e, of the underlying
+ * collection for which <code>col.contains(e)</code>
+ * returns <code>true</code>. That is, every element that doesn't
+ * exist in col is removed. A lock on the mutex is obtained
+ * before the operation proceeds.
+ *
+ * @param col The collection of objects to be removed.
+ * @return <code>true</code> if this collection was modified as a result of this call.
+ * @throws UnsupportedOperationException if this collection does not
+ * support the removeAll operation.
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for this collection.
+ * @throws NullPointerException if some element of c is null and this
+ * collection does not support removing null values.
+ * @throws NullPointerException if c itself is null.
+ */
+ public boolean retainAll(Collection col)
+ {
+ synchronized (mutex)
+ {
+ return c.retainAll(col);
+ }
+ }
+
+ /**
+ * Retrieves the size of the underlying collection.
+ * A lock on the mutex is obtained before the collection
+ * is accessed.
+ *
+ * @return The size of the collection.
+ */
+ public int size()
+ {
+ synchronized (mutex)
+ {
+ return c.size();
+ }
+ }
+
+ /**
+ * Returns an array containing each object within the underlying
+ * collection. A lock is obtained on the mutex before the collection
+ * is accessed.
+ *
+ * @return An array of objects, matching the collection in size. The
+ * elements occur in any order.
+ */
+ public Object[] toArray()
+ {
+ synchronized (mutex)
+ {
+ return c.toArray();
+ }
+ }
+
+ /**
+ * Copies the elements in the underlying collection to the supplied
+ * array. If <code>a.length < size()</code>, a new array of the
+ * same run-time type is created, with a size equal to that of
+ * the collection. If <code>a.length > size()</code>, then the
+ * elements from 0 to <code>size() - 1</code> contain the elements
+ * from this collection. The following element is set to null
+ * to indicate the end of the collection objects. However, this
+ * only makes a difference if null is not a permitted value within
+ * the collection.
+ * Before the copying takes place, a lock is obtained on the mutex.
+ *
+ * @param a An array to copy elements to.
+ * @return An array containing the elements of the underlying collection.
+ * @throws ArrayStoreException if the type of any element of the
+ * collection is not a subtype of the element type of a.
+ */
+ public Object[] toArray(Object[] a)
+ {
+ synchronized (mutex)
+ {
+ return c.toArray(a);
+ }
+ }
+
+ /**
+ * Returns a string representation of the underlying collection.
+ * A lock is obtained on the mutex before the string is created.
+ *
+ * @return A string representation of the collection.
+ */
+ public String toString()
+ {
+ synchronized (mutex)
+ {
+ return c.toString();
+ }
+ }
+ } // class SynchronizedCollection
+
+ /**
+ * The implementation of the various iterator methods in the
+ * synchronized classes. These iterators must "sync" on the same object
+ * as the collection they iterate over.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class SynchronizedIterator implements Iterator
+ {
+ /**
+ * The object to synchronize on. Package visible for use by subclass.
+ */
+ final Object mutex;
+
+ /**
+ * The wrapped iterator.
+ */
+ private final Iterator i;
+
+ /**
+ * Only trusted code creates a wrapper, with the specified sync.
+ * @param sync the mutex
+ * @param i the wrapped iterator
+ */
+ SynchronizedIterator(Object sync, Iterator i)
+ {
+ this.i = i;
+ mutex = sync;
+ }
+
+ /**
+ * Retrieves the next object in the underlying collection.
+ * A lock is obtained on the mutex before the collection is accessed.
+ *
+ * @return The next object in the collection.
+ * @throws NoSuchElementException if there are no more elements
+ */
+ public Object next()
+ {
+ synchronized (mutex)
+ {
+ return i.next();
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if objects can still be retrieved from the iterator
+ * using <code>next()</code>. A lock is obtained on the mutex before
+ * the collection is accessed.
+ *
+ * @return <code>true</code> if at least one element is still to be returned by
+ * <code>next()</code>.
+ */
+ public boolean hasNext()
+ {
+ synchronized (mutex)
+ {
+ return i.hasNext();
+ }
+ }
+
+ /**
+ * Removes the object that was last returned by <code>next()</code>
+ * from the underlying collection. Only one call to this method is
+ * allowed per call to the <code>next()</code> method, and it does
+ * not affect the value that will be returned by <code>next()</code>.
+ * Thus, if element n was retrieved from the collection by
+ * <code>next()</code>, it is this element that gets removed.
+ * Regardless of whether this takes place or not, element n+1 is
+ * still returned on the subsequent <code>next()</code> call.
+ *
+ * @throws IllegalStateException if next has not yet been called or remove
+ * has already been called since the last call to next.
+ * @throws UnsupportedOperationException if this Iterator does not support
+ * the remove operation.
+ */
+ public void remove()
+ {
+ synchronized (mutex)
+ {
+ i.remove();
+ }
+ }
+ } // class SynchronizedIterator
+
+ /**
+ * Returns a synchronized (thread-safe) list wrapper backed by the
+ * given list. Notice that element access through the iterators
+ * is thread-safe, but if the list can be structurally modified
+ * (adding or removing elements) then you should synchronize around the
+ * iteration to avoid non-deterministic behavior:<br>
+ * <pre>
+ * List l = Collections.synchronizedList(new List(...));
+ * ...
+ * synchronized (l)
+ * {
+ * Iterator i = l.iterator();
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre><p>
+ *
+ * The returned List implements Serializable, but can only be serialized if
+ * the list it wraps is likewise Serializable. In addition, if the wrapped
+ * list implements RandomAccess, this does too.
+ *
+ * @param l the list to wrap
+ * @return a synchronized view of the list
+ * @see Serializable
+ * @see RandomAccess
+ */
+ public static List synchronizedList(List l)
+ {
+ if (l instanceof RandomAccess)
+ return new SynchronizedRandomAccessList(l);
+ return new SynchronizedList(l);
+ }
+
+ /**
+ * The implementation of {@link #synchronizedList(List)} for sequential
+ * lists. This class name is required for compatibility with Sun's JDK
+ * serializability. Package visible, so that lists such as Vector.subList()
+ * can specify which object to synchronize on.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ static class SynchronizedList extends SynchronizedCollection
+ implements List
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -7754090372962971524L;
+
+ /**
+ * The wrapped list; stored both here and in the superclass to avoid
+ * excessive casting. Package visible for use by subclass.
+ * @serial the wrapped list
+ */
+ final List list;
+
+ /**
+ * Wrap a given list.
+ * @param l the list to wrap
+ * @throws NullPointerException if l is null
+ */
+ SynchronizedList(List l)
+ {
+ super(l);
+ list = l;
+ }
+
+ /**
+ * Called only by trusted code to specify the mutex as well as the list.
+ * @param sync the mutex
+ * @param l the list
+ */
+ SynchronizedList(Object sync, List l)
+ {
+ super(sync, l);
+ list = l;
+ }
+
+ /**
+ * Insert an element into the underlying list at a given position (optional
+ * operation). This shifts all existing elements from that position to the
+ * end one index to the right. This version of add has no return, since it is
+ * assumed to always succeed if there is no exception. Before the
+ * addition takes place, a lock is obtained on the mutex.
+ *
+ * @param index the location to insert the item
+ * @param o the object to insert
+ * @throws UnsupportedOperationException if this list does not support the
+ * add operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @throws NullPointerException if o is null and this list doesn't support
+ * the addition of null values.
+ */
+ public void add(int index, Object o)
+ {
+ synchronized (mutex)
+ {
+ list.add(index, o);
+ }
+ }
+
+ /**
+ * Add an element to the end of the underlying list (optional operation).
+ * If the list imposes restraints on what can be inserted, such as no null
+ * elements, this should be documented. A lock is obtained on the mutex before
+ * any of the elements are added.
+ *
+ * @param o the object to add
+ * @return <code>true</code>, as defined by Collection for a modified list
+ * @throws UnsupportedOperationException if this list does not support the
+ * add operation
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @throws NullPointerException if o is null and this list doesn't support
+ * the addition of null values.
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ synchronized (mutex)
+ {
+ return list.addAll(index, c);
+ }
+ }
+
+ /**
+ * Tests whether the underlying list is equal to the supplied object.
+ * The object is deemed to be equal if it is also a <code>List</code>
+ * of equal size and with the same elements (i.e. each element, e1,
+ * in list, l1, and each element, e2, in l2, must return <code>true</code> for
+ * <code>e1 == null ? e2 == null : e1.equals(e2)</code>. Before the
+ * comparison is made, a lock is obtained on the mutex.
+ *
+ * @param o The object to test for equality with the underlying list.
+ * @return <code>true</code> if o is equal to the underlying list under the above
+ * definition.
+ */
+ public boolean equals(Object o)
+ {
+ synchronized (mutex)
+ {
+ return list.equals(o);
+ }
+ }
+
+ /**
+ * Retrieves the object at the specified index. A lock
+ * is obtained on the mutex before the list is accessed.
+ *
+ * @param index the index of the element to be returned
+ * @return the element at index index in this list
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object get(int index)
+ {
+ synchronized (mutex)
+ {
+ return list.get(index);
+ }
+ }
+
+ /**
+ * Obtains a hashcode for the underlying list, first obtaining
+ * a lock on the mutex. The calculation of the hashcode is
+ * detailed in the documentation for the <code>List</code>
+ * interface.
+ *
+ * @return The hashcode of the underlying list.
+ * @see List#hashCode()
+ */
+ public int hashCode()
+ {
+ synchronized (mutex)
+ {
+ return list.hashCode();
+ }
+ }
+
+ /**
+ * Obtain the first index at which a given object is to be found in the
+ * underlying list. A lock is obtained on the mutex before the list is
+ * accessed.
+ *
+ * @param o the object to search for
+ * @return the least integer n such that <code>o == null ? get(n) == null :
+ * o.equals(get(n))</code>, or -1 if there is no such index.
+ * @throws ClassCastException if the type of o is not a valid
+ * type for this list.
+ * @throws NullPointerException if o is null and this
+ * list does not support null values.
+ */
+
+ public int indexOf(Object o)
+ {
+ synchronized (mutex)
+ {
+ return list.indexOf(o);
+ }
+ }
+
+ /**
+ * Obtain the last index at which a given object is to be found in this
+ * underlying list. A lock is obtained on the mutex before the list
+ * is accessed.
+ *
+ * @return the greatest integer n such that <code>o == null ? get(n) == null
+ * : o.equals(get(n))</code>, or -1 if there is no such index.
+ * @throws ClassCastException if the type of o is not a valid
+ * type for this list.
+ * @throws NullPointerException if o is null and this
+ * list does not support null values.
+ */
+ public int lastIndexOf(Object o)
+ {
+ synchronized (mutex)
+ {
+ return list.lastIndexOf(o);
+ }
+ }
+
+ /**
+ * Retrieves a synchronized wrapper around the underlying list's
+ * list iterator. A lock is obtained on the mutex before the
+ * list iterator is retrieved.
+ *
+ * @return A list iterator over the elements in the underlying list.
+ * The list iterator allows additional list-specific operations
+ * to be performed, in addition to those supplied by the
+ * standard iterator.
+ */
+ public ListIterator listIterator()
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedListIterator(mutex, list.listIterator());
+ }
+ }
+
+ /**
+ * Retrieves a synchronized wrapper around the underlying list's
+ * list iterator. A lock is obtained on the mutex before the
+ * list iterator is retrieved. The iterator starts at the
+ * index supplied, leading to the element at that index being
+ * the first one returned by <code>next()</code>. Calling
+ * <code>previous()</code> from this initial position returns
+ * index - 1.
+ *
+ * @param index the position, between 0 and size() inclusive, to begin the
+ * iteration from
+ * @return A list iterator over the elements in the underlying list.
+ * The list iterator allows additional list-specific operations
+ * to be performed, in addition to those supplied by the
+ * standard iterator.
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public ListIterator listIterator(int index)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedListIterator(mutex, list.listIterator(index));
+ }
+ }
+
+ /**
+ * Remove the element at a given position in the underlying list (optional
+ * operation). All remaining elements are shifted to the left to fill the gap.
+ * A lock on the mutex is obtained before the element is removed.
+ *
+ * @param index the position within the list of the object to remove
+ * @return the object that was removed
+ * @throws UnsupportedOperationException if this list does not support the
+ * remove operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object remove(int index)
+ {
+ synchronized (mutex)
+ {
+ return list.remove(index);
+ }
+ }
+
+ /**
+ * Replace an element of the underlying list with another object (optional
+ * operation). A lock is obtained on the mutex before the element is
+ * replaced.
+ *
+ * @param index the position within this list of the element to be replaced
+ * @param o the object to replace it with
+ * @return the object that was replaced
+ * @throws UnsupportedOperationException if this list does not support the
+ * set operation.
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @throws NullPointerException if o is null and this
+ * list does not support null values.
+ */
+ public Object set(int index, Object o)
+ {
+ synchronized (mutex)
+ {
+ return list.set(index, o);
+ }
+ }
+
+ /**
+ * Obtain a List view of a subsection of the underlying list, from fromIndex
+ * (inclusive) to toIndex (exclusive). If the two indices are equal, the
+ * sublist is empty. The returned list should be modifiable if and only
+ * if this list is modifiable. Changes to the returned list should be
+ * reflected in this list. If this list is structurally modified in
+ * any way other than through the returned list, the result of any subsequent
+ * operations on the returned list is undefined. A lock is obtained
+ * on the mutex before the creation of the sublist. The returned list
+ * is also synchronized, using the same mutex.
+ *
+ * @param fromIndex the index that the returned list should start from
+ * (inclusive)
+ * @param toIndex the index that the returned list should go to (exclusive)
+ * @return a List backed by a subsection of this list
+ * @throws IndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; size() || fromIndex &gt; toIndex
+ */
+ public List subList(int fromIndex, int toIndex)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedList(mutex, list.subList(fromIndex, toIndex));
+ }
+ }
+ } // class SynchronizedList
+
+ /**
+ * The implementation of {@link #synchronizedList(List)} for random-access
+ * lists. This class name is required for compatibility with Sun's JDK
+ * serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class SynchronizedRandomAccessList
+ extends SynchronizedList implements RandomAccess
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 1530674583602358482L;
+
+ /**
+ * Wrap a given list.
+ * @param l the list to wrap
+ * @throws NullPointerException if l is null
+ */
+ SynchronizedRandomAccessList(List l)
+ {
+ super(l);
+ }
+
+ /**
+ * Called only by trusted code to specify the mutex as well as the
+ * collection.
+ * @param sync the mutex
+ * @param l the list
+ */
+ SynchronizedRandomAccessList(Object sync, List l)
+ {
+ super(sync, l);
+ }
+
+ /**
+ * Obtain a List view of a subsection of the underlying list, from fromIndex
+ * (inclusive) to toIndex (exclusive). If the two indices are equal, the
+ * sublist is empty. The returned list should be modifiable if and only
+ * if this list is modifiable. Changes to the returned list should be
+ * reflected in this list. If this list is structurally modified in
+ * any way other than through the returned list, the result of any subsequent
+ * operations on the returned list is undefined. A lock is obtained
+ * on the mutex before the creation of the sublist. The returned list
+ * is also synchronized, using the same mutex. Random accessibility
+ * is also extended to the new list.
+ *
+ * @param fromIndex the index that the returned list should start from
+ * (inclusive)
+ * @param toIndex the index that the returned list should go to (exclusive)
+ * @return a List backed by a subsection of this list
+ * @throws IndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; size() || fromIndex &gt; toIndex
+ */
+ public List subList(int fromIndex, int toIndex)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedRandomAccessList(mutex,
+ list.subList(fromIndex,
+ toIndex));
+ }
+ }
+ } // class SynchronizedRandomAccessList
+
+ /**
+ * The implementation of {@link SynchronizedList#listIterator()}. This
+ * iterator must "sync" on the same object as the list it iterates over.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class SynchronizedListIterator
+ extends SynchronizedIterator implements ListIterator
+ {
+ /**
+ * The wrapped iterator, stored both here and in the superclass to
+ * avoid excessive casting.
+ */
+ private final ListIterator li;
+
+ /**
+ * Only trusted code creates a wrapper, with the specified sync.
+ * @param sync the mutex
+ * @param li the wrapped iterator
+ */
+ SynchronizedListIterator(Object sync, ListIterator li)
+ {
+ super(sync, li);
+ this.li = li;
+ }
+
+ /**
+ * Insert an element into the underlying list at the current position of
+ * the iterator (optional operation). The element is inserted in between
+ * the element that would be returned by <code>previous()</code> and the
+ * element that would be returned by <code>next()</code>. After the
+ * insertion, a subsequent call to next is unaffected, but
+ * a call to previous returns the item that was added. The values returned
+ * by nextIndex() and previousIndex() are incremented. A lock is obtained
+ * on the mutex before the addition takes place.
+ *
+ * @param o the object to insert into the list
+ * @throws ClassCastException if the object is of a type which cannot be added
+ * to this list.
+ * @throws IllegalArgumentException if some other aspect of the object stops
+ * it being added to this list.
+ * @throws UnsupportedOperationException if this ListIterator does not
+ * support the add operation.
+ */
+ public void add(Object o)
+ {
+ synchronized (mutex)
+ {
+ li.add(o);
+ }
+ }
+
+ /**
+ * Tests whether there are elements remaining in the underlying list
+ * in the reverse direction. In other words, <code>previous()</code>
+ * will not fail with a NoSuchElementException. A lock is obtained
+ * on the mutex before the check takes place.
+ *
+ * @return <code>true</code> if the list continues in the reverse direction
+ */
+ public boolean hasPrevious()
+ {
+ synchronized (mutex)
+ {
+ return li.hasPrevious();
+ }
+ }
+
+ /**
+ * Find the index of the element that would be returned by a call to
+ * <code>next()</code>. If hasNext() returns <code>false</code>, this
+ * returns the list size. A lock is obtained on the mutex before the
+ * query takes place.
+ *
+ * @return the index of the element that would be returned by next()
+ */
+ public int nextIndex()
+ {
+ synchronized (mutex)
+ {
+ return li.nextIndex();
+ }
+ }
+
+ /**
+ * Obtain the previous element from the underlying list. Repeated
+ * calls to previous may be used to iterate backwards over the entire list,
+ * or calls to next and previous may be used together to go forwards and
+ * backwards. Alternating calls to next and previous will return the same
+ * element. A lock is obtained on the mutex before the object is retrieved.
+ *
+ * @return the next element in the list in the reverse direction
+ * @throws NoSuchElementException if there are no more elements
+ */
+ public Object previous()
+ {
+ synchronized (mutex)
+ {
+ return li.previous();
+ }
+ }
+
+ /**
+ * Find the index of the element that would be returned by a call to
+ * previous. If hasPrevious() returns <code>false</code>, this returns -1.
+ * A lock is obtained on the mutex before the query takes place.
+ *
+ * @return the index of the element that would be returned by previous()
+ */
+ public int previousIndex()
+ {
+ synchronized (mutex)
+ {
+ return li.previousIndex();
+ }
+ }
+
+ /**
+ * Replace the element last returned by a call to <code>next()</code> or
+ * <code>previous()</code> with a given object (optional operation). This
+ * method may only be called if neither <code>add()</code> nor
+ * <code>remove()</code> have been called since the last call to
+ * <code>next()</code> or <code>previous</code>. A lock is obtained
+ * on the mutex before the list is modified.
+ *
+ * @param o the object to replace the element with
+ * @throws ClassCastException the object is of a type which cannot be added
+ * to this list
+ * @throws IllegalArgumentException some other aspect of the object stops
+ * it being added to this list
+ * @throws IllegalStateException if neither next or previous have been
+ * called, or if add or remove has been called since the last call
+ * to next or previous
+ * @throws UnsupportedOperationException if this ListIterator does not
+ * support the set operation
+ */
+ public void set(Object o)
+ {
+ synchronized (mutex)
+ {
+ li.set(o);
+ }
+ }
+ } // class SynchronizedListIterator
+
+ /**
+ * Returns a synchronized (thread-safe) map wrapper backed by the given
+ * map. Notice that element access through the collection views and their
+ * iterators are thread-safe, but if the map can be structurally modified
+ * (adding or removing elements) then you should synchronize around the
+ * iteration to avoid non-deterministic behavior:<br>
+ * <pre>
+ * Map m = Collections.synchronizedMap(new Map(...));
+ * ...
+ * Set s = m.keySet(); // safe outside a synchronized block
+ * synchronized (m) // synch on m, not s
+ * {
+ * Iterator i = s.iterator();
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre><p>
+ *
+ * The returned Map implements Serializable, but can only be serialized if
+ * the map it wraps is likewise Serializable.
+ *
+ * @param m the map to wrap
+ * @return a synchronized view of the map
+ * @see Serializable
+ */
+ public static Map synchronizedMap(Map m)
+ {
+ return new SynchronizedMap(m);
+ }
+
+ /**
+ * The implementation of {@link #synchronizedMap(Map)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class SynchronizedMap implements Map, Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 1978198479659022715L;
+
+ /**
+ * The wrapped map.
+ * @serial the real map
+ */
+ private final Map m;
+
+ /**
+ * The object to synchronize on. When an instance is created via public
+ * methods, it will be this; but other uses like
+ * SynchronizedSortedMap.subMap() must specify another mutex. Package
+ * visible for use by subclass.
+ * @serial the lock
+ */
+ final Object mutex;
+
+ /**
+ * Cache the entry set.
+ */
+ private transient Set entries;
+
+ /**
+ * Cache the key set.
+ */
+ private transient Set keys;
+
+ /**
+ * Cache the value collection.
+ */
+ private transient Collection values;
+
+ /**
+ * Wrap a given map.
+ * @param m the map to wrap
+ * @throws NullPointerException if m is null
+ */
+ SynchronizedMap(Map m)
+ {
+ this.m = m;
+ mutex = this;
+ if (m == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Called only by trusted code to specify the mutex as well as the map.
+ * @param sync the mutex
+ * @param m the map
+ */
+ SynchronizedMap(Object sync, Map m)
+ {
+ this.m = m;
+ mutex = sync;
+ }
+
+ /**
+ * Clears all the entries from the underlying map. A lock is obtained
+ * on the mutex before the map is cleared.
+ *
+ * @throws UnsupportedOperationException if clear is not supported
+ */
+ public void clear()
+ {
+ synchronized (mutex)
+ {
+ m.clear();
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains a entry for the given key.
+ * A lock is obtained on the mutex before the map is queried.
+ *
+ * @param key the key to search for.
+ * @return <code>true</code> if the underlying map contains the key.
+ * @throws ClassCastException if the key is of an inappropriate type.
+ * @throws NullPointerException if key is <code>null</code> but the map
+ * does not permit null keys.
+ */
+ public boolean containsKey(Object key)
+ {
+ synchronized (mutex)
+ {
+ return m.containsKey(key);
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains at least one entry with the
+ * given value. In other words, returns <code>true</code> if a value v exists where
+ * <code>(value == null ? v == null : value.equals(v))</code>. This usually
+ * requires linear time. A lock is obtained on the mutex before the map
+ * is queried.
+ *
+ * @param value the value to search for
+ * @return <code>true</code> if the map contains the value
+ * @throws ClassCastException if the type of the value is not a valid type
+ * for this map.
+ * @throws NullPointerException if the value is null and the map doesn't
+ * support null values.
+ */
+ public boolean containsValue(Object value)
+ {
+ synchronized (mutex)
+ {
+ return m.containsValue(value);
+ }
+ }
+
+ // This is one of the ickiest cases of nesting I've ever seen. It just
+ // means "return a SynchronizedSet, except that the iterator() method
+ // returns an SynchronizedIterator whose next() method returns a
+ // synchronized wrapper around its normal return value".
+ public Set entrySet()
+ {
+ // Define this here to spare some nesting.
+ class SynchronizedMapEntry implements Map.Entry
+ {
+ final Map.Entry e;
+ SynchronizedMapEntry(Object o)
+ {
+ e = (Map.Entry) o;
+ }
+
+ /**
+ * Returns <code>true</code> if the object, o, implements <code>Map.Entry</code>
+ * with the same key and value as the underlying entry. A lock is
+ * obtained on the mutex before the comparison takes place.
+ *
+ * @param o The object to compare with this entry.
+ * @return <code>true</code> if o is equivalent to the underlying map entry.
+ */
+ public boolean equals(Object o)
+ {
+ synchronized (mutex)
+ {
+ return e.equals(o);
+ }
+ }
+
+ /**
+ * Returns the key used in the underlying map entry. A lock is obtained
+ * on the mutex before the key is retrieved.
+ *
+ * @return The key of the underlying map entry.
+ */
+ public Object getKey()
+ {
+ synchronized (mutex)
+ {
+ return e.getKey();
+ }
+ }
+
+ /**
+ * Returns the value used in the underlying map entry. A lock is obtained
+ * on the mutex before the value is retrieved.
+ *
+ * @return The value of the underlying map entry.
+ */
+ public Object getValue()
+ {
+ synchronized (mutex)
+ {
+ return e.getValue();
+ }
+ }
+
+ /**
+ * Computes the hash code for the underlying map entry.
+ * This computation is described in the documentation for the
+ * <code>Map</code> interface. A lock is obtained on the mutex
+ * before the underlying map is accessed.
+ *
+ * @return The hash code of the underlying map entry.
+ * @see Map#hashCode()
+ */
+ public int hashCode()
+ {
+ synchronized (mutex)
+ {
+ return e.hashCode();
+ }
+ }
+
+ /**
+ * Replaces the value in the underlying map entry with the specified
+ * object (optional operation). A lock is obtained on the mutex
+ * before the map is altered. The map entry, in turn, will alter
+ * the underlying map object. The operation is undefined if the
+ * <code>remove()</code> method of the iterator has been called
+ * beforehand.
+ *
+ * @param value the new value to store
+ * @return the old value
+ * @throws UnsupportedOperationException if the operation is not supported.
+ * @throws ClassCastException if the value is of the wrong type.
+ * @throws IllegalArgumentException if something about the value
+ * prevents it from existing in this map.
+ * @throws NullPointerException if the map forbids null values.
+ */
+ public Object setValue(Object value)
+ {
+ synchronized (mutex)
+ {
+ return e.setValue(value);
+ }
+ }
+
+ /**
+ * Returns a textual representation of the underlying map entry.
+ * A lock is obtained on the mutex before the entry is accessed.
+ *
+ * @return The contents of the map entry in <code>String</code> form.
+ */
+ public String toString()
+ {
+ synchronized (mutex)
+ {
+ return e.toString();
+ }
+ }
+ } // class SynchronizedMapEntry
+
+ // Now the actual code.
+ if (entries == null)
+ synchronized (mutex)
+ {
+ entries = new SynchronizedSet(mutex, m.entrySet())
+ {
+ /**
+ * Returns an iterator over the set. The iterator has no specific order,
+ * unless further specified. A lock is obtained on the set's mutex
+ * before the iterator is created. The created iterator is also
+ * thread-safe.
+ *
+ * @return A synchronized set iterator.
+ */
+ public Iterator iterator()
+ {
+ synchronized (super.mutex)
+ {
+ return new SynchronizedIterator(super.mutex, c.iterator())
+ {
+ /**
+ * Retrieves the next map entry from the iterator.
+ * A lock is obtained on the iterator's mutex before
+ * the entry is created. The new map entry is enclosed in
+ * a thread-safe wrapper.
+ *
+ * @return A synchronized map entry.
+ */
+ public Object next()
+ {
+ synchronized (super.mutex)
+ {
+ return new SynchronizedMapEntry(super.next());
+ }
+ }
+ };
+ }
+ }
+ };
+ }
+ return entries;
+ }
+
+ /**
+ * Returns <code>true</code> if the object, o, is also an instance
+ * of <code>Map</code> and contains an equivalent
+ * entry set to that of the underlying map. A lock
+ * is obtained on the mutex before the objects are
+ * compared.
+ *
+ * @param o The object to compare.
+ * @return <code>true</code> if o and the underlying map are equivalent.
+ */
+ public boolean equals(Object o)
+ {
+ synchronized (mutex)
+ {
+ return m.equals(o);
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null
+ * if no such mapping exists. An ambiguity exists with maps
+ * that accept null values as a return value of null could
+ * be due to a non-existent mapping or simply a null value
+ * for that key. To resolve this, <code>containsKey</code>
+ * should be used. A lock is obtained on the mutex before
+ * the value is retrieved from the underlying map.
+ *
+ * @param key The key of the required mapping.
+ * @return The value associated with the given key, or
+ * null if no such mapping exists.
+ * @throws ClassCastException if the key is an inappropriate type.
+ * @throws NullPointerException if this map does not accept null keys.
+ */
+ public Object get(Object key)
+ {
+ synchronized (mutex)
+ {
+ return m.get(key);
+ }
+ }
+
+ /**
+ * Calculates the hash code of the underlying map as the
+ * sum of the hash codes of all entries. A lock is obtained
+ * on the mutex before the hash code is computed.
+ *
+ * @return The hash code of the underlying map.
+ */
+ public int hashCode()
+ {
+ synchronized (mutex)
+ {
+ return m.hashCode();
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains no entries.
+ * A lock is obtained on the mutex before the map is examined.
+ *
+ * @return <code>true</code> if the map is empty.
+ */
+ public boolean isEmpty()
+ {
+ synchronized (mutex)
+ {
+ return m.isEmpty();
+ }
+ }
+
+ /**
+ * Returns a thread-safe set view of the keys in the underlying map. The
+ * set is backed by the map, so that changes in one show up in the other.
+ * 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. A lock is obtained
+ * on the mutex before the set is created.
+ *
+ * @return A synchronized set containing the keys of the underlying map.
+ */
+ public Set keySet()
+ {
+ if (keys == null)
+ synchronized (mutex)
+ {
+ keys = new SynchronizedSet(mutex, m.keySet());
+ }
+ return keys;
+ }
+
+ /**
+ * Associates the given key to the given value (optional operation). If the
+ * underlying map already contains the key, its value is replaced. Be aware
+ * that in a map that permits <code>null</code> values, a null return does not
+ * always imply that the mapping was created. A lock is obtained on the mutex
+ * before the modification is made.
+ *
+ * @param key the key to map.
+ * @param value the value to be mapped.
+ * @return the previous value of the key, or null if there was no mapping
+ * @throws UnsupportedOperationException if the operation is not supported
+ * @throws ClassCastException if the key or value is of the wrong type
+ * @throws IllegalArgumentException if something about this key or value
+ * prevents it from existing in this map
+ * @throws NullPointerException if either the key or the value is null,
+ * and the map forbids null keys or values
+ * @see #containsKey(Object)
+ */
+ public Object put(Object key, Object value)
+ {
+ synchronized (mutex)
+ {
+ return m.put(key, value);
+ }
+ }
+
+ /**
+ * Copies all entries of the given map to the underlying one (optional
+ * operation). If the map already contains a key, its value is replaced.
+ * A lock is obtained on the mutex before the operation proceeds.
+ *
+ * @param map the mapping to load into this map
+ * @throws UnsupportedOperationException if the operation is not supported
+ * @throws ClassCastException if a key or value is of the wrong type
+ * @throws IllegalArgumentException if something about a key or value
+ * prevents it from existing in this map
+ * @throws NullPointerException if the map forbids null keys or values, or
+ * if <code>m</code> is null.
+ * @see #put(Object, Object)
+ */
+ public void putAll(Map map)
+ {
+ synchronized (mutex)
+ {
+ m.putAll(map);
+ }
+ }
+
+ /**
+ * Removes the mapping for the key, o, if present (optional operation). If
+ * the key is not present, this returns null. Note that maps which permit
+ * null values may also return null if the key was removed. A prior
+ * <code>containsKey()</code> check is required to avoid this ambiguity.
+ * Before the mapping is removed, a lock is obtained on the mutex.
+ *
+ * @param o the key to remove
+ * @return the value the key mapped to, or null if not present
+ * @throws UnsupportedOperationException if deletion is unsupported
+ * @throws NullPointerException if the key is null and this map doesn't
+ * support null keys.
+ * @throws ClassCastException if the type of the key is not a valid type
+ * for this map.
+ */
+ public Object remove(Object o)
+ {
+ synchronized (mutex)
+ {
+ return m.remove(o);
+ }
+ }
+
+ /**
+ * Retrieves the size of the underlying map. A lock
+ * is obtained on the mutex before access takes place.
+ * Maps with a size greater than <code>Integer.MAX_VALUE</code>
+ * return <code>Integer.MAX_VALUE</code> instead.
+ *
+ * @return The size of the underlying map.
+ */
+ public int size()
+ {
+ synchronized (mutex)
+ {
+ return m.size();
+ }
+ }
+
+ /**
+ * Returns a textual representation of the underlying
+ * map. A lock is obtained on the mutex before the map
+ * is accessed.
+ *
+ * @return The map in <code>String</code> form.
+ */
+ public String toString()
+ {
+ synchronized (mutex)
+ {
+ return m.toString();
+ }
+ }
+
+ /**
+ * Returns a synchronized collection view of the values in the underlying
+ * map. The collection is backed by the map, so that changes in one show up in
+ * the other. 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. A lock is obtained on the mutex before the collection
+ * is created.
+ *
+ * @return the collection of all values in the underlying map.
+ */
+ public Collection values()
+ {
+ if (values == null)
+ synchronized (mutex)
+ {
+ values = new SynchronizedCollection(mutex, m.values());
+ }
+ return values;
+ }
+ } // class SynchronizedMap
+
+ /**
+ * Returns a synchronized (thread-safe) set wrapper backed by the given
+ * set. Notice that element access through the iterator is thread-safe, but
+ * if the set can be structurally modified (adding or removing elements)
+ * then you should synchronize around the iteration to avoid
+ * non-deterministic behavior:<br>
+ * <pre>
+ * Set s = Collections.synchronizedSet(new Set(...));
+ * ...
+ * synchronized (s)
+ * {
+ * Iterator i = s.iterator();
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre><p>
+ *
+ * The returned Set implements Serializable, but can only be serialized if
+ * the set it wraps is likewise Serializable.
+ *
+ * @param s the set to wrap
+ * @return a synchronized view of the set
+ * @see Serializable
+ */
+ public static Set synchronizedSet(Set s)
+ {
+ return new SynchronizedSet(s);
+ }
+
+ /**
+ * The implementation of {@link #synchronizedSet(Set)}. This class
+ * name is required for compatibility with Sun's JDK serializability.
+ * Package visible, so that sets such as Hashtable.keySet()
+ * can specify which object to synchronize on.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ static class SynchronizedSet extends SynchronizedCollection
+ implements Set
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 487447009682186044L;
+
+ /**
+ * Wrap a given set.
+ * @param s the set to wrap
+ * @throws NullPointerException if s is null
+ */
+ SynchronizedSet(Set s)
+ {
+ super(s);
+ }
+
+ /**
+ * Called only by trusted code to specify the mutex as well as the set.
+ * @param sync the mutex
+ * @param s the set
+ */
+ SynchronizedSet(Object sync, Set s)
+ {
+ super(sync, s);
+ }
+
+ /**
+ * Returns <code>true</code> if the object, o, is a <code>Set</code>
+ * of the same size as the underlying set, and contains
+ * each element, e, which occurs in the underlying set.
+ * A lock is obtained on the mutex before the comparison
+ * takes place.
+ *
+ * @param o The object to compare against.
+ * @return <code>true</code> if o is an equivalent set.
+ */
+ public boolean equals(Object o)
+ {
+ synchronized (mutex)
+ {
+ return c.equals(o);
+ }
+ }
+
+ /**
+ * Computes the hash code for the underlying set as the
+ * sum of the hash code of all elements within the set.
+ * A lock is obtained on the mutex before the computation
+ * occurs.
+ *
+ * @return The hash code for the underlying set.
+ */
+ public int hashCode()
+ {
+ synchronized (mutex)
+ {
+ return c.hashCode();
+ }
+ }
+ } // class SynchronizedSet
+
+ /**
+ * Returns a synchronized (thread-safe) sorted map wrapper backed by the
+ * given map. Notice that element access through the collection views,
+ * subviews, and their iterators are thread-safe, but if the map can be
+ * structurally modified (adding or removing elements) then you should
+ * synchronize around the iteration to avoid non-deterministic behavior:<br>
+ * <pre>
+ * SortedMap m = Collections.synchronizedSortedMap(new SortedMap(...));
+ * ...
+ * Set s = m.keySet(); // safe outside a synchronized block
+ * SortedMap m2 = m.headMap(foo); // safe outside a synchronized block
+ * Set s2 = m2.keySet(); // safe outside a synchronized block
+ * synchronized (m) // synch on m, not m2, s or s2
+ * {
+ * Iterator i = s.iterator();
+ * while (i.hasNext())
+ * foo(i.next());
+ * i = s2.iterator();
+ * while (i.hasNext())
+ * bar(i.next());
+ * }
+ * </pre><p>
+ *
+ * The returned SortedMap implements Serializable, but can only be
+ * serialized if the map it wraps is likewise Serializable.
+ *
+ * @param m the sorted map to wrap
+ * @return a synchronized view of the sorted map
+ * @see Serializable
+ */
+ public static SortedMap synchronizedSortedMap(SortedMap m)
+ {
+ return new SynchronizedSortedMap(m);
+ }
+
+ /**
+ * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class SynchronizedSortedMap extends SynchronizedMap
+ implements SortedMap
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -8798146769416483793L;
+
+ /**
+ * The wrapped map; stored both here and in the superclass to avoid
+ * excessive casting.
+ * @serial the wrapped map
+ */
+ private final SortedMap sm;
+
+ /**
+ * Wrap a given map.
+ * @param sm the map to wrap
+ * @throws NullPointerException if sm is null
+ */
+ SynchronizedSortedMap(SortedMap sm)
+ {
+ super(sm);
+ this.sm = sm;
+ }
+
+ /**
+ * Called only by trusted code to specify the mutex as well as the map.
+ * @param sync the mutex
+ * @param sm the map
+ */
+ SynchronizedSortedMap(Object sync, SortedMap sm)
+ {
+ super(sync, sm);
+ this.sm = sm;
+ }
+
+ /**
+ * Returns the comparator used in sorting the underlying map, or null if
+ * it is the keys' natural ordering. A lock is obtained on the mutex
+ * before the comparator is retrieved.
+ *
+ * @return the sorting comparator.
+ */
+ public Comparator comparator()
+ {
+ synchronized (mutex)
+ {
+ return sm.comparator();
+ }
+ }
+
+ /**
+ * Returns the first, lowest sorted, key from the underlying map.
+ * A lock is obtained on the mutex before the map is accessed.
+ *
+ * @return the first key.
+ * @throws NoSuchElementException if this map is empty.
+ */
+ public Object firstKey()
+ {
+ synchronized (mutex)
+ {
+ return sm.firstKey();
+ }
+ }
+
+ /**
+ * Returns a submap containing the keys from the first
+ * key (as returned by <code>firstKey()</code>) to
+ * the key before that specified. The submap supports all
+ * operations supported by the underlying map and all actions
+ * taking place on the submap are also reflected in the underlying
+ * map. A lock is obtained on the mutex prior to submap creation.
+ * This operation is equivalent to <code>subMap(firstKey(), toKey)</code>.
+ * The submap retains the thread-safe status of this map.
+ *
+ * @param toKey the exclusive upper range of the submap.
+ * @return a submap from <code>firstKey()</code> to the
+ * the key preceding toKey.
+ * @throws ClassCastException if toKey is not comparable to the underlying
+ * map's contents.
+ * @throws IllegalArgumentException if toKey is outside the map's range.
+ * @throws NullPointerException if toKey is null. but the map does not allow
+ * null keys.
+ */
+ public SortedMap headMap(Object toKey)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedSortedMap(mutex, sm.headMap(toKey));
+ }
+ }
+
+ /**
+ * Returns the last, highest sorted, key from the underlying map.
+ * A lock is obtained on the mutex before the map is accessed.
+ *
+ * @return the last key.
+ * @throws NoSuchElementException if this map is empty.
+ */
+ public Object lastKey()
+ {
+ synchronized (mutex)
+ {
+ return sm.lastKey();
+ }
+ }
+
+ /**
+ * Returns a submap containing the keys from fromKey to
+ * the key before toKey. The submap supports all
+ * operations supported by the underlying map and all actions
+ * taking place on the submap are also reflected in the underlying
+ * map. A lock is obtained on the mutex prior to submap creation.
+ * The submap retains the thread-safe status of this map.
+ *
+ * @param fromKey the inclusive lower range of the submap.
+ * @param toKey the exclusive upper range of the submap.
+ * @return a submap from fromKey to the key preceding toKey.
+ * @throws ClassCastException if fromKey or toKey is not comparable
+ * to the underlying map's contents.
+ * @throws IllegalArgumentException if fromKey or toKey is outside the map's
+ * range.
+ * @throws NullPointerException if fromKey or toKey is null. but the map does
+ * not allow null keys.
+ */
+ public SortedMap subMap(Object fromKey, Object toKey)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedSortedMap(mutex, sm.subMap(fromKey, toKey));
+ }
+ }
+
+ /**
+ * Returns a submap containing all the keys from fromKey onwards.
+ * The submap supports all operations supported by the underlying
+ * map and all actions taking place on the submap are also reflected
+ * in the underlying map. A lock is obtained on the mutex prior to
+ * submap creation. The submap retains the thread-safe status of
+ * this map.
+ *
+ * @param fromKey the inclusive lower range of the submap.
+ * @return a submap from fromKey to <code>lastKey()</code>.
+ * @throws ClassCastException if fromKey is not comparable to the underlying
+ * map's contents.
+ * @throws IllegalArgumentException if fromKey is outside the map's range.
+ * @throws NullPointerException if fromKey is null. but the map does not allow
+ * null keys.
+ */
+ public SortedMap tailMap(Object fromKey)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedSortedMap(mutex, sm.tailMap(fromKey));
+ }
+ }
+ } // class SynchronizedSortedMap
+
+ /**
+ * Returns a synchronized (thread-safe) sorted set wrapper backed by the
+ * given set. Notice that element access through the iterator and through
+ * subviews are thread-safe, but if the set can be structurally modified
+ * (adding or removing elements) then you should synchronize around the
+ * iteration to avoid non-deterministic behavior:<br>
+ * <pre>
+ * SortedSet s = Collections.synchronizedSortedSet(new SortedSet(...));
+ * ...
+ * SortedSet s2 = s.headSet(foo); // safe outside a synchronized block
+ * synchronized (s) // synch on s, not s2
+ * {
+ * Iterator i = s2.iterator();
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre><p>
+ *
+ * The returned SortedSet implements Serializable, but can only be
+ * serialized if the set it wraps is likewise Serializable.
+ *
+ * @param s the sorted set to wrap
+ * @return a synchronized view of the sorted set
+ * @see Serializable
+ */
+ public static SortedSet synchronizedSortedSet(SortedSet s)
+ {
+ return new SynchronizedSortedSet(s);
+ }
+
+ /**
+ * The implementation of {@link #synchronizedSortedSet(SortedSet)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class SynchronizedSortedSet extends SynchronizedSet
+ implements SortedSet
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 8695801310862127406L;
+
+ /**
+ * The wrapped set; stored both here and in the superclass to avoid
+ * excessive casting.
+ * @serial the wrapped set
+ */
+ private final SortedSet ss;
+
+ /**
+ * Wrap a given set.
+ * @param ss the set to wrap
+ * @throws NullPointerException if ss is null
+ */
+ SynchronizedSortedSet(SortedSet ss)
+ {
+ super(ss);
+ this.ss = ss;
+ }
+
+ /**
+ * Called only by trusted code to specify the mutex as well as the set.
+ * @param sync the mutex
+ * @param l the list
+ */
+ SynchronizedSortedSet(Object sync, SortedSet ss)
+ {
+ super(sync, ss);
+ this.ss = ss;
+ }
+
+ /**
+ * Returns the comparator used in sorting the underlying set, or null if
+ * it is the elements' natural ordering. A lock is obtained on the mutex
+ * before the comparator is retrieved.
+ *
+ * @return the sorting comparator.
+ */
+ public Comparator comparator()
+ {
+ synchronized (mutex)
+ {
+ return ss.comparator();
+ }
+ }
+
+ /**
+ * Returns the first, lowest sorted, element from the underlying set.
+ * A lock is obtained on the mutex before the set is accessed.
+ *
+ * @return the first element.
+ * @throws NoSuchElementException if this set is empty.
+ */
+ public Object first()
+ {
+ synchronized (mutex)
+ {
+ return ss.first();
+ }
+ }
+
+ /**
+ * Returns a subset containing the element from the first
+ * element (as returned by <code>first()</code>) to
+ * the element before that specified. The subset supports all
+ * operations supported by the underlying set and all actions
+ * taking place on the subset are also reflected in the underlying
+ * set. A lock is obtained on the mutex prior to subset creation.
+ * This operation is equivalent to <code>subSet(first(), toElement)</code>.
+ * The subset retains the thread-safe status of this set.
+ *
+ * @param toElement the exclusive upper range of the subset.
+ * @return a subset from <code>first()</code> to the
+ * the element preceding toElement.
+ * @throws ClassCastException if toElement is not comparable to the underlying
+ * set's contents.
+ * @throws IllegalArgumentException if toElement is outside the set's range.
+ * @throws NullPointerException if toElement is null. but the set does not allow
+ * null elements.
+ */
+ public SortedSet headSet(Object toElement)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedSortedSet(mutex, ss.headSet(toElement));
+ }
+ }
+
+ /**
+ * Returns the last, highest sorted, element from the underlying set.
+ * A lock is obtained on the mutex before the set is accessed.
+ *
+ * @return the last element.
+ * @throws NoSuchElementException if this set is empty.
+ */
+ public Object last()
+ {
+ synchronized (mutex)
+ {
+ return ss.last();
+ }
+ }
+
+ /**
+ * Returns a subset containing the elements from fromElement to
+ * the element before toElement. The subset supports all
+ * operations supported by the underlying set and all actions
+ * taking place on the subset are also reflected in the underlying
+ * set. A lock is obtained on the mutex prior to subset creation.
+ * The subset retains the thread-safe status of this set.
+ *
+ * @param fromElement the inclusive lower range of the subset.
+ * @param toElement the exclusive upper range of the subset.
+ * @return a subset from fromElement to the element preceding toElement.
+ * @throws ClassCastException if fromElement or toElement is not comparable
+ * to the underlying set's contents.
+ * @throws IllegalArgumentException if fromElement or toElement is outside the set's
+ * range.
+ * @throws NullPointerException if fromElement or toElement is null. but the set does
+ * not allow null elements.
+ */
+ public SortedSet subSet(Object fromElement, Object toElement)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedSortedSet(mutex,
+ ss.subSet(fromElement, toElement));
+ }
+ }
+
+ /**
+ * Returns a subset containing all the elements from fromElement onwards.
+ * The subset supports all operations supported by the underlying
+ * set and all actions taking place on the subset are also reflected
+ * in the underlying set. A lock is obtained on the mutex prior to
+ * subset creation. The subset retains the thread-safe status of
+ * this set.
+ *
+ * @param fromElement the inclusive lower range of the subset.
+ * @return a subset from fromElement to <code>last()</code>.
+ * @throws ClassCastException if fromElement is not comparable to the underlying
+ * set's contents.
+ * @throws IllegalArgumentException if fromElement is outside the set's range.
+ * @throws NullPointerException if fromElement is null. but the set does not allow
+ * null elements.
+ */
+ public SortedSet tailSet(Object fromElement)
+ {
+ synchronized (mutex)
+ {
+ return new SynchronizedSortedSet(mutex, ss.tailSet(fromElement));
+ }
+ }
+ } // class SynchronizedSortedSet
+
+
+ /**
+ * Returns an unmodifiable view of the given collection. This allows
+ * "read-only" access, although changes in the backing collection show up
+ * in this view. Attempts to modify the collection directly or via iterators
+ * will fail with {@link UnsupportedOperationException}. Although this view
+ * prevents changes to the structure of the collection and its elements, the values
+ * referenced by the objects in the collection can still be modified.
+ * <p>
+ *
+ * Since the collection might be a List or a Set, and those have incompatible
+ * equals and hashCode requirements, this relies on Object's implementation
+ * rather than passing those calls on to the wrapped collection. The returned
+ * Collection implements Serializable, but can only be serialized if
+ * the collection it wraps is likewise Serializable.
+ *
+ * @param c the collection to wrap
+ * @return a read-only view of the collection
+ * @see Serializable
+ */
+ public static Collection unmodifiableCollection(Collection c)
+ {
+ return new UnmodifiableCollection(c);
+ }
+
+ /**
+ * The implementation of {@link #unmodifiableCollection(Collection)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class UnmodifiableCollection
+ implements Collection, Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 1820017752578914078L;
+
+ /**
+ * The wrapped collection. Package visible for use by subclasses.
+ * @serial the real collection
+ */
+ final Collection c;
+
+ /**
+ * Wrap a given collection.
+ * @param c the collection to wrap
+ * @throws NullPointerException if c is null
+ */
+ UnmodifiableCollection(Collection c)
+ {
+ this.c = c;
+ if (c == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Blocks the addition of elements to the underlying collection.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param o the object to add.
+ * @return <code>true</code> if the collection was modified as a result of this action.
+ * @throws UnsupportedOperationException as an unmodifiable collection does not
+ * support the add operation.
+ */
+ public boolean add(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Blocks the addition of a collection of elements to the underlying
+ * collection. This method never returns, throwing an exception instead.
+ *
+ * @param c the collection to add.
+ * @return <code>true</code> if the collection was modified as a result of this action.
+ * @throws UnsupportedOperationException as an unmodifiable collection does not
+ * support the <code>addAll</code> operation.
+ */
+ public boolean addAll(Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Blocks the clearing of the underlying collection. This method never
+ * returns, throwing an exception instead.
+ *
+ * @throws UnsupportedOperationException as an unmodifiable collection does
+ * not support the <code>clear()</code> operation.
+ */
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Test whether the underlying collection contains a given object as one of its
+ * elements.
+ *
+ * @param o the element to look for.
+ * @return <code>true</code> if the underlying collection contains at least
+ * one element e such that
+ * <code>o == null ? e == null : o.equals(e)</code>.
+ * @throws ClassCastException if the type of o is not a valid type for the
+ * underlying collection.
+ * @throws NullPointerException if o is null and the underlying collection
+ * doesn't support null values.
+ */
+ public boolean contains(Object o)
+ {
+ return c.contains(o);
+ }
+
+ /**
+ * Test whether the underlying collection contains every element in a given
+ * collection.
+ *
+ * @param c1 the collection to test for.
+ * @return <code>true</code> if for every element o in c, contains(o) would
+ * return <code>true</code>.
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for the underlying collection.
+ * @throws NullPointerException if some element of c is null and the underlying
+ * collection does not support null values.
+ * @throws NullPointerException if c itself is null.
+ */
+ public boolean containsAll(Collection c1)
+ {
+ return c.containsAll(c1);
+ }
+
+ /**
+ * Tests whether the underlying collection is empty, that is,
+ * if size() == 0.
+ *
+ * @return <code>true</code> if this collection contains no elements.
+ */
+ public boolean isEmpty()
+ {
+ return c.isEmpty();
+ }
+
+ /**
+ * Obtain an Iterator over the underlying collection, which maintains
+ * its unmodifiable nature.
+ *
+ * @return an UnmodifiableIterator over the elements of the underlying
+ * collection, in any order.
+ */
+ public Iterator iterator()
+ {
+ return new UnmodifiableIterator(c.iterator());
+ }
+
+ /**
+ * Blocks the removal of an object from the underlying collection.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param o The object to remove.
+ * @return <code>true</code> if the object was removed (i.e. the underlying
+ * collection returned 1 or more instances of o).
+ * @throws UnsupportedOperationException as an unmodifiable collection
+ * does not support the <code>remove()</code> operation.
+ */
+ public boolean remove(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Blocks the removal of a collection of objects from the underlying
+ * collection. This method never returns, throwing an exception
+ * instead.
+ *
+ * @param c The collection of objects to remove.
+ * @return <code>true</code> if the collection was modified.
+ * @throws UnsupportedOperationException as an unmodifiable collection
+ * does not support the <code>removeAll()</code> operation.
+ */
+ public boolean removeAll(Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Blocks the removal of all elements from the underlying collection,
+ * except those in the supplied collection. This method never returns,
+ * throwing an exception instead.
+ *
+ * @param c The collection of objects to retain.
+ * @return <code>true</code> if the collection was modified.
+ * @throws UnsupportedOperationException as an unmodifiable collection
+ * does not support the <code>retainAll()</code> operation.
+ */
+ public boolean retainAll(Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Retrieves the number of elements in the underlying collection.
+ *
+ * @return the number of elements in the collection.
+ */
+ public int size()
+ {
+ return c.size();
+ }
+
+ /**
+ * Copy the current contents of the underlying collection into an array.
+ *
+ * @return an array of type Object[] with a length equal to the size of the
+ * underlying collection and containing the elements currently in
+ * the underlying collection, in any order.
+ */
+ public Object[] toArray()
+ {
+ return c.toArray();
+ }
+
+ /**
+ * Copy the current contents of the underlying collection into an array. If
+ * the array passed as an argument has length less than the size of the
+ * underlying collection, an array of the same run-time type as a, with a length
+ * equal to the size of the underlying collection, is allocated using reflection.
+ * Otherwise, a itself is used. The elements of the underlying collection are
+ * copied into it, and if there is space in the array, the following element is
+ * set to null. The resultant array is returned.
+ * Note: The fact that the following element is set to null is only useful
+ * if it is known that this collection does not contain any null elements.
+ *
+ * @param a the array to copy this collection into.
+ * @return an array containing the elements currently in the underlying
+ * collection, in any order.
+ * @throws ArrayStoreException if the type of any element of the
+ * collection is not a subtype of the element type of a.
+ */
+ public Object[] toArray(Object[] a)
+ {
+ return c.toArray(a);
+ }
+
+ /**
+ * A textual representation of the unmodifiable collection.
+ *
+ * @return The unmodifiable collection in the form of a <code>String</code>.
+ */
+ public String toString()
+ {
+ return c.toString();
+ }
+ } // class UnmodifiableCollection
+
+ /**
+ * The implementation of the various iterator methods in the
+ * unmodifiable classes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class UnmodifiableIterator implements Iterator
+ {
+ /**
+ * The wrapped iterator.
+ */
+ private final Iterator i;
+
+ /**
+ * Only trusted code creates a wrapper.
+ * @param i the wrapped iterator
+ */
+ UnmodifiableIterator(Iterator i)
+ {
+ this.i = i;
+ }
+
+ /**
+ * Obtains the next element in the underlying collection.
+ *
+ * @return the next element in the collection.
+ * @throws NoSuchElementException if there are no more elements.
+ */
+ public Object next()
+ {
+ return i.next();
+ }
+ /**
+ * Tests whether there are still elements to be retrieved from the
+ * underlying collection by <code>next()</code>. When this method
+ * returns <code>true</code>, an exception will not be thrown on calling
+ * <code>next()</code>.
+ *
+ * @return <code>true</code> if there is at least one more element in the underlying
+ * collection.
+ */
+ public boolean hasNext()
+ {
+ return i.hasNext();
+ }
+
+ /**
+ * Blocks the removal of elements from the underlying collection by the
+ * iterator.
+ *
+ * @throws UnsupportedOperationException as an unmodifiable collection
+ * does not support the removal of elements by its iterator.
+ */
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ } // class UnmodifiableIterator
+
+ /**
+ * Returns an unmodifiable view of the given list. This allows
+ * "read-only" access, although changes in the backing list show up
+ * in this view. Attempts to modify the list directly, via iterators, or
+ * via sublists, will fail with {@link UnsupportedOperationException}.
+ * Although this view prevents changes to the structure of the list and
+ * its elements, the values referenced by the objects in the list can
+ * still be modified.
+ * <p>
+ *
+ * The returned List implements Serializable, but can only be serialized if
+ * the list it wraps is likewise Serializable. In addition, if the wrapped
+ * list implements RandomAccess, this does too.
+ *
+ * @param l the list to wrap
+ * @return a read-only view of the list
+ * @see Serializable
+ * @see RandomAccess
+ */
+ public static List unmodifiableList(List l)
+ {
+ if (l instanceof RandomAccess)
+ return new UnmodifiableRandomAccessList(l);
+ return new UnmodifiableList(l);
+ }
+
+ /**
+ * The implementation of {@link #unmodifiableList(List)} for sequential
+ * lists. This class name is required for compatibility with Sun's JDK
+ * serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class UnmodifiableList extends UnmodifiableCollection
+ implements List
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -283967356065247728L;
+
+
+ /**
+ * The wrapped list; stored both here and in the superclass to avoid
+ * excessive casting. Package visible for use by subclass.
+ * @serial the wrapped list
+ */
+ final List list;
+
+ /**
+ * Wrap a given list.
+ * @param l the list to wrap
+ * @throws NullPointerException if l is null
+ */
+ UnmodifiableList(List l)
+ {
+ super(l);
+ list = l;
+ }
+
+ /**
+ * Blocks the addition of an element to the underlying
+ * list at a specific index. This method never returns,
+ * throwing an exception instead.
+ *
+ * @param index The index at which to place the new element.
+ * @param o the object to add.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * list doesn't support the <code>add()</code> operation.
+ */
+ public void add(int index, Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Blocks the addition of a collection of elements to the
+ * underlying list at a specific index. This method never
+ * returns, throwing an exception instead.
+ *
+ * @param index The index at which to place the new element.
+ * @param c the collections of objects to add.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * list doesn't support the <code>addAll()</code> operation.
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns <code>true</code> if the object, o, is an instance of
+ * <code>List</code> with the same size and elements
+ * as the underlying list.
+ *
+ * @param o The object to compare.
+ * @return <code>true</code> if o is equivalent to the underlying list.
+ */
+ public boolean equals(Object o)
+ {
+ return list.equals(o);
+ }
+
+ /**
+ * Retrieves the element at a given index in the underlying list.
+ *
+ * @param index the index of the element to be returned
+ * @return the element at index index in this list
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object get(int index)
+ {
+ return list.get(index);
+ }
+
+ /**
+ * Computes the hash code for the underlying list.
+ * The exact computation is described in the documentation
+ * of the <code>List</code> interface.
+ *
+ * @return The hash code of the underlying list.
+ * @see List#hashCode()
+ */
+ public int hashCode()
+ {
+ return list.hashCode();
+ }
+
+ /**
+ * Obtain the first index at which a given object is to be found in the
+ * underlying list.
+ *
+ * @param o the object to search for
+ * @return the least integer n such that <code>o == null ? get(n) == null :
+ * o.equals(get(n))</code>, or -1 if there is no such index.
+ * @throws ClassCastException if the type of o is not a valid
+ * type for the underlying list.
+ * @throws NullPointerException if o is null and the underlying
+ * list does not support null values.
+ */
+ public int indexOf(Object o)
+ {
+ return list.indexOf(o);
+ }
+
+ /**
+ * Obtain the last index at which a given object is to be found in the
+ * underlying list.
+ *
+ * @return the greatest integer n such that <code>o == null ? get(n) == null
+ * : o.equals(get(n))</code>, or -1 if there is no such index.
+ * @throws ClassCastException if the type of o is not a valid
+ * type for the underlying list.
+ * @throws NullPointerException if o is null and the underlying
+ * list does not support null values.
+ */
+ public int lastIndexOf(Object o)
+ {
+ return list.lastIndexOf(o);
+ }
+
+ /**
+ * Obtains a list iterator over the underlying list, starting at the beginning
+ * and maintaining the unmodifiable nature of this list.
+ *
+ * @return a <code>UnmodifiableListIterator</code> over the elements of the
+ * underlying list, in order, starting at the beginning.
+ */
+ public ListIterator listIterator()
+ {
+ return new UnmodifiableListIterator(list.listIterator());
+ }
+
+ /**
+ * Obtains a list iterator over the underlying list, starting at the specified
+ * index and maintaining the unmodifiable nature of this list. An initial call
+ * to <code>next()</code> will retrieve the element at the specified index,
+ * and an initial call to <code>previous()</code> will retrieve the element
+ * at index - 1.
+ *
+ *
+ * @param index the position, between 0 and size() inclusive, to begin the
+ * iteration from.
+ * @return a <code>UnmodifiableListIterator</code> over the elements of the
+ * underlying list, in order, starting at the specified index.
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public ListIterator listIterator(int index)
+ {
+ return new UnmodifiableListIterator(list.listIterator(index));
+ }
+
+ /**
+ * Blocks the removal of the element at the specified index.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param index The index of the element to remove.
+ * @return the removed element.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * list does not support the <code>remove()</code>
+ * operation.
+ */
+ public Object remove(int index)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Blocks the replacement of the element at the specified index.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param index The index of the element to replace.
+ * @param o The new object to place at the specified index.
+ * @return the replaced element.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * list does not support the <code>set()</code>
+ * operation.
+ */
+ public Object set(int index, Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Obtain a List view of a subsection of the underlying list, from
+ * fromIndex (inclusive) to toIndex (exclusive). If the two indices
+ * are equal, the sublist is empty. The returned list will be
+ * unmodifiable, like this list. Changes to the elements of the
+ * returned list will be reflected in the underlying list. No structural
+ * modifications can take place in either list.
+ *
+ * @param fromIndex the index that the returned list should start from
+ * (inclusive).
+ * @param toIndex the index that the returned list should go to (exclusive).
+ * @return a List backed by a subsection of the underlying list.
+ * @throws IndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; size() || fromIndex &gt; toIndex.
+ */
+ public List subList(int fromIndex, int toIndex)
+ {
+ return unmodifiableList(list.subList(fromIndex, toIndex));
+ }
+ } // class UnmodifiableList
+
+ /**
+ * The implementation of {@link #unmodifiableList(List)} for random-access
+ * lists. This class name is required for compatibility with Sun's JDK
+ * serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class UnmodifiableRandomAccessList
+ extends UnmodifiableList implements RandomAccess
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -2542308836966382001L;
+
+ /**
+ * Wrap a given list.
+ * @param l the list to wrap
+ * @throws NullPointerException if l is null
+ */
+ UnmodifiableRandomAccessList(List l)
+ {
+ super(l);
+ }
+ } // class UnmodifiableRandomAccessList
+
+ /**
+ * The implementation of {@link UnmodifiableList#listIterator()}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class UnmodifiableListIterator
+ extends UnmodifiableIterator implements ListIterator
+ {
+ /**
+ * The wrapped iterator, stored both here and in the superclass to
+ * avoid excessive casting.
+ */
+ private final ListIterator li;
+
+ /**
+ * Only trusted code creates a wrapper.
+ * @param li the wrapped iterator
+ */
+ UnmodifiableListIterator(ListIterator li)
+ {
+ super(li);
+ this.li = li;
+ }
+
+ /**
+ * Blocks the addition of an object to the list underlying this iterator.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param o The object to add.
+ * @throws UnsupportedOperationException as the iterator of an unmodifiable
+ * list does not support the <code>add()</code> operation.
+ */
+ public void add(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Tests whether there are still elements to be retrieved from the
+ * underlying collection by <code>previous()</code>. When this method
+ * returns <code>true</code>, an exception will not be thrown on calling
+ * <code>previous()</code>.
+ *
+ * @return <code>true</code> if there is at least one more element prior to the
+ * current position in the underlying list.
+ */
+ public boolean hasPrevious()
+ {
+ return li.hasPrevious();
+ }
+
+ /**
+ * Find the index of the element that would be returned by a call to next.
+ * If <code>hasNext()</code> returns <code>false</code>, this returns the list size.
+ *
+ * @return the index of the element that would be returned by
+ * <code>next()</code>.
+ */
+ public int nextIndex()
+ {
+ return li.nextIndex();
+ }
+
+ /**
+ * Obtains the previous element in the underlying list.
+ *
+ * @return the previous element in the list.
+ * @throws NoSuchElementException if there are no more prior elements.
+ */
+ public Object previous()
+ {
+ return li.previous();
+ }
+
+ /**
+ * Find the index of the element that would be returned by a call to
+ * previous. If <code>hasPrevious()</code> returns <code>false</code>,
+ * this returns -1.
+ *
+ * @return the index of the element that would be returned by
+ * <code>previous()</code>.
+ */
+ public int previousIndex()
+ {
+ return li.previousIndex();
+ }
+
+ /**
+ * Blocks the replacement of an element in the list underlying this
+ * iterator. This method never returns, throwing an exception instead.
+ *
+ * @param o The new object to replace the existing one.
+ * @throws UnsupportedOperationException as the iterator of an unmodifiable
+ * list does not support the <code>set()</code> operation.
+ */
+ public void set(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+ } // class UnmodifiableListIterator
+
+ /**
+ * Returns an unmodifiable view of the given map. This allows "read-only"
+ * access, although changes in the backing map show up in this view.
+ * Attempts to modify the map directly, or via collection views or their
+ * iterators will fail with {@link UnsupportedOperationException}.
+ * Although this view prevents changes to the structure of the map and its
+ * entries, the values referenced by the objects in the map can still be
+ * modified.
+ * <p>
+ *
+ * The returned Map implements Serializable, but can only be serialized if
+ * the map it wraps is likewise Serializable.
+ *
+ * @param m the map to wrap
+ * @return a read-only view of the map
+ * @see Serializable
+ */
+ public static Map unmodifiableMap(Map m)
+ {
+ return new UnmodifiableMap(m);
+ }
+
+ /**
+ * The implementation of {@link #unmodifiableMap(Map)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class UnmodifiableMap implements Map, Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -1034234728574286014L;
+
+ /**
+ * The wrapped map.
+ * @serial the real map
+ */
+ private final Map m;
+
+ /**
+ * Cache the entry set.
+ */
+ private transient Set entries;
+
+ /**
+ * Cache the key set.
+ */
+ private transient Set keys;
+
+ /**
+ * Cache the value collection.
+ */
+ private transient Collection values;
+
+ /**
+ * Wrap a given map.
+ * @param m the map to wrap
+ * @throws NullPointerException if m is null
+ */
+ UnmodifiableMap(Map m)
+ {
+ this.m = m;
+ if (m == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Blocks the clearing of entries from the underlying map.
+ * This method never returns, throwing an exception instead.
+ *
+ * @throws UnsupportedOperationException as an unmodifiable
+ * map does not support the <code>clear()</code> operation.
+ */
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains a mapping for
+ * the given key.
+ *
+ * @param key the key to search for
+ * @return <code>true</code> if the map contains the key
+ * @throws ClassCastException if the key is of an inappropriate type
+ * @throws NullPointerException if key is <code>null</code> but the map
+ * does not permit null keys
+ */
+ public boolean containsKey(Object key)
+ {
+ return m.containsKey(key);
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains at least one mapping with
+ * the given value. In other words, it returns <code>true</code> if a value v exists where
+ * <code>(value == null ? v == null : value.equals(v))</code>. This usually
+ * requires linear time.
+ *
+ * @param value the value to search for
+ * @return <code>true</code> if the map contains the value
+ * @throws ClassCastException if the type of the value is not a valid type
+ * for this map.
+ * @throws NullPointerException if the value is null and the map doesn't
+ * support null values.
+ */
+ public boolean containsValue(Object value)
+ {
+ return m.containsValue(value);
+ }
+
+ /**
+ * Returns a unmodifiable set view of the entries in the underlying map.
+ * Each element in the set is a unmodifiable variant of <code>Map.Entry</code>.
+ * 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. These modifications are again limited to the values of
+ * the objects.
+ *
+ * @return the unmodifiable set view of all mapping entries.
+ * @see Map.Entry
+ */
+ public Set entrySet()
+ {
+ if (entries == null)
+ entries = new UnmodifiableEntrySet(m.entrySet());
+ return entries;
+ }
+
+ /**
+ * The implementation of {@link UnmodifiableMap#entrySet()}. This class
+ * name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class UnmodifiableEntrySet extends UnmodifiableSet
+ implements Serializable
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 7854390611657943733L;
+
+ /**
+ * Wrap a given set.
+ * @param s the set to wrap
+ */
+ UnmodifiableEntrySet(Set s)
+ {
+ super(s);
+ }
+
+ // The iterator must return unmodifiable map entries.
+ public Iterator iterator()
+ {
+ return new UnmodifiableIterator(c.iterator())
+ {
+ /**
+ * Obtains the next element from the underlying set of
+ * map entries.
+ *
+ * @return the next element in the collection.
+ * @throws NoSuchElementException if there are no more elements.
+ */
+ public Object next()
+ {
+ final Map.Entry e = (Map.Entry) super.next();
+ return new Map.Entry()
+ {
+ /**
+ * Returns <code>true</code> if the object, o, is also a map entry with an
+ * identical key and value.
+ *
+ * @param o the object to compare.
+ * @return <code>true</code> if o is an equivalent map entry.
+ */
+ public boolean equals(Object o)
+ {
+ return e.equals(o);
+ }
+
+ /**
+ * Returns the key of this map entry.
+ *
+ * @return the key.
+ */
+ public Object getKey()
+ {
+ return e.getKey();
+ }
+
+ /**
+ * Returns the value of this map entry.
+ *
+ * @return the value.
+ */
+ public Object getValue()
+ {
+ return e.getValue();
+ }
+
+ /**
+ * Computes the hash code of this map entry.
+ * The computation is described in the <code>Map</code>
+ * interface documentation.
+ *
+ * @return the hash code of this entry.
+ * @see Map#hashCode()
+ */
+ public int hashCode()
+ {
+ return e.hashCode();
+ }
+
+ /**
+ * Blocks the alteration of the value of this map entry.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param value The new value.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * map entry does not support the <code>setValue()</code>
+ * operation.
+ */
+ public Object setValue(Object value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a textual representation of the map entry.
+ *
+ * @return The map entry as a <code>String</code>.
+ */
+ public String toString()
+ {
+ return e.toString();
+ }
+ };
+ }
+ };
+ }
+ } // class UnmodifiableEntrySet
+
+ /**
+ * Returns <code>true</code> if the object, o, is also an instance
+ * of <code>Map</code> with an equal set of map entries.
+ *
+ * @param o The object to compare.
+ * @return <code>true</code> if o is an equivalent map.
+ */
+ public boolean equals(Object o)
+ {
+ return m.equals(o);
+ }
+
+ /**
+ * Returns the value associated with the supplied key or
+ * null if no such mapping exists. An ambiguity can occur
+ * if null values are accepted by the underlying map.
+ * In this case, <code>containsKey()</code> can be used
+ * to separate the two possible cases of a null result.
+ *
+ * @param key The key to look up.
+ * @return the value associated with the key, or null if key not in map.
+ * @throws ClassCastException if the key is an inappropriate type.
+ * @throws NullPointerException if this map does not accept null keys.
+ * @see #containsKey(Object)
+ */
+ public Object get(Object key)
+ {
+ return m.get(key);
+ }
+
+ /**
+ * Blocks the addition of a new entry to the underlying map.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param key The new key.
+ * @param value The new value.
+ * @return the previous value of the key, or null if there was no mapping.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * map does not support the <code>put()</code> operation.
+ */
+ public Object put(Object key, Object value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Computes the hash code for the underlying map, as the sum
+ * of the hash codes of all entries.
+ *
+ * @return The hash code of the underlying map.
+ * @see Map.Entry#hashCode()
+ */
+ public int hashCode()
+ {
+ return m.hashCode();
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains no entries.
+ *
+ * @return <code>true</code> if the map is empty.
+ */
+ public boolean isEmpty()
+ {
+ return m.isEmpty();
+ }
+
+ /**
+ * Returns a unmodifiable set view of the keys in the underlying map.
+ * The set is backed by the map, so that changes in one show up in the other.
+ * Modifications made while an iterator is in progress cause undefined
+ * behavior. These modifications are again limited to the values of
+ * the keys.
+ *
+ * @return the set view of all keys.
+ */
+ public Set keySet()
+ {
+ if (keys == null)
+ keys = new UnmodifiableSet(m.keySet());
+ return keys;
+ }
+
+ /**
+ * Blocks the addition of the entries in the supplied map.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param m The map, the entries of which should be added
+ * to the underlying map.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * map does not support the <code>putAll</code> operation.
+ */
+ public void putAll(Map m)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Blocks the removal of an entry from the map.
+ * This method never returns, throwing an exception instead.
+ *
+ * @param o The key of the entry to remove.
+ * @return The value the key was associated with, or null
+ * if no such mapping existed. Null is also returned
+ * if the removed entry had a null key.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * map does not support the <code>remove</code> operation.
+ */
+ public Object remove(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /**
+ * Returns the number of key-value mappings in the underlying map.
+ * If there are more than Integer.MAX_VALUE mappings, Integer.MAX_VALUE
+ * is returned.
+ *
+ * @return the number of mappings.
+ */
+ public int size()
+ {
+ return m.size();
+ }
+
+ /**
+ * Returns a textual representation of the map.
+ *
+ * @return The map in the form of a <code>String</code>.
+ */
+ public String toString()
+ {
+ return m.toString();
+ }
+
+ /**
+ * Returns a unmodifiable collection view of the values in the underlying map.
+ * The collection is backed by the map, so that changes in one show up in the other.
+ * Modifications made while an iterator is in progress cause undefined
+ * behavior. These modifications are again limited to the values of
+ * the keys.
+ *
+ * @return the collection view of all values.
+ */
+ public Collection values()
+ {
+ if (values == null)
+ values = new UnmodifiableCollection(m.values());
+ return values;
+ }
+ } // class UnmodifiableMap
+
+ /**
+ * Returns an unmodifiable view of the given set. This allows
+ * "read-only" access, although changes in the backing set show up
+ * in this view. Attempts to modify the set directly or via iterators
+ * will fail with {@link UnsupportedOperationException}.
+ * Although this view prevents changes to the structure of the set and its
+ * entries, the values referenced by the objects in the set can still be
+ * modified.
+ * <p>
+ *
+ * The returned Set implements Serializable, but can only be serialized if
+ * the set it wraps is likewise Serializable.
+ *
+ * @param s the set to wrap
+ * @return a read-only view of the set
+ * @see Serializable
+ */
+ public static Set unmodifiableSet(Set s)
+ {
+ return new UnmodifiableSet(s);
+ }
+
+ /**
+ * The implementation of {@link #unmodifiableSet(Set)}. This class
+ * name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class UnmodifiableSet extends UnmodifiableCollection
+ implements Set
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -9215047833775013803L;
+
+ /**
+ * Wrap a given set.
+ * @param s the set to wrap
+ * @throws NullPointerException if s is null
+ */
+ UnmodifiableSet(Set s)
+ {
+ super(s);
+ }
+
+ /**
+ * Returns <code>true</code> if the object, o, is also an instance of
+ * <code>Set</code> of the same size and with the same entries.
+ *
+ * @return <code>true</code> if o is an equivalent set.
+ */
+ public boolean equals(Object o)
+ {
+ return c.equals(o);
+ }
+
+ /**
+ * Computes the hash code of this set, as the sum of the
+ * hash codes of all elements within the set.
+ *
+ * @return the hash code of the set.
+ */
+ public int hashCode()
+ {
+ return c.hashCode();
+ }
+ } // class UnmodifiableSet
+
+ /**
+ * Returns an unmodifiable view of the given sorted map. This allows
+ * "read-only" access, although changes in the backing map show up in this
+ * view. Attempts to modify the map directly, via subviews, via collection
+ * views, or iterators, will fail with {@link UnsupportedOperationException}.
+ * Although this view prevents changes to the structure of the map and its
+ * entries, the values referenced by the objects in the map can still be
+ * modified.
+ * <p>
+ *
+ * The returned SortedMap implements Serializable, but can only be
+ * serialized if the map it wraps is likewise Serializable.
+ *
+ * @param m the map to wrap
+ * @return a read-only view of the map
+ * @see Serializable
+ */
+ public static SortedMap unmodifiableSortedMap(SortedMap m)
+ {
+ return new UnmodifiableSortedMap(m);
+ }
+
+ /**
+ * The implementation of {@link #unmodifiableSortedMap(SortedMap)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class UnmodifiableSortedMap extends UnmodifiableMap
+ implements SortedMap
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -8806743815996713206L;
+
+ /**
+ * The wrapped map; stored both here and in the superclass to avoid
+ * excessive casting.
+ * @serial the wrapped map
+ */
+ private final SortedMap sm;
+
+ /**
+ * Wrap a given map.
+ * @param sm the map to wrap
+ * @throws NullPointerException if sm is null
+ */
+ UnmodifiableSortedMap(SortedMap sm)
+ {
+ super(sm);
+ this.sm = sm;
+ }
+
+ /**
+ * Returns the comparator used in sorting the underlying map,
+ * or null if it is the keys' natural ordering.
+ *
+ * @return the sorting comparator.
+ */
+ public Comparator comparator()
+ {
+ return sm.comparator();
+ }
+
+ /**
+ * Returns the first (lowest sorted) key in the map.
+ *
+ * @return the first key.
+ * @throws NoSuchElementException if this map is empty.
+ */
+ public Object firstKey()
+ {
+ return sm.firstKey();
+ }
+
+ /**
+ * Returns a unmodifiable view of the portion of the map strictly less
+ * than toKey. The view is backed by the underlying map, so changes in
+ * one show up in the other. The submap supports all optional operations
+ * of the original. This operation is equivalent to
+ * <code>subMap(firstKey(), toKey)</code>.
+ * <p>
+ *
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of toKey. Note that the endpoint, toKey,
+ * is not included; if you want this value to be included, pass its successor
+ * object in to toKey. For example, for Integers, you could request
+ * <code>headMap(new Integer(limit.intValue() + 1))</code>.
+ *
+ * @param toKey the exclusive upper range of the submap.
+ * @return the submap.
+ * @throws ClassCastException if toKey is not comparable to the map contents.
+ * @throws IllegalArgumentException if this is a subMap, and toKey is out
+ * of range.
+ * @throws NullPointerException if toKey is null but the map does not allow
+ * null keys.
+ */
+ public SortedMap headMap(Object toKey)
+ {
+ return new UnmodifiableSortedMap(sm.headMap(toKey));
+ }
+
+ /**
+ * Returns the last (highest sorted) key in the map.
+ *
+ * @return the last key.
+ * @throws NoSuchElementException if this map is empty.
+ */
+ public Object lastKey()
+ {
+ return sm.lastKey();
+ }
+
+ /**
+ * Returns a unmodifiable view of the portion of the map greater than or
+ * equal to fromKey, and strictly less than toKey. The view is backed by
+ * the underlying map, so changes in one show up in the other. The submap
+ * supports all optional operations of the original.
+ * <p>
+ *
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of fromKey and toKey. Note that the
+ * lower endpoint is included, but the upper is not; if you want to
+ * change the inclusion or exclusion of an endpoint, pass its successor
+ * object in instead. For example, for Integers, you could request
+ * <code>subMap(new Integer(lowlimit.intValue() + 1),
+ * new Integer(highlimit.intValue() + 1))</code> to reverse
+ * the inclusiveness of both endpoints.
+ *
+ * @param fromKey the inclusive lower range of the submap.
+ * @param toKey the exclusive upper range of the submap.
+ * @return the submap.
+ * @throws ClassCastException if fromKey or toKey is not comparable to
+ * the map contents.
+ * @throws IllegalArgumentException if this is a subMap, and fromKey or
+ * toKey is out of range.
+ * @throws NullPointerException if fromKey or toKey is null but the map
+ * does not allow null keys.
+ */
+ public SortedMap subMap(Object fromKey, Object toKey)
+ {
+ return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
+ }
+
+ /**
+ * Returns a unmodifiable view of the portion of the map greater than or
+ * equal to fromKey. The view is backed by the underlying map, so changes
+ * in one show up in the other. The submap supports all optional operations
+ * of the original.
+ * <p>
+ *
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of fromKey. Note that the endpoint, fromKey, is
+ * included; if you do not want this value to be included, pass its successor object in
+ * to fromKey. For example, for Integers, you could request
+ * <code>tailMap(new Integer(limit.intValue() + 1))</code>.
+ *
+ * @param fromKey the inclusive lower range of the submap
+ * @return the submap
+ * @throws ClassCastException if fromKey is not comparable to the map
+ * contents
+ * @throws IllegalArgumentException if this is a subMap, and fromKey is out
+ * of range
+ * @throws NullPointerException if fromKey is null but the map does not allow
+ * null keys
+ */
+ public SortedMap tailMap(Object fromKey)
+ {
+ return new UnmodifiableSortedMap(sm.tailMap(fromKey));
+ }
+ } // class UnmodifiableSortedMap
+
+ /**
+ * Returns an unmodifiable view of the given sorted set. This allows
+ * "read-only" access, although changes in the backing set show up
+ * in this view. Attempts to modify the set directly, via subsets, or via
+ * iterators, will fail with {@link UnsupportedOperationException}.
+ * Although this view prevents changes to the structure of the set and its
+ * entries, the values referenced by the objects in the set can still be
+ * modified.
+ * <p>
+ *
+ * The returns SortedSet implements Serializable, but can only be
+ * serialized if the set it wraps is likewise Serializable.
+ *
+ * @param s the set to wrap
+ * @return a read-only view of the set
+ * @see Serializable
+ */
+ public static SortedSet unmodifiableSortedSet(SortedSet s)
+ {
+ return new UnmodifiableSortedSet(s);
+ }
+
+ /**
+ * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static class UnmodifiableSortedSet extends UnmodifiableSet
+ implements SortedSet
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -4929149591599911165L;
+
+ /**
+ * The wrapped set; stored both here and in the superclass to avoid
+ * excessive casting.
+ * @serial the wrapped set
+ */
+ private SortedSet ss;
+
+ /**
+ * Wrap a given set.
+ * @param ss the set to wrap
+ * @throws NullPointerException if ss is null
+ */
+ UnmodifiableSortedSet(SortedSet ss)
+ {
+ super(ss);
+ this.ss = ss;
+ }
+
+ /**
+ * Returns the comparator used in sorting the underlying set,
+ * or null if it is the elements' natural ordering.
+ *
+ * @return the sorting comparator
+ */
+ public Comparator comparator()
+ {
+ return ss.comparator();
+ }
+
+ /**
+ * Returns the first (lowest sorted) element in the underlying
+ * set.
+ *
+ * @return the first element.
+ * @throws NoSuchElementException if the set is empty.
+ */
+ public Object first()
+ {
+ return ss.first();
+ }
+
+ /**
+ * Returns a unmodifiable view of the portion of the set strictly
+ * less than toElement. The view is backed by the underlying set,
+ * so changes in one show up in the other. The subset supports
+ * all optional operations of the original. This operation
+ * is equivalent to <code>subSet(first(), toElement)</code>.
+ * <p>
+ *
+ * The returned set throws an IllegalArgumentException any time an element is
+ * used which is out of the range of toElement. Note that the endpoint, toElement,
+ * is not included; if you want this value included, pass its successor object in to
+ * toElement. For example, for Integers, you could request
+ * <code>headSet(new Integer(limit.intValue() + 1))</code>.
+ *
+ * @param toElement the exclusive upper range of the subset
+ * @return the subset.
+ * @throws ClassCastException if toElement is not comparable to the set
+ * contents.
+ * @throws IllegalArgumentException if this is a subSet, and toElement is out
+ * of range.
+ * @throws NullPointerException if toElement is null but the set does not
+ * allow null elements.
+ */
+ public SortedSet headSet(Object toElement)
+ {
+ return new UnmodifiableSortedSet(ss.headSet(toElement));
+ }
+
+ /**
+ * Returns the last (highest sorted) element in the underlying
+ * set.
+ *
+ * @return the last element.
+ * @throws NoSuchElementException if the set is empty.
+ */
+ public Object last()
+ {
+ return ss.last();
+ }
+
+ /**
+ * Returns a unmodifiable view of the portion of the set greater than or
+ * equal to fromElement, and strictly less than toElement. The view is backed by
+ * the underlying set, so changes in one show up in the other. The subset
+ * supports all optional operations of the original.
+ * <p>
+ *
+ * The returned set throws an IllegalArgumentException any time an element is
+ * used which is out of the range of fromElement and toElement. Note that the
+ * lower endpoint is included, but the upper is not; if you want to
+ * change the inclusion or exclusion of an endpoint, pass its successor
+ * object in instead. For example, for Integers, you can request
+ * <code>subSet(new Integer(lowlimit.intValue() + 1),
+ * new Integer(highlimit.intValue() + 1))</code> to reverse
+ * the inclusiveness of both endpoints.
+ *
+ * @param fromElement the inclusive lower range of the subset.
+ * @param toElement the exclusive upper range of the subset.
+ * @return the subset.
+ * @throws ClassCastException if fromElement or toElement is not comparable
+ * to the set contents.
+ * @throws IllegalArgumentException if this is a subSet, and fromElement or
+ * toElement is out of range.
+ * @throws NullPointerException if fromElement or toElement is null but the
+ * set does not allow null elements.
+ */
+ public SortedSet subSet(Object fromElement, Object toElement)
+ {
+ return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
+ }
+
+ /**
+ * Returns a unmodifiable view of the portion of the set greater than or equal to
+ * fromElement. The view is backed by the underlying set, so changes in one show up
+ * in the other. The subset supports all optional operations of the original.
+ * <p>
+ *
+ * The returned set throws an IllegalArgumentException any time an element is
+ * used which is out of the range of fromElement. Note that the endpoint,
+ * fromElement, is included; if you do not want this value to be included, pass its
+ * successor object in to fromElement. For example, for Integers, you could request
+ * <code>tailSet(new Integer(limit.intValue() + 1))</code>.
+ *
+ * @param fromElement the inclusive lower range of the subset
+ * @return the subset.
+ * @throws ClassCastException if fromElement is not comparable to the set
+ * contents.
+ * @throws IllegalArgumentException if this is a subSet, and fromElement is
+ * out of range.
+ * @throws NullPointerException if fromElement is null but the set does not
+ * allow null elements.
+ */
+ public SortedSet tailSet(Object fromElement)
+ {
+ return new UnmodifiableSortedSet(ss.tailSet(fromElement));
+ }
+ } // class UnmodifiableSortedSet
+} // class Collections
diff --git a/libjava/classpath/java/util/Comparator.java b/libjava/classpath/java/util/Comparator.java
new file mode 100644
index 00000000000..386bdc1d6a2
--- /dev/null
+++ b/libjava/classpath/java/util/Comparator.java
@@ -0,0 +1,119 @@
+/* Comparator.java -- Interface for objects that specify an ordering
+ Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Interface for objects that specify an ordering between objects. The ordering
+ * should be <em>total</em>, such that any two objects of the correct type
+ * can be compared, and the comparison is reflexive, anti-symmetric, and
+ * transitive. It is also recommended that the comparator be <em>consistent
+ * with equals</em>, although this is not a strict requirement. A relation
+ * is consistent with equals if these two statements always have the same
+ * results (if no exceptions occur):<br>
+ * <code>compare((Object) e1, (Object) e2) == 0</code> and
+ * <code>e1.equals((Object) e2)</code><br>
+ * Comparators that violate consistency with equals may cause strange behavior
+ * in sorted lists and sets. For example, a case-sensitive dictionary order
+ * comparison of Strings is consistent with equals, but if it is
+ * case-insensitive it is not, because "abc" and "ABC" compare as equal even
+ * though "abc".equals("ABC") returns false.
+ * <P>
+ * In general, Comparators should be Serializable, because when they are passed
+ * to Serializable data structures such as SortedMap or SortedSet, the entire
+ * data structure will only serialize correctly if the comparator is
+ * Serializable.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Comparable
+ * @see TreeMap
+ * @see TreeSet
+ * @see SortedMap
+ * @see SortedSet
+ * @see Arrays#sort(Object[], Comparator)
+ * @see java.io.Serializable
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Comparator
+{
+ /**
+ * Return an integer that is negative, zero or positive depending on whether
+ * the first argument is less than, equal to or greater than the second
+ * according to this ordering. This method should obey the following
+ * contract:
+ * <ul>
+ * <li>if compare(a, b) &lt; 0 then compare(b, a) &gt; 0</li>
+ * <li>if compare(a, b) throws an exception, so does compare(b, a)</li>
+ * <li>if compare(a, b) &lt; 0 and compare(b, c) &lt; 0 then compare(a, c)
+ * &lt; 0</li>
+ * <li>if compare(a, b) == 0 then compare(a, c) and compare(b, c) must
+ * have the same sign</li>
+ * </ul>
+ * To be consistent with equals, the following additional constraint is
+ * in place:
+ * <ul>
+ * <li>if a.equals(b) or both a and b are null, then
+ * compare(a, b) == 0.</li>
+ * </ul><p>
+ *
+ * Although it is permissible for a comparator to provide an order
+ * inconsistent with equals, that should be documented.
+ *
+ * @param o1 the first object
+ * @param o2 the second object
+ * @return the comparison
+ * @throws ClassCastException if the elements are not of types that can be
+ * compared by this ordering.
+ */
+ int compare(Object o1, Object o2);
+
+ /**
+ * Return true if the object is equal to this object. To be
+ * considered equal, the argument object must satisfy the constraints
+ * of <code>Object.equals()</code>, be a Comparator, and impose the
+ * same ordering as this Comparator. The default implementation
+ * inherited from Object is usually adequate.
+ *
+ * @param obj The object
+ * @return true if it is a Comparator that imposes the same order
+ * @see Object#equals(Object)
+ */
+ boolean equals(Object obj);
+}
diff --git a/libjava/classpath/java/util/ConcurrentModificationException.java b/libjava/classpath/java/util/ConcurrentModificationException.java
new file mode 100644
index 00000000000..3d7ae108415
--- /dev/null
+++ b/libjava/classpath/java/util/ConcurrentModificationException.java
@@ -0,0 +1,92 @@
+/* ConcurrentModificationException.java -- Data structure concurrently modified
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ */
+
+/**
+ * Exception that is thrown by the collections classes when it is detected that
+ * a modification has been made to a data structure when this is not allowed,
+ * such as when a collection is structurally modified while an Iterator is
+ * operating over it. In cases where this can be detected, a
+ * ConcurrentModificationException will be thrown. An Iterator that detects
+ * this condition is referred to as fail-fast. Notice that this can occur
+ * even in single-threaded designs, if you call methods out of order.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see Iterator
+ * @see ListIterator
+ * @see Vector
+ * @see LinkedList
+ * @see HashSet
+ * @see Hashtable
+ * @see TreeMap
+ * @see AbstractList
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class ConcurrentModificationException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = -3666751008965953603L;
+
+ /**
+ * Constructs a ConcurrentModificationException with no detail message.
+ */
+ public ConcurrentModificationException()
+ {
+ }
+
+ /**
+ * Constructs a ConcurrentModificationException with a detail message.
+ *
+ * @param detail the detail message for the exception
+ */
+ public ConcurrentModificationException(String detail)
+ {
+ super(detail);
+ }
+}
diff --git a/libjava/classpath/java/util/Currency.java b/libjava/classpath/java/util/Currency.java
new file mode 100644
index 00000000000..32ea7534735
--- /dev/null
+++ b/libjava/classpath/java/util/Currency.java
@@ -0,0 +1,437 @@
+/* Currency.java -- Representation of a currency
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.java.locale.LocaleHelper;
+
+import java.io.IOException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
+/**
+ * Representation of a currency for a particular locale. Each currency
+ * is identified by its ISO 4217 code, and only one instance of this
+ * class exists per currency. As a result, instances are created
+ * via the <code>getInstance()</code> methods rather than by using
+ * a constructor.
+ *
+ * @see java.util.Locale
+ * @author Guilhem Lavaux (guilhem.lavaux@free.fr)
+ * @author Dalibor Topic (robilad@kaffe.org)
+ * @author Bryce McKinlay (mckinlay@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.4
+ */
+public final class Currency
+ implements Serializable
+{
+ /**
+ * For compatability with Sun's JDK
+ */
+ static final long serialVersionUID = -158308464356906721L;
+
+ /**
+ * The set of properties which map a currency to
+ * the currency information such as the ISO 4217
+ * currency code and the number of decimal points.
+ *
+ * @see #getCurrencyCode()
+ * @serial ignored.
+ */
+ private static transient Properties properties;
+
+ /**
+ * The ISO 4217 currency code associated with this
+ * particular instance.
+ *
+ * @see #getCurrencyCode()
+ * @serial the ISO 4217 currency code
+ */
+ private String currencyCode;
+
+ /**
+ * The number of fraction digits associated with this
+ * particular instance.
+ *
+ * @see #getDefaultFractionDigits()
+ * @serial the number of fraction digits
+ */
+ private transient int fractionDigits;
+
+ /**
+ * A cached map of country codes
+ * instances to international currency code
+ * <code>String</code>s. Seperating this
+ * from the <code>Currency</code> instances
+ * ensures we have a common lookup between
+ * the two <code>getInstance()</code> methods.
+ *
+ * @see #getInstance(java.util.Locale)
+ * @serial ignored.
+ */
+ private static transient Map countryMap;
+
+ /**
+ * A cache of <code>Currency</code> instances to
+ * ensure the singleton nature of this class. The key
+ * is the international currency code.
+ *
+ * @see #getInstance(java.util.Locale)
+ * @see #getInstance(java.lang.String)
+ * @see #readResolve()
+ * @serial ignored.
+ */
+ private static transient Map cache;
+
+ /**
+ * Instantiates the cache and reads in the properties.
+ */
+ static
+ {
+ /* Create a hash map for the locale mappings */
+ countryMap = new HashMap();
+ /* Create a hash map for the cache */
+ cache = new HashMap();
+ /* Create the properties object */
+ properties = new Properties();
+ /* Try and load the properties from our iso4217.properties resource */
+ try
+ {
+ properties.load(Currency.class.getResourceAsStream("iso4217.properties"));
+ }
+ catch (IOException exception)
+ {
+ System.out.println("Failed to load currency resource: " + exception);
+ }
+ }
+
+ /**
+ * Default constructor for deserialization
+ */
+ private Currency()
+ {
+ }
+
+ /**
+ * Constructor to create a <code>Currency</code> object
+ * for a particular <code>Locale</code>.
+ * All components of the given locale, other than the
+ * country code, are ignored. The results of calling this
+ * method may vary over time, as the currency associated with
+ * a particular country changes. For countries without
+ * a given currency (e.g. Antarctica), the result is null.
+ *
+ * @param loc the locale for the new currency, or null if
+ * there is no country code specified or a currency
+ * for this country.
+ */
+ private Currency(Locale loc)
+ {
+ String countryCode;
+ String currencyKey;
+ String fractionDigitsKey;
+ int commaPosition;
+
+ /* Retrieve the country code from the locale */
+ countryCode = loc.getCountry();
+ /* If there is no country code, return */
+ if (countryCode.equals(""))
+ {
+ throw new
+ IllegalArgumentException("Invalid (empty) country code for locale:"
+ + loc);
+ }
+ /* Construct the key for the currency */
+ currencyKey = countryCode + ".currency";
+ /* Construct the key for the fraction digits */
+ fractionDigitsKey = countryCode + ".fractionDigits";
+ /* Retrieve the currency */
+ currencyCode = properties.getProperty(currencyKey);
+ /* Return if the currency code is null */
+ if (currencyCode == null)
+ {
+ return;
+ }
+ /* Split off the first currency code (we only use the first for now) */
+ commaPosition = currencyCode.indexOf(",");
+ if (commaPosition != -1)
+ {
+ currencyCode = currencyCode.substring(0, commaPosition);
+ }
+ /* Retrieve the fraction digits */
+ fractionDigits = Integer.parseInt(properties.getProperty(fractionDigitsKey));
+ }
+
+ /**
+ * Constructor for the "XXX" special case. This allows
+ * a Currency to be constructed from an assumed good
+ * currency code.
+ *
+ * @param code the code to use.
+ */
+ private Currency(String code)
+ {
+ currencyCode = code;
+ fractionDigits = -1; /* Pseudo currency */
+ }
+
+ /**
+ * Returns the ISO4217 currency code of this currency.
+ *
+ * @return a <code>String</code> containing currency code.
+ */
+ public String getCurrencyCode()
+ {
+ return currencyCode;
+ }
+
+ /**
+ * Returns the number of digits which occur after the decimal point
+ * for this particular currency. For example, currencies such
+ * as the U.S. dollar, the Euro and the Great British pound have two
+ * digits following the decimal point to indicate the value which exists
+ * in the associated lower-valued coinage (cents in the case of the first
+ * two, pennies in the latter). Some currencies such as the Japanese
+ * Yen have no digits after the decimal point. In the case of pseudo
+ * currencies, such as IMF Special Drawing Rights, -1 is returned.
+ *
+ * @return the number of digits after the decimal separator for this currency.
+ */
+ public int getDefaultFractionDigits()
+ {
+ return fractionDigits;
+ }
+
+ /**
+ * Builds a new currency instance for this locale.
+ * All components of the given locale, other than the
+ * country code, are ignored. The results of calling this
+ * method may vary over time, as the currency associated with
+ * a particular country changes. For countries without
+ * a given currency (e.g. Antarctica), the result is null.
+ *
+ * @param locale a <code>Locale</code> instance.
+ * @return a new <code>Currency</code> instance.
+ * @throws NullPointerException if the locale or its
+ * country code is null.
+ * @throws IllegalArgumentException if the country of
+ * the given locale is not a supported ISO3166 code.
+ */
+ public static Currency getInstance(Locale locale)
+ {
+ /**
+ * The new instance must be the only available instance
+ * for the currency it supports. We ensure this happens,
+ * while maintaining a suitable performance level, by
+ * creating the appropriate object on the first call to
+ * this method, and returning the cached instance on
+ * later calls.
+ */
+ Currency newCurrency;
+
+ String country = locale.getCountry();
+ if (locale == null || country == null)
+ {
+ throw new
+ NullPointerException("The locale or its country is null.");
+ }
+ /* Attempt to get the currency from the cache */
+ String code = (String) countryMap.get(country);
+ if (code == null)
+ {
+ /* Create the currency for this locale */
+ newCurrency = new Currency(locale);
+ /*
+ * If the currency code is null, then creation failed
+ * and we return null.
+ */
+ code = newCurrency.getCurrencyCode();
+ if (code == null)
+ {
+ return null;
+ }
+ else
+ {
+ /* Cache it */
+ countryMap.put(country, code);
+ cache.put(code, newCurrency);
+ }
+ }
+ else
+ {
+ newCurrency = (Currency) cache.get(code);
+ }
+ /* Return the instance */
+ return newCurrency;
+ }
+
+ /**
+ * Builds the currency corresponding to the specified currency code.
+ *
+ * @param currencyCode a string representing a currency code.
+ * @return a new <code>Currency</code> instance.
+ * @throws NullPointerException if currencyCode is null.
+ * @throws IllegalArgumentException if the supplied currency code
+ * is not a supported ISO 4217 code.
+ */
+ public static Currency getInstance(String currencyCode)
+ {
+ Locale[] allLocales;
+
+ /*
+ * Throw a null pointer exception explicitly if currencyCode is null.
+ * One is not thrown otherwise. It results in an
+ * IllegalArgumentException.
+ */
+ if (currencyCode == null)
+ {
+ throw new NullPointerException("The supplied currency code is null.");
+ }
+ /* Nasty special case to allow an erroneous currency... blame Sun */
+ if (currencyCode.equals("XXX"))
+ return new Currency("XXX");
+ Currency newCurrency = (Currency) cache.get(currencyCode);
+ if (newCurrency == null)
+ {
+ /* Get all locales */
+ allLocales = Locale.getAvailableLocales();
+ /* Loop through each locale, looking for the code */
+ for (int i = 0;i < allLocales.length; i++)
+ {
+ try
+ {
+ Currency testCurrency = getInstance (allLocales[i]);
+ if (testCurrency != null &&
+ testCurrency.getCurrencyCode().equals(currencyCode))
+ {
+ return testCurrency;
+ }
+ }
+ catch (IllegalArgumentException exception)
+ {
+ /* Ignore locales without valid countries */
+ }
+ }
+ /*
+ * If we get this far, the code is not supported by any of
+ * our locales.
+ */
+ throw new IllegalArgumentException("The currency code, " + currencyCode +
+ ", is not supported.");
+ }
+ else
+ {
+ return newCurrency;
+ }
+ }
+
+ /**
+ * This method returns the symbol which precedes or follows a
+ * value in this particular currency in the default locale.
+ * In cases where there is no such symbol for the currency,
+ * the ISO 4217 currency code is returned.
+ *
+ * @return the currency symbol, or the ISO 4217 currency code if
+ * one doesn't exist.
+ */
+ public String getSymbol()
+ {
+ return getSymbol(Locale.getDefault());
+ }
+
+ /**
+ * <p>
+ * This method returns the symbol which precedes or follows a
+ * value in this particular currency. The returned value is
+ * the symbol used to denote the currency in the specified locale.
+ * </p>
+ * <p>
+ * For example, a supplied locale may specify a different symbol
+ * for the currency, due to conflicts with its own currency.
+ * This would be the case with the American currency, the dollar.
+ * Locales that also use a dollar-based currency (e.g. Canada, Australia)
+ * need to differentiate the American dollar using 'US$' rather than '$'.
+ * So, supplying one of these locales to <code>getSymbol()</code> would
+ * return this value, rather than the standard '$'.
+ * </p>
+ * <p>
+ * In cases where there is no such symbol for a particular currency,
+ * the ISO 4217 currency code is returned.
+ * </p>
+ *
+ * @param locale the locale to express the symbol in.
+ * @return the currency symbol, or the ISO 4217 currency code if
+ * one doesn't exist.
+ * @throws NullPointerException if the locale is null.
+ */
+ public String getSymbol(Locale locale)
+ {
+ return LocaleHelper.getLocalizedString(locale, currencyCode,
+ "currenciesSymbol", false, true);
+ }
+
+ /**
+ * Returns the international ISO4217 currency code of this currency.
+ *
+ * @return a <code>String</code> containing the ISO4217 currency code.
+ */
+ public String toString()
+ {
+ return getCurrencyCode();
+ }
+
+ /**
+ * Resolves the deserialized object to the singleton instance for its
+ * particular currency. The currency code of the deserialized instance
+ * is used to return the correct instance.
+ *
+ * @return the singleton instance for the currency specified by the
+ * currency code of the deserialized object. This replaces
+ * the deserialized object as the returned object from
+ * deserialization.
+ * @throws ObjectStreamException if a problem occurs with deserializing
+ * the object.
+ */
+ private Object readResolve()
+ throws ObjectStreamException
+ {
+ return getInstance(currencyCode);
+ }
+
+}
diff --git a/libjava/classpath/java/util/Date.java b/libjava/classpath/java/util/Date.java
new file mode 100644
index 00000000000..aecca29b39e
--- /dev/null
+++ b/libjava/classpath/java/util/Date.java
@@ -0,0 +1,1263 @@
+/* java.util.Date
+ Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+/**
+ * <p>
+ * This class represents a specific time in milliseconds since the epoch.
+ * The epoch is 1970, January 1 00:00:00.0000 UTC.
+ * </p>
+ * <p>
+ * <code>Date</code> is intended to reflect universal time coordinate (UTC),
+ * but this depends on the underlying host environment. Most operating systems
+ * don't handle the leap second, which occurs about once every year or
+ * so. The leap second is added to the last minute of the day on either
+ * the 30th of June or the 31st of December, creating a minute 61 seconds
+ * in length.
+ * </p>
+ * <p>
+ * The representations of the date fields are as follows:
+ * <ul>
+ * <li>
+ * Years are specified as the difference between the year
+ * and 1900. Thus, the final year used is equal to
+ * 1900 + y, where y is the input value.
+ * </li>
+ * <li>
+ * Months are represented using zero-based indexing,
+ * making 0 January and 11 December.
+ * </li>
+ * <li>
+ * Dates are represented with the usual values of
+ * 1 through to 31.
+ * </li>
+ * <li>
+ * Hours are represented in the twenty-four hour clock,
+ * with integer values from 0 to 23. 12am is 0, and
+ * 12pm is 12.
+ * </li>
+ * <li>
+ * Minutes are again as usual, with values from 0 to 59.
+ * </li>
+ * <li>
+ * Seconds are represented with the values 0 through to 61,
+ * with 60 and 61 being leap seconds (as per the ISO C standard).
+ * </li>
+ * </ul>
+ * </p>
+ * <p>
+ * Prior to JDK 1.1, this class was the sole class handling date and time
+ * related functionality. However, this particular solution was not
+ * amenable to internationalization. The new <code>Calendar</code>
+ * class should now be used to handle dates and times, with <code>Date</code>
+ * being used only for values in milliseconds since the epoch. The
+ * <code>Calendar</code> class, and its concrete implementations, handle
+ * the interpretation of these values into minutes, hours, days, months
+ * and years. The formatting and parsing of dates is left to the
+ * <code>DateFormat</code> class, which is able to handle the different
+ * types of date format which occur in different locales.
+ * </p>
+ *
+ * @see Calendar
+ * @see GregorianCalendar
+ * @see java.text.DateFormat
+ * @author Jochen Hoenicke
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class Date
+ implements Cloneable, Comparable, Serializable
+{
+ /**
+ * This is the serialization UID for this class
+ * for compatability with Sun's JDK.
+ */
+ private static final long serialVersionUID = 7523967970034938905L;
+
+ /**
+ * The time in milliseconds since the epoch.
+ */
+ private transient long time;
+
+ /**
+ * An array of week names used to map names to integer values.
+ */
+ private static final String[] weekNames = { "Sun", "Mon", "Tue", "Wed",
+ "Thu", "Fri", "Sat" };
+ /**
+ * An array of month names used to map names to integer values.
+ */
+ private static final String[] monthNames = { "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec" };
+ /**
+ * Creates a new Date Object representing the current time.
+ */
+ public Date()
+ {
+ time = System.currentTimeMillis();
+ }
+
+ /**
+ * Creates a new Date Object representing the given time.
+ *
+ * @param time the time in milliseconds since the epoch.
+ */
+ public Date(long time)
+ {
+ this.time = time;
+ }
+
+ /**
+ * Creates a new Date Object representing the given time.
+ *
+ * @deprecated use <code>new GregorianCalendar(year+1900, month,
+ * day)</code> instead.
+ * @param year the difference between the required year and 1900.
+ * @param month the month as a value between 0 and 11.
+ * @param day the day as a value between 0 and 31.
+ */
+ public Date(int year, int month, int day)
+ {
+ this(year, month, day, 0, 0, 0);
+ }
+
+ /**
+ * Creates a new Date Object representing the given time.
+ *
+ * @deprecated use <code>new GregorianCalendar(year+1900, month,
+ * day, hour, min)</code> instead.
+ * @param year the difference between the required year and 1900.
+ * @param month the month as a value between 0 and 11.
+ * @param day the day as a value between 0 and 31.
+ * @param hour the hour as a value between 0 and 23, in 24-hour
+ * clock notation.
+ * @param min the minute as a value between 0 and 59.
+ */
+ public Date(int year, int month, int day, int hour, int min)
+ {
+ this(year, month, day, hour, min, 0);
+ }
+
+ /**
+ * Creates a new Date Object representing the given time.
+ *
+ * @deprecated use <code>new GregorianCalendar(year+1900, month,
+ * day, hour, min, sec)</code> instead.
+ * @param year the difference between the required year and 1900.
+ * @param month the month as a value between 0 and 11.
+ * @param day the day as a value between 0 and 31.
+ * @param hour the hour as a value between 0 and 23, in 24-hour
+ * clock notation.
+ * @param min the minute as a value between 0 and 59.
+ * @param sec the second as a value between 0 and 61 (with 60
+ * and 61 being leap seconds).
+ */
+ public Date(int year, int month, int day, int hour, int min, int sec)
+ {
+ GregorianCalendar cal =
+ new GregorianCalendar(year + 1900, month, day, hour, min, sec);
+ time = cal.getTimeInMillis();
+ }
+
+ /**
+ * Creates a new Date from the given string representation. This
+ * does the same as <code>new Date(Date.parse(s))</code>
+ * @see #parse
+ * @deprecated use <code>java.text.DateFormat.parse(s)</code> instead.
+ */
+ public Date(String s)
+ {
+ time = parse(s);
+ }
+
+ /**
+ * Returns a copy of this <code>Date</code> object.
+ *
+ * @return a copy, or null if the object couldn't be
+ * cloned.
+ * @see Object#clone()
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the number of milliseconds since the epoch
+ * specified by the given arguments. The arguments are
+ * interpreted relative to UTC rather than the local
+ * time zone.
+ *
+ * @deprecated Use <code>Calendar</code> with a UTC
+ * <code>TimeZone</code> instead.
+ * @param year the difference between the required year and 1900.
+ * @param month the month as a value between 0 and 11.
+ * @param date the day as a value between 0 and 31.
+ * @param hrs the hour as a value between 0 and 23, in 24-hour
+ * clock notation.
+ * @param min the minute as a value between 0 and 59.
+ * @param sec the second as a value between 0 and 61 (with 60
+ * and 61 being leap seconds).
+ * @return the time in milliseconds since the epoch.
+ */
+ public static long UTC(int year, int month, int date,
+ int hrs, int min, int sec)
+ {
+ GregorianCalendar cal =
+ new GregorianCalendar(year + 1900, month, date, hrs, min, sec);
+ cal.set(Calendar.ZONE_OFFSET, 0);
+ cal.set(Calendar.DST_OFFSET, 0);
+ return cal.getTimeInMillis();
+ }
+
+ /**
+ * Gets the time represented by this object.
+ *
+ * @return the time in milliseconds since the epoch.
+ */
+ public long getTime()
+ {
+ return time;
+ }
+
+ /**
+ * Returns the number of minutes offset used with UTC to give the time
+ * represented by this object in the current time zone. The date information
+ * from this object is also used to determine whether or not daylight savings
+ * time is in effect. For example, the offset for the UK would be 0 if the
+ * month of the date object was January, and 1 if the month was August.
+ *
+ * @deprecated use
+ * <code>Calendar.get(Calendar.ZONE_OFFSET)+Calendar.get(Calendar.DST_OFFSET)</code>
+ * instead.
+ * @return The time zone offset in minutes of the local time zone
+ * relative to UTC. The time represented by this object is used to
+ * determine if we should use daylight savings.
+ */
+ public int getTimezoneOffset()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return - (cal.get(Calendar.ZONE_OFFSET)
+ + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
+ }
+
+ /**
+ * Sets the time which this object should represent.
+ *
+ * @param time the time in milliseconds since the epoch.
+ */
+ public void setTime(long time)
+ {
+ this.time = time;
+ }
+
+ /**
+ * Tests if this date is after the specified date.
+ *
+ * @param when the other date
+ * @return true, if the date represented by this object is
+ * strictly later than the time represented by when.
+ */
+ public boolean after(Date when)
+ {
+ return time > when.time;
+ }
+
+ /**
+ * Tests if this date is before the specified date.
+ *
+ * @param when the other date
+ * @return true, if the date represented by when is strictly later
+ * than the time represented by this object.
+ */
+ public boolean before(Date when)
+ {
+ return time < when.time;
+ }
+
+ /**
+ * Compares two dates for equality.
+ *
+ * @param obj the object to compare.
+ * @return true, if obj is a Date object and the time represented
+ * by obj is exactly the same as the time represented by this
+ * object.
+ */
+ public boolean equals(Object obj)
+ {
+ return (obj instanceof Date && time == ((Date) obj).time);
+ }
+
+ /**
+ * Compares two dates.
+ *
+ * @param when the other date.
+ * @return 0, if the date represented
+ * by obj is exactly the same as the time represented by this
+ * object, a negative if this Date is before the other Date, and
+ * a positive value otherwise.
+ */
+ public int compareTo(Date when)
+ {
+ return (time < when.time) ? -1 : (time == when.time) ? 0 : 1;
+ }
+
+ /**
+ * Compares this Date to another object. This behaves like
+ * <code>compareTo(Date)</code>, but it takes a generic object
+ * and throws a <code>ClassCastException</code> if obj is
+ * not a <code>Date</code>.
+ *
+ * @param obj the other date.
+ * @return 0, if the date represented
+ * by obj is exactly the same as the time represented by this
+ * object, a negative if this Date is before the other Date, and
+ * a positive value otherwise.
+ * @exception ClassCastException if obj is not of type Date.
+ */
+ public int compareTo(Object obj)
+ {
+ return compareTo((Date) obj);
+ }
+
+ /**
+ * Computes the hash code of this <code>Date</code> as the
+ * XOR of the most significant and the least significant
+ * 32 bits of the 64 bit milliseconds value.
+ *
+ * @return the hash code.
+ */
+ public int hashCode()
+ {
+ return (int) time ^ (int) (time >>> 32);
+ }
+
+ /**
+ * <p>
+ * Returns a string representation of this date using
+ * the following date format:
+ * </p>
+ * <p>
+ * <code>day mon dd hh:mm:ss zz yyyy</code>
+ * </p>
+ * <p>where the fields used here are:
+ * <ul>
+ * <li>
+ * <code>day</code> -- the day of the week
+ * (Sunday through to Saturday).
+ * </li>
+ * <li>
+ * <code>mon</code> -- the month (Jan to Dec).
+ * </li>
+ * <li>
+ * <code>dd</code> -- the day of the month
+ * as two decimal digits (01 to 31).
+ * </li>
+ * <li>
+ * <code>hh</code> -- the hour of the day
+ * as two decimal digits in 24-hour clock notation
+ * (01 to 23).
+ * </li>
+ * <li>
+ * <code>mm</code> -- the minute of the day
+ * as two decimal digits (01 to 59).
+ * </li>
+ * <li>
+ * <code>ss</code> -- the second of the day
+ * as two decimal digits (01 to 61).
+ * </li>
+ * <li>
+ * <code>zz</code> -- the time zone information if available.
+ * The possible time zones used include the abbreviations
+ * recognised by <code>parse()</code> (e.g. GMT, CET, etc.)
+ * and may reflect the fact that daylight savings time is in
+ * effect. The empty string is used if there is no time zone
+ * information.
+ * </li>
+ * <li>
+ * <code>yyyy</code> -- the year as four decimal digits.
+ * </li>
+ * </ul>
+ * <p>
+ * The <code>DateFormat</code> class should now be
+ * preferred over using this method.
+ * </p>
+ *
+ * @return A string of the form 'day mon dd hh:mm:ss zz yyyy'
+ * @see #parse(String)
+ * @see DateFormat
+ */
+ public String toString()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ String day = "0" + cal.get(Calendar.DATE);
+ String hour = "0" + cal.get(Calendar.HOUR_OF_DAY);
+ String min = "0" + cal.get(Calendar.MINUTE);
+ String sec = "0" + cal.get(Calendar.SECOND);
+ String year = "000" + cal.get(Calendar.YEAR);
+ return weekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " "
+ + monthNames[cal.get(Calendar.MONTH)] + " "
+ + day.substring(day.length() - 2) + " "
+ + hour.substring(hour.length() - 2) + ":"
+ + min.substring(min.length() - 2) + ":"
+ + sec.substring(sec.length() - 2) + " "
+ +
+ cal.getTimeZone().getDisplayName(cal.getTimeZone().inDaylightTime(this),
+ TimeZone.SHORT) + " " +
+ year.substring(year.length() - 4);
+ }
+
+ /**
+ * Returns a locale-dependent string representation of this
+ * <code>Date</code> object.
+ *
+ * @deprecated Use DateFormat.format(Date)
+ * @return A locale-dependent string representation.
+ * @see #parse(String)
+ * @see DateFormat
+ */
+ public String toLocaleString()
+ {
+ return java.text.DateFormat.getInstance().format(this);
+ }
+
+ /**
+ * <p>
+ * Returns a string representation of this <code>Date</code>
+ * object using GMT rather than the local timezone.
+ * The following date format is used:
+ * </p>
+ * <p>
+ * <code>d mon yyyy hh:mm:ss GMT</code>
+ * </p>
+ * <p>where the fields used here are:
+ * <ul>
+ * <li>
+ * <code>d</code> -- the day of the month
+ * as one or two decimal digits (1 to 31).
+ * </li>
+ * <li>
+ * <code>mon</code> -- the month (Jan to Dec).
+ * </li>
+ * <li>
+ * <code>yyyy</code> -- the year as four decimal digits.
+ * </li>
+ * <li>
+ * <code>hh</code> -- the hour of the day
+ * as two decimal digits in 24-hour clock notation
+ * (01 to 23).
+ * </li>
+ * <li>
+ * <code>mm</code> -- the minute of the day
+ * as two decimal digits (01 to 59).
+ * </li>
+ * <li>
+ * <code>ss</code> -- the second of the day
+ * as two decimal digits (01 to 61).
+ * </li>
+ * <li>
+ * <code>GMT</code> -- the literal string "GMT"
+ * indicating Greenwich Mean Time as opposed to
+ * the local timezone.
+ * </li>
+ * </ul>
+ *
+ * @deprecated Use DateFormat.format(Date) with a GMT TimeZone.
+ * @return A string of the form 'd mon yyyy hh:mm:ss GMT' using
+ * GMT as opposed to the local timezone.
+ * @see #parse(String)
+ * @see DateFormat
+ */
+ public String toGMTString()
+ {
+ java.text.DateFormat format = java.text.DateFormat.getInstance();
+ format.setTimeZone(TimeZone.getTimeZone("GMT"));
+ return format.format(this);
+ }
+
+ /**
+ * Parses the time zone string.
+ *
+ * @param tok The token containing the time zone.
+ * @param sign The sign (+ or -) used by the time zone.
+ * @return An integer representing the number of minutes offset
+ * from GMT for the time zone.
+ */
+ private static int parseTz(String tok, char sign)
+ throws IllegalArgumentException
+ {
+ int num;
+
+ try
+ {
+ // parseInt doesn't handle '+' so strip off sign.
+ num = Integer.parseInt(tok.substring(1));
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new IllegalArgumentException(tok);
+ }
+
+ // Convert hours to minutes.
+ if (num < 24)
+ num *= 60;
+ else
+ num = (num / 100) * 60 + num % 100;
+
+ return sign == '-' ? -num : num;
+ }
+
+ /**
+ * Parses the month string.
+ *
+ * @param tok the token containing the month.
+ * @return An integer between 0 and 11, representing
+ * a month from January (0) to December (11),
+ * or -1 if parsing failed.
+ */
+ private static int parseMonth(String tok)
+ {
+ // Initialize strings for month names.
+ // We could possibly use the fields of DateFormatSymbols but that is
+ // localized and thus might not match the English words specified.
+ String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
+ "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
+ "NOVEMBER", "DECEMBER" };
+
+ int i;
+ for (i = 0; i < 12; i++)
+ if (months[i].startsWith(tok))
+ return i;
+
+ // Return -1 if not found.
+ return -1;
+ }
+
+ /**
+ * Parses the day of the week string.
+ *
+ * @param tok the token containing the day of the week.
+ * @return true if the token was parsed successfully.
+ */
+ private static boolean parseDayOfWeek(String tok)
+ {
+ // Initialize strings for days of the week names.
+ // We could possibly use the fields of DateFormatSymbols but that is
+ // localized and thus might not match the English words specified.
+ String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
+ "THURSDAY", "FRIDAY", "SATURDAY" };
+
+ int i;
+ for (i = 0; i < 7; i++)
+ if (daysOfWeek[i].startsWith(tok))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * <p>
+ * Parses a String and returns the time, in milliseconds since the
+ * epoch, it represents. Most syntaxes are handled, including
+ * the IETF date standard "day, dd mon yyyy hh:mm:ss zz" (see
+ * <code>toString()</code> for definitions of these fields).
+ * Standard U.S. time zone abbreviations are recognised, in
+ * addition to time zone offsets in positive or negative minutes.
+ * If a time zone is specified, the specified time is assumed to
+ * be in UTC and the appropriate conversion is applied, following
+ * parsing, to convert this to the local time zone. If no zone
+ * is specified, the time is assumed to already be in the local
+ * time zone.
+ * </p>
+ * <p>
+ * The method parses the string progressively from left to right.
+ * At the end of the parsing process, either a time is returned
+ * or an <code>IllegalArgumentException</code> is thrown to signify
+ * failure. The ASCII characters A-Z, a-z, 0-9, and ',', '+', '-',
+ * ':' and '/' are the only characters permitted within the string,
+ * besides whitespace and characters enclosed within parantheses
+ * '(' and ')'.
+ * </p>
+ * <p>
+ * A sequence of consecutive digits are recognised as a number,
+ * and interpreted as follows:
+ * <ul>
+ * <li>
+ * A number preceded by a sign (+ or -) is taken to be a time zone
+ * offset. The time zone offset can be specified in either hours
+ * or minutes. The former is assumed if the number is less than 24.
+ * Otherwise, the offset is assumed to be in minutes. A - indicates
+ * a time zone west of GMT, while a + represents a time zone to the
+ * east of GMT. The time zones are always assumed to be relative
+ * to GMT, and a (redundant) specification of this can be included
+ * with the time zone. For example, '-9', 'utc-9' and 'GMT-9' all
+ * represent a time zone nine hours west of GMT. Similarly,
+ * '+4', 'ut+4' and 'UTC+4' all give 4 hours east of GMT.
+ * </li>
+ * <li>
+ * A number equal to or greater than 70 is regarded as a year specification.
+ * Values lower than 70 are only assumed to indicate a year if both the
+ * day of the month and the month itself have already been recognised.
+ * Year values less than 100 are interpreted as being relative to the current
+ * century when the <code>Date</code> class is initialised.. Given a century,
+ * x, the year is assumed to be within the range x - 80 to x + 19. The value
+ * itself is then used as a match against the two last digits of one of these
+ * years. For example, take x to be 2004. A two-digit year is assumed to fall
+ * within the range x - 80 (1924) and x + 19 (2023). Thus, any intepreted value
+ * between 0 and 23 is assumed to be 2000 to 2023 and values between 24 and 99
+ * are taken as being 1924 to 1999. This only applies for the case of 2004.
+ * With a different year, the values will be interpreted differently. 2005
+ * will used 0 to 24 as 2000 to 2024 and 25 to 99 as 1925 to 1999, for example.
+ * This behaviour differs from that of <code>SimpleDateFormat</code> and is
+ * time-dependent (a two-digit year will be interpreted differently depending
+ * on the time the code is run).
+ * </li>
+ * <li>
+ * Numbers followed by a colon are interpreted by first an hour, and then
+ * as a minute, once an hour has been found.
+ * </li>
+ * <li>
+ * <li>
+ * Numbers followed by a slash are regarded first as a month, and then as
+ * a day of the month once the month has been found. This follows the
+ * U.S. date format of mm/dd, rather than the European dd/mm. Months
+ * are converted to the recognised value - 1 before storage, in order
+ * to put the number within the range 0 to 11.
+ * </li>
+ * <li>
+ * Numbers followed by commas, whitespace, hyphens or the end of the string
+ * are interpreted in the following order: hour, minute, second, day of month.
+ * The first type not already recognised in the current string being parsed is
+ * assumed.
+ * </li>
+ * </ul>
+ * </p>
+ * <p>
+ * A sequence of consecutive alphabetic characters is recognised as a word,
+ * and interpreted as follows, in a case-insentive fashion:
+ * <ul>
+ * <li>
+ * The characters 'AM' or 'PM' restrict the hour value to a value between 0
+ * and 12. In the latter case, 12 is added to the hour value before storage.
+ * </li>
+ * <li>
+ * Any words which match any prefix of one of the days of the week ('Monday',
+ * 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' and 'Sunday'),
+ * are simply ignored.
+ * </li>
+ * <li>
+ * Any words which match any prefix of one of the months of the year ('January',
+ * 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September',
+ * 'October', 'November', 'December') are recognised and interpreted as the
+ * appropriate value between 0 and 11. The first match made against a
+ * month is the one used, in the order specified here. For example, 'Ma' is
+ * intepreted as 'March' (2) and not as 'May' (4). Similarly, 'Ju' is 'June',
+ * and not 'July'.
+ * </li>
+ * <li>
+ * The words 'GMT', 'UT' and 'UTC' are interpreted as specifying UTC as the
+ * time zone in use for this date.
+ * </li>
+ * <li>
+ * The word pairs 'EST'/'EDT', 'CST'/'CDT', 'MST'/'MDT' and 'PST'/'PDT' are
+ * interpreted as the appropriate U.S. time zone abbreviation. Each pair
+ * is the standard and daylight savings time zone specification, respectively,
+ * for each zone within the U.S, these being Eastern Standard/Daylight Time
+ * (-5), Central Standard/Daylight Time (-6), Mountain Standard/Daylight Time
+ * (-7) and Pacific Standard/Daylight Time (-8).
+ * </li>
+ * </ul>
+ *
+ * @param string The String to parse.
+ * @return The time in milliseconds since the epoch.
+ * @throws IllegalArgumentException if the string fails to parse.
+ * @deprecated Use DateFormat.parse(String)
+ * @see #toString()
+ * @see SimpleDateFormat
+ */
+ public static long parse(String string)
+ {
+ // Initialize date/time fields before parsing begins.
+ int year = -1;
+ int month = -1;
+ int day = -1;
+ int hour = -1;
+ int minute = -1;
+ int second = -1;
+ int timezone = 0;
+ boolean localTimezone = true;
+
+ // Trim out any nested stuff in parentheses now to make parsing easier.
+ StringBuffer buf = new StringBuffer();
+ int parenNesting = 0;
+ int len = string.length();
+ for (int i = 0; i < len; i++)
+ {
+ char ch = string.charAt(i);
+ if (ch >= 'a' && ch <= 'z')
+ ch -= 'a' - 'A';
+ if (ch == '(')
+ parenNesting++;
+ else if (parenNesting == 0)
+ buf.append(ch);
+ else if (ch == ')')
+ parenNesting--;
+ }
+ int tmpMonth;
+
+ // Make all chars upper case to simplify comparisons later.
+ // Also ignore commas; treat them as delimiters.
+ StringTokenizer strtok = new StringTokenizer(buf.toString(), " \t\n\r,");
+
+ while (strtok.hasMoreTokens())
+ {
+ String tok = strtok.nextToken();
+ char firstch = tok.charAt(0);
+ if ((firstch == '+' || firstch == '-') && year >= 0)
+ {
+ timezone = parseTz(tok, firstch);
+ localTimezone = false;
+ }
+ else if (firstch >= '0' && firstch <= '9')
+ {
+ while (tok != null && tok.length() > 0)
+ {
+ int punctOffset = tok.length();
+ int num = 0;
+ int punct;
+ for (int i = 0; ; i++)
+ {
+ if (i >= punctOffset)
+ {
+ punct = -1;
+ break;
+ }
+ else
+ {
+ punct = tok.charAt(i);
+ if (punct >= '0' && punct <= '9')
+ {
+ if (num > 999999999) // in case of overflow
+ throw new IllegalArgumentException(tok);
+ num = 10 * num + (punct - '0');
+ }
+ else
+ {
+ punctOffset = i;
+ break;
+ }
+ }
+
+ }
+
+ if (punct == ':')
+ {
+ if (hour < 0)
+ hour = num;
+ else
+ minute = num;
+ }
+ else if ((num >= 70
+ && (punct == ' ' || punct == ','
+ || punct == '/' || punct < 0))
+ || (num < 70 && day >= 0 && month >= 0 && year < 0))
+ {
+ if (num >= 100)
+ year = num;
+ else
+ {
+ int curYear = 1900 + new Date().getYear();
+ int firstYear = curYear - 80;
+ year = firstYear / 100 * 100 + num;
+ if (year < firstYear)
+ year += 100;
+ }
+ }
+ else if (punct == '/')
+ {
+ if (month < 0)
+ month = num - 1;
+ else
+ day = num;
+ }
+ else if (hour >= 0 && minute < 0)
+ minute = num;
+ else if (minute >= 0 && second < 0)
+ second = num;
+ else if (day < 0)
+ day = num;
+ else
+ throw new IllegalArgumentException(tok);
+
+ // Advance string if there's more to process in this token.
+ if (punct < 0 || punctOffset + 1 >= tok.length())
+ tok = null;
+ else
+ tok = tok.substring(punctOffset + 1);
+ }
+ }
+ else if (firstch >= 'A' && firstch <= 'Z')
+ {
+ if (tok.equals("AM"))
+ {
+ if (hour < 1 || hour > 12)
+ throw new IllegalArgumentException(tok);
+ if (hour == 12)
+ hour = 0;
+ }
+ else if (tok.equals("PM"))
+ {
+ if (hour < 1 || hour > 12)
+ throw new IllegalArgumentException(tok);
+ if (hour < 12)
+ hour += 12;
+ }
+ else if (parseDayOfWeek(tok))
+ ; // Ignore it; throw the token away.
+ else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
+ localTimezone = false;
+ else if (tok.startsWith("UT") || tok.startsWith("GMT"))
+ {
+ int signOffset = 3;
+ if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
+ signOffset = 2;
+
+ char sign = tok.charAt(signOffset);
+ if (sign != '+' && sign != '-')
+ throw new IllegalArgumentException(tok);
+
+ timezone = parseTz(tok.substring(signOffset), sign);
+ localTimezone = false;
+ }
+ else if ((tmpMonth = parseMonth(tok)) >= 0)
+ month = tmpMonth;
+ else if (tok.length() == 3 && tok.charAt(2) == 'T')
+ {
+ // Convert timezone offset from hours to minutes.
+ char ch = tok.charAt(0);
+ if (ch == 'E')
+ timezone = -5 * 60;
+ else if (ch == 'C')
+ timezone = -6 * 60;
+ else if (ch == 'M')
+ timezone = -7 * 60;
+ else if (ch == 'P')
+ timezone = -8 * 60;
+ else
+ throw new IllegalArgumentException(tok);
+
+ // Shift 60 minutes for Daylight Savings Time.
+ if (tok.charAt(1) == 'D')
+ timezone += 60;
+ else if (tok.charAt(1) != 'S')
+ throw new IllegalArgumentException(tok);
+
+ localTimezone = false;
+ }
+ else
+ throw new IllegalArgumentException(tok);
+ }
+ else
+ throw new IllegalArgumentException(tok);
+ }
+
+ // Unspecified hours, minutes, or seconds should default to 0.
+ if (hour < 0)
+ hour = 0;
+ if (minute < 0)
+ minute = 0;
+ if (second < 0)
+ second = 0;
+
+ // Throw exception if any other fields have not been recognized and set.
+ if (year < 0 || month < 0 || day < 0)
+ throw new IllegalArgumentException("Missing field");
+
+ // Return the time in either local time or relative to GMT as parsed.
+ // If no time-zone was specified, get the local one (in minutes) and
+ // convert to milliseconds before adding to the UTC.
+ GregorianCalendar cal
+ = new GregorianCalendar(year, month, day, hour, minute, second);
+ if (!localTimezone)
+ {
+ cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000);
+ cal.set(Calendar.DST_OFFSET, 0);
+ }
+ return cal.getTimeInMillis();
+ }
+
+ /**
+ * Returns the difference between the year represented by this
+ * <code>Date</code> object and 1900.
+ *
+ * @return the year minus 1900 represented by this date object.
+ * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR)
+ * instead. Note the 1900 difference in the year.
+ * @see Calendar
+ * @see #setYear(int)
+ */
+ public int getYear()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return cal.get(Calendar.YEAR) - 1900;
+ }
+
+ /**
+ * Sets the year to the specified year, plus 1900. The other
+ * fields are only altered as required to match the same date
+ * and time in the new year. Usually, this will mean that
+ * the fields are not changed at all, but in the case of
+ * a leap day or leap second, the fields will change in
+ * relation to the existence of such an event in the new year.
+ * For example, if the date specifies February the 29th, 2000,
+ * then this will become March the 1st if the year is changed
+ * to 2001, as 2001 is not a leap year. Similarly, a seconds
+ * value of 60 or 61 may result in the seconds becoming 0 and
+ * the minute increasing by 1, if the new time does not include
+ * a leap second.
+ *
+ * @param year the year minus 1900.
+ * @deprecated Use Calendar instead of Date, and use
+ * set(Calendar.YEAR, year) instead. Note about the 1900
+ * difference in year.
+ * @see #getYear()
+ * @see Calendar
+ */
+ public void setYear(int year)
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ cal.set(Calendar.YEAR, 1900 + year);
+ time = cal.getTimeInMillis();
+ }
+
+ /**
+ * Returns the month represented by this <code>Date</code> object,
+ * as a value between 0 (January) and 11 (December).
+ *
+ * @return the month represented by this date object (zero based).
+ * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH)
+ * instead.
+ * @see #setMonth(int)
+ * @see Calendar
+ */
+ public int getMonth()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return cal.get(Calendar.MONTH);
+ }
+
+ /**
+ * Sets the month to the given value. The other
+ * fields are only altered as necessary to match
+ * the same date and time in the new month. In most
+ * cases, the other fields won't change at all. However,
+ * in the case of a shorter month or a leap second, values
+ * may be adjusted. For example, if the day of the month
+ * is currently 31, and the month value is changed from
+ * January (0) to September (8), the date will become
+ * October the 1st, as September only has 30 days. Similarly,
+ * a seconds value of 60 or 61 (a leap second) may result
+ * in the seconds value being reset to 0 and the minutes
+ * value being incremented by 1, if the new time does
+ * not include a leap second.
+ *
+ * @param month the month, with a zero-based index
+ * from January.
+ * @deprecated Use Calendar instead of Date, and use
+ * set(Calendar.MONTH, month) instead.
+ * @see #getMonth()
+ * @see Calendar
+ */
+ public void setMonth(int month)
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ cal.set(Calendar.MONTH, month);
+ time = cal.getTimeInMillis();
+ }
+
+ /**
+ * Returns the day of the month of this <code>Date</code>
+ * object, as a value between 0 and 31.
+ *
+ * @return the day of month represented by this date object.
+ * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE)
+ * instead.
+ * @see Calendar
+ * @see #setDate(int)
+ */
+ public int getDate()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return cal.get(Calendar.DATE);
+ }
+
+ /**
+ * Sets the date to the given value. The other
+ * fields are only altered as necessary to match
+ * the same date and time on the new day of the month. In most
+ * cases, the other fields won't change at all. However,
+ * in the case of a leap second or the day being out of
+ * the range of the current month, values
+ * may be adjusted. For example, if the day of the month
+ * is currently 30 and the month is June, a new day of the
+ * month value of 31 will cause the month to change to July,
+ * as June only has 30 days . Similarly,
+ * a seconds value of 60 or 61 (a leap second) may result
+ * in the seconds value being reset to 0 and the minutes
+ * value being incremented by 1, if the new time does
+ * not include a leap second.
+ *
+ * @param date the date.
+ * @deprecated Use Calendar instead of Date, and use
+ * set(Calendar.DATE, date) instead.
+ * @see Calendar
+ * @see #getDate()
+ */
+ public void setDate(int date)
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ cal.set(Calendar.DATE, date);
+ time = cal.getTimeInMillis();
+ }
+
+ /**
+ * Returns the day represented by this <code>Date</code>
+ * object as an integer between 0 (Sunday) and 6 (Saturday).
+ *
+ * @return the day represented by this date object.
+ * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK)
+ * instead.
+ * @see Calendar
+ */
+ public int getDay()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ // For Calendar, Sunday is 1. For Date, Sunday is 0.
+ return cal.get(Calendar.DAY_OF_WEEK) - 1;
+ }
+
+ /**
+ * Returns the hours represented by this <code>Date</code>
+ * object as an integer between 0 and 23.
+ *
+ * @return the hours represented by this date object.
+ * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY)
+ * instead.
+ * @see Calendar
+ * @see #setHours(int)
+ */
+ public int getHours()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return cal.get(Calendar.HOUR_OF_DAY);
+ }
+
+ /**
+ * Sets the hours to the given value. The other
+ * fields are only altered as necessary to match
+ * the same date and time in the new hour. In most
+ * cases, the other fields won't change at all. However,
+ * in the case of a leap second, values
+ * may be adjusted. For example,
+ * a seconds value of 60 or 61 (a leap second) may result
+ * in the seconds value being reset to 0 and the minutes
+ * value being incremented by 1 if the new hour does
+ * not contain a leap second.
+ *
+ * @param hours the hours.
+ * @deprecated Use Calendar instead of Date, and use
+ * set(Calendar.HOUR_OF_DAY, hours) instead.
+ * @see Calendar
+ * @see #getHours()
+ */
+ public void setHours(int hours)
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ cal.set(Calendar.HOUR_OF_DAY, hours);
+ time = cal.getTimeInMillis();
+ }
+
+ /**
+ * Returns the number of minutes represented by the <code>Date</code>
+ * object, as an integer between 0 and 59.
+ *
+ * @return the minutes represented by this date object.
+ * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE)
+ * instead.
+ * @see Calendar
+ * @see #setMinutes(int)
+ */
+ public int getMinutes()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return cal.get(Calendar.MINUTE);
+ }
+
+ /**
+ * Sets the minutes to the given value. The other
+ * fields are only altered as necessary to match
+ * the same date and time in the new minute. In most
+ * cases, the other fields won't change at all. However,
+ * in the case of a leap second, values
+ * may be adjusted. For example,
+ * a seconds value of 60 or 61 (a leap second) may result
+ * in the seconds value being reset to 0 and the minutes
+ * value being incremented by 1 if the new minute does
+ * not contain a leap second.
+ *
+ * @param minutes the minutes.
+ * @deprecated Use Calendar instead of Date, and use
+ * set(Calendar.MINUTE, minutes) instead.
+ * @see Calendar
+ * @see #getMinutes()
+ */
+ public void setMinutes(int minutes)
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ cal.set(Calendar.MINUTE, minutes);
+ time = cal.getTimeInMillis();
+ }
+
+ /**
+ * Returns the number of seconds represented by the <code>Date</code>
+ * object, as an integer between 0 and 61 (60 and 61 being leap seconds).
+ *
+ * @return the seconds represented by this date object.
+ * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND)
+ * instead.
+ * @see Calendar
+ * @see #setSeconds(int)
+ */
+ public int getSeconds()
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return cal.get(Calendar.SECOND);
+ }
+
+ /**
+ * Sets the seconds to the given value. The other
+ * fields are only altered as necessary to match
+ * the same date and time in the new minute. In most
+ * cases, the other fields won't change at all. However,
+ * in the case of a leap second, values
+ * may be adjusted. For example, setting the
+ * seconds value to 60 or 61 (a leap second) may result
+ * in the seconds value being reset to 0 and the minutes
+ * value being incremented by 1, if the current time does
+ * not contain a leap second.
+ *
+ * @param seconds the seconds.
+ * @deprecated Use Calendar instead of Date, and use
+ * set(Calendar.SECOND, seconds) instead.
+ * @see Calendar
+ * @see #getSeconds()
+ */
+ public void setSeconds(int seconds)
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ cal.set(Calendar.SECOND, seconds);
+ time = cal.getTimeInMillis();
+ }
+
+ /**
+ * Deserializes a <code>Date</code> object from an
+ * input stream, setting the time (in milliseconds
+ * since the epoch) to the long value read from the
+ * stream.
+ *
+ * @param input the input stream.
+ * @throws IOException if an I/O error occurs in the stream.
+ * @throws ClassNotFoundException if the class of the
+ * serialized object could not be found.
+ */
+ private void readObject(ObjectInputStream input)
+ throws IOException, ClassNotFoundException
+ {
+ input.defaultReadObject();
+ time = input.readLong();
+ }
+
+ /**
+ * Serializes a <code>Date</code> object to an output stream,
+ * storing the time (in milliseconds since the epoch) as a long
+ * value in the stream.
+ *
+ * @serialdata A long value representing the offset from the epoch
+ * in milliseconds. This is the same value that is returned by the
+ * method getTime().
+ * @param output the output stream.
+ * @throws IOException if an I/O error occurs in the stream.
+ */
+ private void writeObject(ObjectOutputStream output)
+ throws IOException
+ {
+ output.defaultWriteObject();
+ output.writeLong(time);
+ }
+
+}
diff --git a/libjava/classpath/java/util/Dictionary.java b/libjava/classpath/java/util/Dictionary.java
new file mode 100644
index 00000000000..0d44ab67de1
--- /dev/null
+++ b/libjava/classpath/java/util/Dictionary.java
@@ -0,0 +1,136 @@
+/* Dictionary.java -- an abstract (and essentially worthless)
+ class which is Hashtable's superclass
+ Copyright (C) 1998, 2001, 2002 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;
+
+/**
+ * A Dictionary maps keys to values; <i>how</i> it does that is
+ * implementation-specific.
+ *
+ * This is an abstract class which has really gone by the wayside.
+ * People at Javasoft are probably embarrassed by it. At this point,
+ * it might as well be an interface rather than a class, but it remains
+ * this poor, laughable skeleton for the sake of backwards compatibility.
+ * At any rate, this was what came before the {@link Map} interface
+ * in the Collections framework.
+ *
+ * @author Jon Zeppieri
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Map
+ * @see Hashtable
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class Dictionary
+{
+ // WARNING: Dictionary is a CORE class in the bootstrap cycle. See the
+ // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+ /**
+ * Sole constructor (often called implicitly).
+ */
+ public Dictionary()
+ {
+ }
+
+ /**
+ * Returns an Enumeration of the values in this Dictionary.
+ *
+ * @return an Enumeration of the values
+ * @see #keys()
+ */
+ public abstract Enumeration elements();
+
+ /**
+ * Returns the value associated with the supplied key, or null
+ * if no such value exists. Since Dictionaries are not allowed null keys
+ * or elements, a null result always means the key is not present.
+ *
+ * @param key the key to use to fetch the value
+ * @return the mapped value
+ * @throws NullPointerException if key is null
+ * @see #put(Object, Object)
+ */
+ public abstract Object get(Object key);
+
+ /**
+ * Returns true when there are no elements in this Dictionary.
+ *
+ * @return <code>size() == 0</code>
+ */
+ public abstract boolean isEmpty();
+
+ /**
+ * Returns an Enumeration of the keys in this Dictionary
+ *
+ * @return an Enumeration of the keys
+ * @see #elements()
+ */
+ public abstract Enumeration keys();
+
+ /**
+ * Inserts a new value into this Dictionary, located by the
+ * supplied key. Dictionary does not support null keys or values, so
+ * a null return can safely be interpreted as adding a new key.
+ *
+ * @param key the key which locates the value
+ * @param value the value to put into the Dictionary
+ * @return the previous value of the key, or null if there was none
+ * @throws NullPointerException if key or value is null
+ * @see #get(Object)
+ */
+ public abstract Object put(Object key, Object value);
+
+ /**
+ * Removes from the Dictionary the value located by the given key. A null
+ * return safely means that the key was not mapped in the Dictionary.
+ *
+ * @param key the key used to locate the value to be removed
+ * @return the value associated with the removed key
+ * @throws NullPointerException if key is null
+ */
+ public abstract Object remove(Object key);
+
+ /**
+ * Returns the number of values currently in this Dictionary.
+ *
+ * @return the number of keys in the Dictionary
+ */
+ public abstract int size();
+} // class Dictionary
diff --git a/libjava/classpath/java/util/EmptyStackException.java b/libjava/classpath/java/util/EmptyStackException.java
new file mode 100644
index 00000000000..e8b4509ee5c
--- /dev/null
+++ b/libjava/classpath/java/util/EmptyStackException.java
@@ -0,0 +1,69 @@
+/* EmptyStackException.java -- Attempt to pop from an empty stack
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ */
+
+/**
+ * This exception is thrown by the Stack class when an attempt is made to pop
+ * or otherwise access elements from an empty stack.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Stack
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class EmptyStackException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0.
+ */
+ private static final long serialVersionUID = 5084686378493302095L;
+
+ /**
+ * Constructs an EmptyStackException with no detail message.
+ */
+ public EmptyStackException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/util/Enumeration.java b/libjava/classpath/java/util/Enumeration.java
new file mode 100644
index 00000000000..1365bbb2f0f
--- /dev/null
+++ b/libjava/classpath/java/util/Enumeration.java
@@ -0,0 +1,81 @@
+/* Enumeration.java -- Interface for enumerating lists of objects
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1.
+ * Status: Believed complete and correct
+ */
+
+/**
+ * Interface for lists of objects that can be returned in sequence. Successive
+ * objects are obtained by the nextElement method.
+ * <p>
+ * As of Java 1.2, the Iterator interface provides the same functionality, but
+ * with shorter method names and a new optional method to remove items from the
+ * list. If writing for 1.2, consider using Iterator instead. Enumerations over
+ * the new collections classes, for use with legacy APIs that require them, can
+ * be obtained by the enumeration method in class Collections.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Iterator
+ * @see Hashtable
+ * @see Vector
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface Enumeration
+{
+ /**
+ * Tests whether there are elements remaining in the enumeration.
+ *
+ * @return true if there is at least one more element in the enumeration,
+ * that is, if the next call to nextElement will not throw a
+ * NoSuchElementException.
+ */
+ boolean hasMoreElements();
+
+ /**
+ * Obtain the next element in the enumeration.
+ *
+ * @return the next element in the enumeration
+ * @throws NoSuchElementException if there are no more elements
+ */
+ Object nextElement();
+}
diff --git a/libjava/classpath/java/util/EventListener.java b/libjava/classpath/java/util/EventListener.java
new file mode 100644
index 00000000000..c9a1795f900
--- /dev/null
+++ b/libjava/classpath/java/util/EventListener.java
@@ -0,0 +1,54 @@
+/* EventListener.java -- tagging interface for all event listeners
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Empty interface that is implemented by classes that need to receive
+ * events. Subinterfaces define methods that can be called to fire an
+ * event notification. Normally the name of these subinterfaces end in
+ * <code>Listener</code> and all method described by the subinterface
+ * take as argument an subclass of <code>EventObject</code>.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see EventObject
+ * @status updated to 1.4
+ */
+public interface EventListener
+{
+}
diff --git a/libjava/classpath/java/util/EventListenerProxy.java b/libjava/classpath/java/util/EventListenerProxy.java
new file mode 100644
index 00000000000..245c5ffb458
--- /dev/null
+++ b/libjava/classpath/java/util/EventListenerProxy.java
@@ -0,0 +1,75 @@
+/* EventListenerProxy.java -- abstract wrapper for event listeners
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An abstract wrapper for event listeners. This allows subclasses to
+ * attach additional parameters to an existing event listener to create
+ * a new one. Subclasses are expected to add methods to set and retrieve
+ * any attached properties.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class EventListenerProxy implements EventListener
+{
+ /** The listener that this proxy wraps. */
+ private final EventListener listener;
+
+ /**
+ * Construct a proxy event listener, given an existing one to augment.
+ *
+ * @param listener the listener to wrap
+ */
+ public EventListenerProxy(EventListener listener)
+ {
+ this.listener = listener;
+ }
+
+ /**
+ * Return the wrapped event listener.
+ *
+ * @return the listener associated with this proxy
+ */
+ public EventListener getListener()
+ {
+ return listener;
+ }
+} // class EventListenerProxy
diff --git a/libjava/classpath/java/util/EventObject.java b/libjava/classpath/java/util/EventObject.java
new file mode 100644
index 00000000000..7ced18aa4ba
--- /dev/null
+++ b/libjava/classpath/java/util/EventObject.java
@@ -0,0 +1,101 @@
+/* EventObject.java -- represents an event on an object
+ Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * Represents Events fired by Objects.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see EventListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class EventObject implements Serializable
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5516075349620653480L;
+
+ /**
+ * The source object; in other words, the object which this event takes
+ * place on.
+ */
+ protected transient Object source;
+
+ /**
+ * Constructs an EventObject with the specified source.
+ *
+ * @param source the source of the event
+ * @throws IllegalArgumentException if source is null (This is not
+ * specified, but matches the behavior of the JDK)
+ */
+ public EventObject(Object source)
+ {
+ // This check for null is stupid, if you ask me, since source is
+ // protected and non-final, so a subclass can set it to null later on.
+ if (source == null)
+ throw new IllegalArgumentException();
+ this.source = source;
+ }
+
+ /**
+ * Returns the source of the event.
+ *
+ * @return the event source
+ */
+ public Object getSource()
+ {
+ return source;
+ }
+
+ /**
+ * Converts the event to a String. The format is not specified, but by
+ * observation, the JDK uses:
+ * <code>getClass().getName() + "[source=" + source + "]";</code>.
+ *
+ * @return String representation of the Event
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[source=" + source + "]";
+ }
+} // class EventObject
diff --git a/libjava/classpath/java/util/GregorianCalendar.java b/libjava/classpath/java/util/GregorianCalendar.java
new file mode 100644
index 00000000000..b086a7d04a4
--- /dev/null
+++ b/libjava/classpath/java/util/GregorianCalendar.java
@@ -0,0 +1,1343 @@
+/* java.util.GregorianCalendar
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+
+/**
+ * <p>
+ * This class represents the Gregorian calendar, that is used in most
+ * countries all over the world. It does also handle the Julian calendar
+ * for dates smaller than the date of the change to the Gregorian calendar.
+ * The Gregorian calendar differs from the Julian calendar by a different
+ * leap year rule (no leap year every 100 years, except if year is divisible
+ * by 400).
+ * </p>
+ * <p>
+ * This change date is different from country to country, and can be changed with
+ * <code>setGregorianChange</code>. The first countries to adopt the Gregorian
+ * calendar did so on the 15th of October, 1582. This date followed October
+ * the 4th, 1582 in the Julian calendar system. The non-existant days that were
+ * omitted when the change took place are interpreted as Gregorian dates.
+ * </p>
+ * <p>
+ * Prior to the changeover date, New Year's Day occurred on the 25th of March.
+ * However, this class always takes New Year's Day as being the 1st of January.
+ * Client code should manually adapt the year value, if required, for dates
+ * between January the 1st and March the 24th in years prior to the changeover.
+ * </p>
+ * <p>
+ * Any date infinitely forwards or backwards in time can be represented by
+ * this class. A <em>proleptic</em> calendar system is used, which allows
+ * future dates to be created via the existing rules. This allows meaningful
+ * and consistent dates to be produced for all years. However, dates are only
+ * historically accurate following March the 1st, 4AD when the Julian calendar
+ * system was adopted. Prior to this, leap year rules were applied erraticly.
+ * </p>
+ * <p>
+ * There are two eras available for the Gregorian calendar, namely BC and AD.
+ * </p>
+ * <p>
+ * Weeks are defined as a period of seven days, beginning on the first day
+ * of the week, as returned by <code>getFirstDayOfWeek()</code>, and ending
+ * on the day prior to this.
+ * </p>
+ * <p>
+ * The weeks of the year are numbered from 1 to a possible 53. The first week
+ * of the year is defined as the first week that contains at least the minimum
+ * number of days of the first week in the new year (retrieved via
+ * <code>getMinimalDaysInFirstWeek()</code>). All weeks after this are numbered
+ * from 2 onwards.
+ * </p>
+ * <p>
+ * For example, take the year 2004. It began on a Thursday. The first week
+ * of 2004 depends both on where a week begins and how long it must minimally
+ * last. Let's say that the week begins on a Monday and must have a minimum
+ * of 5 days. In this case, the first week begins on Monday, the 5th of January.
+ * The first 4 days (Thursday to Sunday) are not eligible, as they are too few
+ * to make up the minimum number of days of the first week which must be in
+ * the new year. If the minimum was lowered to 4 days, then the first week
+ * would instead begin on Monday, the 29th of December, 2003. This first week
+ * has 4 of its days in the new year, and is now eligible.
+ * </p>
+ * <p>
+ * The weeks of the month are numbered from 0 to a possible 6. The first week
+ * of the month (numbered 1) is a set of days, prior to the first day of the week,
+ * which number at least the minimum number of days in a week. Unlike the first
+ * week of the year, the first week of the month only uses days from that particular
+ * month. As a consequence, it may have a variable number of days (from the minimum
+ * number required up to a full week of 7) and it need not start on the first day of
+ * the week. It must, however, be following by the first day of the week, as this
+ * marks the beginning of week 2. Any days of the month which occur prior to the
+ * first week (because the first day of the week occurs before the minimum number
+ * of days is met) are seen as week 0.
+ * </p>
+ * <p>
+ * Again, we will take the example of the year 2004 to demonstrate this. September
+ * 2004 begins on a Wednesday. Taking our first day of the week as Monday, and the
+ * minimum length of the first week as 6, we find that week 1 runs from Monday,
+ * the 6th of September to Sunday the 12th. Prior to the 6th, there are only
+ * 5 days (Wednesday through to Sunday). This is too small a number to meet the
+ * minimum, so these are classed as being days in week 0. Week 2 begins on the
+ * 13th, and so on. This changes if we reduce the minimum to 5. In this case,
+ * week 1 is a truncated week from Wednesday the 1st to Sunday the 5th, and week
+ * 0 doesn't exist. The first seven day week is week 2, starting on the 6th.
+ * </p>
+ * <p>
+ * On using the <code>clear()</code> method, the Gregorian calendar returns
+ * to its default value of the 1st of January, 1970 AD 00:00:00 (the epoch).
+ * The day of the week is set to the correct day for that particular time.
+ * The day is also the first of the month, and the date is in week 0.
+ * </p>
+ *
+ * @see Calendar
+ * @see TimeZone
+ * @see Calendar#getFirstDayOfWeek()
+ * @see Calendar#getMinimalDaysInFirstWeek()
+ */
+public class GregorianCalendar extends Calendar
+{
+ /**
+ * Constant representing the era BC (Before Christ).
+ */
+ public static final int BC = 0;
+
+ /**
+ * Constant representing the era AD (Anno Domini).
+ */
+ public static final int AD = 1;
+
+ /**
+ * The point at which the Gregorian calendar rules were used.
+ * This may be changed by using setGregorianChange;
+ * The default is midnight (UTC) on October 5, 1582 (Julian),
+ * or October 15, 1582 (Gregorian).
+ *
+ * @serial the changeover point from the Julian calendar
+ * system to the Gregorian.
+ */
+ private long gregorianCutover = (new Date((24 * 60 * 60 * 1000L) * (((1582 * (365 * 4
+ + 1)) / 4
+ + (java.util.Calendar.OCTOBER * (31
+ + 30 + 31 + 30 + 31) - 9) / 5 + 5)
+ - ((1970 * (365 * 4 + 1)) / 4 + 1
+ - 13)))).getTime();
+
+ /**
+ * For compatability with Sun's JDK.
+ */
+ static final long serialVersionUID = -8125100834729963327L;
+
+ /**
+ * Days in the epoch. Relative Jan 1, year '0' which is not a leap year.
+ * (although there is no year zero, this does not matter.)
+ * This is consistent with the formula:
+ * = (year-1)*365L + ((year-1) >> 2)
+ *
+ * Plus the gregorian correction:
+ * Math.floor((year-1) / 400.) - Math.floor((year-1) / 100.);
+ * For a correct julian date, the correction is -2 instead.
+ *
+ * The gregorian cutover in 1582 was 10 days, so by calculating the
+ * correction from year zero, we have 15 non-leap days (even centuries)
+ * minus 3 leap days (year 400,800,1200) = 12. Subtracting two corrects
+ * this to the correct number 10.
+ */
+ private static final int EPOCH_DAYS = 719162;
+
+ /**
+ * Constructs a new GregorianCalender representing the current
+ * time, using the default time zone and the default locale.
+ */
+ public GregorianCalendar()
+ {
+ this(TimeZone.getDefault(), Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new GregorianCalender representing the current
+ * time, using the specified time zone and the default locale.
+ *
+ * @param zone a time zone.
+ */
+ public GregorianCalendar(TimeZone zone)
+ {
+ this(zone, Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new GregorianCalender representing the current
+ * time, using the default time zone and the specified locale.
+ *
+ * @param locale a locale.
+ */
+ public GregorianCalendar(Locale locale)
+ {
+ this(TimeZone.getDefault(), locale);
+ }
+
+ /**
+ * Constructs a new GregorianCalender representing the current
+ * time with the given time zone and the given locale.
+ *
+ * @param zone a time zone.
+ * @param locale a locale.
+ */
+ public GregorianCalendar(TimeZone zone, Locale locale)
+ {
+ this(zone, locale, false);
+ setTimeInMillis(System.currentTimeMillis());
+ complete();
+ }
+
+ /**
+ * Common constructor that all constructors should call.
+ * @param zone a time zone.
+ * @param locale a locale.
+ * @param unused unused parameter to make the signature differ from
+ * the public constructor (TimeZone, Locale).
+ */
+ private GregorianCalendar(TimeZone zone, Locale locale, boolean unused)
+ {
+ super(zone, locale);
+ }
+
+ /**
+ * Constructs a new GregorianCalendar representing midnight on the
+ * given date with the default time zone and locale.
+ *
+ * @param year corresponds to the YEAR time field.
+ * @param month corresponds to the MONTH time field.
+ * @param day corresponds to the DAY time field.
+ */
+ public GregorianCalendar(int year, int month, int day)
+ {
+ this(TimeZone.getDefault(), Locale.getDefault(), false);
+ set(year, month, day);
+ }
+
+ /**
+ * Constructs a new GregorianCalendar representing midnight on the
+ * given date with the default time zone and locale.
+ *
+ * @param year corresponds to the YEAR time field.
+ * @param month corresponds to the MONTH time field.
+ * @param day corresponds to the DAY time field.
+ * @param hour corresponds to the HOUR_OF_DAY time field.
+ * @param minute corresponds to the MINUTE time field.
+ */
+ public GregorianCalendar(int year, int month, int day, int hour, int minute)
+ {
+ this(TimeZone.getDefault(), Locale.getDefault(), false);
+ set(year, month, day, hour, minute);
+ }
+
+ /**
+ * Constructs a new GregorianCalendar representing midnight on the
+ * given date with the default time zone and locale.
+ *
+ * @param year corresponds to the YEAR time field.
+ * @param month corresponds to the MONTH time field.
+ * @param day corresponds to the DAY time field.
+ * @param hour corresponds to the HOUR_OF_DAY time field.
+ * @param minute corresponds to the MINUTE time field.
+ * @param second corresponds to the SECOND time field.
+ */
+ public GregorianCalendar(int year, int month, int day, int hour, int minute,
+ int second)
+ {
+ this(TimeZone.getDefault(), Locale.getDefault(), false);
+ set(year, month, day, hour, minute, second);
+ }
+
+ /**
+ * Sets the date of the switch from Julian dates to Gregorian dates.
+ * You can use <code>new Date(Long.MAX_VALUE)</code> to use a pure
+ * Julian calendar, or <code>Long.MIN_VALUE</code> for a pure Gregorian
+ * calendar.
+ *
+ * @param date the date of the change.
+ */
+ public void setGregorianChange(Date date)
+ {
+ gregorianCutover = date.getTime();
+ }
+
+ /**
+ * Gets the date of the switch from Julian dates to Gregorian dates.
+ *
+ * @return the date of the change.
+ */
+ public final Date getGregorianChange()
+ {
+ return new Date(gregorianCutover);
+ }
+
+ /**
+ * <p>
+ * Determines if the given year is a leap year. The result is
+ * undefined if the Gregorian change took place in 1800, so that
+ * the end of February is skipped, and that year is specified.
+ * (well...).
+ * </p>
+ * <p>
+ * To specify a year in the BC era, use a negative value calculated
+ * as 1 - y, where y is the required year in BC. So, 1 BC is 0,
+ * 2 BC is -1, 3 BC is -2, etc.
+ * </p>
+ *
+ * @param year a year (use a negative value for BC).
+ * @return true, if the given year is a leap year, false otherwise.
+ */
+ public boolean isLeapYear(int year)
+ {
+ // Only years divisible by 4 can be leap years
+ if ((year & 3) != 0)
+ return false;
+
+ // Is the leap-day a Julian date? Then it's a leap year
+ if (! isGregorian(year, 31 + 29 - 1))
+ return true;
+
+ // Apply gregorian rules otherwise
+ return ((year % 100) != 0 || (year % 400) == 0);
+ }
+
+ /**
+ * Retrieves the day of the week corresponding to the specified
+ * day of the specified year.
+ *
+ * @param year the year in which the dayOfYear occurs.
+ * @param dayOfYear the day of the year (an integer between 0 and
+ * and 366)
+ */
+ private int getWeekDay(int year, int dayOfYear)
+ {
+ boolean greg = isGregorian(year, dayOfYear);
+ int day = (int) getLinearDay(year, dayOfYear, greg);
+
+ // The epoch was a thursday.
+ int weekday = (day + THURSDAY) % 7;
+ if (weekday <= 0)
+ weekday += 7;
+ return weekday;
+ }
+
+ /**
+ * Returns the day of the week for the first day of a given month (0..11)
+ */
+ private int getFirstDayOfMonth(int year, int month)
+ {
+ int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+ if (month > 11)
+ {
+ year += (month / 12);
+ month = month % 12;
+ }
+
+ if (month < 0)
+ {
+ year += (int) month / 12;
+ month = month % 12;
+ if (month < 0)
+ {
+ month += 12;
+ year--;
+ }
+ }
+
+ int dayOfYear = dayCount[month] + 1;
+ if (month > 1)
+ if (isLeapYear(year))
+ dayOfYear++;
+
+ boolean greg = isGregorian(year, dayOfYear);
+ int day = (int) getLinearDay(year, dayOfYear, greg);
+
+ // The epoch was a thursday.
+ int weekday = (day + THURSDAY) % 7;
+ if (weekday <= 0)
+ weekday += 7;
+ return weekday;
+ }
+
+ /**
+ * Takes a year, and a (zero based) day of year and determines
+ * if it is gregorian or not.
+ */
+ private boolean isGregorian(int year, int dayOfYear)
+ {
+ int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear
+ - EPOCH_DAYS; // gregorian days from 1 to epoch.
+ int gregFactor = (int) Math.floor((double) (year - 1) / 400.)
+ - (int) Math.floor((double) (year - 1) / 100.);
+
+ return ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover);
+ }
+
+ /**
+ * Check set fields for validity, without leniency.
+ *
+ * @throws IllegalArgumentException if a field is invalid
+ */
+ private void nonLeniencyCheck() throws IllegalArgumentException
+ {
+ int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ int year = fields[YEAR];
+ int month = fields[MONTH];
+ int leap = isLeapYear(year) ? 1 : 0;
+
+ if (isSet[ERA] && fields[ERA] != AD && fields[ERA] != BC)
+ throw new IllegalArgumentException("Illegal ERA.");
+ if (isSet[YEAR] && fields[YEAR] < 1)
+ throw new IllegalArgumentException("Illegal YEAR.");
+ if (isSet[MONTH] && (month < 0 || month > 11))
+ throw new IllegalArgumentException("Illegal MONTH.");
+ if (isSet[WEEK_OF_YEAR])
+ {
+ int daysInYear = 365 + leap;
+ daysInYear += (getFirstDayOfMonth(year, 0) - 1); // pad first week
+ int last = getFirstDayOfMonth(year, 11) + 4;
+ if (last > 7)
+ last -= 7;
+ daysInYear += 7 - last;
+ int weeks = daysInYear / 7;
+ if (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > weeks)
+ throw new IllegalArgumentException("Illegal WEEK_OF_YEAR.");
+ }
+
+ if (isSet[WEEK_OF_MONTH])
+ {
+ int weeks = (month == 1 && leap == 0) ? 4 : 5;
+ if (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > weeks)
+ throw new IllegalArgumentException("Illegal WEEK_OF_MONTH.");
+ }
+
+ if (isSet[DAY_OF_MONTH])
+ if (fields[DAY_OF_MONTH] < 1
+ || fields[DAY_OF_MONTH] > month_days[month]
+ + ((month == 1) ? leap : 0))
+ throw new IllegalArgumentException("Illegal DAY_OF_MONTH.");
+
+ if (isSet[DAY_OF_YEAR]
+ && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > 365 + leap))
+ throw new IllegalArgumentException("Illegal DAY_OF_YEAR.");
+
+ if (isSet[DAY_OF_WEEK]
+ && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7))
+ throw new IllegalArgumentException("Illegal DAY_OF_WEEK.");
+
+ if (isSet[DAY_OF_WEEK_IN_MONTH])
+ {
+ int weeks = (month == 1 && leap == 0) ? 4 : 5;
+ if (fields[DAY_OF_WEEK_IN_MONTH] < -weeks
+ || fields[DAY_OF_WEEK_IN_MONTH] > weeks)
+ throw new IllegalArgumentException("Illegal DAY_OF_WEEK_IN_MONTH.");
+ }
+
+ if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM)
+ throw new IllegalArgumentException("Illegal AM_PM.");
+ if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11))
+ throw new IllegalArgumentException("Illegal HOUR.");
+ if (isSet[HOUR_OF_DAY]
+ && (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23))
+ throw new IllegalArgumentException("Illegal HOUR_OF_DAY.");
+ if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59))
+ throw new IllegalArgumentException("Illegal MINUTE.");
+ if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59))
+ throw new IllegalArgumentException("Illegal SECOND.");
+ if (isSet[MILLISECOND]
+ && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999))
+ throw new IllegalArgumentException("Illegal MILLISECOND.");
+ if (isSet[ZONE_OFFSET]
+ && (fields[ZONE_OFFSET] < -12 * 60 * 60 * 1000L
+ || fields[ZONE_OFFSET] > 12 * 60 * 60 * 1000L))
+ throw new IllegalArgumentException("Illegal ZONE_OFFSET.");
+ if (isSet[DST_OFFSET]
+ && (fields[DST_OFFSET] < -12 * 60 * 60 * 1000L
+ || fields[DST_OFFSET] > 12 * 60 * 60 * 1000L))
+ throw new IllegalArgumentException("Illegal DST_OFFSET.");
+ }
+
+ /**
+ * Converts the time field values (<code>fields</code>) to
+ * milliseconds since the epoch UTC (<code>time</code>).
+ *
+ * @throws IllegalArgumentException if any calendar fields
+ * are invalid.
+ */
+ protected synchronized void computeTime()
+ {
+ int millisInDay = 0;
+ int era = fields[ERA];
+ int year = fields[YEAR];
+ int month = fields[MONTH];
+ int day = fields[DAY_OF_MONTH];
+
+ int minute = fields[MINUTE];
+ int second = fields[SECOND];
+ int millis = fields[MILLISECOND];
+ int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ int hour = 0;
+
+ if (! isLenient())
+ nonLeniencyCheck();
+
+ if (! isSet[MONTH] && (! isSet[DAY_OF_WEEK] || isSet[WEEK_OF_YEAR]))
+ {
+ // 5: YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
+ if (isSet[WEEK_OF_YEAR])
+ {
+ int first = getFirstDayOfMonth(year, 0);
+ int offs = 1;
+ int daysInFirstWeek = getFirstDayOfWeek() - first;
+ if (daysInFirstWeek <= 0)
+ daysInFirstWeek += 7;
+
+ if (daysInFirstWeek < getMinimalDaysInFirstWeek())
+ offs += daysInFirstWeek;
+ else
+ offs -= 7 - daysInFirstWeek;
+ month = 0;
+ day = offs + 7 * (fields[WEEK_OF_YEAR] - 1);
+ offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek();
+
+ if (offs < 0)
+ offs += 7;
+ day += offs;
+ }
+ else
+ {
+ // 4: YEAR + DAY_OF_YEAR
+ month = 0;
+ day = fields[DAY_OF_YEAR];
+ }
+ }
+ else
+ {
+ if (isSet[DAY_OF_WEEK])
+ {
+ int first = getFirstDayOfMonth(year, month);
+
+ // 3: YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
+ if (isSet[DAY_OF_WEEK_IN_MONTH])
+ {
+ if (fields[DAY_OF_WEEK_IN_MONTH] < 0)
+ {
+ month++;
+ first = getFirstDayOfMonth(year, month);
+ day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH]);
+ }
+ else
+ day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH] - 1);
+
+ int offs = fields[DAY_OF_WEEK] - first;
+ if (offs < 0)
+ offs += 7;
+ day += offs;
+ }
+ else
+ { // 2: YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
+ int offs = 1;
+ int daysInFirstWeek = getFirstDayOfWeek() - first;
+ if (daysInFirstWeek <= 0)
+ daysInFirstWeek += 7;
+
+ if (daysInFirstWeek < getMinimalDaysInFirstWeek())
+ offs += daysInFirstWeek;
+ else
+ offs -= 7 - daysInFirstWeek;
+
+ day = offs + 7 * (fields[WEEK_OF_MONTH] - 1);
+ offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek();
+ if (offs <= 0)
+ offs += 7;
+ day += offs;
+ }
+ }
+
+ // 1: YEAR + MONTH + DAY_OF_MONTH
+ }
+ if (era == BC && year > 0)
+ year = 1 - year;
+
+ // rest of code assumes day/month/year set
+ // should negative BC years be AD?
+ // get the hour (but no check for validity)
+ if (isSet[HOUR])
+ {
+ hour = fields[HOUR];
+ if (fields[AM_PM] == PM)
+ hour += 12;
+ }
+ else
+ hour = fields[HOUR_OF_DAY];
+
+ // Read the era,year,month,day fields and convert as appropriate.
+ // Calculate number of milliseconds into the day
+ // This takes care of both h, m, s, ms over/underflows.
+ long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L + millis;
+ day += allMillis / (24 * 60 * 60 * 1000L);
+ millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L));
+
+ if (month < 0)
+ {
+ year += (int) month / 12;
+ month = month % 12;
+ if (month < 0)
+ {
+ month += 12;
+ year--;
+ }
+ }
+ if (month > 11)
+ {
+ year += (month / 12);
+ month = month % 12;
+ }
+
+ month_days[1] = isLeapYear(year) ? 29 : 28;
+
+ while (day <= 0)
+ {
+ if (month == 0)
+ {
+ year--;
+ month_days[1] = isLeapYear(year) ? 29 : 28;
+ }
+ month = (month + 11) % 12;
+ day += month_days[month];
+ }
+ while (day > month_days[month])
+ {
+ day -= (month_days[month]);
+ month = (month + 1) % 12;
+ if (month == 0)
+ {
+ year++;
+ month_days[1] = isLeapYear(year) ? 29 : 28;
+ }
+ }
+
+ // ok, by here we have valid day,month,year,era and millisinday
+ int dayOfYear = dayCount[month] + day - 1; // (day starts on 1)
+ if (isLeapYear(year) && month > 1)
+ dayOfYear++;
+
+ int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear
+ - EPOCH_DAYS; // gregorian days from 1 to epoch.
+ int gregFactor = (int) Math.floor((double) (year - 1) / 400.)
+ - (int) Math.floor((double) (year - 1) / 100.);
+
+ if ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover)
+ relativeDay += gregFactor;
+ else
+ relativeDay -= 2;
+
+ time = relativeDay * (24 * 60 * 60 * 1000L) + millisInDay;
+
+ // the epoch was a Thursday.
+ int weekday = (int) (relativeDay + THURSDAY) % 7;
+ if (weekday <= 0)
+ weekday += 7;
+ fields[DAY_OF_WEEK] = weekday;
+
+ // Time zone corrections.
+ TimeZone zone = getTimeZone();
+ int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET]
+ : zone.getRawOffset();
+
+ int dstOffset = isSet[DST_OFFSET] ? fields[DST_OFFSET]
+ : (zone.getOffset((year < 0) ? BC : AD,
+ (year < 0) ? 1 - year
+ : year,
+ month, day, weekday,
+ millisInDay)
+ - zone.getRawOffset());
+
+ time -= rawOffset + dstOffset;
+
+ isTimeSet = true;
+ }
+
+ /**
+ * Get the linear day in days since the epoch, using the
+ * Julian or Gregorian calendar as specified. If you specify a
+ * nonpositive year it is interpreted as BC as following: 0 is 1
+ * BC, -1 is 2 BC and so on.
+ *
+ * @param year the year of the date.
+ * @param dayOfYear the day of year of the date; 1 based.
+ * @param gregorian <code>true</code>, if we should use the Gregorian rules.
+ * @return the days since the epoch, may be negative.
+ */
+ private long getLinearDay(int year, int dayOfYear, boolean gregorian)
+ {
+ // The 13 is the number of days, that were omitted in the Gregorian
+ // Calender until the epoch.
+ // We shift right by 2 instead of dividing by 4, to get correct
+ // results for negative years (and this is even more efficient).
+ long julianDay = (year - 1) * 365L + ((year - 1) >> 2) + (dayOfYear - 1)
+ - EPOCH_DAYS; // gregorian days from 1 to epoch.
+
+ if (gregorian)
+ {
+ // subtract the days that are missing in gregorian calendar
+ // with respect to julian calendar.
+ //
+ // Okay, here we rely on the fact that the gregorian
+ // calendar was introduced in the AD era. This doesn't work
+ // with negative years.
+ //
+ // The additional leap year factor accounts for the fact that
+ // a leap day is not seen on Jan 1 of the leap year.
+ int gregOffset = (int) Math.floor((double) (year - 1) / 400.)
+ - (int) Math.floor((double) (year - 1) / 100.);
+
+ return julianDay + gregOffset;
+ }
+ else
+ julianDay -= 2;
+ return julianDay;
+ }
+
+ /**
+ * Converts the given linear day into era, year, month,
+ * day_of_year, day_of_month, day_of_week, and writes the result
+ * into the fields array.
+ *
+ * @param day the linear day.
+ * @param gregorian true, if we should use Gregorian rules.
+ */
+ private void calculateDay(int[] fields, long day, boolean gregorian)
+ {
+ // the epoch was a Thursday.
+ int weekday = (int) (day + THURSDAY) % 7;
+ if (weekday <= 0)
+ weekday += 7;
+ fields[DAY_OF_WEEK] = weekday;
+
+ // get a first approximation of the year. This may be one
+ // year too big.
+ int year = 1970
+ + (int) (gregorian
+ ? ((day - 100L) * 400L) / (365L * 400L + 100L - 4L
+ + 1L) : ((day - 100L) * 4L) / (365L * 4L + 1L));
+ if (day >= 0)
+ year++;
+
+ long firstDayOfYear = getLinearDay(year, 1, gregorian);
+
+ // Now look in which year day really lies.
+ if (day < firstDayOfYear)
+ {
+ year--;
+ firstDayOfYear = getLinearDay(year, 1, gregorian);
+ }
+
+ day -= firstDayOfYear - 1; // day of year, one based.
+
+ fields[DAY_OF_YEAR] = (int) day;
+ if (year <= 0)
+ {
+ fields[ERA] = BC;
+ fields[YEAR] = 1 - year;
+ }
+ else
+ {
+ fields[ERA] = AD;
+ fields[YEAR] = year;
+ }
+
+ int leapday = isLeapYear(year) ? 1 : 0;
+ if (day <= 31 + 28 + leapday)
+ {
+ fields[MONTH] = (int) day / 32; // 31->JANUARY, 32->FEBRUARY
+ fields[DAY_OF_MONTH] = (int) day - 31 * fields[MONTH];
+ }
+ else
+ {
+ // A few more magic formulas
+ int scaledDay = ((int) day - leapday) * 5 + 8;
+ fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31);
+ fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1;
+ }
+ }
+
+ /**
+ * Converts the milliseconds since the epoch UTC
+ * (<code>time</code>) to time fields
+ * (<code>fields</code>).
+ */
+ protected synchronized void computeFields()
+ {
+ boolean gregorian = (time >= gregorianCutover);
+
+ TimeZone zone = getTimeZone();
+ fields[ZONE_OFFSET] = zone.getRawOffset();
+ long localTime = time + fields[ZONE_OFFSET];
+
+ long day = localTime / (24 * 60 * 60 * 1000L);
+ int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L));
+
+ if (millisInDay < 0)
+ {
+ millisInDay += (24 * 60 * 60 * 1000);
+ day--;
+ }
+
+ calculateDay(fields, day, gregorian);
+ fields[DST_OFFSET] = zone.getOffset(fields[ERA], fields[YEAR],
+ fields[MONTH], fields[DAY_OF_MONTH],
+ fields[DAY_OF_WEEK], millisInDay)
+ - fields[ZONE_OFFSET];
+
+ millisInDay += fields[DST_OFFSET];
+ if (millisInDay >= 24 * 60 * 60 * 1000)
+ {
+ millisInDay -= 24 * 60 * 60 * 1000;
+ calculateDay(fields, ++day, gregorian);
+ }
+
+ fields[DAY_OF_WEEK_IN_MONTH] = (fields[DAY_OF_MONTH] + 6) / 7;
+
+ // which day of the week are we (0..6), relative to getFirstDayOfWeek
+ int relativeWeekday = (7 + fields[DAY_OF_WEEK] - getFirstDayOfWeek()) % 7;
+
+ fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH] - relativeWeekday + 12) / 7;
+
+ int weekOfYear = (fields[DAY_OF_YEAR] - relativeWeekday + 6) / 7;
+
+ // Do the Correction: getMinimalDaysInFirstWeek() is always in the
+ // first week.
+ int minDays = getMinimalDaysInFirstWeek();
+ int firstWeekday = (7 + getWeekDay(fields[YEAR], minDays)
+ - getFirstDayOfWeek()) % 7;
+ if (minDays - firstWeekday < 1)
+ weekOfYear++;
+ fields[WEEK_OF_YEAR] = weekOfYear;
+
+ int hourOfDay = millisInDay / (60 * 60 * 1000);
+ fields[AM_PM] = (hourOfDay < 12) ? AM : PM;
+ int hour = hourOfDay % 12;
+ fields[HOUR] = hour;
+ fields[HOUR_OF_DAY] = hourOfDay;
+ millisInDay %= (60 * 60 * 1000);
+ fields[MINUTE] = millisInDay / (60 * 1000);
+ millisInDay %= (60 * 1000);
+ fields[SECOND] = millisInDay / (1000);
+ fields[MILLISECOND] = millisInDay % 1000;
+
+ areFieldsSet = isSet[ERA] = isSet[YEAR] = isSet[MONTH] = isSet[WEEK_OF_YEAR] = isSet[WEEK_OF_MONTH] = isSet[DAY_OF_MONTH] = isSet[DAY_OF_YEAR] = isSet[DAY_OF_WEEK] = isSet[DAY_OF_WEEK_IN_MONTH] = isSet[AM_PM] = isSet[HOUR] = isSet[HOUR_OF_DAY] = isSet[MINUTE] = isSet[SECOND] = isSet[MILLISECOND] = isSet[ZONE_OFFSET] = isSet[DST_OFFSET] = true;
+ }
+
+ /**
+ * Compares the given calendar with this. An object, o, is
+ * equivalent to this if it is also a <code>GregorianCalendar</code>
+ * with the same time since the epoch under the same conditions
+ * (same change date and same time zone).
+ *
+ * @param o the object to that we should compare.
+ * @return true, if the given object is a calendar, that represents
+ * the same time (but doesn't necessarily have the same fields).
+ * @throws IllegalArgumentException if one of the fields
+ * <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+ * specified, if an unknown field is specified or if one
+ * of the calendar fields receives an illegal value when
+ * leniancy is not enabled.
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof GregorianCalendar))
+ return false;
+
+ GregorianCalendar cal = (GregorianCalendar) o;
+ return (cal.getTimeInMillis() == getTimeInMillis());
+ }
+
+ /**
+ * Adds the specified amount of time to the given time field. The
+ * amount may be negative to subtract the time. If the field overflows
+ * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
+ * @param field one of the time field constants.
+ * @param amount the amount of time to add.
+ * @exception IllegalArgumentException if <code>field</code> is
+ * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or invalid; or
+ * if <code>amount</code> contains an out-of-range value and the calendar
+ * is not in lenient mode.
+ */
+ public void add(int field, int amount)
+ {
+ switch (field)
+ {
+ case YEAR:
+ complete();
+ fields[YEAR] += amount;
+ isTimeSet = false;
+ break;
+ case MONTH:
+ complete();
+ int months = fields[MONTH] + amount;
+ fields[YEAR] += months / 12;
+ fields[MONTH] = months % 12;
+ if (fields[MONTH] < 0)
+ {
+ fields[MONTH] += 12;
+ fields[YEAR]--;
+ }
+ int maxDay = getActualMaximum(DAY_OF_MONTH);
+ if (fields[DAY_OF_MONTH] > maxDay)
+ fields[DAY_OF_MONTH] = maxDay;
+ set(YEAR, fields[YEAR]);
+ set(MONTH, fields[MONTH]);
+ break;
+ case DAY_OF_MONTH:
+ case DAY_OF_YEAR:
+ case DAY_OF_WEEK:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (24 * 60 * 60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case WEEK_OF_YEAR:
+ case WEEK_OF_MONTH:
+ case DAY_OF_WEEK_IN_MONTH:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (7 * 24 * 60 * 60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case AM_PM:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (12 * 60 * 60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case HOUR:
+ case HOUR_OF_DAY:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (60 * 60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case MINUTE:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case SECOND:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (1000L);
+ areFieldsSet = false;
+ break;
+ case MILLISECOND:
+ if (! isTimeSet)
+ computeTime();
+ time += amount;
+ areFieldsSet = false;
+ break;
+ case ZONE_OFFSET:
+ case DST_OFFSET:default:
+ throw new IllegalArgumentException("Invalid or unknown field");
+ }
+ }
+
+ /**
+ * Rolls the specified time field up or down. This means add one
+ * to the specified field, but don't change the other fields. If
+ * the maximum for this field is reached, start over with the
+ * minimum value.
+ *
+ * <strong>Note:</strong> There may be situation, where the other
+ * fields must be changed, e.g rolling the month on May, 31.
+ * The date June, 31 is automatically converted to July, 1.
+ * This requires lenient settings.
+ *
+ * @param field the time field. One of the time field constants.
+ * @param up the direction, true for up, false for down.
+ * @throws IllegalArgumentException if one of the fields
+ * <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+ * specified, if an unknown field is specified or if one
+ * of the calendar fields receives an illegal value when
+ * leniancy is not enabled.
+ */
+ public void roll(int field, boolean up)
+ {
+ roll(field, up ? 1 : -1);
+ }
+
+ /**
+ * Checks that the fields are still within their legal bounds,
+ * following use of the <code>roll()</code> method.
+ *
+ * @param field the field to check.
+ * @param delta multipler for alterations to the <code>time</code>.
+ * @see #roll(int, boolean)
+ * @see #roll(int, int)
+ */
+ private void cleanUpAfterRoll(int field, int delta)
+ {
+ switch (field)
+ {
+ case ERA:
+ case YEAR:
+ case MONTH:
+ // check that day of month is still in correct range
+ if (fields[DAY_OF_MONTH] > getActualMaximum(DAY_OF_MONTH))
+ fields[DAY_OF_MONTH] = getActualMaximum(DAY_OF_MONTH);
+ isTimeSet = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case DAY_OF_MONTH:
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ time += delta * (24 * 60 * 60 * 1000L);
+ break;
+ case WEEK_OF_MONTH:
+ isSet[DAY_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ time += delta * (7 * 24 * 60 * 60 * 1000L);
+ break;
+ case DAY_OF_WEEK_IN_MONTH:
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ time += delta * (7 * 24 * 60 * 60 * 1000L);
+ break;
+ case DAY_OF_YEAR:
+ isSet[MONTH] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ time += delta * (24 * 60 * 60 * 1000L);
+ break;
+ case WEEK_OF_YEAR:
+ isSet[MONTH] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ time += delta * (7 * 24 * 60 * 60 * 1000L);
+ break;
+ case AM_PM:
+ isSet[HOUR_OF_DAY] = false;
+ time += delta * (12 * 60 * 60 * 1000L);
+ break;
+ case HOUR:
+ isSet[HOUR_OF_DAY] = false;
+ time += delta * (60 * 60 * 1000L);
+ break;
+ case HOUR_OF_DAY:
+ isSet[HOUR] = false;
+ isSet[AM_PM] = false;
+ time += delta * (60 * 60 * 1000L);
+ break;
+ case MINUTE:
+ time += delta * (60 * 1000L);
+ break;
+ case SECOND:
+ time += delta * (1000L);
+ break;
+ case MILLISECOND:
+ time += delta;
+ break;
+ }
+ }
+
+ /**
+ * Rolls the specified time field by the given amount. This means
+ * add amount to the specified field, but don't change the other
+ * fields. If the maximum for this field is reached, start over
+ * with the minimum value and vice versa for negative amounts.
+ *
+ * <strong>Note:</strong> There may be situation, where the other
+ * fields must be changed, e.g rolling the month on May, 31.
+ * The date June, 31 is automatically corrected to June, 30.
+ *
+ * @param field the time field. One of the time field constants.
+ * @param amount the amount by which we should roll.
+ * @throws IllegalArgumentException if one of the fields
+ * <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+ * specified, if an unknown field is specified or if one
+ * of the calendar fields receives an illegal value when
+ * leniancy is not enabled.
+ */
+ public void roll(int field, int amount)
+ {
+ switch (field)
+ {
+ case DAY_OF_WEEK:
+ // day of week is special: it rolls automatically
+ add(field, amount);
+ return;
+ case ZONE_OFFSET:
+ case DST_OFFSET:
+ throw new IllegalArgumentException("Can't roll time zone");
+ }
+ complete();
+ int min = getActualMinimum(field);
+ int range = getActualMaximum(field) - min + 1;
+ int oldval = fields[field];
+ int newval = (oldval - min + range + amount) % range + min;
+ if (newval < min)
+ newval += range;
+ fields[field] = newval;
+ cleanUpAfterRoll(field, newval - oldval);
+ }
+
+ /**
+ * The minimum values for the calendar fields.
+ */
+ private static final int[] minimums =
+ {
+ BC, 1, 0, 0, 1, 1, 1, SUNDAY, 1, AM,
+ 1, 0, 0, 0, 0, -(12 * 60 * 60 * 1000),
+ 0
+ };
+
+ /**
+ * The maximum values for the calendar fields.
+ */
+ private static final int[] maximums =
+ {
+ AD, 5000000, 11, 53, 5, 31, 366,
+ SATURDAY, 5, PM, 12, 23, 59, 59, 999,
+ +(12 * 60 * 60 * 1000),
+ (12 * 60 * 60 * 1000)
+ };
+
+ /**
+ * Gets the smallest value that is allowed for the specified field.
+ *
+ * @param field one of the time field constants.
+ * @return the smallest value for the specified field.
+ */
+ public int getMinimum(int field)
+ {
+ return minimums[field];
+ }
+
+ /**
+ * Gets the biggest value that is allowed for the specified field.
+ *
+ * @param field one of the time field constants.
+ * @return the biggest value.
+ */
+ public int getMaximum(int field)
+ {
+ return maximums[field];
+ }
+
+ /**
+ * Gets the greatest minimum value that is allowed for the specified field.
+ * This is the largest value returned by the <code>getActualMinimum(int)</code>
+ * method.
+ *
+ * @param field the time field. One of the time field constants.
+ * @return the greatest minimum value.
+ * @see #getActualMinimum(int)
+ */
+ public int getGreatestMinimum(int field)
+ {
+ if (field == WEEK_OF_YEAR)
+ return 1;
+ return minimums[field];
+ }
+
+ /**
+ * Gets the smallest maximum value that is allowed for the
+ * specified field. This is the smallest value returned
+ * by the <code>getActualMaximum(int)</code>. For example,
+ * this is 28 for DAY_OF_MONTH (as all months have at least
+ * 28 days).
+ *
+ * @param field the time field. One of the time field constants.
+ * @return the least maximum value.
+ * @see #getActualMaximum(int)
+ * @since 1.2
+ */
+ public int getLeastMaximum(int field)
+ {
+ switch (field)
+ {
+ case WEEK_OF_YEAR:
+ return 52;
+ case DAY_OF_MONTH:
+ return 28;
+ case DAY_OF_YEAR:
+ return 365;
+ case DAY_OF_WEEK_IN_MONTH:
+ case WEEK_OF_MONTH:
+ return 4;
+ default:
+ return maximums[field];
+ }
+ }
+
+ /**
+ * Gets the actual minimum value that is allowed for the specified field.
+ * This value is dependent on the values of the other fields. Note that
+ * this calls <code>complete()</code> if not enough fields are set. This
+ * can have ugly side effects. The value given depends on the current
+ * time used by this instance.
+ *
+ * @param field the time field. One of the time field constants.
+ * @return the actual minimum value.
+ * @since 1.2
+ */
+ public int getActualMinimum(int field)
+ {
+ if (field == WEEK_OF_YEAR)
+ {
+ int min = getMinimalDaysInFirstWeek();
+ if (min == 0)
+ return 1;
+ if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+ complete();
+
+ int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+ int weekday = getWeekDay(year, min);
+ if ((7 + weekday - getFirstDayOfWeek()) % 7 >= min - 1)
+ return 1;
+ return 0;
+ }
+ return minimums[field];
+ }
+
+ /**
+ * Gets the actual maximum value that is allowed for the specified field.
+ * This value is dependent on the values of the other fields. Note that
+ * this calls <code>complete()</code> if not enough fields are set. This
+ * can have ugly side effects. The value given depends on the current time
+ * used by this instance; thus, leap years have a maximum day of month value of
+ * 29, rather than 28.
+ *
+ * @param field the time field. One of the time field constants.
+ * @return the actual maximum value.
+ */
+ public int getActualMaximum(int field)
+ {
+ switch (field)
+ {
+ case WEEK_OF_YEAR:
+ {
+ if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+ complete();
+
+ // This is wrong for the year that contains the gregorian change.
+ // I.e it gives the weeks in the julian year or in the gregorian
+ // year in that case.
+ int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+ int lastDay = isLeapYear(year) ? 366 : 365;
+ int weekday = getWeekDay(year, lastDay);
+ int week = (lastDay + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
+
+ int minimalDays = getMinimalDaysInFirstWeek();
+ int firstWeekday = getWeekDay(year, minimalDays);
+ /*
+ * Is there a set of days at the beginning of the year, before the
+ * first day of the week, equal to or greater than the minimum number
+ * of days required in the first week?
+ */
+ if (minimalDays - (7 + firstWeekday - getFirstDayOfWeek()) % 7 < 1)
+ return week + 1; /* Add week 1: firstWeekday through to firstDayOfWeek */
+ }
+ case DAY_OF_MONTH:
+ {
+ if (! areFieldsSet || ! isSet[MONTH])
+ complete();
+ int month = fields[MONTH];
+
+ // If you change this, you should also change
+ // SimpleTimeZone.getDaysInMonth();
+ if (month == FEBRUARY)
+ {
+ if (! isSet[YEAR] || ! isSet[ERA])
+ complete();
+ int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+ return isLeapYear(year) ? 29 : 28;
+ }
+ else if (month < AUGUST)
+ return 31 - (month & 1);
+ else
+ return 30 + (month & 1);
+ }
+ case DAY_OF_YEAR:
+ {
+ if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+ complete();
+ int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+ return isLeapYear(year) ? 366 : 365;
+ }
+ case DAY_OF_WEEK_IN_MONTH:
+ {
+ // This is wrong for the month that contains the gregorian change.
+ int daysInMonth = getActualMaximum(DAY_OF_MONTH);
+
+ // That's black magic, I know
+ return (daysInMonth - (fields[DAY_OF_MONTH] - 1) % 7 + 6) / 7;
+ }
+ case WEEK_OF_MONTH:
+ {
+ int daysInMonth = getActualMaximum(DAY_OF_MONTH);
+ int weekday = (daysInMonth - fields[DAY_OF_MONTH]
+ + fields[DAY_OF_WEEK] - SUNDAY) % 7 + SUNDAY;
+ return (daysInMonth + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
+ }
+ default:
+ return maximums[field];
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/HashMap.java b/libjava/classpath/java/util/HashMap.java
new file mode 100644
index 00000000000..5ca9cf6d500
--- /dev/null
+++ b/libjava/classpath/java/util/HashMap.java
@@ -0,0 +1,906 @@
+/* HashMap.java -- a class providing a basic hashtable data structure,
+ mapping Object --> Object
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+// NOTE: This implementation is very similar to that of Hashtable. If you fix
+// a bug in here, chances are you should make a similar change to the Hashtable
+// code.
+
+// NOTE: This implementation has some nasty coding style in order to
+// support LinkedHashMap, which extends this.
+
+/**
+ * This class provides a hashtable-backed implementation of the
+ * Map interface.
+ * <p>
+ *
+ * It uses a hash-bucket approach; that is, hash collisions are handled
+ * by linking the new node off of the pre-existing node (or list of
+ * nodes). In this manner, techniques such as linear probing (which
+ * can cause primary clustering) and rehashing (which does not fit very
+ * well with Java's method of precomputing hash codes) are avoided.
+ * <p>
+ *
+ * Under ideal circumstances (no collisions), HashMap offers O(1)
+ * performance on most operations (<code>containsValue()</code> is,
+ * of course, O(n)). In the worst case (all keys map to the same
+ * hash code -- very unlikely), most operations are O(n).
+ * <p>
+ *
+ * HashMap is part of the JDK1.2 Collections API. It differs from
+ * Hashtable in that it accepts the null key and null values, and it
+ * does not support "Enumeration views." Also, it is not synchronized;
+ * if you plan to use it in multiple threads, consider using:<br>
+ * <code>Map m = Collections.synchronizedMap(new HashMap(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * <code>ConcurrentModificationException</code> rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Jochen Hoenicke
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Object#hashCode()
+ * @see Collection
+ * @see Map
+ * @see TreeMap
+ * @see LinkedHashMap
+ * @see IdentityHashMap
+ * @see Hashtable
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class HashMap extends AbstractMap
+ implements Map, Cloneable, Serializable
+{
+ /**
+ * Default number of buckets. This is the value the JDK 1.3 uses. Some
+ * early documentation specified this value as 101. That is incorrect.
+ * Package visible for use by HashSet.
+ */
+ static final int DEFAULT_CAPACITY = 11;
+
+ /**
+ * The default load factor; this is explicitly specified by the spec.
+ * Package visible for use by HashSet.
+ */
+ static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = 362498820763181265L;
+
+ /**
+ * The rounded product of the capacity and the load factor; when the number
+ * of elements exceeds the threshold, the HashMap calls
+ * <code>rehash()</code>.
+ * @serial the threshold for rehashing
+ */
+ private int threshold;
+
+ /**
+ * Load factor of this HashMap: used in computing the threshold.
+ * Package visible for use by HashSet.
+ * @serial the load factor
+ */
+ final float loadFactor;
+
+ /**
+ * Array containing the actual key-value mappings.
+ * Package visible for use by nested and subclasses.
+ */
+ transient HashEntry[] buckets;
+
+ /**
+ * Counts the number of modifications this HashMap has undergone, used
+ * by Iterators to know when to throw ConcurrentModificationExceptions.
+ * Package visible for use by nested and subclasses.
+ */
+ transient int modCount;
+
+ /**
+ * The size of this HashMap: denotes the number of key-value pairs.
+ * Package visible for use by nested and subclasses.
+ */
+ transient int size;
+
+ /**
+ * The cache for {@link #entrySet()}.
+ */
+ private transient Set entries;
+
+ /**
+ * Class to represent an entry in the hash table. Holds a single key-value
+ * pair. Package visible for use by subclass.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ static class HashEntry extends AbstractMap.BasicMapEntry
+ {
+ /**
+ * The next entry in the linked list. Package visible for use by subclass.
+ */
+ HashEntry next;
+
+ /**
+ * Simple constructor.
+ * @param key the key
+ * @param value the value
+ */
+ HashEntry(Object key, Object value)
+ {
+ super(key, value);
+ }
+
+ /**
+ * Called when this entry is accessed via {@link #put(Object, Object)}.
+ * This version does nothing, but in LinkedHashMap, it must do some
+ * bookkeeping for access-traversal mode.
+ */
+ void access()
+ {
+ }
+
+ /**
+ * Called when this entry is removed from the map. This version simply
+ * returns the value, but in LinkedHashMap, it must also do bookkeeping.
+ *
+ * @return the value of this key as it is removed
+ */
+ Object cleanup()
+ {
+ return value;
+ }
+ }
+
+ /**
+ * Construct a new HashMap with the default capacity (11) and the default
+ * load factor (0.75).
+ */
+ public HashMap()
+ {
+ this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Construct a new HashMap from the given Map, with initial capacity
+ * the greater of the size of <code>m</code> or the default of 11.
+ * <p>
+ *
+ * Every element in Map m will be put into this new HashMap.
+ *
+ * @param m a Map whose key / value pairs will be put into the new HashMap.
+ * <b>NOTE: key / value pairs are not cloned in this constructor.</b>
+ * @throws NullPointerException if m is null
+ */
+ public HashMap(Map m)
+ {
+ this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
+ putAll(m);
+ }
+
+ /**
+ * Construct a new HashMap with a specific inital capacity and
+ * default load factor of 0.75.
+ *
+ * @param initialCapacity the initial capacity of this HashMap (&gt;=0)
+ * @throws IllegalArgumentException if (initialCapacity &lt; 0)
+ */
+ public HashMap(int initialCapacity)
+ {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Construct a new HashMap with a specific inital capacity and load factor.
+ *
+ * @param initialCapacity the initial capacity (&gt;=0)
+ * @param loadFactor the load factor (&gt; 0, not NaN)
+ * @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
+ * ! (loadFactor &gt; 0.0)
+ */
+ public HashMap(int initialCapacity, float loadFactor)
+ {
+ if (initialCapacity < 0)
+ throw new IllegalArgumentException("Illegal Capacity: "
+ + initialCapacity);
+ if (! (loadFactor > 0)) // check for NaN too
+ throw new IllegalArgumentException("Illegal Load: " + loadFactor);
+
+ if (initialCapacity == 0)
+ initialCapacity = 1;
+ buckets = new HashEntry[initialCapacity];
+ this.loadFactor = loadFactor;
+ threshold = (int) (initialCapacity * loadFactor);
+ }
+
+ /**
+ * Returns the number of kay-value mappings currently in this Map.
+ *
+ * @return the size
+ */
+ public int size()
+ {
+ return size;
+ }
+
+ /**
+ * Returns true if there are no key-value mappings currently in this Map.
+ *
+ * @return <code>size() == 0</code>
+ */
+ public boolean isEmpty()
+ {
+ return size == 0;
+ }
+
+ /**
+ * Return the value in this HashMap associated with the supplied key,
+ * or <code>null</code> if the key maps to nothing. NOTE: Since the value
+ * could also be null, you must use containsKey to see if this key
+ * actually maps to something.
+ *
+ * @param key the key for which to fetch an associated value
+ * @return what the key maps to, if present
+ * @see #put(Object, Object)
+ * @see #containsKey(Object)
+ */
+ public Object get(Object key)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ while (e != null)
+ {
+ if (equals(key, e.key))
+ return e.value;
+ e = e.next;
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the supplied object <code>equals()</code> a key
+ * in this HashMap.
+ *
+ * @param key the key to search for in this HashMap
+ * @return true if the key is in the table
+ * @see #containsValue(Object)
+ */
+ public boolean containsKey(Object key)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ while (e != null)
+ {
+ if (equals(key, e.key))
+ return true;
+ e = e.next;
+ }
+ return false;
+ }
+
+ /**
+ * Puts the supplied value into the Map, mapped by the supplied key.
+ * The value may be retrieved by any object which <code>equals()</code>
+ * this key. NOTE: Since the prior value could also be null, you must
+ * first use containsKey if you want to see if you are replacing the
+ * key's mapping.
+ *
+ * @param key the key used to locate the value
+ * @param value the value to be stored in the HashMap
+ * @return the prior mapping of the key, or null if there was none
+ * @see #get(Object)
+ * @see Object#equals(Object)
+ */
+ public Object put(Object key, Object value)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+
+ while (e != null)
+ {
+ if (equals(key, e.key))
+ {
+ e.access(); // Must call this for bookkeeping in LinkedHashMap.
+ Object r = e.value;
+ e.value = value;
+ return r;
+ }
+ else
+ e = e.next;
+ }
+
+ // At this point, we know we need to add a new entry.
+ modCount++;
+ if (++size > threshold)
+ {
+ rehash();
+ // Need a new hash value to suit the bigger table.
+ idx = hash(key);
+ }
+
+ // LinkedHashMap cannot override put(), hence this call.
+ addEntry(key, value, idx, true);
+ return null;
+ }
+
+ /**
+ * Copies all elements of the given map into this hashtable. If this table
+ * already has a mapping for a key, the new mapping replaces the current
+ * one.
+ *
+ * @param m the map to be hashed into this
+ */
+ public void putAll(Map m)
+ {
+ Iterator itr = m.entrySet().iterator();
+ while (itr.hasNext())
+ {
+ Map.Entry e = (Map.Entry) itr.next();
+ // Optimize in case the Entry is one of our own.
+ if (e instanceof AbstractMap.BasicMapEntry)
+ {
+ AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
+ put(entry.key, entry.value);
+ }
+ else
+ put(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * Removes from the HashMap and returns the value which is mapped by the
+ * supplied key. If the key maps to nothing, then the HashMap remains
+ * unchanged, and <code>null</code> is returned. NOTE: Since the value
+ * could also be null, you must use containsKey to see if you are
+ * actually removing a mapping.
+ *
+ * @param key the key used to locate the value to remove
+ * @return whatever the key mapped to, if present
+ */
+ public Object remove(Object key)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ HashEntry last = null;
+
+ while (e != null)
+ {
+ if (equals(key, e.key))
+ {
+ modCount++;
+ if (last == null)
+ buckets[idx] = e.next;
+ else
+ last.next = e.next;
+ size--;
+ // Method call necessary for LinkedHashMap to work correctly.
+ return e.cleanup();
+ }
+ last = e;
+ e = e.next;
+ }
+ return null;
+ }
+
+ /**
+ * Clears the Map so it has no keys. This is O(1).
+ */
+ public void clear()
+ {
+ if (size != 0)
+ {
+ modCount++;
+ Arrays.fill(buckets, null);
+ size = 0;
+ }
+ }
+
+ /**
+ * Returns true if this HashMap contains a value <code>o</code>, such that
+ * <code>o.equals(value)</code>.
+ *
+ * @param value the value to search for in this HashMap
+ * @return true if at least one key maps to the value
+ * @see containsKey(Object)
+ */
+ public boolean containsValue(Object value)
+ {
+ for (int i = buckets.length - 1; i >= 0; i--)
+ {
+ HashEntry e = buckets[i];
+ while (e != null)
+ {
+ if (equals(value, e.value))
+ return true;
+ e = e.next;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a shallow clone of this HashMap. The Map itself is cloned,
+ * but its contents are not. This is O(n).
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ HashMap copy = null;
+ try
+ {
+ copy = (HashMap) super.clone();
+ }
+ catch (CloneNotSupportedException x)
+ {
+ // This is impossible.
+ }
+ copy.buckets = new HashEntry[buckets.length];
+ copy.putAllInternal(this);
+ // Clear the entry cache. AbstractMap.clone() does the others.
+ copy.entries = null;
+ return copy;
+ }
+
+ /**
+ * Returns a "set view" of this HashMap's keys. The set is backed by the
+ * HashMap, so changes in one show up in the other. The set supports
+ * element removal, but not element addition.
+ *
+ * @return a set view of the keys
+ * @see #values()
+ * @see #entrySet()
+ */
+ public Set keySet()
+ {
+ if (keys == null)
+ // Create an AbstractSet with custom implementations of those methods
+ // that can be overridden easily and efficiently.
+ keys = new AbstractSet()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ // Cannot create the iterator directly, because of LinkedHashMap.
+ return HashMap.this.iterator(KEYS);
+ }
+
+ public void clear()
+ {
+ HashMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return containsKey(o);
+ }
+
+ public boolean remove(Object o)
+ {
+ // Test against the size of the HashMap to determine if anything
+ // really got removed. This is necessary because the return value
+ // of HashMap.remove() is ambiguous in the null case.
+ int oldsize = size;
+ HashMap.this.remove(o);
+ return oldsize != size;
+ }
+ };
+ return keys;
+ }
+
+ /**
+ * Returns a "collection view" (or "bag view") of this HashMap's values.
+ * The collection is backed by the HashMap, so changes in one show up
+ * in the other. The collection supports element removal, but not element
+ * addition.
+ *
+ * @return a bag view of the values
+ * @see #keySet()
+ * @see #entrySet()
+ */
+ public Collection values()
+ {
+ if (values == null)
+ // We don't bother overriding many of the optional methods, as doing so
+ // wouldn't provide any significant performance advantage.
+ values = new AbstractCollection()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ // Cannot create the iterator directly, because of LinkedHashMap.
+ return HashMap.this.iterator(VALUES);
+ }
+
+ public void clear()
+ {
+ HashMap.this.clear();
+ }
+ };
+ return values;
+ }
+
+ /**
+ * Returns a "set view" of this HashMap's entries. The set is backed by
+ * the HashMap, so changes in one show up in the other. The set supports
+ * element removal, but not element addition.<p>
+ *
+ * Note that the iterators for all three views, from keySet(), entrySet(),
+ * and values(), traverse the HashMap in the same sequence.
+ *
+ * @return a set view of the entries
+ * @see #keySet()
+ * @see #values()
+ * @see Map.Entry
+ */
+ public Set entrySet()
+ {
+ if (entries == null)
+ // Create an AbstractSet with custom implementations of those methods
+ // that can be overridden easily and efficiently.
+ entries = new AbstractSet()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ // Cannot create the iterator directly, because of LinkedHashMap.
+ return HashMap.this.iterator(ENTRIES);
+ }
+
+ public void clear()
+ {
+ HashMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return getEntry(o) != null;
+ }
+
+ public boolean remove(Object o)
+ {
+ HashEntry e = getEntry(o);
+ if (e != null)
+ {
+ HashMap.this.remove(e.key);
+ return true;
+ }
+ return false;
+ }
+ };
+ return entries;
+ }
+
+ /**
+ * Helper method for put, that creates and adds a new Entry. This is
+ * overridden in LinkedHashMap for bookkeeping purposes.
+ *
+ * @param key the key of the new Entry
+ * @param value the value
+ * @param idx the index in buckets where the new Entry belongs
+ * @param callRemove whether to call the removeEldestEntry method
+ * @see #put(Object, Object)
+ */
+ void addEntry(Object key, Object value, int idx, boolean callRemove)
+ {
+ HashEntry e = new HashEntry(key, value);
+ e.next = buckets[idx];
+ buckets[idx] = e;
+ }
+
+ /**
+ * Helper method for entrySet(), which matches both key and value
+ * simultaneously.
+ *
+ * @param o the entry to match
+ * @return the matching entry, if found, or null
+ * @see #entrySet()
+ */
+ // Package visible, for use in nested classes.
+ final HashEntry getEntry(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return null;
+ Map.Entry me = (Map.Entry) o;
+ Object key = me.getKey();
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ while (e != null)
+ {
+ if (equals(e.key, key))
+ return equals(e.value, me.getValue()) ? e : null;
+ e = e.next;
+ }
+ return null;
+ }
+
+ /**
+ * Helper method that returns an index in the buckets array for `key'
+ * based on its hashCode(). Package visible for use by subclasses.
+ *
+ * @param key the key
+ * @return the bucket number
+ */
+ final int hash(Object key)
+ {
+ return key == null ? 0 : Math.abs(key.hashCode() % buckets.length);
+ }
+
+ /**
+ * Generates a parameterized iterator. Must be overrideable, since
+ * LinkedHashMap iterates in a different order.
+ *
+ * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+ * @return the appropriate iterator
+ */
+ Iterator iterator(int type)
+ {
+ return new HashIterator(type);
+ }
+
+ /**
+ * A simplified, more efficient internal implementation of putAll(). clone()
+ * should not call putAll or put, in order to be compatible with the JDK
+ * implementation with respect to subclasses.
+ *
+ * @param m the map to initialize this from
+ */
+ void putAllInternal(Map m)
+ {
+ Iterator itr = m.entrySet().iterator();
+ size = 0;
+ while (itr.hasNext())
+ {
+ size++;
+ Map.Entry e = (Map.Entry) itr.next();
+ Object key = e.getKey();
+ int idx = hash(key);
+ addEntry(key, e.getValue(), idx, false);
+ }
+ }
+
+ /**
+ * Increases the size of the HashMap and rehashes all keys to new
+ * array indices; this is called when the addition of a new value
+ * would cause size() &gt; threshold. Note that the existing Entry
+ * objects are reused in the new hash table.
+ *
+ * <p>This is not specified, but the new size is twice the current size
+ * plus one; this number is not always prime, unfortunately.
+ */
+ private void rehash()
+ {
+ HashEntry[] oldBuckets = buckets;
+
+ int newcapacity = (buckets.length * 2) + 1;
+ threshold = (int) (newcapacity * loadFactor);
+ buckets = new HashEntry[newcapacity];
+
+ for (int i = oldBuckets.length - 1; i >= 0; i--)
+ {
+ HashEntry e = oldBuckets[i];
+ while (e != null)
+ {
+ int idx = hash(e.key);
+ HashEntry dest = buckets[idx];
+ HashEntry next = e.next;
+ e.next = buckets[idx];
+ buckets[idx] = e;
+ e = next;
+ }
+ }
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>capacity</i>(int) that is the length of the
+ * bucket array, the <i>size</i>(int) of the hash map
+ * are emitted first. They are followed by size entries,
+ * each consisting of a key (Object) and a value (Object).
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ // Write the threshold and loadFactor fields.
+ s.defaultWriteObject();
+
+ s.writeInt(buckets.length);
+ s.writeInt(size);
+ // Avoid creating a wasted Set by creating the iterator directly.
+ Iterator it = iterator(ENTRIES);
+ while (it.hasNext())
+ {
+ HashEntry entry = (HashEntry) it.next();
+ s.writeObject(entry.key);
+ s.writeObject(entry.value);
+ }
+ }
+
+ /**
+ * Deserializes this object from the given stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>capacity</i>(int) that is the length of the
+ * bucket array, the <i>size</i>(int) of the hash map
+ * are emitted first. They are followed by size entries,
+ * each consisting of a key (Object) and a value (Object).
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ // Read the threshold and loadFactor fields.
+ s.defaultReadObject();
+
+ // Read and use capacity, followed by key/value pairs.
+ buckets = new HashEntry[s.readInt()];
+ int len = s.readInt();
+ size = len;
+ while (len-- > 0)
+ {
+ Object key = s.readObject();
+ addEntry(key, s.readObject(), hash(key), false);
+ }
+ }
+
+ /**
+ * Iterate over HashMap's entries.
+ * This implementation is parameterized to give a sequential view of
+ * keys, values, or entries.
+ *
+ * @author Jon Zeppieri
+ */
+ private final class HashIterator implements Iterator
+ {
+ /**
+ * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
+ * or {@link #ENTRIES}.
+ */
+ private final int type;
+ /**
+ * The number of modifications to the backing HashMap that we know about.
+ */
+ private int knownMod = modCount;
+ /** The number of elements remaining to be returned by next(). */
+ private int count = size;
+ /** Current index in the physical hash table. */
+ private int idx = buckets.length;
+ /** The last Entry returned by a next() call. */
+ private HashEntry last;
+ /**
+ * The next entry that should be returned by next(). It is set to something
+ * if we're iterating through a bucket that contains multiple linked
+ * entries. It is null if next() needs to find a new bucket.
+ */
+ private HashEntry next;
+
+ /**
+ * Construct a new HashIterator with the supplied type.
+ * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+ */
+ HashIterator(int type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Returns true if the Iterator has more elements.
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the HashMap was modified
+ */
+ public boolean hasNext()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ return count > 0;
+ }
+
+ /**
+ * Returns the next element in the Iterator's sequential view.
+ * @return the next element
+ * @throws ConcurrentModificationException if the HashMap was modified
+ * @throws NoSuchElementException if there is none
+ */
+ public Object next()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (count == 0)
+ throw new NoSuchElementException();
+ count--;
+ HashEntry e = next;
+
+ while (e == null)
+ e = buckets[--idx];
+
+ next = e.next;
+ last = e;
+ if (type == VALUES)
+ return e.value;
+ if (type == KEYS)
+ return e.key;
+ return e;
+ }
+
+ /**
+ * Removes from the backing HashMap the last element which was fetched
+ * with the <code>next()</code> method.
+ * @throws ConcurrentModificationException if the HashMap was modified
+ * @throws IllegalStateException if called when there is no last element
+ */
+ public void remove()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (last == null)
+ throw new IllegalStateException();
+
+ HashMap.this.remove(last.key);
+ last = null;
+ knownMod++;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/HashSet.java b/libjava/classpath/java/util/HashSet.java
new file mode 100644
index 00000000000..681d5bb1b07
--- /dev/null
+++ b/libjava/classpath/java/util/HashSet.java
@@ -0,0 +1,293 @@
+/* HashSet.java -- a class providing a HashMap-backed Set
+ Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * This class provides a HashMap-backed implementation of the Set interface.
+ * <p>
+ *
+ * Most operations are O(1), assuming no hash collisions. In the worst
+ * case (where all hashes collide), operations are O(n). Setting the
+ * initial capacity too low will force many resizing operations, but
+ * setting the initial capacity too high (or loadfactor too low) leads
+ * to wasted memory and slower iteration.
+ * <p>
+ *
+ * HashSet accepts the null key and null values. It is not synchronized,
+ * so if you need multi-threaded access, consider using:<br>
+ * <code>Set s = Collections.synchronizedSet(new HashSet(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see Set
+ * @see TreeSet
+ * @see Collections#synchronizedSet(Set)
+ * @see HashMap
+ * @see LinkedHashSet
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class HashSet extends AbstractSet
+ implements Set, Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = -5024744406713321676L;
+
+ /**
+ * The HashMap which backs this Set.
+ */
+ private transient HashMap map;
+
+ /**
+ * Construct a new, empty HashSet whose backing HashMap has the default
+ * capacity (11) and loadFacor (0.75).
+ */
+ public HashSet()
+ {
+ this(HashMap.DEFAULT_CAPACITY, HashMap.DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Construct a new, empty HashSet whose backing HashMap has the supplied
+ * capacity and the default load factor (0.75).
+ *
+ * @param initialCapacity the initial capacity of the backing HashMap
+ * @throws IllegalArgumentException if the capacity is negative
+ */
+ public HashSet(int initialCapacity)
+ {
+ this(initialCapacity, HashMap.DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Construct a new, empty HashSet whose backing HashMap has the supplied
+ * capacity and load factor.
+ *
+ * @param initialCapacity the initial capacity of the backing HashMap
+ * @param loadFactor the load factor of the backing HashMap
+ * @throws IllegalArgumentException if either argument is negative, or
+ * if loadFactor is POSITIVE_INFINITY or NaN
+ */
+ public HashSet(int initialCapacity, float loadFactor)
+ {
+ map = init(initialCapacity, loadFactor);
+ }
+
+ /**
+ * Construct a new HashSet with the same elements as are in the supplied
+ * collection (eliminating any duplicates, of course). The backing storage
+ * has twice the size of the collection, or the default size of 11,
+ * whichever is greater; and the default load factor (0.75).
+ *
+ * @param c a collection of initial set elements
+ * @throws NullPointerException if c is null
+ */
+ public HashSet(Collection c)
+ {
+ this(Math.max(2 * c.size(), HashMap.DEFAULT_CAPACITY));
+ addAll(c);
+ }
+
+ /**
+ * Adds the given Object to the set if it is not already in the Set.
+ * This set permits a null element.
+ *
+ * @param o the Object to add to this Set
+ * @return true if the set did not already contain o
+ */
+ public boolean add(Object o)
+ {
+ return map.put(o, "") == null;
+ }
+
+ /**
+ * Empties this Set of all elements; this takes constant time.
+ */
+ public void clear()
+ {
+ map.clear();
+ }
+
+ /**
+ * Returns a shallow copy of this Set. The Set itself is cloned; its
+ * elements are not.
+ *
+ * @return a shallow clone of the set
+ */
+ public Object clone()
+ {
+ HashSet copy = null;
+ try
+ {
+ copy = (HashSet) super.clone();
+ }
+ catch (CloneNotSupportedException x)
+ {
+ // Impossible to get here.
+ }
+ copy.map = (HashMap) map.clone();
+ return copy;
+ }
+
+ /**
+ * Returns true if the supplied element is in this Set.
+ *
+ * @param o the Object to look for
+ * @return true if it is in the set
+ */
+ public boolean contains(Object o)
+ {
+ return map.containsKey(o);
+ }
+
+ /**
+ * Returns true if this set has no elements in it.
+ *
+ * @return <code>size() == 0</code>.
+ */
+ public boolean isEmpty()
+ {
+ return map.size == 0;
+ }
+
+ /**
+ * Returns an Iterator over the elements of this Set, which visits the
+ * elements in no particular order. For this class, the Iterator allows
+ * removal of elements. The iterator is fail-fast, and will throw a
+ * ConcurrentModificationException if the set is modified externally.
+ *
+ * @return a set iterator
+ * @see ConcurrentModificationException
+ */
+ public Iterator iterator()
+ {
+ // Avoid creating intermediate keySet() object by using non-public API.
+ return map.iterator(HashMap.KEYS);
+ }
+
+ /**
+ * Removes the supplied Object from this Set if it is in the Set.
+ *
+ * @param o the object to remove
+ * @return true if an element was removed
+ */
+ public boolean remove(Object o)
+ {
+ return (map.remove(o) != null);
+ }
+
+ /**
+ * Returns the number of elements in this Set (its cardinality).
+ *
+ * @return the size of the set
+ */
+ public int size()
+ {
+ return map.size;
+ }
+
+ /**
+ * Helper method which initializes the backing Map. Overridden by
+ * LinkedHashSet for correct semantics.
+ *
+ * @param capacity the initial capacity
+ * @param load the initial load factor
+ * @return the backing HashMap
+ */
+ HashMap init(int capacity, float load)
+ {
+ return new HashMap(capacity, load);
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>capacity</i> (int) and <i>loadFactor</i> (float)
+ * of the backing store, followed by the set size (int),
+ * then a listing of its elements (Object) in no order
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ // Avoid creating intermediate keySet() object by using non-public API.
+ Iterator it = map.iterator(HashMap.KEYS);
+ s.writeInt(map.buckets.length);
+ s.writeFloat(map.loadFactor);
+ s.writeInt(map.size);
+ while (it.hasNext())
+ s.writeObject(it.next());
+ }
+
+ /**
+ * Deserializes this object from the given stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>capacity</i> (int) and <i>loadFactor</i> (float)
+ * of the backing store, followed by the set size (int),
+ * then a listing of its elements (Object) in no order
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+
+ map = init(s.readInt(), s.readFloat());
+ for (int size = s.readInt(); size > 0; size--)
+ map.put(s.readObject(), "");
+ }
+}
diff --git a/libjava/classpath/java/util/Hashtable.java b/libjava/classpath/java/util/Hashtable.java
new file mode 100644
index 00000000000..011cafaa855
--- /dev/null
+++ b/libjava/classpath/java/util/Hashtable.java
@@ -0,0 +1,1151 @@
+/* Hashtable.java -- a class providing a basic hashtable data structure,
+ mapping Object --> Object
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+// NOTE: This implementation is very similar to that of HashMap. If you fix
+// a bug in here, chances are you should make a similar change to the HashMap
+// code.
+
+/**
+ * A class which implements a hashtable data structure.
+ * <p>
+ *
+ * This implementation of Hashtable uses a hash-bucket approach. That is:
+ * linear probing and rehashing is avoided; instead, each hashed value maps
+ * to a simple linked-list which, in the best case, only has one node.
+ * Assuming a large enough table, low enough load factor, and / or well
+ * implemented hashCode() methods, Hashtable should provide O(1)
+ * insertion, deletion, and searching of keys. Hashtable is O(n) in
+ * the worst case for all of these (if all keys hash to the same bucket).
+ * <p>
+ *
+ * This is a JDK-1.2 compliant implementation of Hashtable. As such, it
+ * belongs, partially, to the Collections framework (in that it implements
+ * Map). For backwards compatibility, it inherits from the obsolete and
+ * utterly useless Dictionary class.
+ * <p>
+ *
+ * Being a hybrid of old and new, Hashtable has methods which provide redundant
+ * capability, but with subtle and even crucial differences.
+ * For example, one can iterate over various aspects of a Hashtable with
+ * either an Iterator (which is the JDK-1.2 way of doing things) or with an
+ * Enumeration. The latter can end up in an undefined state if the Hashtable
+ * changes while the Enumeration is open.
+ * <p>
+ *
+ * Unlike HashMap, Hashtable does not accept `null' as a key value. Also,
+ * all accesses are synchronized: in a single thread environment, this is
+ * expensive, but in a multi-thread environment, this saves you the effort
+ * of extra synchronization. However, the old-style enumerators are not
+ * synchronized, because they can lead to unspecified behavior even if
+ * they were synchronized. You have been warned.
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * <code>ConcurrentModificationException</code> rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Warren Levy
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see HashMap
+ * @see TreeMap
+ * @see IdentityHashMap
+ * @see LinkedHashMap
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Hashtable extends Dictionary
+ implements Map, Cloneable, Serializable
+{
+ // WARNING: Hashtable is a CORE class in the bootstrap cycle. See the
+ // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+ /** Default number of buckets. This is the value the JDK 1.3 uses. Some
+ * early documentation specified this value as 101. That is incorrect.
+ */
+ private static final int DEFAULT_CAPACITY = 11;
+
+ /** An "enum" of iterator types. */
+ // Package visible for use by nested classes.
+ static final int KEYS = 0,
+ VALUES = 1,
+ ENTRIES = 2;
+
+ /**
+ * The default load factor; this is explicitly specified by the spec.
+ */
+ private static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 1421746759512286392L;
+
+ /**
+ * The rounded product of the capacity and the load factor; when the number
+ * of elements exceeds the threshold, the Hashtable calls
+ * <code>rehash()</code>.
+ * @serial
+ */
+ private int threshold;
+
+ /**
+ * Load factor of this Hashtable: used in computing the threshold.
+ * @serial
+ */
+ private final float loadFactor;
+
+ /**
+ * Array containing the actual key-value mappings.
+ */
+ // Package visible for use by nested classes.
+ transient HashEntry[] buckets;
+
+ /**
+ * Counts the number of modifications this Hashtable has undergone, used
+ * by Iterators to know when to throw ConcurrentModificationExceptions.
+ */
+ // Package visible for use by nested classes.
+ transient int modCount;
+
+ /**
+ * The size of this Hashtable: denotes the number of key-value pairs.
+ */
+ // Package visible for use by nested classes.
+ transient int size;
+
+ /**
+ * The cache for {@link #keySet()}.
+ */
+ private transient Set keys;
+
+ /**
+ * The cache for {@link #values()}.
+ */
+ private transient Collection values;
+
+ /**
+ * The cache for {@link #entrySet()}.
+ */
+ private transient Set entries;
+
+ /**
+ * Class to represent an entry in the hash table. Holds a single key-value
+ * pair. A Hashtable Entry is identical to a HashMap Entry, except that
+ * `null' is not allowed for keys and values.
+ */
+ private static final class HashEntry extends AbstractMap.BasicMapEntry
+ {
+ /** The next entry in the linked list. */
+ HashEntry next;
+
+ /**
+ * Simple constructor.
+ * @param key the key, already guaranteed non-null
+ * @param value the value, already guaranteed non-null
+ */
+ HashEntry(Object key, Object value)
+ {
+ super(key, value);
+ }
+
+ /**
+ * Resets the value.
+ * @param newVal the new value
+ * @return the prior value
+ * @throws NullPointerException if <code>newVal</code> is null
+ */
+ public Object setValue(Object newVal)
+ {
+ if (newVal == null)
+ throw new NullPointerException();
+ return super.setValue(newVal);
+ }
+ }
+
+ /**
+ * Construct a new Hashtable with the default capacity (11) and the default
+ * load factor (0.75).
+ */
+ public Hashtable()
+ {
+ this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Construct a new Hashtable from the given Map, with initial capacity
+ * the greater of the size of <code>m</code> or the default of 11.
+ * <p>
+ *
+ * Every element in Map m will be put into this new Hashtable.
+ *
+ * @param m a Map whose key / value pairs will be put into
+ * the new Hashtable. <b>NOTE: key / value pairs
+ * are not cloned in this constructor.</b>
+ * @throws NullPointerException if m is null, or if m contains a mapping
+ * to or from `null'.
+ * @since 1.2
+ */
+ public Hashtable(Map m)
+ {
+ this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
+ putAll(m);
+ }
+
+ /**
+ * Construct a new Hashtable with a specific inital capacity and
+ * default load factor of 0.75.
+ *
+ * @param initialCapacity the initial capacity of this Hashtable (&gt;= 0)
+ * @throws IllegalArgumentException if (initialCapacity &lt; 0)
+ */
+ public Hashtable(int initialCapacity)
+ {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Construct a new Hashtable with a specific initial capacity and
+ * load factor.
+ *
+ * @param initialCapacity the initial capacity (&gt;= 0)
+ * @param loadFactor the load factor (&gt; 0, not NaN)
+ * @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
+ * ! (loadFactor &gt; 0.0)
+ */
+ public Hashtable(int initialCapacity, float loadFactor)
+ {
+ if (initialCapacity < 0)
+ throw new IllegalArgumentException("Illegal Capacity: "
+ + initialCapacity);
+ if (! (loadFactor > 0)) // check for NaN too
+ throw new IllegalArgumentException("Illegal Load: " + loadFactor);
+
+ if (initialCapacity == 0)
+ initialCapacity = 1;
+ buckets = new HashEntry[initialCapacity];
+ this.loadFactor = loadFactor;
+ threshold = (int) (initialCapacity * loadFactor);
+ }
+
+ /**
+ * Returns the number of key-value mappings currently in this hashtable.
+ * @return the size
+ */
+ public synchronized int size()
+ {
+ return size;
+ }
+
+ /**
+ * Returns true if there are no key-value mappings currently in this table.
+ * @return <code>size() == 0</code>
+ */
+ public synchronized boolean isEmpty()
+ {
+ return size == 0;
+ }
+
+ /**
+ * Return an enumeration of the keys of this table. There's no point
+ * in synchronizing this, as you have already been warned that the
+ * enumeration is not specified to be thread-safe.
+ *
+ * @return the keys
+ * @see #elements()
+ * @see #keySet()
+ */
+ public Enumeration keys()
+ {
+ return new Enumerator(KEYS);
+ }
+
+ /**
+ * Return an enumeration of the values of this table. There's no point
+ * in synchronizing this, as you have already been warned that the
+ * enumeration is not specified to be thread-safe.
+ *
+ * @return the values
+ * @see #keys()
+ * @see #values()
+ */
+ public Enumeration elements()
+ {
+ return new Enumerator(VALUES);
+ }
+
+ /**
+ * Returns true if this Hashtable contains a value <code>o</code>,
+ * such that <code>o.equals(value)</code>. This is the same as
+ * <code>containsValue()</code>, and is O(n).
+ * <p>
+ *
+ * @param value the value to search for in this Hashtable
+ * @return true if at least one key maps to the value
+ * @throws NullPointerException if <code>value</code> is null
+ * @see #containsValue(Object)
+ * @see #containsKey(Object)
+ */
+ public synchronized boolean contains(Object value)
+ {
+ for (int i = buckets.length - 1; i >= 0; i--)
+ {
+ HashEntry e = buckets[i];
+ while (e != null)
+ {
+ if (value.equals(e.value))
+ return true;
+ e = e.next;
+ }
+ }
+
+ // Must throw on null argument even if the table is empty
+ if (value == null)
+ throw new NullPointerException();
+
+ return false;
+ }
+
+ /**
+ * Returns true if this Hashtable contains a value <code>o</code>, such that
+ * <code>o.equals(value)</code>. This is the new API for the old
+ * <code>contains()</code>.
+ *
+ * @param value the value to search for in this Hashtable
+ * @return true if at least one key maps to the value
+ * @see #contains(Object)
+ * @see #containsKey(Object)
+ * @throws NullPointerException if <code>value</code> is null
+ * @since 1.2
+ */
+ public boolean containsValue(Object value)
+ {
+ // Delegate to older method to make sure code overriding it continues
+ // to work.
+ return contains(value);
+ }
+
+ /**
+ * Returns true if the supplied object <code>equals()</code> a key
+ * in this Hashtable.
+ *
+ * @param key the key to search for in this Hashtable
+ * @return true if the key is in the table
+ * @throws NullPointerException if key is null
+ * @see #containsValue(Object)
+ */
+ public synchronized boolean containsKey(Object key)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ while (e != null)
+ {
+ if (key.equals(e.key))
+ return true;
+ e = e.next;
+ }
+ return false;
+ }
+
+ /**
+ * Return the value in this Hashtable associated with the supplied key,
+ * or <code>null</code> if the key maps to nothing.
+ *
+ * @param key the key for which to fetch an associated value
+ * @return what the key maps to, if present
+ * @throws NullPointerException if key is null
+ * @see #put(Object, Object)
+ * @see #containsKey(Object)
+ */
+ public synchronized Object get(Object key)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ while (e != null)
+ {
+ if (key.equals(e.key))
+ return e.value;
+ e = e.next;
+ }
+ return null;
+ }
+
+ /**
+ * Puts the supplied value into the Map, mapped by the supplied key.
+ * Neither parameter may be null. The value may be retrieved by any
+ * object which <code>equals()</code> this key.
+ *
+ * @param key the key used to locate the value
+ * @param value the value to be stored in the table
+ * @return the prior mapping of the key, or null if there was none
+ * @throws NullPointerException if key or value is null
+ * @see #get(Object)
+ * @see Object#equals(Object)
+ */
+ public synchronized Object put(Object key, Object value)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+
+ // Check if value is null since it is not permitted.
+ if (value == null)
+ throw new NullPointerException();
+
+ while (e != null)
+ {
+ if (key.equals(e.key))
+ {
+ // Bypass e.setValue, since we already know value is non-null.
+ Object r = e.value;
+ e.value = value;
+ return r;
+ }
+ else
+ {
+ e = e.next;
+ }
+ }
+
+ // At this point, we know we need to add a new entry.
+ modCount++;
+ if (++size > threshold)
+ {
+ rehash();
+ // Need a new hash value to suit the bigger table.
+ idx = hash(key);
+ }
+
+ e = new HashEntry(key, value);
+
+ e.next = buckets[idx];
+ buckets[idx] = e;
+
+ return null;
+ }
+
+ /**
+ * Removes from the table and returns the value which is mapped by the
+ * supplied key. If the key maps to nothing, then the table remains
+ * unchanged, and <code>null</code> is returned.
+ *
+ * @param key the key used to locate the value to remove
+ * @return whatever the key mapped to, if present
+ */
+ public synchronized Object remove(Object key)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ HashEntry last = null;
+
+ while (e != null)
+ {
+ if (key.equals(e.key))
+ {
+ modCount++;
+ if (last == null)
+ buckets[idx] = e.next;
+ else
+ last.next = e.next;
+ size--;
+ return e.value;
+ }
+ last = e;
+ e = e.next;
+ }
+ return null;
+ }
+
+ /**
+ * Copies all elements of the given map into this hashtable. However, no
+ * mapping can contain null as key or value. If this table already has
+ * a mapping for a key, the new mapping replaces the current one.
+ *
+ * @param m the map to be hashed into this
+ * @throws NullPointerException if m is null, or contains null keys or values
+ */
+ public synchronized void putAll(Map m)
+ {
+ Iterator itr = m.entrySet().iterator();
+
+ while (itr.hasNext())
+ {
+ Map.Entry e = (Map.Entry) itr.next();
+ // Optimize in case the Entry is one of our own.
+ if (e instanceof AbstractMap.BasicMapEntry)
+ {
+ AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
+ put(entry.key, entry.value);
+ }
+ else
+ {
+ put(e.getKey(), e.getValue());
+ }
+ }
+ }
+
+ /**
+ * Clears the hashtable so it has no keys. This is O(1).
+ */
+ public synchronized void clear()
+ {
+ if (size > 0)
+ {
+ modCount++;
+ Arrays.fill(buckets, null);
+ size = 0;
+ }
+ }
+
+ /**
+ * Returns a shallow clone of this Hashtable. The Map itself is cloned,
+ * but its contents are not. This is O(n).
+ *
+ * @return the clone
+ */
+ public synchronized Object clone()
+ {
+ Hashtable copy = null;
+ try
+ {
+ copy = (Hashtable) super.clone();
+ }
+ catch (CloneNotSupportedException x)
+ {
+ // This is impossible.
+ }
+ copy.buckets = new HashEntry[buckets.length];
+ copy.putAllInternal(this);
+ // Clear the caches.
+ copy.keys = null;
+ copy.values = null;
+ copy.entries = null;
+ return copy;
+ }
+
+ /**
+ * Converts this Hashtable to a String, surrounded by braces, and with
+ * key/value pairs listed with an equals sign between, separated by a
+ * comma and space. For example, <code>"{a=1, b=2}"</code>.<p>
+ *
+ * NOTE: if the <code>toString()</code> method of any key or value
+ * throws an exception, this will fail for the same reason.
+ *
+ * @return the string representation
+ */
+ public synchronized String toString()
+ {
+ // Since we are already synchronized, and entrySet().iterator()
+ // would repeatedly re-lock/release the monitor, we directly use the
+ // unsynchronized HashIterator instead.
+ Iterator entries = new HashIterator(ENTRIES);
+ StringBuffer r = new StringBuffer("{");
+ for (int pos = size; pos > 0; pos--)
+ {
+ r.append(entries.next());
+ if (pos > 1)
+ r.append(", ");
+ }
+ r.append("}");
+ return r.toString();
+ }
+
+ /**
+ * Returns a "set view" of this Hashtable's keys. The set is backed by
+ * the hashtable, so changes in one show up in the other. The set supports
+ * element removal, but not element addition. The set is properly
+ * synchronized on the original hashtable. Sun has not documented the
+ * proper interaction of null with this set, but has inconsistent behavior
+ * in the JDK. Therefore, in this implementation, contains, remove,
+ * containsAll, retainAll, removeAll, and equals just ignore a null key
+ * rather than throwing a {@link NullPointerException}.
+ *
+ * @return a set view of the keys
+ * @see #values()
+ * @see #entrySet()
+ * @since 1.2
+ */
+ public Set keySet()
+ {
+ if (keys == null)
+ {
+ // Create a synchronized AbstractSet with custom implementations of
+ // those methods that can be overridden easily and efficiently.
+ Set r = new AbstractSet()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new HashIterator(KEYS);
+ }
+
+ public void clear()
+ {
+ Hashtable.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (o == null)
+ return false;
+ return containsKey(o);
+ }
+
+ public boolean remove(Object o)
+ {
+ return Hashtable.this.remove(o) != null;
+ }
+ };
+ // We must specify the correct object to synchronize upon, hence the
+ // use of a non-public API
+ keys = new Collections.SynchronizedSet(this, r);
+ }
+ return keys;
+ }
+
+ /**
+ * Returns a "collection view" (or "bag view") of this Hashtable's values.
+ * The collection is backed by the hashtable, so changes in one show up
+ * in the other. The collection supports element removal, but not element
+ * addition. The collection is properly synchronized on the original
+ * hashtable. Sun has not documented the proper interaction of null with
+ * this set, but has inconsistent behavior in the JDK. Therefore, in this
+ * implementation, contains, remove, containsAll, retainAll, removeAll, and
+ * equals just ignore a null value rather than throwing a
+ * {@link NullPointerException}.
+ *
+ * @return a bag view of the values
+ * @see #keySet()
+ * @see #entrySet()
+ * @since 1.2
+ */
+ public Collection values()
+ {
+ if (values == null)
+ {
+ // We don't bother overriding many of the optional methods, as doing so
+ // wouldn't provide any significant performance advantage.
+ Collection r = new AbstractCollection()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new HashIterator(VALUES);
+ }
+
+ public void clear()
+ {
+ Hashtable.this.clear();
+ }
+ };
+ // We must specify the correct object to synchronize upon, hence the
+ // use of a non-public API
+ values = new Collections.SynchronizedCollection(this, r);
+ }
+ return values;
+ }
+
+ /**
+ * Returns a "set view" of this Hashtable's entries. The set is backed by
+ * the hashtable, so changes in one show up in the other. The set supports
+ * element removal, but not element addition. The set is properly
+ * synchronized on the original hashtable. Sun has not documented the
+ * proper interaction of null with this set, but has inconsistent behavior
+ * in the JDK. Therefore, in this implementation, contains, remove,
+ * containsAll, retainAll, removeAll, and equals just ignore a null entry,
+ * or an entry with a null key or value, rather than throwing a
+ * {@link NullPointerException}. However, calling entry.setValue(null)
+ * will fail.
+ * <p>
+ *
+ * Note that the iterators for all three views, from keySet(), entrySet(),
+ * and values(), traverse the hashtable in the same sequence.
+ *
+ * @return a set view of the entries
+ * @see #keySet()
+ * @see #values()
+ * @see Map.Entry
+ * @since 1.2
+ */
+ public Set entrySet()
+ {
+ if (entries == null)
+ {
+ // Create an AbstractSet with custom implementations of those methods
+ // that can be overridden easily and efficiently.
+ Set r = new AbstractSet()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new HashIterator(ENTRIES);
+ }
+
+ public void clear()
+ {
+ Hashtable.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return getEntry(o) != null;
+ }
+
+ public boolean remove(Object o)
+ {
+ HashEntry e = getEntry(o);
+ if (e != null)
+ {
+ Hashtable.this.remove(e.key);
+ return true;
+ }
+ return false;
+ }
+ };
+ // We must specify the correct object to synchronize upon, hence the
+ // use of a non-public API
+ entries = new Collections.SynchronizedSet(this, r);
+ }
+ return entries;
+ }
+
+ /**
+ * Returns true if this Hashtable equals the supplied Object <code>o</code>.
+ * As specified by Map, this is:
+ * <code>
+ * (o instanceof Map) && entrySet().equals(((Map) o).entrySet());
+ * </code>
+ *
+ * @param o the object to compare to
+ * @return true if o is an equal map
+ * @since 1.2
+ */
+ public boolean equals(Object o)
+ {
+ // no need to synchronize, entrySet().equals() does that
+ if (o == this)
+ return true;
+ if (!(o instanceof Map))
+ return false;
+
+ return entrySet().equals(((Map) o).entrySet());
+ }
+
+ /**
+ * Returns the hashCode for this Hashtable. As specified by Map, this is
+ * the sum of the hashCodes of all of its Map.Entry objects
+ *
+ * @return the sum of the hashcodes of the entries
+ * @since 1.2
+ */
+ public synchronized int hashCode()
+ {
+ // Since we are already synchronized, and entrySet().iterator()
+ // would repeatedly re-lock/release the monitor, we directly use the
+ // unsynchronized HashIterator instead.
+ Iterator itr = new HashIterator(ENTRIES);
+ int hashcode = 0;
+ for (int pos = size; pos > 0; pos--)
+ hashcode += itr.next().hashCode();
+
+ return hashcode;
+ }
+
+ /**
+ * Helper method that returns an index in the buckets array for `key'
+ * based on its hashCode().
+ *
+ * @param key the key
+ * @return the bucket number
+ * @throws NullPointerException if key is null
+ */
+ private int hash(Object key)
+ {
+ // Note: Inline Math.abs here, for less method overhead, and to avoid
+ // a bootstrap dependency, since Math relies on native methods.
+ int hash = key.hashCode() % buckets.length;
+ return hash < 0 ? -hash : hash;
+ }
+
+ /**
+ * Helper method for entrySet(), which matches both key and value
+ * simultaneously. Ignores null, as mentioned in entrySet().
+ *
+ * @param o the entry to match
+ * @return the matching entry, if found, or null
+ * @see #entrySet()
+ */
+ // Package visible, for use in nested classes.
+ HashEntry getEntry(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return null;
+ Object key = ((Map.Entry) o).getKey();
+ if (key == null)
+ return null;
+
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ while (e != null)
+ {
+ if (o.equals(e))
+ return e;
+ e = e.next;
+ }
+ return null;
+ }
+
+ /**
+ * A simplified, more efficient internal implementation of putAll(). clone()
+ * should not call putAll or put, in order to be compatible with the JDK
+ * implementation with respect to subclasses.
+ *
+ * @param m the map to initialize this from
+ */
+ void putAllInternal(Map m)
+ {
+ Iterator itr = m.entrySet().iterator();
+ size = 0;
+
+ while (itr.hasNext())
+ {
+ size++;
+ Map.Entry e = (Map.Entry) itr.next();
+ Object key = e.getKey();
+ int idx = hash(key);
+ HashEntry he = new HashEntry(key, e.getValue());
+ he.next = buckets[idx];
+ buckets[idx] = he;
+ }
+ }
+
+ /**
+ * Increases the size of the Hashtable and rehashes all keys to new array
+ * indices; this is called when the addition of a new value would cause
+ * size() &gt; threshold. Note that the existing Entry objects are reused in
+ * the new hash table.
+ * <p>
+ *
+ * This is not specified, but the new size is twice the current size plus
+ * one; this number is not always prime, unfortunately. This implementation
+ * is not synchronized, as it is only invoked from synchronized methods.
+ */
+ protected void rehash()
+ {
+ HashEntry[] oldBuckets = buckets;
+
+ int newcapacity = (buckets.length * 2) + 1;
+ threshold = (int) (newcapacity * loadFactor);
+ buckets = new HashEntry[newcapacity];
+
+ for (int i = oldBuckets.length - 1; i >= 0; i--)
+ {
+ HashEntry e = oldBuckets[i];
+ while (e != null)
+ {
+ int idx = hash(e.key);
+ HashEntry dest = buckets[idx];
+
+ if (dest != null)
+ {
+ while (dest.next != null)
+ dest = dest.next;
+ dest.next = e;
+ }
+ else
+ {
+ buckets[idx] = e;
+ }
+
+ HashEntry next = e.next;
+ e.next = null;
+ e = next;
+ }
+ }
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>capacity</i> (int) that is the length of the
+ * bucket array, the <i>size</i> (int) of the hash map
+ * are emitted first. They are followed by size entries,
+ * each consisting of a key (Object) and a value (Object).
+ */
+ private synchronized void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ // Write the threshold and loadFactor fields.
+ s.defaultWriteObject();
+
+ s.writeInt(buckets.length);
+ s.writeInt(size);
+ // Since we are already synchronized, and entrySet().iterator()
+ // would repeatedly re-lock/release the monitor, we directly use the
+ // unsynchronized HashIterator instead.
+ Iterator it = new HashIterator(ENTRIES);
+ while (it.hasNext())
+ {
+ HashEntry entry = (HashEntry) it.next();
+ s.writeObject(entry.key);
+ s.writeObject(entry.value);
+ }
+ }
+
+ /**
+ * Deserializes this object from the given stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>capacity</i> (int) that is the length of the
+ * bucket array, the <i>size</i> (int) of the hash map
+ * are emitted first. They are followed by size entries,
+ * each consisting of a key (Object) and a value (Object).
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ // Read the threshold and loadFactor fields.
+ s.defaultReadObject();
+
+ // Read and use capacity.
+ buckets = new HashEntry[s.readInt()];
+ int len = s.readInt();
+
+ // Read and use key/value pairs.
+ // TODO: should we be defensive programmers, and check for illegal nulls?
+ while (--len >= 0)
+ put(s.readObject(), s.readObject());
+ }
+
+ /**
+ * A class which implements the Iterator interface and is used for
+ * iterating over Hashtables.
+ * This implementation is parameterized to give a sequential view of
+ * keys, values, or entries; it also allows the removal of elements,
+ * as per the Javasoft spec. Note that it is not synchronized; this is
+ * a performance enhancer since it is never exposed externally and is
+ * only used within synchronized blocks above.
+ *
+ * @author Jon Zeppieri
+ */
+ private final class HashIterator implements Iterator
+ {
+ /**
+ * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
+ * or {@link #ENTRIES}.
+ */
+ final int type;
+ /**
+ * The number of modifications to the backing Hashtable that we know about.
+ */
+ int knownMod = modCount;
+ /** The number of elements remaining to be returned by next(). */
+ int count = size;
+ /** Current index in the physical hash table. */
+ int idx = buckets.length;
+ /** The last Entry returned by a next() call. */
+ HashEntry last;
+ /**
+ * The next entry that should be returned by next(). It is set to something
+ * if we're iterating through a bucket that contains multiple linked
+ * entries. It is null if next() needs to find a new bucket.
+ */
+ HashEntry next;
+
+ /**
+ * Construct a new HashIterator with the supplied type.
+ * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+ */
+ HashIterator(int type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Returns true if the Iterator has more elements.
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the hashtable was modified
+ */
+ public boolean hasNext()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ return count > 0;
+ }
+
+ /**
+ * Returns the next element in the Iterator's sequential view.
+ * @return the next element
+ * @throws ConcurrentModificationException if the hashtable was modified
+ * @throws NoSuchElementException if there is none
+ */
+ public Object next()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (count == 0)
+ throw new NoSuchElementException();
+ count--;
+ HashEntry e = next;
+
+ while (e == null)
+ e = buckets[--idx];
+
+ next = e.next;
+ last = e;
+ if (type == VALUES)
+ return e.value;
+ if (type == KEYS)
+ return e.key;
+ return e;
+ }
+
+ /**
+ * Removes from the backing Hashtable the last element which was fetched
+ * with the <code>next()</code> method.
+ * @throws ConcurrentModificationException if the hashtable was modified
+ * @throws IllegalStateException if called when there is no last element
+ */
+ public void remove()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (last == null)
+ throw new IllegalStateException();
+
+ Hashtable.this.remove(last.key);
+ last = null;
+ knownMod++;
+ }
+ } // class HashIterator
+
+
+ /**
+ * Enumeration view of this Hashtable, providing sequential access to its
+ * elements; this implementation is parameterized to provide access either
+ * to the keys or to the values in the Hashtable.
+ *
+ * <b>NOTE</b>: Enumeration is not safe if new elements are put in the table
+ * as this could cause a rehash and we'd completely lose our place. Even
+ * without a rehash, it is undetermined if a new element added would
+ * appear in the enumeration. The spec says nothing about this, but
+ * the "Java Class Libraries" book infers that modifications to the
+ * hashtable during enumeration causes indeterminate results. Don't do it!
+ *
+ * @author Jon Zeppieri
+ */
+ private final class Enumerator implements Enumeration
+ {
+ /**
+ * The type of this Iterator: {@link #KEYS} or {@link #VALUES}.
+ */
+ final int type;
+ /** The number of elements remaining to be returned by next(). */
+ int count = size;
+ /** Current index in the physical hash table. */
+ int idx = buckets.length;
+ /**
+ * Entry which will be returned by the next nextElement() call. It is
+ * set if we are iterating through a bucket with multiple entries, or null
+ * if we must look in the next bucket.
+ */
+ HashEntry next;
+
+ /**
+ * Construct the enumeration.
+ * @param type either {@link #KEYS} or {@link #VALUES}.
+ */
+ Enumerator(int type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Checks whether more elements remain in the enumeration.
+ * @return true if nextElement() will not fail.
+ */
+ public boolean hasMoreElements()
+ {
+ return count > 0;
+ }
+
+ /**
+ * Returns the next element.
+ * @return the next element
+ * @throws NoSuchElementException if there is none.
+ */
+ public Object nextElement()
+ {
+ if (count == 0)
+ throw new NoSuchElementException("Hashtable Enumerator");
+ count--;
+ HashEntry e = next;
+
+ while (e == null)
+ e = buckets[--idx];
+
+ next = e.next;
+ return type == VALUES ? e.value : e.key;
+ }
+ } // class Enumerator
+} // class Hashtable
diff --git a/libjava/classpath/java/util/IdentityHashMap.java b/libjava/classpath/java/util/IdentityHashMap.java
new file mode 100644
index 00000000000..6369fac691b
--- /dev/null
+++ b/libjava/classpath/java/util/IdentityHashMap.java
@@ -0,0 +1,935 @@
+/* IdentityHashMap.java -- a class providing a hashtable data structure,
+ mapping Object --> Object, which uses object identity for hashing.
+ Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * This class provides a hashtable-backed implementation of the
+ * Map interface, but uses object identity to do its hashing. In fact,
+ * it uses object identity for comparing values, as well. It uses a
+ * linear-probe hash table, which may have faster performance
+ * than the chaining employed by HashMap.
+ * <p>
+ *
+ * <em>WARNING: This is not a general purpose map. Because it uses
+ * System.identityHashCode and ==, instead of hashCode and equals, for
+ * comparison, it violated Map's general contract, and may cause
+ * undefined behavior when compared to other maps which are not
+ * IdentityHashMaps. This is designed only for the rare cases when
+ * identity semantics are needed.</em> An example use is
+ * topology-preserving graph transformations, such as deep cloning,
+ * or as proxy object mapping such as in debugging.
+ * <p>
+ *
+ * This map permits <code>null</code> keys and values, and does not
+ * guarantee that elements will stay in the same order over time. The
+ * basic operations (<code>get</code> and <code>put</code>) take
+ * constant time, provided System.identityHashCode is decent. You can
+ * tune the behavior by specifying the expected maximum size. As more
+ * elements are added, the map may need to allocate a larger table,
+ * which can be expensive.
+ * <p>
+ *
+ * This implementation is unsynchronized. If you want multi-thread
+ * access to be consistent, you must synchronize it, perhaps by using
+ * <code>Collections.synchronizedMap(new IdentityHashMap(...));</code>.
+ * The iterators are <i>fail-fast</i>, meaning that a structural modification
+ * made to the map outside of an iterator's remove method cause the
+ * iterator, and in the case of the entrySet, the Map.Entry, to
+ * fail with a {@link ConcurrentModificationException}.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see System#identityHashCode(Object)
+ * @see Collection
+ * @see Map
+ * @see HashMap
+ * @see TreeMap
+ * @see LinkedHashMap
+ * @see WeakHashMap
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class IdentityHashMap extends AbstractMap
+ implements Map, Serializable, Cloneable
+{
+ /** The default capacity. */
+ private static final int DEFAULT_CAPACITY = 21;
+
+ /**
+ * This object is used to mark deleted items. Package visible for use by
+ * nested classes.
+ */
+ static final Object tombstone = new Object();
+
+ /**
+ * This object is used to mark empty slots. We need this because
+ * using null is ambiguous. Package visible for use by nested classes.
+ */
+ static final Object emptyslot = new Object();
+
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 8188218128353913216L;
+
+ /**
+ * The number of mappings in the table. Package visible for use by nested
+ * classes.
+ * @serial
+ */
+ int size;
+
+ /**
+ * The table itself. Package visible for use by nested classes.
+ */
+ transient Object[] table;
+
+ /**
+ * The number of structural modifications made so far. Package visible for
+ * use by nested classes.
+ */
+ transient int modCount;
+
+ /**
+ * The cache for {@link #entrySet()}.
+ */
+ private transient Set entries;
+
+ /**
+ * The threshold for rehashing, which is 75% of (table.length / 2).
+ */
+ private transient int threshold;
+
+ /**
+ * Create a new IdentityHashMap with the default capacity (21 entries).
+ */
+ public IdentityHashMap()
+ {
+ this(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * Create a new IdentityHashMap with the indicated number of
+ * entries. If the number of elements added to this hash map
+ * exceeds this maximum, the map will grow itself; however, that
+ * incurs a performance penalty.
+ *
+ * @param max initial size
+ * @throws IllegalArgumentException if max is negative
+ */
+ public IdentityHashMap(int max)
+ {
+ if (max < 0)
+ throw new IllegalArgumentException();
+ // Need at least two slots, or hash() will break.
+ if (max < 2)
+ max = 2;
+ table = new Object[max << 1];
+ Arrays.fill(table, emptyslot);
+ threshold = (max >> 2) * 3;
+ }
+
+ /**
+ * Create a new IdentityHashMap whose contents are taken from the
+ * given Map.
+ *
+ * @param m The map whose elements are to be put in this map
+ * @throws NullPointerException if m is null
+ */
+ public IdentityHashMap(Map m)
+ {
+ this(Math.max(m.size() << 1, DEFAULT_CAPACITY));
+ putAll(m);
+ }
+
+ /**
+ * Remove all mappings from this map.
+ */
+ public void clear()
+ {
+ if (size != 0)
+ {
+ modCount++;
+ Arrays.fill(table, emptyslot);
+ size = 0;
+ }
+ }
+
+ /**
+ * Creates a shallow copy where keys and values are not cloned.
+ */
+ public Object clone()
+ {
+ try
+ {
+ IdentityHashMap copy = (IdentityHashMap) super.clone();
+ copy.table = (Object[]) table.clone();
+ copy.entries = null; // invalidate the cache
+ return copy;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // Can't happen.
+ return null;
+ }
+ }
+
+ /**
+ * Tests whether the specified key is in this map. Unlike normal Maps,
+ * this test uses <code>entry == key</code> instead of
+ * <code>entry == null ? key == null : entry.equals(key)</code>.
+ *
+ * @param key the key to look for
+ * @return true if the key is contained in the map
+ * @see #containsValue(Object)
+ * @see #get(Object)
+ */
+ public boolean containsKey(Object key)
+ {
+ return key == table[hash(key)];
+ }
+
+ /**
+ * Returns true if this HashMap contains the value. Unlike normal maps,
+ * this test uses <code>entry == value</code> instead of
+ * <code>entry == null ? value == null : entry.equals(value)</code>.
+ *
+ * @param value the value to search for in this HashMap
+ * @return true if at least one key maps to the value
+ * @see #containsKey(Object)
+ */
+ public boolean containsValue(Object value)
+ {
+ for (int i = table.length - 1; i > 0; i -= 2)
+ if (table[i] == value)
+ return true;
+ return false;
+ }
+
+ /**
+ * Returns a "set view" of this Map's entries. The set is backed by
+ * the Map, so changes in one show up in the other. The set supports
+ * element removal, but not element addition.
+ * <p>
+ *
+ * <em>The semantics of this set, and of its contained entries, are
+ * different from the contract of Set and Map.Entry in order to make
+ * IdentityHashMap work. This means that while you can compare these
+ * objects between IdentityHashMaps, comparing them with regular sets
+ * or entries is likely to have undefined behavior.</em> The entries
+ * in this set are reference-based, rather than the normal object
+ * equality. Therefore, <code>e1.equals(e2)</code> returns
+ * <code>e1.getKey() == e2.getKey() && e1.getValue() == e2.getValue()</code>,
+ * and <code>e.hashCode()</code> returns
+ * <code>System.identityHashCode(e.getKey()) ^
+ * System.identityHashCode(e.getValue())</code>.
+ * <p>
+ *
+ * Note that the iterators for all three views, from keySet(), entrySet(),
+ * and values(), traverse the Map in the same sequence.
+ *
+ * @return a set view of the entries
+ * @see #keySet()
+ * @see #values()
+ * @see Map.Entry
+ */
+ public Set entrySet()
+ {
+ if (entries == null)
+ entries = new AbstractSet()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new IdentityIterator(ENTRIES);
+ }
+
+ public void clear()
+ {
+ IdentityHashMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry m = (Map.Entry) o;
+ return m.getValue() == table[hash(m.getKey()) + 1];
+ }
+
+ public int hashCode()
+ {
+ return IdentityHashMap.this.hashCode();
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Object key = ((Map.Entry) o).getKey();
+ int h = hash(key);
+ if (table[h] == key)
+ {
+ size--;
+ modCount++;
+ table[h] = tombstone;
+ table[h + 1] = tombstone;
+ return true;
+ }
+ return false;
+ }
+ };
+ return entries;
+ }
+
+ /**
+ * Compares two maps for equality. This returns true only if both maps
+ * have the same reference-identity comparisons. While this returns
+ * <code>this.entrySet().equals(m.entrySet())</code> as specified by Map,
+ * this will not work with normal maps, since the entry set compares
+ * with == instead of .equals.
+ *
+ * @param o the object to compare to
+ * @return true if it is equal
+ */
+ public boolean equals(Object o)
+ {
+ // Why did Sun specify this one? The superclass does the right thing.
+ return super.equals(o);
+ }
+
+ /**
+ * Return the value in this Map associated with the supplied key, or
+ * <code>null</code> if the key maps to nothing.
+ *
+ * <p>NOTE: Since the value could also be null, you must use
+ * containsKey to see if this key actually maps to something.
+ * Unlike normal maps, this tests for the key with <code>entry ==
+ * key</code> instead of <code>entry == null ? key == null :
+ * entry.equals(key)</code>.
+ *
+ * @param key the key for which to fetch an associated value
+ * @return what the key maps to, if present
+ * @see #put(Object, Object)
+ * @see #containsKey(Object)
+ */
+ public Object get(Object key)
+ {
+ int h = hash(key);
+ return table[h] == key ? table[h + 1] : null;
+ }
+
+ /**
+ * Returns the hashcode of this map. This guarantees that two
+ * IdentityHashMaps that compare with equals() will have the same hash code,
+ * but may break with comparison to normal maps since it uses
+ * System.identityHashCode() instead of hashCode().
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ int hash = 0;
+ for (int i = table.length - 2; i >= 0; i -= 2)
+ {
+ Object key = table[i];
+ if (key == emptyslot || key == tombstone)
+ continue;
+ hash += (System.identityHashCode(key)
+ ^ System.identityHashCode(table[i + 1]));
+ }
+ return hash;
+ }
+
+ /**
+ * Returns true if there are no key-value mappings currently in this Map
+ * @return <code>size() == 0</code>
+ */
+ public boolean isEmpty()
+ {
+ return size == 0;
+ }
+
+ /**
+ * Returns a "set view" of this Map's keys. The set is backed by the
+ * Map, so changes in one show up in the other. The set supports
+ * element removal, but not element addition.
+ * <p>
+ *
+ * <em>The semantics of this set are different from the contract of Set
+ * in order to make IdentityHashMap work. This means that while you can
+ * compare these objects between IdentityHashMaps, comparing them with
+ * regular sets is likely to have undefined behavior.</em> The hashCode
+ * of the set is the sum of the identity hash codes, instead of the
+ * regular hashCodes, and equality is determined by reference instead
+ * of by the equals method.
+ * <p>
+ *
+ * @return a set view of the keys
+ * @see #values()
+ * @see #entrySet()
+ */
+ public Set keySet()
+ {
+ if (keys == null)
+ keys = new AbstractSet()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new IdentityIterator(KEYS);
+ }
+
+ public void clear()
+ {
+ IdentityHashMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return containsKey(o);
+ }
+
+ public int hashCode()
+ {
+ int hash = 0;
+ for (int i = table.length - 2; i >= 0; i -= 2)
+ {
+ Object key = table[i];
+ if (key == emptyslot || key == tombstone)
+ continue;
+ hash += System.identityHashCode(key);
+ }
+ return hash;
+
+ }
+
+ public boolean remove(Object o)
+ {
+ int h = hash(o);
+ if (table[h] == o)
+ {
+ size--;
+ modCount++;
+ table[h] = tombstone;
+ table[h + 1] = tombstone;
+ return true;
+ }
+ return false;
+ }
+ };
+ return keys;
+ }
+
+ /**
+ * Puts the supplied value into the Map, mapped by the supplied key.
+ * The value may be retrieved by any object which <code>equals()</code>
+ * this key. NOTE: Since the prior value could also be null, you must
+ * first use containsKey if you want to see if you are replacing the
+ * key's mapping. Unlike normal maps, this tests for the key
+ * with <code>entry == key</code> instead of
+ * <code>entry == null ? key == null : entry.equals(key)</code>.
+ *
+ * @param key the key used to locate the value
+ * @param value the value to be stored in the HashMap
+ * @return the prior mapping of the key, or null if there was none
+ * @see #get(Object)
+ */
+ public Object put(Object key, Object value)
+ {
+ // Rehash if the load factor is too high.
+ if (size > threshold)
+ {
+ Object[] old = table;
+ // This isn't necessarily prime, but it is an odd number of key/value
+ // slots, which has a higher probability of fewer collisions.
+ table = new Object[(old.length * 2) + 2];
+ Arrays.fill(table, emptyslot);
+ size = 0;
+ threshold = (table.length >>> 3) * 3;
+
+ for (int i = old.length - 2; i >= 0; i -= 2)
+ {
+ Object oldkey = old[i];
+ if (oldkey != tombstone && oldkey != emptyslot)
+ // Just use put. This isn't very efficient, but it is ok.
+ put(oldkey, old[i + 1]);
+ }
+ }
+
+ int h = hash(key);
+ if (table[h] == key)
+ {
+ Object r = table[h + 1];
+ table[h + 1] = value;
+ return r;
+ }
+
+ // At this point, we add a new mapping.
+ modCount++;
+ size++;
+ table[h] = key;
+ table[h + 1] = value;
+ return null;
+ }
+
+ /**
+ * Copies all of the mappings from the specified map to this. If a key
+ * is already in this map, its value is replaced.
+ *
+ * @param m the map to copy
+ * @throws NullPointerException if m is null
+ */
+ public void putAll(Map m)
+ {
+ // Why did Sun specify this one? The superclass does the right thing.
+ super.putAll(m);
+ }
+
+ /**
+ * Removes from the HashMap and returns the value which is mapped by
+ * the supplied key. If the key maps to nothing, then the HashMap
+ * remains unchanged, and <code>null</code> is returned.
+ *
+ * NOTE: Since the value could also be null, you must use
+ * containsKey to see if you are actually removing a mapping.
+ * Unlike normal maps, this tests for the key with <code>entry ==
+ * key</code> instead of <code>entry == null ? key == null :
+ * entry.equals(key)</code>.
+ *
+ * @param key the key used to locate the value to remove
+ * @return whatever the key mapped to, if present
+ */
+ public Object remove(Object key)
+ {
+ int h = hash(key);
+ if (table[h] == key)
+ {
+ modCount++;
+ size--;
+ Object r = table[h + 1];
+ table[h] = tombstone;
+ table[h + 1] = tombstone;
+ return r;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the number of kay-value mappings currently in this Map
+ * @return the size
+ */
+ public int size()
+ {
+ return size;
+ }
+
+ /**
+ * Returns a "collection view" (or "bag view") of this Map's values.
+ * The collection is backed by the Map, so changes in one show up
+ * in the other. The collection supports element removal, but not element
+ * addition.
+ * <p>
+ *
+ * <em>The semantics of this set are different from the contract of
+ * Collection in order to make IdentityHashMap work. This means that
+ * while you can compare these objects between IdentityHashMaps, comparing
+ * them with regular sets is likely to have undefined behavior.</em>
+ * Likewise, contains and remove go by == instead of equals().
+ * <p>
+ *
+ * @return a bag view of the values
+ * @see #keySet()
+ * @see #entrySet()
+ */
+ public Collection values()
+ {
+ if (values == null)
+ values = new AbstractCollection()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new IdentityIterator(VALUES);
+ }
+
+ public void clear()
+ {
+ IdentityHashMap.this.clear();
+ }
+
+ public boolean remove(Object o)
+ {
+ for (int i = table.length - 1; i > 0; i -= 2)
+ if (table[i] == o)
+ {
+ modCount++;
+ table[i - 1] = tombstone;
+ table[i] = tombstone;
+ size--;
+ return true;
+ }
+ return false;
+ }
+ };
+ return values;
+ }
+
+ /**
+ * Helper method which computes the hash code, then traverses the table
+ * until it finds the key, or the spot where the key would go.
+ *
+ * @param key the key to check
+ * @return the index where the key belongs
+ * @see #IdentityHashMap(int)
+ * @see #put(Object, Object)
+ */
+ // Package visible for use by nested classes.
+ int hash(Object key)
+ {
+ // Implementation note: it is feasible for the table to have no
+ // emptyslots, if it is full with entries and tombstones, so we must
+ // remember where we started. If we encounter the key or an emptyslot,
+ // we are done. If we encounter a tombstone, the key may still be in
+ // the array. If we don't encounter the key, we use the first emptyslot
+ // or tombstone we encountered as the location where the key would go.
+ // By requiring at least 2 key/value slots, and rehashing at 75%
+ // capacity, we guarantee that there will always be either an emptyslot
+ // or a tombstone somewhere in the table.
+ int h = Math.abs(System.identityHashCode(key) % (table.length >> 1)) << 1;
+ int del = -1;
+ int save = h;
+
+ do
+ {
+ if (table[h] == key)
+ return h;
+ if (table[h] == emptyslot)
+ break;
+ if (table[h] == tombstone && del < 0)
+ del = h;
+ h -= 2;
+ if (h < 0)
+ h = table.length - 2;
+ }
+ while (h != save);
+
+ return del < 0 ? h : del;
+ }
+
+ /**
+ * This class allows parameterized iteration over IdentityHashMaps. Based
+ * on its construction, it returns the key or value of a mapping, or
+ * creates the appropriate Map.Entry object with the correct fail-fast
+ * semantics and identity comparisons.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private class IdentityIterator implements Iterator
+ {
+ /**
+ * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
+ * or {@link #ENTRIES}.
+ */
+ final int type;
+ /** The number of modifications to the backing Map that we know about. */
+ int knownMod = modCount;
+ /** The number of elements remaining to be returned by next(). */
+ int count = size;
+ /** Location in the table. */
+ int loc = table.length;
+
+ /**
+ * Construct a new Iterator with the supplied type.
+ * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+ */
+ IdentityIterator(int type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Returns true if the Iterator has more elements.
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the Map was modified
+ */
+ public boolean hasNext()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ return count > 0;
+ }
+
+ /**
+ * Returns the next element in the Iterator's sequential view.
+ * @return the next element
+ * @throws ConcurrentModificationException if the Map was modified
+ * @throws NoSuchElementException if there is none
+ */
+ public Object next()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (count == 0)
+ throw new NoSuchElementException();
+ count--;
+
+ Object key;
+ do
+ {
+ loc -= 2;
+ key = table[loc];
+ }
+ while (key == emptyslot || key == tombstone);
+
+ return type == KEYS ? key : (type == VALUES ? table[loc + 1]
+ : new IdentityEntry(loc));
+ }
+
+ /**
+ * Removes from the backing Map the last element which was fetched
+ * with the <code>next()</code> method.
+ *
+ * @throws ConcurrentModificationException if the Map was modified
+ * @throws IllegalStateException if called when there is no last element
+ */
+ public void remove()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (loc == table.length || table[loc] == tombstone)
+ throw new IllegalStateException();
+ modCount++;
+ size--;
+ table[loc] = tombstone;
+ table[loc + 1] = tombstone;
+ knownMod++;
+ }
+ } // class IdentityIterator
+
+ /**
+ * This class provides Map.Entry objects for IdentityHashMaps. The entry
+ * is fail-fast, and will throw a ConcurrentModificationException if
+ * the underlying map is modified, or if remove is called on the iterator
+ * that generated this object. It is identity based, so it violates
+ * the general contract of Map.Entry, and is probably unsuitable for
+ * comparison to normal maps; but it works among other IdentityHashMaps.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private final class IdentityEntry implements Map.Entry
+ {
+ /** The location of this entry. */
+ final int loc;
+ /** The number of modifications to the backing Map that we know about. */
+ final int knownMod = modCount;
+
+ /**
+ * Constructs the Entry.
+ *
+ * @param loc the location of this entry in table
+ */
+ IdentityEntry(int loc)
+ {
+ this.loc = loc;
+ }
+
+ /**
+ * Compares the specified object with this entry, using identity
+ * semantics. Note that this can lead to undefined results with
+ * Entry objects created by normal maps.
+ *
+ * @param o the object to compare
+ * @return true if it is equal
+ * @throws ConcurrentModificationException if the entry was invalidated
+ * by modifying the Map or calling Iterator.remove()
+ */
+ public boolean equals(Object o)
+ {
+ if (knownMod != modCount || table[loc] == tombstone)
+ throw new ConcurrentModificationException();
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry e = (Map.Entry) o;
+ return table[loc] == e.getKey() && table[loc + 1] == e.getValue();
+ }
+
+ /**
+ * Returns the key of this entry.
+ *
+ * @return the key
+ * @throws ConcurrentModificationException if the entry was invalidated
+ * by modifying the Map or calling Iterator.remove()
+ */
+ public Object getKey()
+ {
+ if (knownMod != modCount || table[loc] == tombstone)
+ throw new ConcurrentModificationException();
+ return table[loc];
+ }
+
+ /**
+ * Returns the value of this entry.
+ *
+ * @return the value
+ * @throws ConcurrentModificationException if the entry was invalidated
+ * by modifying the Map or calling Iterator.remove()
+ */
+ public Object getValue()
+ {
+ if (knownMod != modCount || table[loc] == tombstone)
+ throw new ConcurrentModificationException();
+ return table[loc + 1];
+ }
+
+ /**
+ * Returns the hashcode of the entry, using identity semantics.
+ * Note that this can lead to undefined results with Entry objects
+ * created by normal maps.
+ *
+ * @return the hash code
+ * @throws ConcurrentModificationException if the entry was invalidated
+ * by modifying the Map or calling Iterator.remove()
+ */
+ public int hashCode()
+ {
+ if (knownMod != modCount || table[loc] == tombstone)
+ throw new ConcurrentModificationException();
+ return (System.identityHashCode(table[loc])
+ ^ System.identityHashCode(table[loc + 1]));
+ }
+
+ /**
+ * Replaces the value of this mapping, and returns the old value.
+ *
+ * @param value the new value
+ * @return the old value
+ * @throws ConcurrentModificationException if the entry was invalidated
+ * by modifying the Map or calling Iterator.remove()
+ */
+ public Object setValue(Object value)
+ {
+ if (knownMod != modCount || table[loc] == tombstone)
+ throw new ConcurrentModificationException();
+ Object r = table[loc + 1];
+ table[loc + 1] = value;
+ return r;
+ }
+
+ /**
+ * This provides a string representation of the entry. It is of the form
+ * "key=value", where string concatenation is used on key and value.
+ *
+ * @return the string representation
+ * @throws ConcurrentModificationException if the entry was invalidated
+ * by modifying the Map or calling Iterator.remove()
+ */
+ public String toString()
+ {
+ if (knownMod != modCount || table[loc] == tombstone)
+ throw new ConcurrentModificationException();
+ return table[loc] + "=" + table[loc + 1];
+ }
+ } // class IdentityEntry
+
+ /**
+ * Reads the object from a serial stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @serialData expects the size (int), followed by that many key (Object)
+ * and value (Object) pairs, with the pairs in no particular
+ * order
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+
+ int num = s.readInt();
+ table = new Object[Math.max(num << 1, DEFAULT_CAPACITY) << 1];
+ // Read key/value pairs.
+ while (--num >= 0)
+ put(s.readObject(), s.readObject());
+ }
+
+ /**
+ * Writes the object to a serial stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData outputs the size (int), followed by that many key (Object)
+ * and value (Object) pairs, with the pairs in no particular
+ * order
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ s.defaultWriteObject();
+ s.writeInt(size);
+ for (int i = table.length - 2; i >= 0; i -= 2)
+ {
+ Object key = table[i];
+ if (key != tombstone && key != emptyslot)
+ {
+ s.writeObject(key);
+ s.writeObject(table[i + 1]);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/Iterator.java b/libjava/classpath/java/util/Iterator.java
new file mode 100644
index 00000000000..31ecff8a257
--- /dev/null
+++ b/libjava/classpath/java/util/Iterator.java
@@ -0,0 +1,87 @@
+/* Iterator.java -- Interface for iterating over collections
+ Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An object which iterates over a collection. An Iterator is used to return
+ * the items once only, in sequence, by successive calls to the next method.
+ * It is also possible to remove elements from the underlying collection by
+ * using the optional remove method. Iterator is intended as a replacement
+ * for the Enumeration interface of previous versions of Java, which did not
+ * have the remove method and had less conveniently named methods.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see ListIterator
+ * @see Enumeration
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Iterator
+{
+ /**
+ * Tests whether there are elements remaining in the collection. In other
+ * words, calling <code>next()</code> will not throw an exception.
+ *
+ * @return true if there is at least one more element in the collection
+ */
+ boolean hasNext();
+
+ /**
+ * Obtain the next element in the collection.
+ *
+ * @return the next element in the collection
+ * @throws NoSuchElementException if there are no more elements
+ */
+ Object next();
+
+ /**
+ * Remove from the underlying collection the last element returned by next
+ * (optional operation). This method can be called only once after each
+ * call to <code>next()</code>. It does not affect what will be returned
+ * by subsequent calls to next.
+ *
+ * @throws IllegalStateException if next has not yet been called or remove
+ * has already been called since the last call to next.
+ * @throws UnsupportedOperationException if this Iterator does not support
+ * the remove operation.
+ */
+ void remove();
+}
diff --git a/libjava/classpath/java/util/LinkedHashMap.java b/libjava/classpath/java/util/LinkedHashMap.java
new file mode 100644
index 00000000000..8e895a9e0d8
--- /dev/null
+++ b/libjava/classpath/java/util/LinkedHashMap.java
@@ -0,0 +1,501 @@
+/* LinkedHashMap.java -- a class providing hashtable data structure,
+ mapping Object --> Object, with linked list traversal
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This class provides a hashtable-backed implementation of the
+ * Map interface, with predictable traversal order.
+ * <p>
+ *
+ * It uses a hash-bucket approach; that is, hash collisions are handled
+ * by linking the new node off of the pre-existing node (or list of
+ * nodes). In this manner, techniques such as linear probing (which
+ * can cause primary clustering) and rehashing (which does not fit very
+ * well with Java's method of precomputing hash codes) are avoided. In
+ * addition, this maintains a doubly-linked list which tracks either
+ * insertion or access order.
+ * <p>
+ *
+ * In insertion order, calling <code>put</code> adds the key to the end of
+ * traversal, unless the key was already in the map; changing traversal order
+ * requires removing and reinserting a key. On the other hand, in access
+ * order, all calls to <code>put</code> and <code>get</code> cause the
+ * accessed key to move to the end of the traversal list. Note that any
+ * accesses to the map's contents via its collection views and iterators do
+ * not affect the map's traversal order, since the collection views do not
+ * call <code>put</code> or <code>get</code>.
+ * <p>
+ *
+ * One of the nice features of tracking insertion order is that you can
+ * copy a hashtable, and regardless of the implementation of the original,
+ * produce the same results when iterating over the copy. This is possible
+ * without needing the overhead of <code>TreeMap</code>.
+ * <p>
+ *
+ * When using this {@link #LinkedHashMap(int, float, boolean) constructor},
+ * you can build an access-order mapping. This can be used to implement LRU
+ * caches, for example. By overriding {@link #removeEldestEntry(Map.Entry)},
+ * you can also control the removal of the oldest entry, and thereby do
+ * things like keep the map at a fixed size.
+ * <p>
+ *
+ * Under ideal circumstances (no collisions), LinkedHashMap offers O(1)
+ * performance on most operations (<code>containsValue()</code> is,
+ * of course, O(n)). In the worst case (all keys map to the same
+ * hash code -- very unlikely), most operations are O(n). Traversal is
+ * faster than in HashMap (proportional to the map size, and not the space
+ * allocated for the map), but other operations may be slower because of the
+ * overhead of the maintaining the traversal order list.
+ * <p>
+ *
+ * LinkedHashMap accepts the null key and null values. It is not
+ * synchronized, so if you need multi-threaded access, consider using:<br>
+ * <code>Map m = Collections.synchronizedMap(new LinkedHashMap(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Object#hashCode()
+ * @see Collection
+ * @see Map
+ * @see HashMap
+ * @see TreeMap
+ * @see Hashtable
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class LinkedHashMap extends HashMap
+{
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 3801124242820219131L;
+
+ /**
+ * The oldest Entry to begin iteration at.
+ */
+ transient LinkedHashEntry root;
+
+ /**
+ * The iteration order of this linked hash map: <code>true</code> for
+ * access-order, <code>false</code> for insertion-order.
+ *
+ * @serial true for access order traversal
+ */
+ final boolean accessOrder;
+
+ /**
+ * Class to represent an entry in the hash table. Holds a single key-value
+ * pair and the doubly-linked insertion order list.
+ */
+ class LinkedHashEntry extends HashEntry
+ {
+ /**
+ * The predecessor in the iteration list. If this entry is the root
+ * (eldest), pred points to the newest entry.
+ */
+ LinkedHashEntry pred;
+
+ /** The successor in the iteration list, null if this is the newest. */
+ LinkedHashEntry succ;
+
+ /**
+ * Simple constructor.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ LinkedHashEntry(Object key, Object value)
+ {
+ super(key, value);
+ if (root == null)
+ {
+ root = this;
+ pred = this;
+ }
+ else
+ {
+ pred = root.pred;
+ pred.succ = this;
+ root.pred = this;
+ }
+ }
+
+ /**
+ * Called when this entry is accessed via put or get. This version does
+ * the necessary bookkeeping to keep the doubly-linked list in order,
+ * after moving this element to the newest position in access order.
+ */
+ void access()
+ {
+ if (accessOrder && succ != null)
+ {
+ modCount++;
+ if (this == root)
+ {
+ root = succ;
+ pred.succ = this;
+ succ = null;
+ }
+ else
+ {
+ pred.succ = succ;
+ succ.pred = pred;
+ succ = null;
+ pred = root.pred;
+ pred.succ = this;
+ root.pred = this;
+ }
+ }
+ }
+
+ /**
+ * Called when this entry is removed from the map. This version does
+ * the necessary bookkeeping to keep the doubly-linked list in order.
+ *
+ * @return the value of this key as it is removed
+ */
+ Object cleanup()
+ {
+ if (this == root)
+ {
+ root = succ;
+ if (succ != null)
+ succ.pred = pred;
+ }
+ else if (succ == null)
+ {
+ pred.succ = null;
+ root.pred = pred;
+ }
+ else
+ {
+ pred.succ = succ;
+ succ.pred = pred;
+ }
+ return value;
+ }
+ } // class LinkedHashEntry
+
+ /**
+ * Construct a new insertion-ordered LinkedHashMap with the default
+ * capacity (11) and the default load factor (0.75).
+ */
+ public LinkedHashMap()
+ {
+ super();
+ accessOrder = false;
+ }
+
+ /**
+ * Construct a new insertion-ordered LinkedHashMap from the given Map,
+ * with initial capacity the greater of the size of <code>m</code> or
+ * the default of 11.
+ * <p>
+ *
+ * Every element in Map m will be put into this new HashMap, in the
+ * order of m's iterator.
+ *
+ * @param m a Map whose key / value pairs will be put into
+ * the new HashMap. <b>NOTE: key / value pairs
+ * are not cloned in this constructor.</b>
+ * @throws NullPointerException if m is null
+ */
+ public LinkedHashMap(Map m)
+ {
+ super(m);
+ accessOrder = false;
+ }
+
+ /**
+ * Construct a new insertion-ordered LinkedHashMap with a specific
+ * inital capacity and default load factor of 0.75.
+ *
+ * @param initialCapacity the initial capacity of this HashMap (&gt;= 0)
+ * @throws IllegalArgumentException if (initialCapacity &lt; 0)
+ */
+ public LinkedHashMap(int initialCapacity)
+ {
+ super(initialCapacity);
+ accessOrder = false;
+ }
+
+ /**
+ * Construct a new insertion-orderd LinkedHashMap with a specific
+ * inital capacity and load factor.
+ *
+ * @param initialCapacity the initial capacity (&gt;= 0)
+ * @param loadFactor the load factor (&gt; 0, not NaN)
+ * @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
+ * ! (loadFactor &gt; 0.0)
+ */
+ public LinkedHashMap(int initialCapacity, float loadFactor)
+ {
+ super(initialCapacity, loadFactor);
+ accessOrder = false;
+ }
+
+ /**
+ * Construct a new LinkedHashMap with a specific inital capacity, load
+ * factor, and ordering mode.
+ *
+ * @param initialCapacity the initial capacity (&gt;=0)
+ * @param loadFactor the load factor (&gt;0, not NaN)
+ * @param accessOrder true for access-order, false for insertion-order
+ * @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
+ * ! (loadFactor &gt; 0.0)
+ */
+ public LinkedHashMap(int initialCapacity, float loadFactor,
+ boolean accessOrder)
+ {
+ super(initialCapacity, loadFactor);
+ this.accessOrder = accessOrder;
+ }
+
+ /**
+ * Clears the Map so it has no keys. This is O(1).
+ */
+ public void clear()
+ {
+ super.clear();
+ root = null;
+ }
+
+ /**
+ * Returns <code>true</code> if this HashMap contains a value
+ * <code>o</code>, such that <code>o.equals(value)</code>.
+ *
+ * @param value the value to search for in this HashMap
+ * @return <code>true</code> if at least one key maps to the value
+ */
+ public boolean containsValue(Object value)
+ {
+ LinkedHashEntry e = root;
+ while (e != null)
+ {
+ if (equals(value, e.value))
+ return true;
+ e = e.succ;
+ }
+ return false;
+ }
+
+ /**
+ * Return the value in this Map associated with the supplied key,
+ * or <code>null</code> if the key maps to nothing. If this is an
+ * access-ordered Map and the key is found, this performs structural
+ * modification, moving the key to the newest end of the list. NOTE:
+ * Since the value could also be null, you must use containsKey to
+ * see if this key actually maps to something.
+ *
+ * @param key the key for which to fetch an associated value
+ * @return what the key maps to, if present
+ * @see #put(Object, Object)
+ * @see #containsKey(Object)
+ */
+ public Object get(Object key)
+ {
+ int idx = hash(key);
+ HashEntry e = buckets[idx];
+ while (e != null)
+ {
+ if (equals(key, e.key))
+ {
+ e.access();
+ return e.value;
+ }
+ e = e.next;
+ }
+ return null;
+ }
+
+ /**
+ * Returns <code>true</code> if this map should remove the eldest entry.
+ * This method is invoked by all calls to <code>put</code> and
+ * <code>putAll</code> which place a new entry in the map, providing
+ * the implementer an opportunity to remove the eldest entry any time
+ * a new one is added. This can be used to save memory usage of the
+ * hashtable, as well as emulating a cache, by deleting stale entries.
+ * <p>
+ *
+ * For example, to keep the Map limited to 100 entries, override as follows:
+ * <pre>
+ * private static final int MAX_ENTRIES = 100;
+ * protected boolean removeEldestEntry(Map.Entry eldest)
+ * {
+ * return size() &gt; MAX_ENTRIES;
+ * }
+ * </pre><p>
+ *
+ * Typically, this method does not modify the map, but just uses the
+ * return value as an indication to <code>put</code> whether to proceed.
+ * However, if you override it to modify the map, you must return false
+ * (indicating that <code>put</code> should leave the modified map alone),
+ * or you face unspecified behavior. Remember that in access-order mode,
+ * even calling <code>get</code> is a structural modification, but using
+ * the collections views (such as <code>keySet</code>) is not.
+ * <p>
+ *
+ * This method is called after the eldest entry has been inserted, so
+ * if <code>put</code> was called on a previously empty map, the eldest
+ * entry is the one you just put in! The default implementation just
+ * returns <code>false</code>, so that this map always behaves like
+ * a normal one with unbounded growth.
+ *
+ * @param eldest the eldest element which would be removed if this
+ * returns true. For an access-order map, this is the least
+ * recently accessed; for an insertion-order map, this is the
+ * earliest element inserted.
+ * @return true if <code>eldest</code> should be removed
+ */
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ {
+ return false;
+ }
+
+ /**
+ * Helper method called by <code>put</code>, which creates and adds a
+ * new Entry, followed by performing bookkeeping (like removeEldestEntry).
+ *
+ * @param key the key of the new Entry
+ * @param value the value
+ * @param idx the index in buckets where the new Entry belongs
+ * @param callRemove whether to call the removeEldestEntry method
+ * @see #put(Object, Object)
+ * @see #removeEldestEntry(Map.Entry)
+ * @see LinkedHashEntry#LinkedHashEntry(Object, Object)
+ */
+ void addEntry(Object key, Object value, int idx, boolean callRemove)
+ {
+ LinkedHashEntry e = new LinkedHashEntry(key, value);
+ e.next = buckets[idx];
+ buckets[idx] = e;
+ if (callRemove && removeEldestEntry(root))
+ remove(root.key);
+ }
+
+ /**
+ * Helper method, called by clone() to reset the doubly-linked list.
+ *
+ * @param m the map to add entries from
+ * @see #clone()
+ */
+ void putAllInternal(Map m)
+ {
+ root = null;
+ super.putAllInternal(m);
+ }
+
+ /**
+ * Generates a parameterized iterator. This allows traversal to follow
+ * the doubly-linked list instead of the random bin order of HashMap.
+ *
+ * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+ * @return the appropriate iterator
+ */
+ Iterator iterator(final int type)
+ {
+ return new Iterator()
+ {
+ /** The current Entry. */
+ LinkedHashEntry current = root;
+
+ /** The previous Entry returned by next(). */
+ LinkedHashEntry last;
+
+ /** The number of known modifications to the backing Map. */
+ int knownMod = modCount;
+
+ /**
+ * Returns true if the Iterator has more elements.
+ *
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the HashMap was modified
+ */
+ public boolean hasNext()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ return current != null;
+ }
+
+ /**
+ * Returns the next element in the Iterator's sequential view.
+ *
+ * @return the next element
+ * @throws ConcurrentModificationException if the HashMap was modified
+ * @throws NoSuchElementException if there is none
+ */
+ public Object next()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (current == null)
+ throw new NoSuchElementException();
+ last = current;
+ current = current.succ;
+ return type == VALUES ? last.value : type == KEYS ? last.key : last;
+ }
+
+ /**
+ * Removes from the backing HashMap the last element which was fetched
+ * with the <code>next()</code> method.
+ *
+ * @throws ConcurrentModificationException if the HashMap was modified
+ * @throws IllegalStateException if called when there is no last element
+ */
+ public void remove()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (last == null)
+ throw new IllegalStateException();
+ LinkedHashMap.this.remove(last.key);
+ last = null;
+ knownMod++;
+ }
+ };
+ }
+} // class LinkedHashMap
diff --git a/libjava/classpath/java/util/LinkedHashSet.java b/libjava/classpath/java/util/LinkedHashSet.java
new file mode 100644
index 00000000000..6c68195c3bd
--- /dev/null
+++ b/libjava/classpath/java/util/LinkedHashSet.java
@@ -0,0 +1,160 @@
+/* LinkedHashSet.java -- a set backed by a LinkedHashMap, for linked
+ list traversal.
+ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * This class provides a hashtable-backed implementation of the
+ * Set interface, with predictable traversal order.
+ * <p>
+ *
+ * It uses a hash-bucket approach; that is, hash collisions are handled
+ * by linking the new node off of the pre-existing node (or list of
+ * nodes). In this manner, techniques such as linear probing (which
+ * can cause primary clustering) and rehashing (which does not fit very
+ * well with Java's method of precomputing hash codes) are avoided. In
+ * addition, this maintains a doubly-linked list which tracks insertion
+ * order. Note that the insertion order is not modified if an
+ * <code>add</code> simply reinserts an element in the set.
+ * <p>
+ *
+ * One of the nice features of tracking insertion order is that you can
+ * copy a set, and regardless of the implementation of the original,
+ * produce the same results when iterating over the copy. This is possible
+ * without needing the overhead of <code>TreeSet</code>.
+ * <p>
+ *
+ * Under ideal circumstances (no collisions), LinkedHashSet offers O(1)
+ * performance on most operations. In the worst case (all elements map
+ * to the same hash code -- very unlikely), most operations are O(n).
+ * <p>
+ *
+ * LinkedHashSet accepts the null entry. It is not synchronized, so if
+ * you need multi-threaded access, consider using:<br>
+ * <code>Set s = Collections.synchronizedSet(new LinkedHashSet(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Object#hashCode()
+ * @see Collection
+ * @see Set
+ * @see HashSet
+ * @see TreeSet
+ * @see Collections#synchronizedSet(Set)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class LinkedHashSet extends HashSet
+ implements Set, Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = -2851667679971038690L;
+
+ /**
+ * Construct a new, empty HashSet whose backing HashMap has the default
+ * capacity (11) and loadFacor (0.75).
+ */
+ public LinkedHashSet()
+ {
+ super();
+ }
+
+ /**
+ * Construct a new, empty HashSet whose backing HashMap has the supplied
+ * capacity and the default load factor (0.75).
+ *
+ * @param initialCapacity the initial capacity of the backing HashMap
+ * @throws IllegalArgumentException if the capacity is negative
+ */
+ public LinkedHashSet(int initialCapacity)
+ {
+ super(initialCapacity);
+ }
+
+ /**
+ * Construct a new, empty HashSet whose backing HashMap has the supplied
+ * capacity and load factor.
+ *
+ * @param initialCapacity the initial capacity of the backing HashMap
+ * @param loadFactor the load factor of the backing HashMap
+ * @throws IllegalArgumentException if either argument is negative, or
+ * if loadFactor is POSITIVE_INFINITY or NaN
+ */
+ public LinkedHashSet(int initialCapacity, float loadFactor)
+ {
+ super(initialCapacity, loadFactor);
+ }
+
+ /**
+ * Construct a new HashSet with the same elements as are in the supplied
+ * collection (eliminating any duplicates, of course). The backing storage
+ * has twice the size of the collection, or the default size of 11,
+ * whichever is greater; and the default load factor (0.75).
+ *
+ * @param c a collection of initial set elements
+ * @throws NullPointerException if c is null
+ */
+ public LinkedHashSet(Collection c)
+ {
+ super(c);
+ }
+
+ /**
+ * Helper method which initializes the backing Map.
+ *
+ * @param capacity the initial capacity
+ * @param load the initial load factor
+ * @return the backing HashMap
+ */
+ HashMap init(int capacity, float load)
+ {
+ return new LinkedHashMap(capacity, load);
+ }
+
+}
diff --git a/libjava/classpath/java/util/LinkedList.java b/libjava/classpath/java/util/LinkedList.java
new file mode 100644
index 00000000000..2a35425fa24
--- /dev/null
+++ b/libjava/classpath/java/util/LinkedList.java
@@ -0,0 +1,958 @@
+/* LinkedList.java -- Linked list implementation of the List interface
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+
+/**
+ * Linked list implementation of the List interface. In addition to the
+ * methods of the List interface, this class provides access to the first
+ * and last list elements in O(1) time for easy stack, queue, or double-ended
+ * queue (deque) creation. The list is doubly-linked, with traversal to a
+ * given index starting from the end closest to the element.<p>
+ *
+ * LinkedList is not synchronized, so if you need multi-threaded access,
+ * consider using:<br>
+ * <code>List l = Collections.synchronizedList(new LinkedList(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Original author unknown
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see List
+ * @see ArrayList
+ * @see Vector
+ * @see Collections#synchronizedList(List)
+ * @since 1.2
+ * @status missing javadoc, but complete to 1.4
+ */
+public class LinkedList extends AbstractSequentialList
+ implements List, Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = 876323262645176354L;
+
+ /**
+ * The first element in the list.
+ */
+ transient Entry first;
+
+ /**
+ * The last element in the list.
+ */
+ transient Entry last;
+
+ /**
+ * The current length of the list.
+ */
+ transient int size = 0;
+
+ /**
+ * Class to represent an entry in the list. Holds a single element.
+ */
+ private static final class Entry
+ {
+ /** The element in the list. */
+ Object data;
+
+ /** The next list entry, null if this is last. */
+ Entry next;
+
+ /** The previous list entry, null if this is first. */
+ Entry previous;
+
+ /**
+ * Construct an entry.
+ * @param data the list element
+ */
+ Entry(Object data)
+ {
+ this.data = data;
+ }
+ } // class Entry
+
+ /**
+ * Obtain the Entry at a given position in a list. This method of course
+ * takes linear time, but it is intelligent enough to take the shorter of the
+ * paths to get to the Entry required. This implies that the first or last
+ * entry in the list is obtained in constant time, which is a very desirable
+ * property.
+ * For speed and flexibility, range checking is not done in this method:
+ * Incorrect values will be returned if (n &lt; 0) or (n &gt;= size).
+ *
+ * @param n the number of the entry to get
+ * @return the entry at position n
+ */
+ // Package visible for use in nested classes.
+ Entry getEntry(int n)
+ {
+ Entry e;
+ if (n < size / 2)
+ {
+ e = first;
+ // n less than size/2, iterate from start
+ while (n-- > 0)
+ e = e.next;
+ }
+ else
+ {
+ e = last;
+ // n greater than size/2, iterate from end
+ while (++n < size)
+ e = e.previous;
+ }
+ return e;
+ }
+
+ /**
+ * Remove an entry from the list. This will adjust size and deal with
+ * `first' and `last' appropriatly.
+ *
+ * @param e the entry to remove
+ */
+ // Package visible for use in nested classes.
+ void removeEntry(Entry e)
+ {
+ modCount++;
+ size--;
+ if (size == 0)
+ first = last = null;
+ else
+ {
+ if (e == first)
+ {
+ first = e.next;
+ e.next.previous = null;
+ }
+ else if (e == last)
+ {
+ last = e.previous;
+ e.previous.next = null;
+ }
+ else
+ {
+ e.next.previous = e.previous;
+ e.previous.next = e.next;
+ }
+ }
+ }
+
+ /**
+ * Checks that the index is in the range of possible elements (inclusive).
+ *
+ * @param index the index to check
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size
+ */
+ private void checkBoundsInclusive(int index)
+ {
+ if (index < 0 || index > size)
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size);
+ }
+
+ /**
+ * Checks that the index is in the range of existing elements (exclusive).
+ *
+ * @param index the index to check
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size
+ */
+ private void checkBoundsExclusive(int index)
+ {
+ if (index < 0 || index >= size)
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size);
+ }
+
+ /**
+ * Create an empty linked list.
+ */
+ public LinkedList()
+ {
+ }
+
+ /**
+ * Create a linked list containing the elements, in order, of a given
+ * collection.
+ *
+ * @param c the collection to populate this list from
+ * @throws NullPointerException if c is null
+ */
+ public LinkedList(Collection c)
+ {
+ addAll(c);
+ }
+
+ /**
+ * Returns the first element in the list.
+ *
+ * @return the first list element
+ * @throws NoSuchElementException if the list is empty
+ */
+ public Object getFirst()
+ {
+ if (size == 0)
+ throw new NoSuchElementException();
+ return first.data;
+ }
+
+ /**
+ * Returns the last element in the list.
+ *
+ * @return the last list element
+ * @throws NoSuchElementException if the list is empty
+ */
+ public Object getLast()
+ {
+ if (size == 0)
+ throw new NoSuchElementException();
+ return last.data;
+ }
+
+ /**
+ * Remove and return the first element in the list.
+ *
+ * @return the former first element in the list
+ * @throws NoSuchElementException if the list is empty
+ */
+ public Object removeFirst()
+ {
+ if (size == 0)
+ throw new NoSuchElementException();
+ modCount++;
+ size--;
+ Object r = first.data;
+
+ if (first.next != null)
+ first.next.previous = null;
+ else
+ last = null;
+
+ first = first.next;
+
+ return r;
+ }
+
+ /**
+ * Remove and return the last element in the list.
+ *
+ * @return the former last element in the list
+ * @throws NoSuchElementException if the list is empty
+ */
+ public Object removeLast()
+ {
+ if (size == 0)
+ throw new NoSuchElementException();
+ modCount++;
+ size--;
+ Object r = last.data;
+
+ if (last.previous != null)
+ last.previous.next = null;
+ else
+ first = null;
+
+ last = last.previous;
+
+ return r;
+ }
+
+ /**
+ * Insert an element at the first of the list.
+ *
+ * @param o the element to insert
+ */
+ public void addFirst(Object o)
+ {
+ Entry e = new Entry(o);
+
+ modCount++;
+ if (size == 0)
+ first = last = e;
+ else
+ {
+ e.next = first;
+ first.previous = e;
+ first = e;
+ }
+ size++;
+ }
+
+ /**
+ * Insert an element at the last of the list.
+ *
+ * @param o the element to insert
+ */
+ public void addLast(Object o)
+ {
+ addLastEntry(new Entry(o));
+ }
+
+ /**
+ * Inserts an element at the end of the list.
+ *
+ * @param e the entry to add
+ */
+ private void addLastEntry(Entry e)
+ {
+ modCount++;
+ if (size == 0)
+ first = last = e;
+ else
+ {
+ e.previous = last;
+ last.next = e;
+ last = e;
+ }
+ size++;
+ }
+
+ /**
+ * Returns true if the list contains the given object. Comparison is done by
+ * <code>o == null ? e = null : o.equals(e)</code>.
+ *
+ * @param o the element to look for
+ * @return true if it is found
+ */
+ public boolean contains(Object o)
+ {
+ Entry e = first;
+ while (e != null)
+ {
+ if (equals(o, e.data))
+ return true;
+ e = e.next;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the size of the list.
+ *
+ * @return the list size
+ */
+ public int size()
+ {
+ return size;
+ }
+
+ /**
+ * Adds an element to the end of the list.
+ *
+ * @param o the entry to add
+ * @return true, as it always succeeds
+ */
+ public boolean add(Object o)
+ {
+ addLastEntry(new Entry(o));
+ return true;
+ }
+
+ /**
+ * Removes the entry at the lowest index in the list that matches the given
+ * object, comparing by <code>o == null ? e = null : o.equals(e)</code>.
+ *
+ * @param o the object to remove
+ * @return true if an instance of the object was removed
+ */
+ public boolean remove(Object o)
+ {
+ Entry e = first;
+ while (e != null)
+ {
+ if (equals(o, e.data))
+ {
+ removeEntry(e);
+ return true;
+ }
+ e = e.next;
+ }
+ return false;
+ }
+
+ /**
+ * Append the elements of the collection in iteration order to the end of
+ * this list. If this list is modified externally (for example, if this
+ * list is the collection), behavior is unspecified.
+ *
+ * @param c the collection to append
+ * @return true if the list was modified
+ * @throws NullPointerException if c is null
+ */
+ public boolean addAll(Collection c)
+ {
+ return addAll(size, c);
+ }
+
+ /**
+ * Insert the elements of the collection in iteration order at the given
+ * index of this list. If this list is modified externally (for example,
+ * if this list is the collection), behavior is unspecified.
+ *
+ * @param c the collection to append
+ * @return true if the list was modified
+ * @throws NullPointerException if c is null
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ checkBoundsInclusive(index);
+ int csize = c.size();
+
+ if (csize == 0)
+ return false;
+
+ Iterator itr = c.iterator();
+
+ // Get the entries just before and after index. If index is at the start
+ // of the list, BEFORE is null. If index is at the end of the list, AFTER
+ // is null. If the list is empty, both are null.
+ Entry after = null;
+ Entry before = null;
+ if (index != size)
+ {
+ after = getEntry(index);
+ before = after.previous;
+ }
+ else
+ before = last;
+
+ // Create the first new entry. We do not yet set the link from `before'
+ // to the first entry, in order to deal with the case where (c == this).
+ // [Actually, we don't have to handle this case to fufill the
+ // contract for addAll(), but Sun's implementation appears to.]
+ Entry e = new Entry(itr.next());
+ e.previous = before;
+ Entry prev = e;
+ Entry firstNew = e;
+
+ // Create and link all the remaining entries.
+ for (int pos = 1; pos < csize; pos++)
+ {
+ e = new Entry(itr.next());
+ e.previous = prev;
+ prev.next = e;
+ prev = e;
+ }
+
+ // Link the new chain of entries into the list.
+ modCount++;
+ size += csize;
+ prev.next = after;
+ if (after != null)
+ after.previous = e;
+ else
+ last = e;
+
+ if (before != null)
+ before.next = firstNew;
+ else
+ first = firstNew;
+ return true;
+ }
+
+ /**
+ * Remove all elements from this list.
+ */
+ public void clear()
+ {
+ if (size > 0)
+ {
+ modCount++;
+ first = null;
+ last = null;
+ size = 0;
+ }
+ }
+
+ /**
+ * Return the element at index.
+ *
+ * @param index the place to look
+ * @return the element at index
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object get(int index)
+ {
+ checkBoundsExclusive(index);
+ return getEntry(index).data;
+ }
+
+ /**
+ * Replace the element at the given location in the list.
+ *
+ * @param index which index to change
+ * @param o the new element
+ * @return the prior element
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public Object set(int index, Object o)
+ {
+ checkBoundsExclusive(index);
+ Entry e = getEntry(index);
+ Object old = e.data;
+ e.data = o;
+ return old;
+ }
+
+ /**
+ * Inserts an element in the given position in the list.
+ *
+ * @param index where to insert the element
+ * @param o the element to insert
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public void add(int index, Object o)
+ {
+ checkBoundsInclusive(index);
+ Entry e = new Entry(o);
+
+ if (index < size)
+ {
+ modCount++;
+ Entry after = getEntry(index);
+ e.next = after;
+ e.previous = after.previous;
+ if (after.previous == null)
+ first = e;
+ else
+ after.previous.next = e;
+ after.previous = e;
+ size++;
+ }
+ else
+ addLastEntry(e);
+ }
+
+ /**
+ * Removes the element at the given position from the list.
+ *
+ * @param index the location of the element to remove
+ * @return the removed element
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public Object remove(int index)
+ {
+ checkBoundsExclusive(index);
+ Entry e = getEntry(index);
+ removeEntry(e);
+ return e.data;
+ }
+
+ /**
+ * Returns the first index where the element is located in the list, or -1.
+ *
+ * @param o the element to look for
+ * @return its position, or -1 if not found
+ */
+ public int indexOf(Object o)
+ {
+ int index = 0;
+ Entry e = first;
+ while (e != null)
+ {
+ if (equals(o, e.data))
+ return index;
+ index++;
+ e = e.next;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the last index where the element is located in the list, or -1.
+ *
+ * @param o the element to look for
+ * @return its position, or -1 if not found
+ */
+ public int lastIndexOf(Object o)
+ {
+ int index = size - 1;
+ Entry e = last;
+ while (e != null)
+ {
+ if (equals(o, e.data))
+ return index;
+ index--;
+ e = e.previous;
+ }
+ return -1;
+ }
+
+ /**
+ * Obtain a ListIterator over this list, starting at a given index. The
+ * ListIterator returned by this method supports the add, remove and set
+ * methods.
+ *
+ * @param index the index of the element to be returned by the first call to
+ * next(), or size() to be initially positioned at the end of the list
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public ListIterator listIterator(int index)
+ {
+ checkBoundsInclusive(index);
+ return new LinkedListItr(index);
+ }
+
+ /**
+ * Create a shallow copy of this LinkedList (the elements are not cloned).
+ *
+ * @return an object of the same class as this object, containing the
+ * same elements in the same order
+ */
+ public Object clone()
+ {
+ LinkedList copy = null;
+ try
+ {
+ copy = (LinkedList) super.clone();
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ }
+ copy.clear();
+ copy.addAll(this);
+ return copy;
+ }
+
+ /**
+ * Returns an array which contains the elements of the list in order.
+ *
+ * @return an array containing the list elements
+ */
+ public Object[] toArray()
+ {
+ Object[] array = new Object[size];
+ Entry e = first;
+ for (int i = 0; i < size; i++)
+ {
+ array[i] = e.data;
+ e = e.next;
+ }
+ return array;
+ }
+
+ /**
+ * Returns an Array whose component type is the runtime component type of
+ * the passed-in Array. The returned Array is populated with all of the
+ * elements in this LinkedList. If the passed-in Array is not large enough
+ * to store all of the elements in this List, a new Array will be created
+ * and returned; if the passed-in Array is <i>larger</i> than the size
+ * of this List, then size() index will be set to null.
+ *
+ * @param a the passed-in Array
+ * @return an array representation of this list
+ * @throws ArrayStoreException if the runtime type of a does not allow
+ * an element in this list
+ * @throws NullPointerException if a is null
+ */
+ public Object[] toArray(Object[] a)
+ {
+ if (a.length < size)
+ a = (Object[]) Array.newInstance(a.getClass().getComponentType(), size);
+ else if (a.length > size)
+ a[size] = null;
+ Entry e = first;
+ for (int i = 0; i < size; i++)
+ {
+ a[i] = e.data;
+ e = e.next;
+ }
+ return a;
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData the size of the list (int), followed by all the elements
+ * (Object) in proper order
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ s.writeInt(size);
+ Entry e = first;
+ while (e != null)
+ {
+ s.writeObject(e.data);
+ e = e.next;
+ }
+ }
+
+ /**
+ * Deserializes this object from the given stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @serialData the size of the list (int), followed by all the elements
+ * (Object) in proper order
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ int i = s.readInt();
+ while (--i >= 0)
+ addLastEntry(new Entry(s.readObject()));
+ }
+
+ /**
+ * A ListIterator over the list. This class keeps track of its
+ * position in the list and the two list entries it is between.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private final class LinkedListItr implements ListIterator
+ {
+ /** Number of modifications we know about. */
+ private int knownMod = modCount;
+
+ /** Entry that will be returned by next(). */
+ private Entry next;
+
+ /** Entry that will be returned by previous(). */
+ private Entry previous;
+
+ /** Entry that will be affected by remove() or set(). */
+ private Entry lastReturned;
+
+ /** Index of `next'. */
+ private int position;
+
+ /**
+ * Initialize the iterator.
+ *
+ * @param index the initial index
+ */
+ LinkedListItr(int index)
+ {
+ if (index == size)
+ {
+ next = null;
+ previous = last;
+ }
+ else
+ {
+ next = getEntry(index);
+ previous = next.previous;
+ }
+ position = index;
+ }
+
+ /**
+ * Checks for iterator consistency.
+ *
+ * @throws ConcurrentModificationException if the list was modified
+ */
+ private void checkMod()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ }
+
+ /**
+ * Returns the index of the next element.
+ *
+ * @return the next index
+ * @throws ConcurrentModificationException if the list was modified
+ */
+ public int nextIndex()
+ {
+ checkMod();
+ return position;
+ }
+
+ /**
+ * Returns the index of the previous element.
+ *
+ * @return the previous index
+ * @throws ConcurrentModificationException if the list was modified
+ */
+ public int previousIndex()
+ {
+ checkMod();
+ return position - 1;
+ }
+
+ /**
+ * Returns true if more elements exist via next.
+ *
+ * @return true if next will succeed
+ * @throws ConcurrentModificationException if the list was modified
+ */
+ public boolean hasNext()
+ {
+ checkMod();
+ return (next != null);
+ }
+
+ /**
+ * Returns true if more elements exist via previous.
+ *
+ * @return true if previous will succeed
+ * @throws ConcurrentModificationException if the list was modified
+ */
+ public boolean hasPrevious()
+ {
+ checkMod();
+ return (previous != null);
+ }
+
+ /**
+ * Returns the next element.
+ *
+ * @return the next element
+ * @throws ConcurrentModificationException if the list was modified
+ * @throws NoSuchElementException if there is no next
+ */
+ public Object next()
+ {
+ checkMod();
+ if (next == null)
+ throw new NoSuchElementException();
+ position++;
+ lastReturned = previous = next;
+ next = lastReturned.next;
+ return lastReturned.data;
+ }
+
+ /**
+ * Returns the previous element.
+ *
+ * @return the previous element
+ * @throws ConcurrentModificationException if the list was modified
+ * @throws NoSuchElementException if there is no previous
+ */
+ public Object previous()
+ {
+ checkMod();
+ if (previous == null)
+ throw new NoSuchElementException();
+ position--;
+ lastReturned = next = previous;
+ previous = lastReturned.previous;
+ return lastReturned.data;
+ }
+
+ /**
+ * Remove the most recently returned element from the list.
+ *
+ * @throws ConcurrentModificationException if the list was modified
+ * @throws IllegalStateException if there was no last element
+ */
+ public void remove()
+ {
+ checkMod();
+ if (lastReturned == null)
+ throw new IllegalStateException();
+
+ // Adjust the position to before the removed element, if the element
+ // being removed is behind the cursor.
+ if (lastReturned == previous)
+ position--;
+
+ next = lastReturned.next;
+ previous = lastReturned.previous;
+ removeEntry(lastReturned);
+ knownMod++;
+
+ lastReturned = null;
+ }
+
+ /**
+ * Adds an element between the previous and next, and advance to the next.
+ *
+ * @param o the element to add
+ * @throws ConcurrentModificationException if the list was modified
+ */
+ public void add(Object o)
+ {
+ checkMod();
+ modCount++;
+ knownMod++;
+ size++;
+ position++;
+ Entry e = new Entry(o);
+ e.previous = previous;
+ e.next = next;
+
+ if (previous != null)
+ previous.next = e;
+ else
+ first = e;
+
+ if (next != null)
+ next.previous = e;
+ else
+ last = e;
+
+ previous = e;
+ lastReturned = null;
+ }
+
+ /**
+ * Changes the contents of the element most recently returned.
+ *
+ * @param o the new element
+ * @throws ConcurrentModificationException if the list was modified
+ * @throws IllegalStateException if there was no last element
+ */
+ public void set(Object o)
+ {
+ checkMod();
+ if (lastReturned == null)
+ throw new IllegalStateException();
+ lastReturned.data = o;
+ }
+ } // class LinkedListItr
+}
diff --git a/libjava/classpath/java/util/List.java b/libjava/classpath/java/util/List.java
new file mode 100644
index 00000000000..445811292ac
--- /dev/null
+++ b/libjava/classpath/java/util/List.java
@@ -0,0 +1,451 @@
+/* List.java -- An ordered collection which allows indexed access
+ Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An ordered collection (also known as a list). This collection allows
+ * access to elements by position, as well as control on where elements
+ * are inserted. Unlike sets, duplicate elements are permitted by this
+ * general contract (if a subclass forbids duplicates, this should be
+ * documented).
+ * <p>
+ *
+ * List places additional requirements on <code>iterator</code>,
+ * <code>add</code>, <code>remove</code>, <code>equals</code>, and
+ * <code>hashCode</code>, in addition to requiring more methods. List
+ * indexing is 0-based (like arrays), although some implementations may
+ * require time proportional to the index to obtain an arbitrary element.
+ * The List interface is incompatible with Set; you cannot implement both
+ * simultaneously.
+ * <p>
+ *
+ * Lists also provide a <code>ListIterator</code> which allows bidirectional
+ * traversal and other features atop regular iterators. Lists can be
+ * searched for arbitrary elements, and allow easy insertion and removal
+ * of multiple elements in one method call.
+ * <p>
+ *
+ * Note: While lists may contain themselves as elements, this leads to
+ * undefined (usually infinite recursive) behavior for some methods like
+ * hashCode or equals.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see Set
+ * @see ArrayList
+ * @see LinkedList
+ * @see Vector
+ * @see Arrays#asList(Object[])
+ * @see Collections#nCopies(int, Object)
+ * @see Collections#EMPTY_LIST
+ * @see AbstractList
+ * @see AbstractSequentialList
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface List extends Collection
+{
+ /**
+ * Insert an element into the list at a given position (optional operation).
+ * This shifts all existing elements from that position to the end one
+ * index to the right. This version of add has no return, since it is
+ * assumed to always succeed if there is no exception.
+ *
+ * @param index the location to insert the item
+ * @param o the object to insert
+ * @throws UnsupportedOperationException if this list does not support the
+ * add operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @throws NullPointerException if o is null and this list doesn't support
+ * the addition of null values.
+ */
+ void add(int index, Object o);
+
+ /**
+ * Add an element to the end of the list (optional operation). If the list
+ * imposes restraints on what can be inserted, such as no null elements,
+ * this should be documented.
+ *
+ * @param o the object to add
+ * @return true, as defined by Collection for a modified list
+ * @throws UnsupportedOperationException if this list does not support the
+ * add operation
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @throws NullPointerException if o is null and this list doesn't support
+ * the addition of null values.
+ */
+ boolean add(Object o);
+
+ /**
+ * Insert the contents of a collection into the list at a given position
+ * (optional operation). Shift all elements at that position to the right
+ * by the number of elements inserted. This operation is undefined if
+ * this list is modified during the operation (for example, if you try
+ * to insert a list into itself).
+ *
+ * @param index the location to insert the collection
+ * @param c the collection to insert
+ * @return true if the list was modified by this action, that is, if c is
+ * non-empty
+ * @throws UnsupportedOperationException if this list does not support the
+ * addAll operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ * @throws ClassCastException if some element of c cannot be added to this
+ * list due to its type
+ * @throws IllegalArgumentException if some element of c cannot be added
+ * to this list for some other reason
+ * @throws NullPointerException if some element of c is null and this list
+ * doesn't support the addition of null values.
+ * @throws NullPointerException if the specified collection is null
+ * @see #add(int, Object)
+ */
+ boolean addAll(int index, Collection c);
+
+ /**
+ * Add the contents of a collection to the end of the list (optional
+ * operation). This operation is undefined if this list is modified
+ * during the operation (for example, if you try to insert a list into
+ * itself).
+ *
+ * @param c the collection to add
+ * @return true if the list was modified by this action, that is, if c is
+ * non-empty
+ * @throws UnsupportedOperationException if this list does not support the
+ * addAll operation
+ * @throws ClassCastException if some element of c cannot be added to this
+ * list due to its type
+ * @throws IllegalArgumentException if some element of c cannot be added
+ * to this list for some other reason
+ * @throws NullPointerException if the specified collection is null
+ * @throws NullPointerException if some element of c is null and this list
+ * doesn't support the addition of null values.
+ * @see #add(Object)
+ */
+ boolean addAll(Collection c);
+
+ /**
+ * Clear the list, such that a subsequent call to isEmpty() would return
+ * true (optional operation).
+ *
+ * @throws UnsupportedOperationException if this list does not support the
+ * clear operation
+ */
+ void clear();
+
+ /**
+ * Test whether this list contains a given object as one of its elements.
+ * This is defined as the existence of an element e such that
+ * <code>o == null ? e == null : o.equals(e)</code>.
+ *
+ * @param o the element to look for
+ * @return true if this list contains the element
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this list.
+ * @throws NullPointerException if o is null and the list doesn't
+ * support null values.
+ */
+ boolean contains(Object o);
+
+ /**
+ * Test whether this list contains every element in a given collection.
+ *
+ * @param c the collection to test for
+ * @return true if for every element o in c, contains(o) would return true
+ * @throws NullPointerException if the collection is null
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for this list.
+ * @throws NullPointerException if some element of c is null and this
+ * list does not support null values.
+ * @see #contains(Object)
+ */
+ boolean containsAll(Collection c);
+
+ /**
+ * Test whether this list is equal to another object. A List is defined to be
+ * equal to an object if and only if that object is also a List, and the two
+ * lists have the same sequence. Two lists l1 and l2 are equal if and only
+ * if <code>l1.size() == l2.size()</code>, and for every integer n between 0
+ * and <code>l1.size() - 1</code> inclusive, <code>l1.get(n) == null ?
+ * l2.get(n) == null : l1.get(n).equals(l2.get(n))</code>.
+ *
+ * @param o the object to test for equality with this list
+ * @return true if o is equal to this list
+ * @see Object#equals(Object)
+ * @see #hashCode()
+ */
+ boolean equals(Object o);
+
+ /**
+ * Get the element at a given index in this list.
+ *
+ * @param index the index of the element to be returned
+ * @return the element at index index in this list
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ Object get(int index);
+
+ /**
+ * Obtains a hash code for this list. In order to obey the general
+ * contract of the hashCode method of class Object, this value is
+ * calculated as follows:
+ *
+<p><pre>hashCode = 1;
+Iterator i = list.iterator();
+while (i.hasNext())
+{
+ Object obj = i.next();
+ hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
+}</pre>
+ *
+ * <p>This ensures that the general contract of Object.hashCode()
+ * is adhered to.
+ *
+ * @return the hash code of this list
+ * @see Object#hashCode()
+ * @see #equals(Object)
+ */
+ int hashCode();
+
+ /**
+ * Obtain the first index at which a given object is to be found in this
+ * list.
+ *
+ * @param o the object to search for
+ * @return the least integer n such that <code>o == null ? get(n) == null :
+ * o.equals(get(n))</code>, or -1 if there is no such index.
+ * @throws ClassCastException if the type of o is not a valid
+ * type for this list.
+ * @throws NullPointerException if o is null and this
+ * list does not support null values.
+ */
+ int indexOf(Object o);
+
+ /**
+ * Test whether this list is empty, that is, if size() == 0.
+ *
+ * @return true if this list contains no elements
+ */
+ boolean isEmpty();
+
+ /**
+ * Obtain an Iterator over this list, whose sequence is the list order.
+ *
+ * @return an Iterator over the elements of this list, in order
+ */
+ Iterator iterator();
+
+ /**
+ * Obtain the last index at which a given object is to be found in this
+ * list.
+ *
+ * @return the greatest integer n such that <code>o == null ? get(n) == null
+ * : o.equals(get(n))</code>, or -1 if there is no such index.
+ * @throws ClassCastException if the type of o is not a valid
+ * type for this list.
+ * @throws NullPointerException if o is null and this
+ * list does not support null values.
+ */
+ int lastIndexOf(Object o);
+
+ /**
+ * Obtain a ListIterator over this list, starting at the beginning.
+ *
+ * @return a ListIterator over the elements of this list, in order, starting
+ * at the beginning
+ */
+ ListIterator listIterator();
+
+ /**
+ * Obtain a ListIterator over this list, starting at a given position.
+ * A first call to next() would return the same as get(index), and a
+ * first call to previous() would return the same as get(index - 1).
+ *
+ * @param index the position, between 0 and size() inclusive, to begin the
+ * iteration from
+ * @return a ListIterator over the elements of this list, in order, starting
+ * at index
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ ListIterator listIterator(int index);
+
+ /**
+ * Remove the element at a given position in this list (optional operation).
+ * Shifts all remaining elements to the left to fill the gap.
+ *
+ * @param index the position within the list of the object to remove
+ * @return the object that was removed
+ * @throws UnsupportedOperationException if this list does not support the
+ * remove operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ Object remove(int index);
+
+ /**
+ * Remove the first occurence of an object from this list (optional
+ * operation). That is, remove the first element e such that
+ * <code>o == null ? e == null : o.equals(e)</code>.
+ *
+ * @param o the object to remove
+ * @return true if the list changed as a result of this call, that is, if
+ * the list contained at least one occurrence of o
+ * @throws UnsupportedOperationException if this list does not support the
+ * remove operation
+ * @throws ClassCastException if the type of o is not a valid
+ * type for this list.
+ * @throws NullPointerException if o is null and this
+ * list does not support removing null values.
+ */
+ boolean remove(Object o);
+
+ /**
+ * Remove all elements of a given collection from this list (optional
+ * operation). That is, remove every element e such that c.contains(e).
+ *
+ * @param c the collection to filter out
+ * @return true if this list was modified as a result of this call
+ * @throws UnsupportedOperationException if this list does not support the
+ * removeAll operation
+ * @throws NullPointerException if the collection is null
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for this list.
+ * @throws NullPointerException if some element of c is null and this
+ * list does not support removing null values.
+ * @see #remove(Object)
+ * @see #contains(Object)
+ */
+ boolean removeAll(Collection c);
+
+ /**
+ * Remove all elements of this list that are not contained in a given
+ * collection (optional operation). That is, remove every element e such
+ * that !c.contains(e).
+ *
+ * @param c the collection to retain
+ * @return true if this list was modified as a result of this call
+ * @throws UnsupportedOperationException if this list does not support the
+ * retainAll operation
+ * @throws NullPointerException if the collection is null
+ * @throws ClassCastException if the type of any element in c is not a valid
+ * type for this list.
+ * @throws NullPointerException if some element of c is null and this
+ * list does not support retaining null values.
+ * @see #remove(Object)
+ * @see #contains(Object)
+ */
+ boolean retainAll(Collection c);
+
+ /**
+ * Replace an element of this list with another object (optional operation).
+ *
+ * @param index the position within this list of the element to be replaced
+ * @param o the object to replace it with
+ * @return the object that was replaced
+ * @throws UnsupportedOperationException if this list does not support the
+ * set operation
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ * @throws ClassCastException if o cannot be added to this list due to its
+ * type
+ * @throws IllegalArgumentException if o cannot be added to this list for
+ * some other reason
+ * @throws NullPointerException if o is null and this
+ * list does not support null values.
+ */
+ Object set(int index, Object o);
+
+ /**
+ * Get the number of elements in this list. If the list contains more
+ * than Integer.MAX_VALUE elements, return Integer.MAX_VALUE.
+ *
+ * @return the number of elements in the list
+ */
+ int size();
+
+ /**
+ * Obtain a List view of a subsection of this list, from fromIndex
+ * (inclusive) to toIndex (exclusive). If the two indices are equal, the
+ * sublist is empty. The returned list should be modifiable if and only
+ * if this list is modifiable. Changes to the returned list should be
+ * reflected in this list. If this list is structurally modified in
+ * any way other than through the returned list, the result of any subsequent
+ * operations on the returned list is undefined.
+ *
+ * @param fromIndex the index that the returned list should start from
+ * (inclusive)
+ * @param toIndex the index that the returned list should go to (exclusive)
+ * @return a List backed by a subsection of this list
+ * @throws IndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; size() || fromIndex &gt; toIndex
+ */
+ List subList(int fromIndex, int toIndex);
+
+ /**
+ * Copy the current contents of this list into an array.
+ *
+ * @return an array of type Object[] and length equal to the length of this
+ * list, containing the elements currently in this list, in order
+ */
+ Object[] toArray();
+
+ /**
+ * Copy the current contents of this list into an array. If the array passed
+ * as an argument has length less than that of this list, an array of the
+ * same run-time type as a, and length equal to the length of this list, is
+ * allocated using Reflection. Otherwise, a itself is used. The elements of
+ * this list are copied into it, and if there is space in the array, the
+ * following element is set to null. The resultant array is returned.
+ * Note: The fact that the following element is set to null is only useful
+ * if it is known that this list does not contain any null elements.
+ *
+ * @param a the array to copy this list into
+ * @return an array containing the elements currently in this list, in
+ * order
+ * @throws ArrayStoreException if the type of any element of the
+ * collection is not a subtype of the element type of a
+ * @throws NullPointerException if the specified array is null
+ */
+ Object[] toArray(Object[] a);
+}
diff --git a/libjava/classpath/java/util/ListIterator.java b/libjava/classpath/java/util/ListIterator.java
new file mode 100644
index 00000000000..5e17108c991
--- /dev/null
+++ b/libjava/classpath/java/util/ListIterator.java
@@ -0,0 +1,170 @@
+/* ListIterator.java -- Extended Iterator for iterating over ordered lists
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An extended version of Iterator to support the extra features of Lists. The
+ * elements may be accessed in forward or reverse order, elements may be
+ * replaced as well as removed, and new elements may be inserted, during the
+ * traversal of the list.
+ * <p>
+ *
+ * A list with n elements provides n+1 iterator positions (the front, the end,
+ * or between two elements). Note that <code>remove</code> and <code>set</code>
+ * operate on the last element returned, whether it was by <code>next</code>
+ * or <code>previous</code>.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see List
+ * @see Iterator
+ * @see Enumeration
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface ListIterator extends Iterator
+{
+ /**
+ * Tests whether there are elements remaining in the list in the forward
+ * direction. In other words, next() will not fail with a
+ * NoSuchElementException.
+ *
+ * @return true if the list continues in the forward direction
+ */
+ boolean hasNext();
+
+ /**
+ * Tests whether there are elements remaining in the list in the reverse
+ * direction. In other words, previous() will not fail with a
+ * NoSuchElementException.
+ *
+ * @return true if the list continues in the reverse direction
+ */
+ boolean hasPrevious();
+
+ /**
+ * Obtain the next element in the list in the forward direction. Repeated
+ * calls to next may be used to iterate over the entire list, or calls to
+ * next and previous may be used together to go forwards and backwards.
+ * Alternating calls to next and previous will return the same element.
+ *
+ * @return the next element in the list in the forward direction
+ * @throws NoSuchElementException if there are no more elements
+ */
+ Object next();
+
+ /**
+ * Obtain the next element in the list in the reverse direction. Repeated
+ * calls to previous may be used to iterate backwards over the entire list,
+ * or calls to next and previous may be used together to go forwards and
+ * backwards. Alternating calls to next and previous will return the same
+ * element.
+ *
+ * @return the next element in the list in the reverse direction
+ * @throws NoSuchElementException if there are no more elements
+ */
+ Object previous();
+
+ /**
+ * Find the index of the element that would be returned by a call to next.
+ * If hasNext() returns false, this returns the list size.
+ *
+ * @return the index of the element that would be returned by next()
+ */
+ int nextIndex();
+
+ /**
+ * Find the index of the element that would be returned by a call to
+ * previous. If hasPrevious() returns false, this returns -1.
+ *
+ * @return the index of the element that would be returned by previous()
+ */
+ int previousIndex();
+
+ /**
+ * Insert an element into the list at the current position of the iterator
+ * (optional operation). The element is inserted in between the element that
+ * would be returned by previous and the element that would be returned by
+ * next. After the insertion, a subsequent call to next is unaffected, but
+ * a call to previous returns the item that was added. The values returned
+ * by nextIndex() and previousIndex() are incremented.
+ *
+ * @param o the object to insert into the list
+ * @throws ClassCastException if the object is of a type which cannot be added
+ * to this list.
+ * @throws IllegalArgumentException if some other aspect of the object stops
+ * it being added to this list.
+ * @throws UnsupportedOperationException if this ListIterator does not
+ * support the add operation.
+ */
+ void add(Object o);
+
+ /**
+ * Remove from the list the element last returned by a call to next or
+ * previous (optional operation). This method may only be called if neither
+ * add nor remove have been called since the last call to next or previous.
+ *
+ * @throws IllegalStateException if neither next or previous have been
+ * called, or if add or remove has been called since the last call
+ * to next or previous
+ * @throws UnsupportedOperationException if this ListIterator does not
+ * support the remove operation
+ */
+ void remove();
+
+ /**
+ * Replace the element last returned by a call to next or previous with a
+ * given object (optional operation). This method may only be called if
+ * neither add nor remove have been called since the last call to next or
+ * previous.
+ *
+ * @param o the object to replace the element with
+ * @throws ClassCastException the object is of a type which cannot be added
+ * to this list
+ * @throws IllegalArgumentException some other aspect of the object stops
+ * it being added to this list
+ * @throws IllegalStateException if neither next or previous have been
+ * called, or if add or remove has been called since the last call
+ * to next or previous
+ * @throws UnsupportedOperationException if this ListIterator does not
+ * support the set operation
+ */
+ void set(Object o);
+}
diff --git a/libjava/classpath/java/util/ListResourceBundle.java b/libjava/classpath/java/util/ListResourceBundle.java
new file mode 100644
index 00000000000..2bc51c3b013
--- /dev/null
+++ b/libjava/classpath/java/util/ListResourceBundle.java
@@ -0,0 +1,140 @@
+/* ListResourceBundle -- a resource bundle build around a list
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A <code>ListResouceBundle</code> provides an easy way, to create your own
+ * resource bundle. It is an abstract class that you can subclass. You should
+ * then overwrite the getContents method, that provides a key/value list.
+ *
+ * <p>The key/value list is a two dimensional list of Object. The first
+ * dimension ranges over the resources. The second dimension ranges from
+ * zero (key) to one (value). The keys must be of type String, and they are
+ * case-sensitive. For example:
+ *
+<br><pre>public class MyResources
+ extends ListResourceBundle
+{
+ public Object[][] getContents()
+ {
+ return contents;
+ }
+
+ static final Object[][] contents =
+ {
+ // LOCALIZED STRINGS
+ {"s1", "The disk \"{1}\" contains {0}."}, // MessageFormat pattern
+ {"s2", "1"}, // location of {0} in pattern
+ {"s3", "My Disk"}, // sample disk name
+ {"s4", "no files"}, // first ChoiceFormat choice
+ {"s5", "one file"}, // second ChoiceFormat choice
+ {"s6", "{0,number} files"} // third ChoiceFormat choice
+ {"s7", "3 Mar 96"}, // sample date
+ {"s8", new Dimension(1,5)} // real object, not just string
+ // END OF LOCALIZED MATERIAL
+ };
+}</pre>
+ *
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Locale
+ * @see PropertyResourceBundle
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ListResourceBundle extends ResourceBundle
+{
+ /**
+ * The constructor. It does nothing special.
+ */
+ public ListResourceBundle()
+ {
+ }
+
+ /**
+ * Gets a resource for a given key. This is called by <code>getObject</code>.
+ *
+ * @param key the key of the resource
+ * @return the resource for the key, or null if it doesn't exist
+ */
+ public final Object handleGetObject(String key)
+ {
+ Object[][] contents = getContents();
+ int i = contents.length;
+ while (--i >= 0)
+ if (key.equals(contents[i][0]))
+ return contents[i][1];
+ return null;
+ }
+
+ /**
+ * This method should return all keys for which a resource exists.
+ *
+ * @return an enumeration of the keys
+ */
+ public Enumeration getKeys()
+ {
+ // We make a new Set that holds all the keys, then return an enumeration
+ // for that. This prevents modifications from ruining the enumeration,
+ // as well as ignoring duplicates.
+ final Object[][] contents = getContents();
+ Set s = new HashSet();
+ int i = contents.length;
+ while (--i >= 0)
+ s.add(contents[i][0]);
+ ResourceBundle bundle = parent;
+ // Eliminate tail recursion.
+ while (bundle != null)
+ {
+ Enumeration e = bundle.getKeys();
+ while (e.hasMoreElements())
+ s.add(e.nextElement());
+ bundle = bundle.parent;
+ }
+ return Collections.enumeration(s);
+ }
+
+ /**
+ * Gets the key/value list. You must override this method, and should not
+ * provide duplicate keys or null entries.
+ *
+ * @return a two dimensional list of String key / Object resouce pairs
+ */
+ protected abstract Object[][] getContents();
+} // class ListResourceBundle
diff --git a/libjava/classpath/java/util/Locale.java b/libjava/classpath/java/util/Locale.java
new file mode 100644
index 00000000000..6d3f8463252
--- /dev/null
+++ b/libjava/classpath/java/util/Locale.java
@@ -0,0 +1,952 @@
+/* Locale.java -- i18n locales
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.classpath.SystemProperties;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * Locales represent a specific country and culture. Classes which can be
+ * passed a Locale object tailor their information for a given locale. For
+ * instance, currency number formatting is handled differently for the USA
+ * and France.
+ *
+ * <p>Locales are made up of a language code, a country code, and an optional
+ * set of variant strings. Language codes are represented by
+ * <a href="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
+ * ISO 639:1988</a> w/ additions from ISO 639/RA Newsletter No. 1/1989
+ * and a decision of the Advisory Committee of ISO/TC39 on August 8, 1997.
+ *
+ * <p>Country codes are represented by
+ * <a href="http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html">
+ * ISO 3166</a>. Variant strings are vendor and browser specific. Standard
+ * variant strings include "POSIX" for POSIX, "WIN" for MS-Windows, and
+ * "MAC" for Macintosh. When there is more than one variant string, they must
+ * be separated by an underscore (U+005F).
+ *
+ * <p>The default locale is determined by the values of the system properties
+ * user.language, user.region, and user.variant, defaulting to "en". Note that
+ * the locale does NOT contain the conversion and formatting capabilities (for
+ * that, use ResourceBundle and java.text). Rather, it is an immutable tag
+ * object for identifying a given locale, which is referenced by these other
+ * classes when they must make locale-dependent decisions.
+ *
+ * @see ResourceBundle
+ * @see java.text.Format
+ * @see java.text.NumberFormat
+ * @see java.text.Collator
+ * @author Jochen Hoenicke
+ * @author Paul Fisher
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Locale implements Serializable, Cloneable
+{
+ /** Locale which represents the English language. */
+ public static final Locale ENGLISH = getLocale("en");
+
+ /** Locale which represents the French language. */
+ public static final Locale FRENCH = getLocale("fr");
+
+ /** Locale which represents the German language. */
+ public static final Locale GERMAN = getLocale("de");
+
+ /** Locale which represents the Italian language. */
+ public static final Locale ITALIAN = getLocale("it");
+
+ /** Locale which represents the Japanese language. */
+ public static final Locale JAPANESE = getLocale("ja");
+
+ /** Locale which represents the Korean language. */
+ public static final Locale KOREAN = getLocale("ko");
+
+ /** Locale which represents the Chinese language. */
+ public static final Locale CHINESE = getLocale("zh");
+
+ /** Locale which represents the Chinese language as used in China. */
+ public static final Locale SIMPLIFIED_CHINESE = getLocale("zh", "CN");
+
+ /**
+ * Locale which represents the Chinese language as used in Taiwan.
+ * Same as TAIWAN Locale.
+ */
+ public static final Locale TRADITIONAL_CHINESE = getLocale("zh", "TW");
+
+ /** Locale which represents France. */
+ public static final Locale FRANCE = getLocale("fr", "FR");
+
+ /** Locale which represents Germany. */
+ public static final Locale GERMANY = getLocale("de", "DE");
+
+ /** Locale which represents Italy. */
+ public static final Locale ITALY = getLocale("it", "IT");
+
+ /** Locale which represents Japan. */
+ public static final Locale JAPAN = getLocale("ja", "JP");
+
+ /** Locale which represents Korea. */
+ public static final Locale KOREA = getLocale("ko", "KR");
+
+ /**
+ * Locale which represents China.
+ * Same as SIMPLIFIED_CHINESE Locale.
+ */
+ public static final Locale CHINA = SIMPLIFIED_CHINESE;
+
+ /**
+ * Locale which represents the People's Republic of China.
+ * Same as CHINA Locale.
+ */
+ public static final Locale PRC = CHINA;
+
+ /**
+ * Locale which represents Taiwan.
+ * Same as TRADITIONAL_CHINESE Locale.
+ */
+ public static final Locale TAIWAN = TRADITIONAL_CHINESE;
+
+ /** Locale which represents the United Kingdom. */
+ public static final Locale UK = getLocale("en", "GB");
+
+ /** Locale which represents the United States. */
+ public static final Locale US = getLocale("en", "US");
+
+ /** Locale which represents the English speaking portion of Canada. */
+ public static final Locale CANADA = getLocale("en", "CA");
+
+ /** Locale which represents the French speaking portion of Canada. */
+ public static final Locale CANADA_FRENCH = getLocale("fr", "CA");
+
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 9149081749638150636L;
+
+ /**
+ * The language code, as returned by getLanguage().
+ *
+ * @serial the languange, possibly ""
+ */
+ private String language;
+
+ /**
+ * The country code, as returned by getCountry().
+ *
+ * @serial the country, possibly ""
+ */
+ private String country;
+
+ /**
+ * The variant code, as returned by getVariant().
+ *
+ * @serial the variant, possibly ""
+ */
+ private String variant;
+
+ /**
+ * This is the cached hashcode. When writing to stream, we write -1.
+ *
+ * @serial should be -1 in serial streams
+ */
+ private transient int hashcode;
+
+ /**
+ * Array storing all available locales.
+ */
+ private static transient Locale[] availableLocales;
+
+ /**
+ * Locale cache. Only created locale objects are stored.
+ * Contains all supported locales when getAvailableLocales()
+ * got called.
+ */
+ private static transient HashMap localeMap;
+
+ /**
+ * The default locale. Except for during bootstrapping, this should never be
+ * null. Note the logic in the main constructor, to detect when
+ * bootstrapping has completed.
+ */
+ private static Locale defaultLocale =
+ getLocale(SystemProperties.getProperty("user.language", "en"),
+ SystemProperties.getProperty("user.region", ""),
+ SystemProperties.getProperty("user.variant", ""));
+
+ /**
+ * Array storing all the available two-letter ISO639 languages.
+ */
+ private static transient String[] languageCache;
+
+ /**
+ * Array storing all the available two-letter ISO3166 country codes.
+ */
+ private static transient String[] countryCache;
+
+ /**
+ * Retrieves the locale with the specified language from the cache.
+ *
+ * @param language the language of the locale to retrieve.
+ * @return the locale.
+ */
+ private static Locale getLocale(String language)
+ {
+ return getLocale(language, "", "");
+ }
+
+ /**
+ * Retrieves the locale with the specified language and region
+ * from the cache.
+ *
+ * @param language the language of the locale to retrieve.
+ * @param region the region of the locale to retrieve.
+ * @return the locale.
+ */
+ private static Locale getLocale(String language, String region)
+ {
+ return getLocale(language, region, "");
+ }
+
+ /**
+ * Retrieves the locale with the specified language, region
+ * and variant from the cache.
+ *
+ * @param language the language of the locale to retrieve.
+ * @param region the region of the locale to retrieve.
+ * @param variant the variant of the locale to retrieve.
+ * @return the locale.
+ */
+ private static Locale getLocale(String language, String region, String variant)
+ {
+ if (localeMap == null)
+ localeMap = new HashMap(256);
+
+ String name = language + "_" + region + "_" + variant;
+ Locale locale = (Locale) localeMap.get(name);
+
+ if (locale == null)
+ {
+ locale = new Locale(language, region, variant);
+ localeMap.put(name, locale);
+ }
+
+ return locale;
+ }
+
+ /**
+ * Convert new iso639 codes to the old ones.
+ *
+ * @param language the language to check
+ * @return the appropriate code
+ */
+ private String convertLanguage(String language)
+ {
+ if (language.equals(""))
+ return language;
+ language = language.toLowerCase();
+ int index = "he,id,yi".indexOf(language);
+ if (index != -1)
+ return "iw,in,ji".substring(index, index + 2);
+ return language;
+ }
+
+ /**
+ * Creates a new locale for the given language and country.
+ *
+ * @param language lowercase two-letter ISO-639 A2 language code
+ * @param country uppercase two-letter ISO-3166 A2 contry code
+ * @param variant vendor and browser specific
+ * @throws NullPointerException if any argument is null
+ */
+ public Locale(String language, String country, String variant)
+ {
+ // During bootstrap, we already know the strings being passed in are
+ // the correct capitalization, and not null. We can't call
+ // String.toUpperCase during this time, since that depends on the
+ // default locale.
+ if (defaultLocale != null)
+ {
+ language = convertLanguage(language).intern();
+ country = country.toUpperCase().intern();
+ variant = variant.intern();
+ }
+ this.language = language;
+ this.country = country;
+ this.variant = variant;
+ hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
+ }
+
+ /**
+ * Creates a new locale for the given language and country.
+ *
+ * @param language lowercase two-letter ISO-639 A2 language code
+ * @param country uppercase two-letter ISO-3166 A2 country code
+ * @throws NullPointerException if either argument is null
+ */
+ public Locale(String language, String country)
+ {
+ this(language, country, "");
+ }
+
+ /**
+ * Creates a new locale for a language.
+ *
+ * @param language lowercase two-letter ISO-639 A2 language code
+ * @throws NullPointerException if either argument is null
+ * @since 1.4
+ */
+ public Locale(String language)
+ {
+ this(language, "", "");
+ }
+
+ /**
+ * Returns the default Locale. The default locale is generally once set
+ * on start up and then never changed. Normally you should use this locale
+ * for everywhere you need a locale. The initial setting matches the
+ * default locale, the user has chosen.
+ *
+ * @return the default locale for this virtual machine
+ */
+ public static Locale getDefault()
+ {
+ return defaultLocale;
+ }
+
+ /**
+ * Changes the default locale. Normally only called on program start up.
+ * Note that this doesn't change the locale for other programs. This has
+ * a security check,
+ * <code>PropertyPermission("user.language", "write")</code>, because of
+ * its potential impact to running code.
+ *
+ * @param newLocale the new default locale
+ * @throws NullPointerException if newLocale is null
+ * @throws SecurityException if permission is denied
+ */
+ public static void setDefault(Locale newLocale)
+ {
+ if (newLocale == null)
+ throw new NullPointerException();
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission("user.language", "write"));
+ defaultLocale = newLocale;
+ }
+
+ /**
+ * Returns the list of available locales.
+ *
+ * @return the installed locales
+ */
+ public static synchronized Locale[] getAvailableLocales()
+ {
+ if (availableLocales == null)
+ {
+ String[] localeNames = LocaleData.localeNames;
+ availableLocales = new Locale[localeNames.length];
+
+ for (int i = 0; i < localeNames.length; i++)
+ {
+ String language;
+ String region = "";
+ String variant = "";
+ String name = localeNames[i];
+
+ language = name.substring(0, 2);
+
+ if (name.length() > 2)
+ region = name.substring(3);
+
+ int index = region.indexOf("_");
+ if (index > 0)
+ {
+ variant = region.substring(index + 1);
+ region = region.substring(0, index - 1);
+ }
+
+ availableLocales[i] = getLocale(language, region, variant);
+ }
+ }
+
+ return availableLocales;
+ }
+
+ /**
+ * Returns a list of all 2-letter uppercase country codes as defined
+ * in ISO 3166.
+ *
+ * @return a list of acceptable country codes
+ */
+ public static String[] getISOCountries()
+ {
+ if (countryCache == null)
+ {
+ countryCache = getISOStrings("territories");
+ }
+
+ return countryCache;
+ }
+
+ /**
+ * Returns a list of all 2-letter lowercase language codes as defined
+ * in ISO 639 (both old and new variant).
+ *
+ * @return a list of acceptable language codes
+ */
+ public static String[] getISOLanguages()
+ {
+ if (languageCache == null)
+ {
+ languageCache = getISOStrings("languages");
+ }
+ return languageCache;
+ }
+
+ /**
+ * Returns the set of keys from the specified resource hashtable, filtered
+ * so that only two letter strings are returned.
+ *
+ * @param tableName the name of the table from which to retrieve the keys.
+ * @return an array of two-letter strings.
+ */
+ private static String[] getISOStrings(String tableName)
+ {
+ int count = 0;
+ ResourceBundle bundle =
+ ResourceBundle.getBundle("gnu.java.locale.LocaleInformation");
+ Enumeration e = bundle.getKeys();
+ ArrayList tempList = new ArrayList();
+
+ while (e.hasMoreElements())
+ {
+ String key = (String) e.nextElement();
+
+ if (key.startsWith(tableName + "."))
+ {
+ String str = key.substring(tableName.length() + 1);
+
+ if (str.length() == 2
+ && Character.isLetter(str.charAt(0))
+ && Character.isLetter(str.charAt(1)))
+ {
+ tempList.add(str);
+ ++count;
+ }
+ }
+ }
+
+ String[] strings = new String[count];
+
+ for (int a = 0; a < count; ++a)
+ strings[a] = (String) tempList.get(a);
+
+ return strings;
+ }
+
+ /**
+ * Returns the language code of this locale. Some language codes have changed
+ * as ISO 639 has evolved; this returns the old name, even if you built
+ * the locale with the new one.
+ *
+ * @return language code portion of this locale, or an empty String
+ */
+ public String getLanguage()
+ {
+ return language;
+ }
+
+ /**
+ * Returns the country code of this locale.
+ *
+ * @return country code portion of this locale, or an empty String
+ */
+ public String getCountry()
+ {
+ return country;
+ }
+
+ /**
+ * Returns the variant code of this locale.
+ *
+ * @return the variant code portion of this locale, or an empty String
+ */
+ public String getVariant()
+ {
+ return variant;
+ }
+
+ /**
+ * Gets the string representation of the current locale. This consists of
+ * the language, the country, and the variant, separated by an underscore.
+ * The variant is listed only if there is a language or country. Examples:
+ * "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC".
+ *
+ * @return the string representation of this Locale
+ * @see #getDisplayName()
+ */
+ public String toString()
+ {
+ if (language.length() == 0 && country.length() == 0)
+ return "";
+ else if (country.length() == 0 && variant.length() == 0)
+ return language;
+ StringBuffer result = new StringBuffer(language);
+ result.append('_').append(country);
+ if (variant.length() != 0)
+ result.append('_').append(variant);
+ return result.toString();
+ }
+
+ /**
+ * Returns the three-letter ISO language abbrevation of this locale.
+ *
+ * @throws MissingResourceException if the three-letter code is not known
+ */
+ public String getISO3Language()
+ {
+ // We know all strings are interned so we can use '==' for better performance.
+ if (language == "")
+ return "";
+ int index
+ = ("aa,ab,af,am,ar,as,ay,az,ba,be,bg,bh,bi,bn,bo,br,ca,co,cs,cy,da,"
+ + "de,dz,el,en,eo,es,et,eu,fa,fi,fj,fo,fr,fy,ga,gd,gl,gn,gu,ha,iw,"
+ + "hi,hr,hu,hy,ia,in,ie,ik,in,is,it,iu,iw,ja,ji,jw,ka,kk,kl,km,kn,"
+ + "ko,ks,ku,ky,la,ln,lo,lt,lv,mg,mi,mk,ml,mn,mo,mr,ms,mt,my,na,ne,"
+ + "nl,no,oc,om,or,pa,pl,ps,pt,qu,rm,rn,ro,ru,rw,sa,sd,sg,sh,si,sk,"
+ + "sl,sm,sn,so,sq,sr,ss,st,su,sv,sw,ta,te,tg,th,ti,tk,tl,tn,to,tr,"
+ + "ts,tt,tw,ug,uk,ur,uz,vi,vo,wo,xh,ji,yo,za,zh,zu")
+ .indexOf(language);
+
+ if (index % 3 != 0 || language.length() != 2)
+ throw new MissingResourceException
+ ("Can't find ISO3 language for " + language,
+ "java.util.Locale", language);
+
+ // Don't read this aloud. These are the three letter language codes.
+ return
+ ("aarabkaframharaasmaymazebakbelbulbihbisbenbodbrecatcoscescymdandeu"
+ + "dzoellengepospaesteusfasfinfijfaofrafrygaigdhglggrngujhauhebhinhrv"
+ + "hunhyeinaindileipkindislitaikuhebjpnyidjawkatkazkalkhmkankorkaskur"
+ + "kirlatlinlaolitlavmlgmrimkdmalmonmolmarmsamltmyanaunepnldnorociorm"
+ + "oripanpolpusporquerohrunronruskinsansndsagsrpsinslkslvsmosnasomsqi"
+ + "srpsswsotsunsweswatamteltgkthatirtuktgltsntonturtsotattwiuigukrurd"
+ + "uzbvievolwolxhoyidyorzhazhozul")
+ .substring(index, index + 3);
+ }
+
+ /**
+ * Returns the three-letter ISO country abbrevation of the locale.
+ *
+ * @throws MissingResourceException if the three-letter code is not known
+ */
+ public String getISO3Country()
+ {
+ // We know all strings are interned so we can use '==' for better performance.
+ if (country == "")
+ return "";
+ int index
+ = ("AD,AE,AF,AG,AI,AL,AM,AN,AO,AQ,AR,AS,AT,AU,AW,AZ,BA,BB,BD,BE,BF,"
+ + "BG,BH,BI,BJ,BM,BN,BO,BR,BS,BT,BV,BW,BY,BZ,CA,CC,CF,CG,CH,CI,CK,"
+ + "CL,CM,CN,CO,CR,CU,CV,CX,CY,CZ,DE,DJ,DK,DM,DO,DZ,EC,EE,EG,EH,ER,"
+ + "ES,ET,FI,FJ,FK,FM,FO,FR,FX,GA,GB,GD,GE,GF,GH,GI,GL,GM,GN,GP,GQ,"
+ + "GR,GS,GT,GU,GW,GY,HK,HM,HN,HR,HT,HU,ID,IE,IL,IN,IO,IQ,IR,IS,IT,"
+ + "JM,JO,JP,KE,KG,KH,KI,KM,KN,KP,KR,KW,KY,KZ,LA,LB,LC,LI,LK,LR,LS,"
+ + "LT,LU,LV,LY,MA,MC,MD,MG,MH,MK,ML,MM,MN,MO,MP,MQ,MR,MS,MT,MU,MV,"
+ + "MW,MX,MY,MZ,NA,NC,NE,NF,NG,NI,NL,NO,NP,NR,NU,NZ,OM,PA,PE,PF,PG,"
+ + "PH,PK,PL,PM,PN,PR,PT,PW,PY,QA,RE,RO,RU,RW,SA,SB,SC,SD,SE,SG,SH,"
+ + "SI,SJ,SK,SL,SM,SN,SO,SR,ST,SV,SY,SZ,TC,TD,TF,TG,TH,TJ,TK,TM,TN,"
+ + "TO,TP,TR,TT,TV,TW,TZ,UA,UG,UM,US,UY,UZ,VA,VC,VE,VG,VI,VN,VU,WF,"
+ + "WS,YE,YT,YU,ZA,ZM,ZR,ZW")
+ .indexOf(country);
+
+ if (index % 3 != 0 || country.length() != 2)
+ throw new MissingResourceException
+ ("Can't find ISO3 country for " + country,
+ "java.util.Locale", country);
+
+ // Don't read this aloud. These are the three letter country codes.
+ return
+ ("ANDAREAFGATGAIAALBARMANTAGOATAARGASMAUTAUSABWAZEBIHBRBBGDBELBFABGR"
+ + "BHRBDIBENBMUBRNBOLBRABHSBTNBVTBWABLRBLZCANCCKCAFCOGCHECIVCOKCHLCMR"
+ + "CHNCOLCRICUBCPVCXRCYPCZEDEUDJIDNKDMADOMDZAECUESTEGYESHERIESPETHFIN"
+ + "FJIFLKFSMFROFRAFXXGABGBRGRDGEOGUFGHAGIBGRLGMBGINGLPGNQGRCSGSGTMGUM"
+ + "GNBGUYHKGHMDHNDHRVHTIHUNIDNIRLISRINDIOTIRQIRNISLITAJAMJORJPNKENKGZ"
+ + "KHMKIRCOMKNAPRKKORKWTCYMKAZLAOLBNLCALIELKALBRLSOLTULUXLVALBYMARMCO"
+ + "MDAMDGMHLMKDMLIMMRMNGMACMNPMTQMRTMSRMLTMUSMDVMWIMEXMYSMOZNAMNCLNER"
+ + "NFKNGANICNLDNORNPLNRUNIUNZLOMNPANPERPYFPNGPHLPAKPOLSPMPCNPRIPRTPLW"
+ + "PRYQATREUROMRUSRWASAUSLBSYCSDNSWESGPSHNSVNSJMSVKSLESMRSENSOMSURSTP"
+ + "SLVSYRSWZTCATCDATFTGOTHATJKTKLTKMTUNTONTMPTURTTOTUVTWNTZAUKRUGAUMI"
+ + "USAURYUZBVATVCTVENVGBVIRVNMVUTWLFWSMYEMMYTYUGZAFZMBZARZWE")
+ .substring(index, index + 3);
+ }
+
+ /**
+ * Gets the country name suitable for display to the user, formatted
+ * for the default locale. This has the same effect as
+ * <pre>
+ * getDisplayLanguage(Locale.getDefault());
+ * </pre>
+ *
+ * @return the language name of this locale localized to the default locale,
+ * with the ISO code as backup
+ */
+ public String getDisplayLanguage()
+ {
+ return getDisplayLanguage(defaultLocale);
+ }
+
+ /**
+ * <p>
+ * Gets the name of the language specified by this locale, in a form suitable
+ * for display to the user. If possible, the display name will be localized
+ * to the specified locale. For example, if the locale instance is
+ * <code>Locale.GERMANY</code>, and the specified locale is <code>Locale.UK</code>,
+ * the result would be 'German'. Using the German locale would instead give
+ * 'Deutsch'. If the display name can not be localized to the supplied
+ * locale, it will fall back on other output in the following order:
+ * </p>
+ * <ul>
+ * <li>the display name in the default locale</li>
+ * <li>the display name in English</li>
+ * <li>the ISO code</li>
+ * </ul>
+ * <p>
+ * If the language is unspecified by this locale, then the empty string is
+ * returned.
+ * </p>
+ *
+ * @param inLocale the locale to use for formatting the display string.
+ * @return the language name of this locale localized to the given locale,
+ * with the default locale, English and the ISO code as backups.
+ * @throws NullPointerException if the supplied locale is null.
+ */
+ public String getDisplayLanguage(Locale inLocale)
+ {
+ try
+ {
+ ResourceBundle res =
+ ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ inLocale,
+ ClassLoader.getSystemClassLoader());
+
+ return res.getString("languages." + language);
+ }
+ catch (MissingResourceException e)
+ {
+ return language;
+ }
+ }
+
+ /**
+ * Returns the country name of this locale localized to the
+ * default locale. If the localized is not found, the ISO code
+ * is returned. This has the same effect as
+ * <pre>
+ * getDisplayCountry(Locale.getDefault());
+ * </pre>
+ *
+ * @return the country name of this locale localized to the given locale,
+ * with the ISO code as backup
+ */
+ public String getDisplayCountry()
+ {
+ return getDisplayCountry(defaultLocale);
+ }
+
+ /**
+ * <p>
+ * Gets the name of the country specified by this locale, in a form suitable
+ * for display to the user. If possible, the display name will be localized
+ * to the specified locale. For example, if the locale instance is
+ * <code>Locale.GERMANY</code>, and the specified locale is <code>Locale.UK</code>,
+ * the result would be 'Germany'. Using the German locale would instead give
+ * 'Deutschland'. If the display name can not be localized to the supplied
+ * locale, it will fall back on other output in the following order:
+ * </p>
+ * <ul>
+ * <li>the display name in the default locale</li>
+ * <li>the display name in English</li>
+ * <li>the ISO code</li>
+ * </ul>
+ * <p>
+ * If the country is unspecified by this locale, then the empty string is
+ * returned.
+ * </p>
+ *
+ * @param inLocale the locale to use for formatting the display string.
+ * @return the country name of this locale localized to the given locale,
+ * with the default locale, English and the ISO code as backups.
+ * @throws NullPointerException if the supplied locale is null.
+ */
+ public String getDisplayCountry(Locale inLocale)
+ {
+ try
+ {
+ ResourceBundle res =
+ ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ inLocale,
+ ClassLoader.getSystemClassLoader());
+
+ return res.getString("territories." + country);
+ }
+ catch (MissingResourceException e)
+ {
+ return country;
+ }
+ }
+
+ /**
+ * Returns the variant name of this locale localized to the
+ * default locale. If the localized is not found, the variant code
+ * itself is returned. This has the same effect as
+ * <pre>
+ * getDisplayVariant(Locale.getDefault());
+ * </pre>
+ *
+ * @return the variant code of this locale localized to the given locale,
+ * with the ISO code as backup
+ */
+ public String getDisplayVariant()
+ {
+ return getDisplayVariant(defaultLocale);
+ }
+
+
+ /**
+ * <p>
+ * Gets the name of the variant specified by this locale, in a form suitable
+ * for display to the user. If possible, the display name will be localized
+ * to the specified locale. For example, if the locale instance is a revised
+ * variant, and the specified locale is <code>Locale.UK</code>, the result
+ * would be 'REVISED'. Using the German locale would instead give
+ * 'Revidiert'. If the display name can not be localized to the supplied
+ * locale, it will fall back on other output in the following order:
+ * </p>
+ * <ul>
+ * <li>the display name in the default locale</li>
+ * <li>the display name in English</li>
+ * <li>the ISO code</li>
+ * </ul>
+ * <p>
+ * If the variant is unspecified by this locale, then the empty string is
+ * returned.
+ * </p>
+ *
+ * @param inLocale the locale to use for formatting the display string.
+ * @return the variant name of this locale localized to the given locale,
+ * with the default locale, English and the ISO code as backups.
+ * @throws NullPointerException if the supplied locale is null.
+ */
+ public String getDisplayVariant(Locale inLocale)
+ {
+ try
+ {
+ ResourceBundle res =
+ ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ inLocale,
+ ClassLoader.getSystemClassLoader());
+
+ return res.getString("variants." + variant);
+ }
+ catch (MissingResourceException e)
+ {
+ return variant;
+ }
+ }
+
+ /**
+ * Gets all local components suitable for display to the user, formatted
+ * for the default locale. For the language component, getDisplayLanguage
+ * is called. For the country component, getDisplayCountry is called.
+ * For the variant set component, getDisplayVariant is called.
+ *
+ * <p>The returned String will be one of the following forms:<br>
+ * <pre>
+ * language (country, variant)
+ * language (country)
+ * language (variant)
+ * country (variant)
+ * language
+ * country
+ * variant
+ * </pre>
+ *
+ * @return String version of this locale, suitable for display to the user
+ */
+ public String getDisplayName()
+ {
+ return getDisplayName(defaultLocale);
+ }
+
+ /**
+ * Gets all local components suitable for display to the user, formatted
+ * for a specified locale. For the language component,
+ * getDisplayLanguage(Locale) is called. For the country component,
+ * getDisplayCountry(Locale) is called. For the variant set component,
+ * getDisplayVariant(Locale) is called.
+ *
+ * <p>The returned String will be one of the following forms:<br>
+ * <pre>
+ * language (country, variant)
+ * language (country)
+ * language (variant)
+ * country (variant)
+ * language
+ * country
+ * variant
+ * </pre>
+ *
+ * @param locale locale to use for formatting
+ * @return String version of this locale, suitable for display to the user
+ */
+ public String getDisplayName(Locale locale)
+ {
+ StringBuffer result = new StringBuffer();
+ int count = 0;
+ String[] delimiters = {"", " (", ","};
+ if (language.length() != 0)
+ {
+ result.append(delimiters[count++]);
+ result.append(getDisplayLanguage(locale));
+ }
+ if (country.length() != 0)
+ {
+ result.append(delimiters[count++]);
+ result.append(getDisplayCountry(locale));
+ }
+ if (variant.length() != 0)
+ {
+ result.append(delimiters[count++]);
+ result.append(getDisplayVariant(locale));
+ }
+ if (count > 1)
+ result.append(")");
+ return result.toString();
+ }
+
+ /**
+ * Does the same as <code>Object.clone()</code> but does not throw
+ * a <code>CloneNotSupportedException</code>. Why anyone would
+ * use this method is a secret to me, since this class is immutable.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ // This class is final, so no need to use native super.clone().
+ return new Locale(language, country, variant);
+ }
+
+ /**
+ * Return the hash code for this locale. The hashcode is the logical
+ * xor of the hash codes of the language, the country and the variant.
+ * The hash code is precomputed, since <code>Locale</code>s are often
+ * used in hash tables.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ return hashcode;
+ }
+
+ /**
+ * Compares two locales. To be equal, obj must be a Locale with the same
+ * language, country, and variant code.
+ *
+ * @param obj the other locale
+ * @return true if obj is equal to this
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (! (obj instanceof Locale))
+ return false;
+ Locale l = (Locale) obj;
+
+ return (language == l.language
+ && country == l.country
+ && variant == l.variant);
+ }
+
+ /**
+ * Write the locale to an object stream.
+ *
+ * @param output 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 input the stream to read from
+ * @throws IOException if reading fails
+ * @throws ClassNotFoundException if reading fails
+ * @serialData the hashCode is always invalid and must be recomputed
+ */
+ 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();
+ }
+} // class Locale
diff --git a/libjava/classpath/java/util/Map.java b/libjava/classpath/java/util/Map.java
new file mode 100644
index 00000000000..256e98899f6
--- /dev/null
+++ b/libjava/classpath/java/util/Map.java
@@ -0,0 +1,338 @@
+/* Map.java: interface Map -- An object that maps keys to values
+ interface Map.Entry -- an Entry in a Map
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An object that maps keys onto values. Keys cannot be duplicated. This
+ * interface replaces the obsolete {@link Dictionary} abstract class.
+ * <p>
+ *
+ * The map has three collection views, which are backed by the map
+ * (modifications on one show up on the other): a set of keys, a collection
+ * of values, and a set of key-value mappings. Some maps have a guaranteed
+ * order, but not all do.
+ * <p>
+ *
+ * Note: Be careful about using mutable keys. Behavior is unspecified if
+ * a key's comparison behavior is changed after the fact. As a corollary
+ * to this rule, don't use a Map as one of its own keys or values, as it makes
+ * hashCode and equals have undefined behavior.
+ * <p>
+ *
+ * All maps are recommended to provide a no argument constructor, which builds
+ * an empty map, and one that accepts a Map parameter and copies the mappings
+ * (usually by putAll), to create an equivalent map. Unfortunately, Java
+ * cannot enforce these suggestions.
+ * <p>
+ *
+ * The map may be unmodifiable, in which case unsupported operations will
+ * throw an UnsupportedOperationException. Note that some operations may be
+ * safe, such as putAll(m) where m is empty, even if the operation would
+ * normally fail with a non-empty argument.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see HashMap
+ * @see TreeMap
+ * @see Hashtable
+ * @see SortedMap
+ * @see Collection
+ * @see Set
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Map
+{
+ /**
+ * Remove all entries from this Map (optional operation).
+ *
+ * @throws UnsupportedOperationException if clear is not supported
+ */
+ void clear();
+
+ /**
+ * Returns true if this contains a mapping for the given key.
+ *
+ * @param key the key to search for
+ * @return true if the map contains the key
+ * @throws ClassCastException if the key is of an inappropriate type
+ * @throws NullPointerException if key is <code>null</code> but the map
+ * does not permit null keys
+ */
+ boolean containsKey(Object key);
+
+ /**
+ * Returns true if this contains at least one mapping with the given value.
+ * In other words, returns true if a value v exists where
+ * <code>(value == null ? v == null : value.equals(v))</code>. This usually
+ * requires linear time.
+ *
+ * @param value the value to search for
+ * @return true if the map contains the value
+ * @throws ClassCastException if the type of the value is not a valid type
+ * for this map.
+ * @throws NullPointerException if the value is null and the map doesn't
+ * support null values.
+ */
+ boolean containsValue(Object value);
+
+ /**
+ * 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.
+ *
+ * @return the set view of all mapping entries
+ * @see Map.Entry
+ */
+ Set entrySet();
+
+ /**
+ * Compares the specified object with this map for equality. Returns
+ * <code>true</code> if the other object is a Map with the same mappings,
+ * that is,<br>
+ * <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
+ * This allows comparison of maps, regardless of implementation.
+ *
+ * @param o the object to be compared
+ * @return true if the object equals this map
+ * @see Set#equals(Object)
+ */
+ boolean equals(Object o);
+
+ /**
+ * Returns the value mapped by the given key. Returns <code>null</code> if
+ * there is no mapping. However, in Maps that accept null values, you
+ * must rely on <code>containsKey</code> to determine if a mapping exists.
+ *
+ * @param key the key to look up
+ * @return the value associated with the key, or null if key not in map
+ * @throws ClassCastException if the key is an inappropriate type
+ * @throws NullPointerException if this map does not accept null keys
+ * @see #containsKey(Object)
+ */
+ Object get(Object key);
+
+ /**
+ * Associates the given key to the given value (optional operation). If the
+ * map already contains the key, its value is replaced. Be aware that in
+ * a map that permits <code>null</code> values, a null return does not
+ * always imply that the mapping was created.
+ *
+ * @param key the key to map
+ * @param value the value to be mapped
+ * @return the previous value of the key, or null if there was no mapping
+ * @throws UnsupportedOperationException if the operation is not supported
+ * @throws ClassCastException if the key or value is of the wrong type
+ * @throws IllegalArgumentException if something about this key or value
+ * prevents it from existing in this map
+ * @throws NullPointerException if either the key or the value is null,
+ * and the map forbids null keys or values
+ * @see #containsKey(Object)
+ */
+ Object put(Object key, Object value);
+
+ /**
+ * Returns the hash code for this map. This is the sum of all hashcodes
+ * for each Map.Entry object in entrySet. This allows comparison of maps,
+ * regardless of implementation, and satisfies the contract of
+ * Object.hashCode.
+ *
+ * @return the hash code
+ * @see Map.Entry#hashCode()
+ */
+ int hashCode();
+
+ /**
+ * Returns true if the map contains no mappings.
+ *
+ * @return true if the map is empty
+ */
+ boolean isEmpty();
+
+ /**
+ * 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
+ */
+ Set keySet();
+
+ /**
+ * Copies all entries of the given map to this one (optional operation). If
+ * the map already contains a key, its value is replaced.
+ *
+ * @param m the mapping to load into this map
+ * @throws UnsupportedOperationException if the operation is not supported
+ * @throws ClassCastException if a key or value is of the wrong type
+ * @throws IllegalArgumentException if something about a key or value
+ * prevents it from existing in this map
+ * @throws NullPointerException if the map forbids null keys or values, or
+ * if <code>m</code> is null.
+ * @see #put(Object, Object)
+ */
+ void putAll(Map m);
+
+ /**
+ * Removes the mapping for this key if present (optional operation). If
+ * the key is not present, this returns null. Note that maps which permit
+ * null values may also return null if the key was removed.
+ *
+ * @param key the key to remove
+ * @return the value the key mapped to, or null if not present.
+ * @throws UnsupportedOperationException if deletion is unsupported
+ * @throws NullPointerException if the key is null and this map doesn't
+ * support null keys.
+ * @throws ClassCastException if the type of the key is not a valid type
+ * for this map.
+ */
+ Object remove(Object key);
+
+ /**
+ * Returns the number of key-value mappings in the map. If there are more
+ * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE.
+ *
+ * @return the number of mappings
+ */
+ int size();
+
+ /**
+ * 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
+ */
+ Collection values();
+
+ /**
+ * A map entry (key-value pair). The Map.entrySet() method returns a set
+ * view of these objects; there is no other valid way to come across them.
+ * These objects are only valid for the duration of an iteration; in other
+ * words, if you mess with one after modifying the map, you are asking
+ * for undefined behavior.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Map
+ * @see Map#entrySet()
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ interface Entry
+ {
+ /**
+ * Get the key corresponding to this entry.
+ *
+ * @return the key
+ */
+ Object getKey();
+
+ /**
+ * Get the value corresponding to this entry. If you already called
+ * Iterator.remove(), this is undefined.
+ *
+ * @return the value
+ */
+ Object getValue();
+
+ /**
+ * Replaces the value with the specified object (optional operation).
+ * This writes through to the map, and is undefined if you already
+ * called Iterator.remove().
+ *
+ * @param value the new value to store
+ * @return the old value
+ * @throws UnsupportedOperationException if the operation is not supported
+ * @throws ClassCastException if the value is of the wrong type
+ * @throws IllegalArgumentException if something about the value
+ * prevents it from existing in this map
+ * @throws NullPointerException if the map forbids null values
+ */
+ Object setValue(Object value);
+
+
+ /**
+ * Returns the hash code of the entry. This is defined as the
+ * exclusive-or of the hashcodes of the key and value (using 0 for
+ * <code>null</code>). In other words, this must be:
+ *
+<p><pre>(getKey() == null ? 0 : getKey().hashCode())
+^ (getValue() == null ? 0 : getValue().hashCode())</pre>
+ *
+ * @return the hash code
+ */
+ int hashCode();
+
+ /**
+ * Compares the specified object with this entry. Returns true only if
+ * the object is a mapping of identical key and value. In other words,
+ * this must be:
+ *
+<p><pre>(o instanceof Map.Entry)
+&& (getKey() == null ? ((HashMap) o).getKey() == null
+ : getKey().equals(((HashMap) o).getKey()))
+&& (getValue() == null ? ((HashMap) o).getValue() == null
+ : getValue().equals(((HashMap) o).getValue()))</pre>
+ *
+ * @param o the object to compare
+ *
+ * @return <code>true</code> if it is equal
+ */
+ boolean equals(Object o);
+ }
+}
diff --git a/libjava/classpath/java/util/MissingResourceException.java b/libjava/classpath/java/util/MissingResourceException.java
new file mode 100644
index 00000000000..26640de90df
--- /dev/null
+++ b/libjava/classpath/java/util/MissingResourceException.java
@@ -0,0 +1,105 @@
+/* MissingResourceException.java -- thrown for a missing resource
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This exception is thrown when a resource is missing.
+ *
+ * @author Jochen Hoenicke
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see ResourceBundle
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class MissingResourceException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -4876345176062000401L;
+
+ /**
+ * The name of the resource bundle requested by user.
+ *
+ * @serial the class name of the resource bundle
+ */
+ private final String className;
+
+ /**
+ * The key of the resource in the bundle requested by user.
+ *
+ * @serial the name of the resouce
+ */
+ private final String key;
+
+ /**
+ * Creates a new exception, with the specified parameters.
+ *
+ * @param s the detail message
+ * @param className the name of the resource bundle
+ * @param key the key of the missing resource
+ */
+ public MissingResourceException(String s, String className, String key)
+ {
+ super(s);
+ this.className = className;
+ this.key = key;
+ }
+
+ /**
+ * Gets the name of the resource bundle, for which a resource is missing.
+ *
+ * @return the name of the resource bundle
+ */
+ public String getClassName()
+ {
+ return className;
+ }
+
+ /**
+ * Gets the key of the resource that is missing bundle, this is an empty
+ * string if the whole resource bundle is missing.
+ *
+ * @return the name of the resource bundle
+ */
+ public String getKey()
+ {
+ return key;
+ }
+}
diff --git a/libjava/classpath/java/util/NoSuchElementException.java b/libjava/classpath/java/util/NoSuchElementException.java
new file mode 100644
index 00000000000..5e1a2176d62
--- /dev/null
+++ b/libjava/classpath/java/util/NoSuchElementException.java
@@ -0,0 +1,88 @@
+/* NoSuchElementException.java -- Attempt to access element that does not exist
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ */
+
+/**
+ * Exception thrown when an attempt is made to access an element that does not
+ * exist. This exception is thrown by the Enumeration, Iterator and
+ * ListIterator classes if the nextElement, next or previous method goes
+ * beyond the end of the list of elements that are being accessed. It is also
+ * thrown by Vector and Stack when attempting to access the first or last
+ * element of an empty collection.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Enumeration
+ * @see Iterator
+ * @see ListIterator
+ * @see Enumeration#nextElement()
+ * @see Iterator#next()
+ * @see ListIterator#previous()
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class NoSuchElementException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0.
+ */
+ private static final long serialVersionUID = 6769829250639411880L;
+
+ /**
+ * Constructs a NoSuchElementException with no detail message.
+ */
+ public NoSuchElementException()
+ {
+ }
+
+ /**
+ * Constructs a NoSuchElementException with a detail message.
+ *
+ * @param detail the detail message for the exception
+ */
+ public NoSuchElementException(String detail)
+ {
+ super(detail);
+ }
+}
diff --git a/libjava/classpath/java/util/Observable.java b/libjava/classpath/java/util/Observable.java
new file mode 100644
index 00000000000..4c2cddb5496
--- /dev/null
+++ b/libjava/classpath/java/util/Observable.java
@@ -0,0 +1,180 @@
+/* Observable.java -- an object to be observed
+ Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This class represents an object which is observable. Other objects may
+ * register their intent to be notified when this object changes; and when
+ * this object does change, it will trigger the <code>update</code> method
+ * of each observer.
+ *
+ * Note that the <code>notifyObservers()</code> method of this class is
+ * unrelated to the <code>notify()</code> of Object.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Observer
+ * @status updated to 1.4
+ */
+public class Observable
+{
+ /** Tracks whether this object has changed. */
+ private boolean changed;
+
+ /* List of the Observers registered as interested in this Observable. */
+ private LinkedHashSet observers;
+
+ /**
+ * Constructs an Observable with zero Observers.
+ */
+ public Observable()
+ {
+ observers = new LinkedHashSet();
+ }
+
+ /**
+ * Adds an Observer. If the observer was already added this method does
+ * nothing.
+ *
+ * @param observer Observer to add
+ * @throws NullPointerException if observer is null
+ */
+ public synchronized void addObserver(Observer observer)
+ {
+ observers.add(observer);
+ }
+
+ /**
+ * Reset this Observable's state to unchanged. This is called automatically
+ * by <code>notifyObservers</code> once all observers have been notified.
+ *
+ * @see #notifyObservers()
+ */
+ protected synchronized void clearChanged()
+ {
+ changed = false;
+ }
+
+ /**
+ * Returns the number of observers for this object.
+ *
+ * @return number of Observers for this
+ */
+ public synchronized int countObservers()
+ {
+ return observers.size();
+ }
+
+ /**
+ * Deletes an Observer of this Observable.
+ *
+ * @param victim Observer to delete
+ */
+ public synchronized void deleteObserver(Observer victim)
+ {
+ observers.remove(victim);
+ }
+
+ /**
+ * Deletes all Observers of this Observable.
+ */
+ public synchronized void deleteObservers()
+ {
+ observers.clear();
+ }
+
+ /**
+ * True if <code>setChanged</code> has been called more recently than
+ * <code>clearChanged</code>.
+ *
+ * @return whether or not this Observable has changed
+ */
+ public synchronized boolean hasChanged()
+ {
+ return changed;
+ }
+
+ /**
+ * If the Observable has actually changed then tell all Observers about it,
+ * then reset state to unchanged.
+ *
+ * @see #notifyObservers(Object)
+ * @see Observer#update(Observable, Object)
+ */
+ public void notifyObservers()
+ {
+ notifyObservers(null);
+ }
+
+ /**
+ * If the Observable has actually changed then tell all Observers about it,
+ * then reset state to unchanged. Note that though the order of
+ * notification is unspecified in subclasses, in Observable it is in the
+ * order of registration.
+ *
+ * @param obj argument to Observer's update method
+ * @see Observer#update(Observable, Object)
+ */
+ public void notifyObservers(Object obj)
+ {
+ if (! hasChanged())
+ return;
+ // Create clone inside monitor, as that is relatively fast and still
+ // important to keep threadsafe, but update observers outside of the
+ // lock since update() can call arbitrary code.
+ Set s;
+ synchronized (this)
+ {
+ s = (Set) observers.clone();
+ }
+ int i = s.size();
+ Iterator iter = s.iterator();
+ while (--i >= 0)
+ ((Observer) iter.next()).update(this, obj);
+ clearChanged();
+ }
+
+ /**
+ * Marks this Observable as having changed.
+ */
+ protected synchronized void setChanged()
+ {
+ changed = true;
+ }
+}
diff --git a/libjava/classpath/java/util/Observer.java b/libjava/classpath/java/util/Observer.java
new file mode 100644
index 00000000000..c59a0ca6c68
--- /dev/null
+++ b/libjava/classpath/java/util/Observer.java
@@ -0,0 +1,60 @@
+/* Observer.java -- an object that will be informed of changes in an Observable
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Interface that is implemented when a class wants to be informed of changes
+ * in Observable objects.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see Observable
+ * @status updated to 1.4
+ */
+public interface Observer
+{
+ /**
+ * This method is called whenever the observable object changes, and has
+ * called <code>notifyObservers</code>. The Observable object can pass
+ * arbitrary information in the second parameter.
+ *
+ * @param observable the Observable object that changed
+ * @param arg arbitrary information, usually relating to the change
+ */
+ void update(Observable observable, Object arg);
+}
diff --git a/libjava/classpath/java/util/Properties.java b/libjava/classpath/java/util/Properties.java
new file mode 100644
index 00000000000..c7c19b3a380
--- /dev/null
+++ b/libjava/classpath/java/util/Properties.java
@@ -0,0 +1,574 @@
+/* Properties.java -- a set of persistent properties
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * A set of persistent properties, which can be saved or loaded from a stream.
+ * A property list may also contain defaults, searched if the main list
+ * does not contain a property for a given key.
+ *
+ * An example of a properties file for the german language is given
+ * here. This extends the example given in ListResourceBundle.
+ * Create a file MyResource_de.properties with the following contents
+ * and put it in the CLASSPATH. (The character
+ * <code>\</code><code>u00e4</code> is the german umlaut)
+ *
+ *
+<pre>s1=3
+s2=MeineDisk
+s3=3. M\<code></code>u00e4rz 96
+s4=Die Diskette ''{1}'' enth\<code></code>u00e4lt {0} in {2}.
+s5=0
+s6=keine Dateien
+s7=1
+s8=eine Datei
+s9=2
+s10={0,number} Dateien
+s11=Das Formatieren schlug fehl mit folgender Exception: {0}
+s12=FEHLER
+s13=Ergebnis
+s14=Dialog
+s15=Auswahlkriterium
+s16=1,3</pre>
+ *
+ * <p>Although this is a sub class of a hash table, you should never
+ * insert anything other than strings to this property, or several
+ * methods, that need string keys and values, will fail. To ensure
+ * this, you should use the <code>get/setProperty</code> method instead
+ * of <code>get/put</code>.
+ *
+ * Properties are saved in ISO 8859-1 encoding, using Unicode escapes with
+ * a single <code>u</code> for any character which cannot be represented.
+ *
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see PropertyResourceBundle
+ * @status updated to 1.4
+ */
+public class Properties extends Hashtable
+{
+ // WARNING: Properties is a CORE class in the bootstrap cycle. See the
+ // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+ /**
+ * The property list that contains default values for any keys not
+ * in this property list.
+ *
+ * @serial the default properties
+ */
+ protected Properties defaults;
+
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 4112578634029874840L;
+
+ /**
+ * Creates a new empty property list with no default values.
+ */
+ public Properties()
+ {
+ }
+
+ /**
+ * Create a new empty property list with the specified default values.
+ *
+ * @param defaults a Properties object containing the default values
+ */
+ public Properties(Properties defaults)
+ {
+ this.defaults = defaults;
+ }
+
+ /**
+ * Adds the given key/value pair to this properties. This calls
+ * the hashtable method put.
+ *
+ * @param key the key for this property
+ * @param value the value for this property
+ * @return The old value for the given key
+ * @see #getProperty(String)
+ * @since 1.2
+ */
+ public Object setProperty(String key, String value)
+ {
+ return put(key, value);
+ }
+
+ /**
+ * Reads a property list from an input stream. The stream should
+ * have the following format: <br>
+ *
+ * An empty line or a line starting with <code>#</code> or
+ * <code>!</code> is ignored. An backslash (<code>\</code>) at the
+ * end of the line makes the line continueing on the next line
+ * (but make sure there is no whitespace after the backslash).
+ * Otherwise, each line describes a key/value pair. <br>
+ *
+ * The chars up to the first whitespace, = or : are the key. You
+ * can include this caracters in the key, if you precede them with
+ * a backslash (<code>\</code>). The key is followed by optional
+ * whitespaces, optionally one <code>=</code> or <code>:</code>,
+ * and optionally some more whitespaces. The rest of the line is
+ * the resource belonging to the key. <br>
+ *
+ * Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a
+ * space), and unicode characters with the
+ * <code>\\u</code><em>xxxx</em> notation are detected, and
+ * converted to the corresponding single character. <br>
+ *
+ *
+<pre># This is a comment
+key = value
+k\:5 \ a string starting with space and ending with newline\n
+# This is a multiline specification; note that the value contains
+# no white space.
+weekdays: Sunday,Monday,Tuesday,Wednesday,\\
+ Thursday,Friday,Saturday
+# The safest way to include a space at the end of a value:
+label = Name:\\u0020</pre>
+ *
+ * @param inStream the input stream
+ * @throws IOException if an error occurred when reading the input
+ * @throws NullPointerException if in is null
+ */
+ public void load(InputStream inStream) throws IOException
+ {
+ // The spec says that the file must be encoded using ISO-8859-1.
+ BufferedReader reader =
+ new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1"));
+ String line;
+
+ while ((line = reader.readLine()) != null)
+ {
+ char c = 0;
+ int pos = 0;
+ // Leading whitespaces must be deleted first.
+ while (pos < line.length()
+ && Character.isWhitespace(c = line.charAt(pos)))
+ pos++;
+
+ // If empty line or begins with a comment character, skip this line.
+ if ((line.length() - pos) == 0
+ || line.charAt(pos) == '#' || line.charAt(pos) == '!')
+ continue;
+
+ // The characters up to the next Whitespace, ':', or '='
+ // describe the key. But look for escape sequences.
+ StringBuffer key = new StringBuffer();
+ while (pos < line.length()
+ && ! Character.isWhitespace(c = line.charAt(pos++))
+ && c != '=' && c != ':')
+ {
+ if (c == '\\')
+ {
+ if (pos == line.length())
+ {
+ // The line continues on the next line.
+ line = reader.readLine();
+ pos = 0;
+ while (pos < line.length()
+ && Character.isWhitespace(c = line.charAt(pos)))
+ pos++;
+ }
+ else
+ {
+ c = line.charAt(pos++);
+ switch (c)
+ {
+ case 'n':
+ key.append('\n');
+ break;
+ case 't':
+ key.append('\t');
+ break;
+ case 'r':
+ key.append('\r');
+ break;
+ case 'u':
+ if (pos + 4 <= line.length())
+ {
+ char uni = (char) Integer.parseInt
+ (line.substring(pos, pos + 4), 16);
+ key.append(uni);
+ pos += 4;
+ } // else throw exception?
+ break;
+ default:
+ key.append(c);
+ break;
+ }
+ }
+ }
+ else
+ key.append(c);
+ }
+
+ boolean isDelim = (c == ':' || c == '=');
+ while (pos < line.length()
+ && Character.isWhitespace(c = line.charAt(pos)))
+ pos++;
+
+ if (! isDelim && (c == ':' || c == '='))
+ {
+ pos++;
+ while (pos < line.length()
+ && Character.isWhitespace(c = line.charAt(pos)))
+ pos++;
+ }
+
+ StringBuffer element = new StringBuffer(line.length() - pos);
+ while (pos < line.length())
+ {
+ c = line.charAt(pos++);
+ if (c == '\\')
+ {
+ if (pos == line.length())
+ {
+ // The line continues on the next line.
+ line = reader.readLine();
+
+ // We might have seen a backslash at the end of
+ // the file. The JDK ignores the backslash in
+ // this case, so we follow for compatibility.
+ if (line == null)
+ break;
+
+ pos = 0;
+ while (pos < line.length()
+ && Character.isWhitespace(c = line.charAt(pos)))
+ pos++;
+ element.ensureCapacity(line.length() - pos +
+ element.length());
+ }
+ else
+ {
+ c = line.charAt(pos++);
+ switch (c)
+ {
+ case 'n':
+ element.append('\n');
+ break;
+ case 't':
+ element.append('\t');
+ break;
+ case 'r':
+ element.append('\r');
+ break;
+ case 'u':
+ if (pos + 4 <= line.length())
+ {
+ char uni = (char) Integer.parseInt
+ (line.substring(pos, pos + 4), 16);
+ element.append(uni);
+ pos += 4;
+ } // else throw exception?
+ break;
+ default:
+ element.append(c);
+ break;
+ }
+ }
+ }
+ else
+ element.append(c);
+ }
+ put(key.toString(), element.toString());
+ }
+ }
+
+ /**
+ * Calls <code>store(OutputStream out, String header)</code> and
+ * ignores the IOException that may be thrown.
+ *
+ * @param out the stream to write to
+ * @param header a description of the property list
+ * @throws ClassCastException if this property contains any key or
+ * value that are not strings
+ * @deprecated use {@link #store(OutputStream, String)} instead
+ */
+ public void save(OutputStream out, String header)
+ {
+ try
+ {
+ store(out, header);
+ }
+ catch (IOException ex)
+ {
+ }
+ }
+
+ /**
+ * Writes the key/value pairs to the given output stream, in a format
+ * suitable for <code>load</code>.<br>
+ *
+ * If header is not null, this method writes a comment containing
+ * the header as first line to the stream. The next line (or first
+ * line if header is null) contains a comment with the current date.
+ * Afterwards the key/value pairs are written to the stream in the
+ * following format.<br>
+ *
+ * Each line has the form <code>key = value</code>. Newlines,
+ * Returns and tabs are written as <code>\n,\t,\r</code> resp.
+ * The characters <code>\, !, #, =</code> and <code>:</code> are
+ * preceeded by a backslash. Spaces are preceded with a backslash,
+ * if and only if they are at the beginning of the key. Characters
+ * that are not in the ascii range 33 to 127 are written in the
+ * <code>\</code><code>u</code>xxxx Form.<br>
+ *
+ * Following the listing, the output stream is flushed but left open.
+ *
+ * @param out the output stream
+ * @param header the header written in the first line, may be null
+ * @throws ClassCastException if this property contains any key or
+ * value that isn't a string
+ * @throws IOException if writing to the stream fails
+ * @throws NullPointerException if out is null
+ * @since 1.2
+ */
+ public void store(OutputStream out, String header) throws IOException
+ {
+ // The spec says that the file must be encoded using ISO-8859-1.
+ PrintWriter writer
+ = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
+ if (header != null)
+ writer.println("#" + header);
+ writer.println ("#" + Calendar.getInstance ().getTime ());
+
+ Iterator iter = entrySet ().iterator ();
+ int i = size ();
+ StringBuffer s = new StringBuffer (); // Reuse the same buffer.
+ while (--i >= 0)
+ {
+ Map.Entry entry = (Map.Entry) iter.next ();
+ formatForOutput ((String) entry.getKey (), s, true);
+ s.append ('=');
+ formatForOutput ((String) entry.getValue (), s, false);
+ writer.println (s);
+ }
+
+ writer.flush ();
+ }
+
+ /**
+ * Gets the property with the specified key in this property list.
+ * If the key is not found, the default property list is searched.
+ * If the property is not found in the default, null is returned.
+ *
+ * @param key The key for this property
+ * @return the value for the given key, or null if not found
+ * @throws ClassCastException if this property contains any key or
+ * value that isn't a string
+ * @see #defaults
+ * @see #setProperty(String, String)
+ * @see #getProperty(String, String)
+ */
+ public String getProperty(String key)
+ {
+ return getProperty(key, null);
+ }
+
+ /**
+ * Gets the property with the specified key in this property list. If
+ * the key is not found, the default property list is searched. If the
+ * property is not found in the default, the specified defaultValue is
+ * returned.
+ *
+ * @param key The key for this property
+ * @param defaultValue A default value
+ * @return The value for the given key
+ * @throws ClassCastException if this property contains any key or
+ * value that isn't a string
+ * @see #defaults
+ * @see #setProperty(String, String)
+ */
+ public String getProperty(String key, String defaultValue)
+ {
+ Properties prop = this;
+ // Eliminate tail recursion.
+ do
+ {
+ String value = (String) prop.get(key);
+ if (value != null)
+ return value;
+ prop = prop.defaults;
+ }
+ while (prop != null);
+ return defaultValue;
+ }
+
+ /**
+ * Returns an enumeration of all keys in this property list, including
+ * the keys in the default property list.
+ *
+ * @return an Enumeration of all defined keys
+ */
+ public Enumeration propertyNames()
+ {
+ // We make a new Set that holds all the keys, then return an enumeration
+ // for that. This prevents modifications from ruining the enumeration,
+ // as well as ignoring duplicates.
+ Properties prop = this;
+ Set s = new HashSet();
+ // Eliminate tail recursion.
+ do
+ {
+ s.addAll(prop.keySet());
+ prop = prop.defaults;
+ }
+ while (prop != null);
+ return Collections.enumeration(s);
+ }
+
+ /**
+ * Prints the key/value pairs to the given print stream. This is
+ * mainly useful for debugging purposes.
+ *
+ * @param out the print stream, where the key/value pairs are written to
+ * @throws ClassCastException if this property contains a key or a
+ * value that isn't a string
+ * @see #list(PrintWriter)
+ */
+ public void list(PrintStream out)
+ {
+ PrintWriter writer = new PrintWriter (out);
+ list (writer);
+ }
+
+ /**
+ * Prints the key/value pairs to the given print writer. This is
+ * mainly useful for debugging purposes.
+ *
+ * @param out the print writer where the key/value pairs are written to
+ * @throws ClassCastException if this property contains a key or a
+ * value that isn't a string
+ * @see #list(PrintStream)
+ * @since 1.1
+ */
+ public void list(PrintWriter out)
+ {
+ out.println ("-- listing properties --");
+
+ Iterator iter = entrySet ().iterator ();
+ int i = size ();
+ while (--i >= 0)
+ {
+ Map.Entry entry = (Map.Entry) iter.next ();
+ out.print ((String) entry.getKey () + "=");
+
+ // JDK 1.3/1.4 restrict the printed value, but not the key,
+ // to 40 characters, including the truncating ellipsis.
+ String s = (String ) entry.getValue ();
+ if (s != null && s.length () > 40)
+ out.println (s.substring (0, 37) + "...");
+ else
+ out.println (s);
+ }
+ out.flush ();
+ }
+
+ /**
+ * Formats a key or value for output in a properties file.
+ * See store for a description of the format.
+ *
+ * @param str the string to format
+ * @param buffer the buffer to add it to
+ * @param key true if all ' ' must be escaped for the key, false if only
+ * leading spaces must be escaped for the value
+ * @see #store(OutputStream, String)
+ */
+ private void formatForOutput(String str, StringBuffer buffer, boolean key)
+ {
+ if (key)
+ {
+ buffer.setLength(0);
+ buffer.ensureCapacity(str.length());
+ }
+ else
+ buffer.ensureCapacity(buffer.length() + str.length());
+ boolean head = true;
+ int size = str.length();
+ for (int i = 0; i < size; i++)
+ {
+ char c = str.charAt(i);
+ switch (c)
+ {
+ case '\n':
+ buffer.append("\\n");
+ break;
+ case '\r':
+ buffer.append("\\r");
+ break;
+ case '\t':
+ buffer.append("\\t");
+ break;
+ case ' ':
+ buffer.append(head ? "\\ " : " ");
+ break;
+ case '\\':
+ case '!':
+ case '#':
+ case '=':
+ case ':':
+ buffer.append('\\').append(c);
+ break;
+ default:
+ if (c < ' ' || c > '~')
+ {
+ String hex = Integer.toHexString(c);
+ buffer.append("\\u0000".substring(0, 6 - hex.length()));
+ buffer.append(hex);
+ }
+ else
+ buffer.append(c);
+ }
+ if (c != ' ')
+ head = key;
+ }
+ }
+} // class Properties
diff --git a/libjava/classpath/java/util/PropertyPermission.java b/libjava/classpath/java/util/PropertyPermission.java
new file mode 100644
index 00000000000..d1bdbd1d058
--- /dev/null
+++ b/libjava/classpath/java/util/PropertyPermission.java
@@ -0,0 +1,271 @@
+/* PropertyPermission.java -- permission to get and set System properties
+ Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+
+/**
+ * This class represents the permission to access and modify a property.<br>
+ *
+ * The name is the name of the property, e.g. xxx. You can also
+ * use an asterisk "*" as described in BasicPermission.<br>
+ *
+ * The action string is a comma-separated list of keywords. There are
+ * two possible actions:
+ * <dl>
+ * <dt>read</dt>
+ * <dd>Allows to read the property via <code>System.getProperty</code>.</dd>
+ * <dt>write</dt>
+ * <dd>Allows to write the property via <code>System.setProperty</code>.</dd>
+ * </dl>
+ *
+ * The action string is case insensitive (it is converted to lower case).
+ *
+ * @see Permission
+ * @see BasicPermission
+ * @see SecurityManager
+ * @author Jochen Hoenicke
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class PropertyPermission extends BasicPermission
+{
+ /**
+ * PropertyPermission uses a more efficient representation than the
+ * serialized form; this documents the difference.
+ *
+ * @serialField action String the action string
+ */
+ private static final ObjectStreamField[] serialPersistentFields =
+ {
+ new ObjectStreamField("action", String.class)
+ };
+
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 885438825399942851L;
+
+ /** Permission to read. */
+ private static final int READ = 1;
+ /** Permission to write. */
+ private static final int WRITE = 2;
+
+ /** The set of actions permitted. */
+ // Package visible for use by PropertyPermissionCollection.
+ transient int actions;
+
+ /**
+ * The String forms of the actions permitted.
+ */
+ private static final String actionStrings[] =
+ {
+ "", "read", "write", "read,write"
+ };
+
+ /**
+ * Constructs a PropertyPermission with the specified property. Possible
+ * actions are read and write, comma-separated and case-insensitive.
+ *
+ * @param name the name of the property
+ * @param actions the action string
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException if name string contains an
+ * illegal wildcard or actions string contains an illegal action
+ * (this includes a null actions string)
+ */
+ public PropertyPermission(String name, String actions)
+ {
+ super(name);
+ if (actions == null)
+ throw new IllegalArgumentException();
+ setActions(actions);
+ }
+
+ /**
+ * Parse the action string and convert actions from external to internal
+ * form. This will set the internal actions field.
+ *
+ * @param str the action string
+ * @throws IllegalArgumentException if actions string contains an
+ * illegal action
+ */
+ private void setActions(String str)
+ {
+ // Initialising the class java.util.Locale ...
+ // tries to initialise the Locale.defaultLocale static
+ // which calls System.getProperty,
+ // which calls SecurityManager.checkPropertiesAccess,
+ // which creates a PropertyPermission with action "read,write",
+ // which calls setActions("read,write").
+ // If we now were to call toLowerCase on 'str',
+ // this would call Locale.getDefault() which returns null
+ // because Locale.defaultLocale hasn't been set yet
+ // then toLowerCase will fail with a null pointer exception.
+ //
+ // The solution is to take a punt on 'str' being lower case, and
+ // test accordingly. If that fails, we convert 'str' to lower case
+ // and try the tests again.
+ if ("read".equals(str))
+ actions = READ;
+ else if ("write".equals(str))
+ actions = WRITE;
+ else if ("read,write".equals(str) || "write,read".equals(str))
+ actions = READ | WRITE;
+ else
+ {
+ String lstr = str.toLowerCase();
+ if ("read".equals(lstr))
+ actions = READ;
+ else if ("write".equals(lstr))
+ actions = WRITE;
+ else if ("read,write".equals(lstr) || "write,read".equals(lstr))
+ actions = READ | WRITE;
+ else
+ throw new IllegalArgumentException("illegal action " + str);
+ }
+ }
+
+ /**
+ * Reads an object from the stream. This converts the external to the
+ * internal representation.
+ *
+ * @param s the stream to read from
+ * @throws IOException if the stream fails
+ * @throws ClassNotFoundException if reserialization fails
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ ObjectInputStream.GetField fields = s.readFields();
+ setActions((String) fields.get("actions", null));
+ }
+
+ /**
+ * Writes an object to the stream. This converts the internal to the
+ * external representation.
+ *
+ * @param s the stram to write to
+ * @throws IOException if the stream fails
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ ObjectOutputStream.PutField fields = s.putFields();
+ fields.put("actions", getActions());
+ s.writeFields();
+ }
+
+ /**
+ * Check if this permission implies p. This returns true iff all of
+ * the following conditions are true:
+ * <ul>
+ * <li> p is a PropertyPermission </li>
+ * <li> this.getName() implies p.getName(),
+ * e.g. <code>java.*</code> implies <code>java.home</code> </li>
+ * <li> this.getActions is a subset of p.getActions </li>
+ * </ul>
+ *
+ * @param p the permission to check
+ * @return true if this permission implies p
+ */
+ public boolean implies(Permission p)
+ {
+ // BasicPermission checks for name and type.
+ if (super.implies(p))
+ {
+ // We have to check the actions.
+ PropertyPermission pp = (PropertyPermission) p;
+ return (pp.actions & ~actions) == 0;
+ }
+ return false;
+ }
+
+ /**
+ * Check to see whether this object is the same as another
+ * PropertyPermission object; this is true if it has the same name and
+ * actions.
+ *
+ * @param obj the other object
+ * @return true if the two are equivalent
+ */
+ public boolean equals(Object obj)
+ {
+ return super.equals(obj) && actions == ((PropertyPermission) obj).actions;
+ }
+
+ /**
+ * Returns the hash code for this permission. It is equivalent to
+ * <code>getName().hashCode()</code>.
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /**
+ * Returns the action string. Note that this may differ from the string
+ * given at the constructor: The actions are converted to lowercase and
+ * may be reordered.
+ *
+ * @return one of "read", "write", or "read,write"
+ */
+ public String getActions()
+ {
+ return actionStrings[actions];
+ }
+
+ /**
+ * Returns a permission collection suitable to take
+ * PropertyPermission objects.
+ *
+ * @return a new empty PermissionCollection
+ */
+ public PermissionCollection newPermissionCollection()
+ {
+ return new PropertyPermissionCollection();
+ }
+}
diff --git a/libjava/classpath/java/util/PropertyPermissionCollection.java b/libjava/classpath/java/util/PropertyPermissionCollection.java
new file mode 100644
index 00000000000..c95fa4e66bf
--- /dev/null
+++ b/libjava/classpath/java/util/PropertyPermissionCollection.java
@@ -0,0 +1,166 @@
+/* PropertyPermissionCollection.java -- a collection of PropertyPermissions
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.security.Permission;
+import java.security.PermissionCollection;
+
+/**
+ * This class provides the implementation for
+ * <code>PropertyPermission.newPermissionCollection()</code>. It only accepts
+ * PropertyPermissions, and correctly implements <code>implies</code>. It
+ * is synchronized, as specified in the superclass.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status an undocumented class, but this matches Sun's serialization
+ */
+class PropertyPermissionCollection extends PermissionCollection
+{
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 7015263904581634791L;
+
+ /**
+ * The permissions.
+ *
+ * @serial the table of permissions in the collection
+ */
+ private final Hashtable permissions = new Hashtable();
+
+ /**
+ * A flag to detect if "*" is in the collection.
+ *
+ * @serial true if "*" is in the collection
+ */
+ private boolean all_allowed;
+
+ /**
+ * Adds a PropertyPermission to this collection.
+ *
+ * @param permission the permission to add
+ * @throws IllegalArgumentException if permission is not a PropertyPermission
+ * @throws SecurityException if collection is read-only
+ */
+ public void add(Permission permission)
+ {
+ if (isReadOnly())
+ throw new SecurityException("readonly");
+ if (! (permission instanceof PropertyPermission))
+ throw new IllegalArgumentException();
+ PropertyPermission pp = (PropertyPermission) permission;
+ String name = pp.getName();
+ if (name.equals("*"))
+ all_allowed = true;
+ PropertyPermission old = (PropertyPermission) permissions.get(name);
+ if (old != null)
+ {
+ if ((pp.actions | old.actions) == old.actions)
+ pp = old; // Old implies pp.
+ else if ((pp.actions | old.actions) != pp.actions)
+ // Here pp doesn't imply old; the only case left is both actions.
+ pp = new PropertyPermission(name, "read,write");
+ }
+ permissions.put(name, pp);
+ }
+
+ /**
+ * Returns true if this collection implies the given permission. This even
+ * returns true for this case:
+ *
+ * <pre>
+ * collection.add(new PropertyPermission("a.*", "read"));
+ * collection.add(new PropertyPermission("a.b.*", "write"));
+ * collection.implies(new PropertyPermission("a.b.c", "read,write"));
+ * </pre>
+ *
+ * @param permission the permission to check
+ * @return true if it is implied by this
+ */
+ public boolean implies(Permission permission)
+ {
+ if (! (permission instanceof PropertyPermission))
+ return false;
+ PropertyPermission toImply = (PropertyPermission) permission;
+ int actions = toImply.actions;
+
+ if (all_allowed)
+ {
+ int all_actions = ((PropertyPermission) permissions.get("*")).actions;
+ actions &= ~all_actions;
+ if (actions == 0)
+ return true;
+ }
+
+ String name = toImply.getName();
+ if (name.equals("*"))
+ return false;
+
+ int prefixLength = name.length();
+ if (name.endsWith("*"))
+ prefixLength -= 2;
+
+ while (true)
+ {
+ PropertyPermission forName =
+ (PropertyPermission) permissions.get(name);
+ if (forName != null)
+ {
+ actions &= ~forName.actions;
+ if (actions == 0)
+ return true;
+ }
+
+ prefixLength = name.lastIndexOf('.', prefixLength - 1);
+ if (prefixLength < 0)
+ return false;
+ name = name.substring(0, prefixLength + 1) + '*';
+ }
+ }
+
+ /**
+ * Enumerate over the collection.
+ *
+ * @return an enumeration of the collection contents
+ */
+ public Enumeration elements()
+ {
+ return permissions.elements();
+ }
+}
diff --git a/libjava/classpath/java/util/PropertyResourceBundle.java b/libjava/classpath/java/util/PropertyResourceBundle.java
new file mode 100644
index 00000000000..aaff0766a35
--- /dev/null
+++ b/libjava/classpath/java/util/PropertyResourceBundle.java
@@ -0,0 +1,152 @@
+/* PropertyResourceBundle -- a resource bundle built from a Property file
+ Copyright (C) 1998, 1999, 2001, 2002 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.IOException;
+import java.io.InputStream;
+
+/**
+ * This class is a concrete <code>ResourceBundle</code> that gets it
+ * resources from a property file. This implies that the resources are
+ * strings. For more information about resource bundles see the class
+ * <code>ResourceBundle</code>.
+ *
+ * You should not use this class directly, or subclass it, but you get
+ * an object of this class automatically when you call
+ * <code>ResourceBundle.getBundle()</code> and there is a properties
+ * file.
+ *
+ * If there is also a class for this resource and the same locale, the
+ * class will be chosen. The properties file should have the name of the
+ * resource bundle, appended with the locale (e.g. <code>_de</code> and the
+ * extension <code>.properties</code>. The file should have the same format
+ * as for <code>Properties.load()</code>
+ *
+ * An example of a properties file for the german language is given
+ * here. This extends the example given in ListResourceBundle.
+ * Create a file MyResource_de.properties with the following contents
+ * and put it in the CLASSPATH. (The char <code>\u00e4</code> is the
+ * german umlaut)
+ *
+ *
+<pre>
+s1=3
+s2=MeineDisk
+s3=3. M\u00e4rz 96
+s4=Die Diskette ''{1}'' enth\u00e4lt {0} in {2}.
+s5=0
+s6=keine Dateien
+s7=1
+s8=eine Datei
+s9=2
+s10={0,number} Dateien
+s11=Die Formatierung warf eine Exception: {0}
+s12=FEHLER
+s13=Ergebnis
+s14=Dialog
+s15=Auswahlkriterium
+s16=1,3
+</pre>
+ *
+ * @author Jochen Hoenicke
+ * @see ResourceBundle
+ * @see ListResourceBundle
+ * @see Properties#load(InputStream)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class PropertyResourceBundle extends ResourceBundle
+{
+ /** The properties file this bundle is based on. */
+ private Properties properties;
+
+ /**
+ * Creates a new property resource bundle.
+ *
+ * @param stream an input stream, where the resources are read from
+ * @throws NullPointerException if stream is null
+ * @throws IOException if reading the stream fails
+ */
+ public PropertyResourceBundle(InputStream stream) throws IOException
+ {
+ properties = new Properties();
+ properties.load(stream);
+ }
+
+ /**
+ * Called by <code>getObject</code> when a resource is needed. This
+ * returns the resource given by the key.
+ *
+ * @param key the key of the resource
+ * @return the resource for the key, or null if it doesn't exist
+ */
+ public Object handleGetObject(String key)
+ {
+ return properties.getProperty(key);
+ }
+
+ /**
+ * This method should return all keys for which a resource exists.
+ *
+ * @return an enumeration of the keys
+ */
+ public Enumeration getKeys()
+ {
+ if (parent == null)
+ return properties.propertyNames();
+ // We make a new Set that holds all the keys, then return an enumeration
+ // for that. This prevents modifications from ruining the enumeration,
+ // as well as ignoring duplicates.
+ Set s = new HashSet();
+ Enumeration e = properties.propertyNames();
+ while (e.hasMoreElements())
+ s.add(e.nextElement());
+ ResourceBundle bundle = parent;
+ // Eliminate tail recursion.
+ do
+ {
+ e = bundle.getKeys();
+ while (e.hasMoreElements())
+ s.add(e.nextElement());
+ bundle = bundle.parent;
+ }
+ while (bundle != null);
+ return Collections.enumeration(s);
+ }
+} // class PropertyResourceBundle
diff --git a/libjava/classpath/java/util/Random.java b/libjava/classpath/java/util/Random.java
new file mode 100644
index 00000000000..bc005075140
--- /dev/null
+++ b/libjava/classpath/java/util/Random.java
@@ -0,0 +1,429 @@
+/* Random.java -- a pseudo-random number generator
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 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;
+
+/**
+ * This class generates pseudorandom numbers. It uses the same
+ * algorithm as the original JDK-class, so that your programs behave
+ * exactly the same way, if started with the same seed.
+ *
+ * The algorithm is described in <em>The Art of Computer Programming,
+ * Volume 2</em> by Donald Knuth in Section 3.2.1. It is a 48-bit seed,
+ * linear congruential formula.
+ *
+ * If two instances of this class are created with the same seed and
+ * the same calls to these classes are made, they behave exactly the
+ * same way. This should be even true for foreign implementations
+ * (like this), so every port must use the same algorithm as described
+ * here.
+ *
+ * If you want to implement your own pseudorandom algorithm, you
+ * should extend this class and overload the <code>next()</code> and
+ * <code>setSeed(long)</code> method. In that case the above
+ * paragraph doesn't apply to you.
+ *
+ * This class shouldn't be used for security sensitive purposes (like
+ * generating passwords or encryption keys. See <code>SecureRandom</code>
+ * in package <code>java.security</code> for this purpose.
+ *
+ * For simple random doubles between 0.0 and 1.0, you may consider using
+ * Math.random instead.
+ *
+ * @see java.security.SecureRandom
+ * @see Math#random()
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class Random implements Serializable
+{
+ /**
+ * True if the next nextGaussian is available. This is used by
+ * nextGaussian, which generates two gaussian numbers by one call,
+ * and returns the second on the second call.
+ *
+ * @serial whether nextNextGaussian is available
+ * @see #nextGaussian()
+ * @see #nextNextGaussian
+ */
+ private boolean haveNextNextGaussian;
+
+ /**
+ * The next nextGaussian, when available. This is used by nextGaussian,
+ * which generates two gaussian numbers by one call, and returns the
+ * second on the second call.
+ *
+ * @serial the second gaussian of a pair
+ * @see #nextGaussian()
+ * @see #haveNextNextGaussian
+ */
+ private double nextNextGaussian;
+
+ /**
+ * The seed. This is the number set by setSeed and which is used
+ * in next.
+ *
+ * @serial the internal state of this generator
+ * @see #next()
+ */
+ private long seed;
+
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 3905348978240129619L;
+
+ /**
+ * Creates a new pseudorandom number generator. The seed is initialized
+ * to the current time, as if by
+ * <code>setSeed(System.currentTimeMillis());</code>.
+ *
+ * @see System#currentTimeMillis()
+ */
+ public Random()
+ {
+ this(System.currentTimeMillis());
+ }
+
+ /**
+ * Creates a new pseudorandom number generator, starting with the
+ * specified seed, using <code>setSeed(seed);</code>.
+ *
+ * @param seed the initial seed
+ */
+ public Random(long seed)
+ {
+ setSeed(seed);
+ }
+
+ /**
+ * Sets the seed for this pseudorandom number generator. As described
+ * above, two instances of the same random class, starting with the
+ * same seed, should produce the same results, if the same methods
+ * are called. The implementation for java.util.Random is:
+ *
+<pre>public synchronized void setSeed(long seed)
+{
+ this.seed = (seed ^ 0x5DEECE66DL) & ((1L &lt;&lt; 48) - 1);
+ haveNextNextGaussian = false;
+}</pre>
+ *
+ * @param seed the new seed
+ */
+ public synchronized void setSeed(long seed)
+ {
+ this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
+ haveNextNextGaussian = false;
+ }
+
+ /**
+ * Generates the next pseudorandom number. This returns
+ * an int value whose <code>bits</code> low order bits are
+ * independent chosen random bits (0 and 1 are equally likely).
+ * The implementation for java.util.Random is:
+ *
+<pre>protected synchronized int next(int bits)
+{
+ seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L &lt;&lt; 48) - 1);
+ return (int) (seed &gt;&gt;&gt; (48 - bits));
+}</pre>
+ *
+ * @param bits the number of random bits to generate, in the range 1..32
+ * @return the next pseudorandom value
+ * @since 1.1
+ */
+ protected synchronized int next(int bits)
+ {
+ seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
+ return (int) (seed >>> (48 - bits));
+ }
+
+ /**
+ * Fills an array of bytes with random numbers. All possible values
+ * are (approximately) equally likely.
+ * The JDK documentation gives no implementation, but it seems to be:
+ *
+<pre>public void nextBytes(byte[] bytes)
+{
+ for (int i = 0; i &lt; bytes.length; i += 4)
+ {
+ int random = next(32);
+ for (int j = 0; i + j &lt; bytes.length && j &lt; 4; j++)
+ {
+ bytes[i+j] = (byte) (random & 0xff)
+ random &gt;&gt;= 8;
+ }
+ }
+}</pre>
+ *
+ * @param bytes the byte array that should be filled
+ * @throws NullPointerException if bytes is null
+ * @since 1.1
+ */
+ public void nextBytes(byte[] bytes)
+ {
+ int random;
+ // Do a little bit unrolling of the above algorithm.
+ int max = bytes.length & ~0x3;
+ for (int i = 0; i < max; i += 4)
+ {
+ random = next(32);
+ bytes[i] = (byte) random;
+ bytes[i + 1] = (byte) (random >> 8);
+ bytes[i + 2] = (byte) (random >> 16);
+ bytes[i + 3] = (byte) (random >> 24);
+ }
+ if (max < bytes.length)
+ {
+ random = next(32);
+ for (int j = max; j < bytes.length; j++)
+ {
+ bytes[j] = (byte) random;
+ random >>= 8;
+ }
+ }
+ }
+
+ /**
+ * Generates the next pseudorandom number. This returns
+ * an int value whose 32 bits are independent chosen random bits
+ * (0 and 1 are equally likely). The implementation for
+ * java.util.Random is:
+ *
+<pre>public int nextInt()
+{
+ return next(32);
+}</pre>
+ *
+ * @return the next pseudorandom value
+ */
+ public int nextInt()
+ {
+ return next(32);
+ }
+
+ /**
+ * Generates the next pseudorandom number. This returns
+ * a value between 0(inclusive) and <code>n</code>(exclusive), and
+ * each value has the same likelihodd (1/<code>n</code>).
+ * (0 and 1 are equally likely). The implementation for
+ * java.util.Random is:
+ *
+<pre>
+public int nextInt(int n)
+{
+ if (n &lt;= 0)
+ throw new IllegalArgumentException("n must be positive");
+
+ if ((n & -n) == n) // i.e., n is a power of 2
+ return (int)((n * (long) next(31)) &gt;&gt; 31);
+
+ int bits, val;
+ do
+ {
+ bits = next(31);
+ val = bits % n;
+ }
+ while(bits - val + (n-1) &lt; 0);
+
+ return val;
+}</pre>
+ *
+ * <p>This algorithm would return every value with exactly the same
+ * probability, if the next()-method would be a perfect random number
+ * generator.
+ *
+ * The loop at the bottom only accepts a value, if the random
+ * number was between 0 and the highest number less then 1<<31,
+ * which is divisible by n. The probability for this is high for small
+ * n, and the worst case is 1/2 (for n=(1<<30)+1).
+ *
+ * The special treatment for n = power of 2, selects the high bits of
+ * the random number (the loop at the bottom would select the low order
+ * bits). This is done, because the low order bits of linear congruential
+ * number generators (like the one used in this class) are known to be
+ * ``less random'' than the high order bits.
+ *
+ * @param n the upper bound
+ * @throws IllegalArgumentException if the given upper bound is negative
+ * @return the next pseudorandom value
+ * @since 1.2
+ */
+ public int nextInt(int n)
+ {
+ if (n <= 0)
+ throw new IllegalArgumentException("n must be positive");
+ if ((n & -n) == n) // i.e., n is a power of 2
+ return (int) ((n * (long) next(31)) >> 31);
+ int bits, val;
+ do
+ {
+ bits = next(31);
+ val = bits % n;
+ }
+ while (bits - val + (n - 1) < 0);
+ return val;
+ }
+
+ /**
+ * Generates the next pseudorandom long number. All bits of this
+ * long are independently chosen and 0 and 1 have equal likelihood.
+ * The implementation for java.util.Random is:
+ *
+<pre>public long nextLong()
+{
+ return ((long) next(32) &lt;&lt; 32) + next(32);
+}</pre>
+ *
+ * @return the next pseudorandom value
+ */
+ public long nextLong()
+ {
+ return ((long) next(32) << 32) + next(32);
+ }
+
+ /**
+ * Generates the next pseudorandom boolean. True and false have
+ * the same probability. The implementation is:
+ *
+<pre>public boolean nextBoolean()
+{
+ return next(1) != 0;
+}</pre>
+ *
+ * @return the next pseudorandom boolean
+ * @since 1.2
+ */
+ public boolean nextBoolean()
+ {
+ return next(1) != 0;
+ }
+
+ /**
+ * Generates the next pseudorandom float uniformly distributed
+ * between 0.0f (inclusive) and 1.0f (exclusive). The
+ * implementation is as follows.
+ *
+<pre>public float nextFloat()
+{
+ return next(24) / ((float)(1 &lt;&lt; 24));
+}</pre>
+ *
+ * @return the next pseudorandom float
+ */
+ public float nextFloat()
+ {
+ return next(24) / (float) (1 << 24);
+ }
+
+ /**
+ * Generates the next pseudorandom double uniformly distributed
+ * between 0.0 (inclusive) and 1.0 (exclusive). The
+ * implementation is as follows.
+ *
+<pre>public double nextDouble()
+{
+ return (((long) next(26) &lt;&lt; 27) + next(27)) / (double)(1L &lt;&lt; 53);
+}</pre>
+ *
+ * @return the next pseudorandom double
+ */
+ public double nextDouble()
+ {
+ return (((long) next(26) << 27) + next(27)) / (double) (1L << 53);
+ }
+
+ /**
+ * Generates the next pseudorandom, Gaussian (normally) distributed
+ * double value, with mean 0.0 and standard deviation 1.0.
+ * The algorithm is as follows.
+ *
+<pre>public synchronized double nextGaussian()
+{
+ if (haveNextNextGaussian)
+ {
+ haveNextNextGaussian = false;
+ return nextNextGaussian;
+ }
+ else
+ {
+ double v1, v2, s;
+ do
+ {
+ v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
+ v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
+ s = v1 * v1 + v2 * v2;
+ }
+ while (s >= 1);
+
+ double norm = Math.sqrt(-2 * Math.log(s) / s);
+ nextNextGaussian = v2 * norm;
+ haveNextNextGaussian = true;
+ return v1 * norm;
+ }
+}</pre>
+ *
+ * <p>This is described in section 3.4.1 of <em>The Art of Computer
+ * Programming, Volume 2</em> by Donald Knuth.
+ *
+ * @return the next pseudorandom Gaussian distributed double
+ */
+ public synchronized double nextGaussian()
+ {
+ if (haveNextNextGaussian)
+ {
+ haveNextNextGaussian = false;
+ return nextNextGaussian;
+ }
+ double v1, v2, s;
+ do
+ {
+ v1 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
+ v2 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
+ s = v1 * v1 + v2 * v2;
+ }
+ while (s >= 1);
+ double norm = Math.sqrt(-2 * Math.log(s) / s);
+ nextNextGaussian = v2 * norm;
+ haveNextNextGaussian = true;
+ return v1 * norm;
+ }
+}
diff --git a/libjava/classpath/java/util/RandomAccess.java b/libjava/classpath/java/util/RandomAccess.java
new file mode 100644
index 00000000000..054266a1c74
--- /dev/null
+++ b/libjava/classpath/java/util/RandomAccess.java
@@ -0,0 +1,64 @@
+/* RandomAccess.java -- A tagging interface that lists can use to tailor
+ operations to the correct algorithm
+ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Marker interface used to inform <code>List</code> implementations that
+ * they support fast (usually constant time) random access. This allows
+ * generic list algorithms to tailor their behavior based on the list
+ * type.
+ * <p>
+ *
+ * For example, some sorts are n*log(n) on an array, but decay to quadratic
+ * time on a linked list. As a rule of thumb, this interface should be
+ * used is this loop:<br>
+ * <code>for (int i = 0, n = list.size(); i &lt; n; i++) list.get(i);</code>
+ * <br>runs faster than this loop:<br>
+ * <code>for (Iterator i = list.iterator(); i.hasNext(); ) i.next();</code>
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see List
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface RandomAccess
+{
+ // Tagging interface only.
+}
diff --git a/libjava/classpath/java/util/ResourceBundle.java b/libjava/classpath/java/util/ResourceBundle.java
new file mode 100644
index 00000000000..91007e9b1aa
--- /dev/null
+++ b/libjava/classpath/java/util/ResourceBundle.java
@@ -0,0 +1,580 @@
+/* ResourceBundle -- aids in loading resource bundles
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.classpath.VMStackWalker;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A resource bundle contains locale-specific data. If you need localized
+ * data, you can load a resource bundle that matches the locale with
+ * <code>getBundle</code>. Now you can get your object by calling
+ * <code>getObject</code> or <code>getString</code> on that bundle.
+ *
+ * <p>When a bundle is demanded for a specific locale, the ResourceBundle
+ * is searched in following order (<i>def. language</i> stands for the
+ * two letter ISO language code of the default locale (see
+ * <code>Locale.getDefault()</code>).
+ *
+<pre>baseName_<i>language code</i>_<i>country code</i>_<i>variant</i>
+baseName_<i>language code</i>_<i>country code</i>
+baseName_<i>language code</i>
+baseName_<i>def. language</i>_<i>def. country</i>_<i>def. variant</i>
+baseName_<i>def. language</i>_<i>def. country</i>
+baseName_<i>def. language</i>
+baseName</pre>
+ *
+ * <p>A bundle is backed up by less specific bundles (omitting variant, country
+ * or language). But it is not backed up by the default language locale.
+ *
+ * <p>If you provide a bundle for a given locale, say
+ * <code>Bundle_en_UK_POSIX</code>, you must also provide a bundle for
+ * all sub locales, ie. <code>Bundle_en_UK</code>, <code>Bundle_en</code>, and
+ * <code>Bundle</code>.
+ *
+ * <p>When a bundle is searched, we look first for a class with the given
+ * name, then for a file with <code>.properties</code> extension in the
+ * classpath. The name must be a fully qualified classname (with dots as
+ * path separators).
+ *
+ * <p>(Note: This implementation always backs up the class with a properties
+ * file if that is existing, but you shouldn't rely on this, if you want to
+ * be compatible to the standard JDK.)
+ *
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Locale
+ * @see ListResourceBundle
+ * @see PropertyResourceBundle
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ResourceBundle
+{
+ /**
+ * 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.
+ */
+ protected ResourceBundle parent;
+
+ /**
+ * The locale of this resource bundle. You can read this with
+ * <code>getLocale</code> and it is automatically set in
+ * <code>getBundle</code>.
+ */
+ 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().
+ */
+ private static final Locale emptyLocale = new Locale("");
+
+ /**
+ * The constructor. It does nothing special.
+ */
+ public ResourceBundle()
+ {
+ }
+
+ /**
+ * Get a String from this resource bundle. Since most localized Objects
+ * are Strings, this method provides a convenient way to get them without
+ * casting.
+ *
+ * @param key the name of the resource
+ * @throws MissingResourceException if the resource can't be found
+ * @throws NullPointerException if key is null
+ * @throws ClassCastException if resource is not a string
+ */
+ public final String getString(String key)
+ {
+ return (String) getObject(key);
+ }
+
+ /**
+ * Get an array of Strings from this resource bundle. This method
+ * provides a convenient way to get it without casting.
+ *
+ * @param key the name of the resource
+ * @throws MissingResourceException if the resource can't be found
+ * @throws NullPointerException if key is null
+ * @throws ClassCastException if resource is not a string
+ */
+ public final String[] getStringArray(String key)
+ {
+ return (String[]) getObject(key);
+ }
+
+ /**
+ * Get an object from this resource bundle. This will call
+ * <code>handleGetObject</code> for this resource and all of its parents,
+ * until it finds a non-null resource.
+ *
+ * @param key the name of the resource
+ * @throws MissingResourceException if the resource can't be found
+ * @throws NullPointerException if key is null
+ */
+ public final Object getObject(String key)
+ {
+ for (ResourceBundle bundle = this; bundle != null; bundle = bundle.parent)
+ {
+ Object o = bundle.handleGetObject(key);
+ if (o != null)
+ return o;
+ }
+
+ String className = getClass().getName();
+ throw new MissingResourceException("Key '" + key
+ + "'not found in Bundle: "
+ + className, className, key);
+ }
+
+ /**
+ * Return the actual locale of this bundle. You can use it after calling
+ * getBundle, to know if the bundle for the desired locale was loaded or
+ * if the fall back was used.
+ *
+ * @return the bundle's locale
+ */
+ public Locale getLocale()
+ {
+ return locale;
+ }
+
+ /**
+ * Set the parent of this bundle. The parent is consulted when you call
+ * getObject and there is no such resource in the current bundle.
+ *
+ * @param parent the parent of this bundle
+ */
+ protected void setParent(ResourceBundle parent)
+ {
+ this.parent = parent;
+ }
+
+ /**
+ * Get the appropriate ResourceBundle for the default locale. This is like
+ * calling <code>getBundle(baseName, Locale.getDefault(),
+ * getClass().getClassLoader()</code>, except that any security check of
+ * getClassLoader won't fail.
+ *
+ * @param baseName the name of the ResourceBundle
+ * @return the desired resource bundle
+ * @throws MissingResourceException if the resource bundle can't be found
+ * @throws NullPointerException if baseName is null
+ */
+ public static ResourceBundle getBundle(String baseName)
+ {
+ ClassLoader cl = VMStackWalker.getCallingClassLoader();
+ if (cl == null)
+ cl = ClassLoader.getSystemClassLoader();
+ return getBundle(baseName, Locale.getDefault(), cl);
+ }
+
+ /**
+ * Get the appropriate ResourceBundle for the given locale. This is like
+ * calling <code>getBundle(baseName, locale,
+ * getClass().getClassLoader()</code>, except that any security check of
+ * getClassLoader won't fail.
+ *
+ * @param baseName the name of the ResourceBundle
+ * @param locale A locale
+ * @return the desired resource bundle
+ * @throws MissingResourceException if the resource bundle can't be found
+ * @throws NullPointerException if baseName or locale is null
+ */
+ public static ResourceBundle getBundle(String baseName, Locale locale)
+ {
+ ClassLoader cl = VMStackWalker.getCallingClassLoader();
+ if (cl == null)
+ cl = ClassLoader.getSystemClassLoader();
+ return getBundle(baseName, locale, cl);
+ }
+
+ /** Cache key for the ResourceBundle cache. Resource bundles are keyed
+ by the combination of bundle name, locale, and class loader. */
+ private static class BundleKey
+ {
+ String baseName;
+ Locale locale;
+ ClassLoader classLoader;
+ int hashcode;
+
+ BundleKey() {}
+
+ BundleKey(String s, Locale l, ClassLoader cl)
+ {
+ set(s, l, cl);
+ }
+
+ void set(String s, Locale l, ClassLoader cl)
+ {
+ baseName = s;
+ locale = l;
+ classLoader = cl;
+ hashcode = baseName.hashCode() ^ locale.hashCode() ^
+ classLoader.hashCode();
+ }
+
+ public int hashCode()
+ {
+ return hashcode;
+ }
+
+ public boolean equals(Object o)
+ {
+ 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);
+ }
+ }
+
+ /** A cache lookup key. This avoids having to a new one for every
+ * getBundle() call. */
+ private static BundleKey lookupKey = new BundleKey();
+
+ /** Singleton cache entry to represent previous failed lookups. */
+ private static Object nullEntry = new Object();
+
+ /**
+ * Get the appropriate ResourceBundle for the given locale. The following
+ * strategy is used:
+ *
+ * <p>A sequence of candidate bundle names are generated, and tested in
+ * this order, where the suffix 1 means the string from the specified
+ * locale, and the suffix 2 means the string from the default locale:</p>
+ *
+ * <ul>
+ * <li>baseName + "_" + language1 + "_" + country1 + "_" + variant1</li>
+ * <li>baseName + "_" + language1 + "_" + country1</li>
+ * <li>baseName + "_" + language1</li>
+ * <li>baseName + "_" + language2 + "_" + country2 + "_" + variant2</li>
+ * <li>baseName + "_" + language2 + "_" + country2</li>
+ * <li>baseName + "_" + language2</li>
+ * <li>baseName</li>
+ * </ul>
+ *
+ * <p>In the sequence, entries with an empty string are ignored. Next,
+ * <code>getBundle</code> tries to instantiate the resource bundle:</p>
+ *
+ * <ul>
+ * <li>First, an attempt is made to load a class in the specified classloader
+ * which is a subclass of ResourceBundle, and which has a public constructor
+ * with no arguments, via reflection.</li>
+ * <li>Next, a search is made for a property resource file, by replacing
+ * '.' with '/' and appending ".properties", and using
+ * ClassLoader.getResource(). If a file is found, then a
+ * PropertyResourceBundle is created from the file's contents.</li>
+ * </ul>
+ * If no resource bundle was found, a MissingResourceException is thrown.
+ *
+ * <p>Next, the parent chain is implemented. The remaining candidate names
+ * in the above sequence are tested in a similar manner, and if any results
+ * in a resource bundle, it is assigned as the parent of the first bundle
+ * using the <code>setParent</code> method (unless the first bundle already
+ * has a parent).</p>
+ *
+ * <p>For example, suppose the following class and property files are
+ * provided: MyResources.class, MyResources_fr_CH.properties,
+ * MyResources_fr_CH.class, MyResources_fr.properties,
+ * MyResources_en.properties, and MyResources_es_ES.class. The contents of
+ * all files are valid (that is, public non-abstract subclasses of
+ * ResourceBundle with public nullary constructors for the ".class" files,
+ * syntactically correct ".properties" files). The default locale is
+ * Locale("en", "UK").</p>
+ *
+ * <p>Calling getBundle with the shown locale argument values instantiates
+ * resource bundles from the following sources:</p>
+ *
+ * <ul>
+ * <li>Locale("fr", "CH"): result MyResources_fr_CH.class, parent
+ * MyResources_fr.properties, parent MyResources.class</li>
+ * <li>Locale("fr", "FR"): result MyResources_fr.properties, parent
+ * MyResources.class</li>
+ * <li>Locale("de", "DE"): result MyResources_en.properties, parent
+ * MyResources.class</li>
+ * <li>Locale("en", "US"): result MyResources_en.properties, parent
+ * MyResources.class</li>
+ * <li>Locale("es", "ES"): result MyResources_es_ES.class, parent
+ * MyResources.class</li>
+ * </ul>
+ *
+ * <p>The file MyResources_fr_CH.properties is never used because it is hidden
+ * by MyResources_fr_CH.class.</p>
+ *
+ * @param baseName the name of the ResourceBundle
+ * @param locale A locale
+ * @param classLoader a ClassLoader
+ * @return the desired resource bundle
+ * @throws MissingResourceException if the resource bundle can't be found
+ * @throws NullPointerException if any argument is null
+ * @since 1.2
+ */
+ // This method is synchronized so that the cache is properly
+ // handled.
+ 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);
+
+ Object obj = bundleCache.get(lookupKey);
+ ResourceBundle rb = null;
+
+ if (obj instanceof ResourceBundle)
+ {
+ return (ResourceBundle) obj;
+ }
+ else if (obj == nullEntry)
+ {
+ // Lookup has failed previously. Fall through.
+ }
+ 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",
+ baseName, "");
+ }
+
+ /**
+ * Override this method to provide the resource for a keys. This gets
+ * called by <code>getObject</code>. If you don't have a resource
+ * for the given key, you should return null instead throwing a
+ * MissingResourceException. You don't have to ask the parent, getObject()
+ * already does this; nor should you throw a MissingResourceException.
+ *
+ * @param key the key of the resource
+ * @return the resource for the key, or null if not in bundle
+ * @throws NullPointerException if key is null
+ */
+ protected abstract Object handleGetObject(String key);
+
+ /**
+ * This method should return all keys for which a resource exists; you
+ * should include the enumeration of any parent's keys, after filtering out
+ * duplicates.
+ *
+ * @return an enumeration of the keys
+ */
+ public abstract Enumeration getKeys();
+
+ /**
+ * Tries to load a class or a property file with the specified name.
+ *
+ * @param localizedName the name
+ * @param classloader the classloader
+ * @return the resource bundle if it was loaded, otherwise the backup
+ */
+ private static ResourceBundle tryBundle(String localizedName,
+ ClassLoader classloader)
+ {
+ ResourceBundle bundle = null;
+ try
+ {
+ Class rbClass;
+ if (classloader == null)
+ rbClass = Class.forName(localizedName);
+ else
+ rbClass = classloader.loadClass(localizedName);
+ // Note that we do the check up front instead of catching
+ // ClassCastException. The reason for this is that some crazy
+ // programs (Eclipse) have classes that do not extend
+ // ResourceBundle but that have the same name as a property
+ // bundle; in fact Eclipse relies on ResourceBundle not
+ // instantiating these classes.
+ if (ResourceBundle.class.isAssignableFrom(rbClass))
+ bundle = (ResourceBundle) rbClass.newInstance();
+ }
+ catch (IllegalAccessException ex) {}
+ catch (InstantiationException ex) {}
+ catch (ClassNotFoundException ex) {}
+
+ if (bundle == null)
+ {
+ try
+ {
+ InputStream is;
+ String resourceName
+ = localizedName.replace('.', '/') + ".properties";
+ if (classloader == null)
+ is = ClassLoader.getSystemResourceAsStream(resourceName);
+ else
+ is = classloader.getResourceAsStream(resourceName);
+ if (is != null)
+ bundle = new PropertyResourceBundle(is);
+ }
+ catch (IOException ex)
+ {
+ MissingResourceException mre = new MissingResourceException
+ ("Failed to load bundle: " + localizedName, localizedName, "");
+ mre.initCause(ex);
+ throw mre;
+ }
+ }
+
+ return bundle;
+ }
+
+ /**
+ * Tries to load a the bundle for a given locale, also loads the backup
+ * locales with the same language.
+ *
+ * @param baseName the raw bundle name, without locale qualifiers
+ * @param locale the locale
+ * @param classloader the classloader
+ * @param bundle the backup (parent) bundle
+ * @param wantBase whether a resource bundle made only from the base name
+ * (with no locale information attached) should be returned.
+ * @return the resource bundle if it was loaded, otherwise the backup
+ */
+ private static ResourceBundle tryBundle(String baseName, Locale locale,
+ ClassLoader classLoader,
+ boolean wantBase)
+ {
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+ String variant = locale.getVariant();
+
+ int baseLen = baseName.length();
+
+ // Build up a StringBuffer containing the complete bundle name, fully
+ // qualified by locale.
+ StringBuffer sb = new StringBuffer(baseLen + variant.length() + 7);
+
+ sb.append(baseName);
+
+ if (language.length() > 0)
+ {
+ sb.append('_');
+ sb.append(language);
+
+ if (country.length() > 0)
+ {
+ sb.append('_');
+ sb.append(country);
+
+ if (variant.length() > 0)
+ {
+ sb.append('_');
+ sb.append(variant);
+ }
+ }
+ }
+
+ // Now try to load bundles, starting with the most specialized name.
+ // Build up the parent chain as we go.
+ String bundleName = sb.toString();
+ ResourceBundle first = null; // The most specialized bundle.
+ ResourceBundle last = null; // The least specialized bundle.
+
+ while (true)
+ {
+ ResourceBundle foundBundle = tryBundle(bundleName, classLoader);
+ if (foundBundle != null)
+ {
+ if (first == null)
+ first = foundBundle;
+ if (last != null)
+ last.parent = foundBundle;
+ foundBundle.locale = locale;
+ last = foundBundle;
+ }
+ int idx = bundleName.lastIndexOf('_');
+ // Try the non-localized base name only if we already have a
+ // localized child bundle, or wantBase is true.
+ if (idx > baseLen || (idx == baseLen && (first != null || wantBase)))
+ bundleName = bundleName.substring(0, idx);
+ else
+ break;
+ }
+
+ return first;
+ }
+}
diff --git a/libjava/classpath/java/util/Set.java b/libjava/classpath/java/util/Set.java
new file mode 100644
index 00000000000..839959e620c
--- /dev/null
+++ b/libjava/classpath/java/util/Set.java
@@ -0,0 +1,264 @@
+/* Set.java -- A collection that prohibits duplicates
+ Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A collection that contains no duplicates. In other words, for two set
+ * elements e1 and e2, <code>e1.equals(e2)</code> returns false. There
+ * are additional stipulations on <code>add</code>, <code>equals</code>
+ * and <code>hashCode</code>, as well as the requirements that constructors
+ * do not permit duplicate elements. The Set interface is incompatible with
+ * List; you cannot implement both simultaneously.
+ * <p>
+ *
+ * Note: Be careful about using mutable objects in sets. In particular,
+ * if a mutable object changes to become equal to another set element, you
+ * have violated the contract. As a special case of this, a Set is not
+ * allowed to be an element of itself, without risking undefined behavior.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see List
+ * @see SortedSet
+ * @see HashSet
+ * @see TreeSet
+ * @see LinkedHashSet
+ * @see AbstractSet
+ * @see Collections#singleton(Object)
+ * @see Collections#EMPTY_SET
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Set extends Collection
+{
+ /**
+ * Adds the specified element to the set if it is not already present
+ * (optional operation). In particular, the comparison algorithm is
+ * <code>o == null ? e == null : o.equals(e)</code>. Sets need not permit
+ * all values, and may document what exceptions will be thrown if
+ * a value is not permitted.
+ *
+ * @param o the object to add
+ * @return true if the object was not previously in the set
+ * @throws UnsupportedOperationException if this operation is not allowed
+ * @throws ClassCastException if the class of o prevents it from being added
+ * @throws IllegalArgumentException if some aspect of o prevents it from
+ * being added
+ * @throws NullPointerException if null is not permitted in this set
+ */
+ boolean add(Object o);
+
+ /**
+ * Adds all of the elements of the given collection to this set (optional
+ * operation). If the argument is also a Set, this returns the mathematical
+ * <i>union</i> of the two. The behavior is unspecified if the set is
+ * modified while this is taking place.
+ *
+ * @param c the collection to add
+ * @return true if the set changed as a result
+ * @throws UnsupportedOperationException if this operation is not allowed
+ * @throws ClassCastException if the class of an element prevents it from
+ * being added
+ * @throws IllegalArgumentException if something about an element prevents
+ * it from being added
+ * @throws NullPointerException if null is not permitted in this set, or
+ * if the argument c is null
+ * @see #add(Object)
+ */
+ boolean addAll(Collection c);
+
+ /**
+ * Removes all elements from this set (optional operation). This set will
+ * be empty afterwords, unless an exception occurs.
+ *
+ * @throws UnsupportedOperationException if this operation is not allowed
+ */
+ void clear();
+
+ /**
+ * Returns true if the set contains the specified element. In other words,
+ * this looks for <code>o == null ? e == null : o.equals(e)</code>.
+ *
+ * @param o the object to look for
+ * @return true if it is found in the set
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this set.
+ * @throws NullPointerException if o is null and this set doesn't
+ * support null values.
+ */
+ boolean contains(Object o);
+
+ /**
+ * Returns true if this set contains all elements in the specified
+ * collection. If the argument is also a set, this is the <i>subset</i>
+ * relationship.
+ *
+ * @param c the collection to check membership in
+ * @return true if all elements in this set are in c
+ * @throws NullPointerException if c is null
+ * @throws ClassCastException if the type of any element in c is not
+ * a valid type for this set.
+ * @throws NullPointerException if some element of c is null and this
+ * set doesn't support null values.
+ * @see #contains(Object)
+ */
+ boolean containsAll(Collection c);
+
+ /**
+ * Compares the specified object to this for equality. For sets, the object
+ * must be a set, the two must have the same size, and every element in
+ * one must be in the other.
+ *
+ * @param o the object to compare to
+ * @return true if it is an equal set
+ */
+ boolean equals(Object o);
+
+ /**
+ * Returns the hash code for this set. In order to satisfy the contract of
+ * equals, this is the sum of the hashcode of all elements in the set.
+ *
+ * @return the sum of the hashcodes of all set elements
+ * @see #equals(Object)
+ */
+ int hashCode();
+
+ /**
+ * Returns true if the set contains no elements.
+ *
+ * @return true if the set is empty
+ */
+ boolean isEmpty();
+
+ /**
+ * Returns an iterator over the set. The iterator has no specific order,
+ * unless further specified.
+ *
+ * @return a set iterator
+ */
+ Iterator iterator();
+
+ /**
+ * Removes the specified element from this set (optional operation). If
+ * an element e exists, <code>o == null ? e == null : o.equals(e)</code>,
+ * it is removed from the set.
+ *
+ * @param o the object to remove
+ * @return true if the set changed (an object was removed)
+ * @throws UnsupportedOperationException if this operation is not allowed
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this set.
+ * @throws NullPointerException if o is null and this set doesn't allow
+ * the removal of a null value.
+ */
+ boolean remove(Object o);
+
+ /**
+ * Removes from this set all elements contained in the specified collection
+ * (optional operation). If the argument is a set, this returns the
+ * <i>asymmetric set difference</i> of the two sets.
+ *
+ * @param c the collection to remove from this set
+ * @return true if this set changed as a result
+ * @throws UnsupportedOperationException if this operation is not allowed
+ * @throws NullPointerException if c is null
+ * @throws ClassCastException if the type of any element in c is not
+ * a valid type for this set.
+ * @throws NullPointerException if some element of c is null and this
+ * set doesn't support removing null values.
+ * @see #remove(Object)
+ */
+ boolean removeAll(Collection c);
+
+ /**
+ * Retains only the elements in this set that are also in the specified
+ * collection (optional operation). If the argument is also a set, this
+ * performs the <i>intersection</i> of the two sets.
+ *
+ * @param c the collection to keep
+ * @return true if this set was modified
+ * @throws UnsupportedOperationException if this operation is not allowed
+ * @throws NullPointerException if c is null
+ * @throws ClassCastException if the type of any element in c is not
+ * a valid type for this set.
+ * @throws NullPointerException if some element of c is null and this
+ * set doesn't support retaining null values.
+ * @see #remove(Object)
+ */
+ boolean retainAll(Collection c);
+
+ /**
+ * Returns the number of elements in the set. If there are more
+ * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
+ * the <i>cardinality</i> of the set.
+ *
+ * @return the number of elements
+ */
+ int size();
+
+ /**
+ * Returns an array containing the elements of this set. If the set
+ * makes a guarantee about iteration order, the array has the same
+ * order. The array is distinct from the set; modifying one does not
+ * affect the other.
+ *
+ * @return an array of this set's elements
+ * @see #toArray(Object[])
+ */
+ Object[] toArray();
+
+ /**
+ * Returns an array containing the elements of this set, of the same runtime
+ * type of the argument. If the given set is large enough, it is reused,
+ * and null is inserted in the first unused slot. Otherwise, reflection
+ * is used to build a new array. If the set makes a guarantee about iteration
+ * order, the array has the same order. The array is distinct from the set;
+ * modifying one does not affect the other.
+ *
+ * @param a the array to determine the return type; if it is big enough
+ * it is used and returned
+ * @return an array holding the elements of the set
+ * @throws ArrayStoreException if the runtime type of a is not a supertype
+ * of all elements in the set
+ * @throws NullPointerException if a is null
+ * @see #toArray()
+ */
+ Object[] toArray(Object[] a);
+}
diff --git a/libjava/classpath/java/util/SimpleTimeZone.java b/libjava/classpath/java/util/SimpleTimeZone.java
new file mode 100644
index 00000000000..995ccea84ca
--- /dev/null
+++ b/libjava/classpath/java/util/SimpleTimeZone.java
@@ -0,0 +1,1077 @@
+/* java.util.SimpleTimeZone
+ Copyright (C) 1998, 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+
+/**
+ * This class represents a simple time zone offset and handles
+ * daylight savings. It can only handle one daylight savings rule, so
+ * it can't represent historical changes.
+ *
+ * This object is tightly bound to the Gregorian calendar. It assumes
+ * a regular seven days week, and the month lengths are that of the
+ * Gregorian Calendar. It can only handle daylight savings for years
+ * lying in the AD era.
+ *
+ * @see Calendar
+ * @see GregorianCalendar
+ * @author Jochen Hoenicke
+ */
+public class SimpleTimeZone extends TimeZone
+{
+ /**
+ * The raw time zone offset in milliseconds to GMT, ignoring
+ * daylight savings.
+ * @serial
+ */
+ private int rawOffset;
+
+ /**
+ * True, if this timezone uses daylight savings, false otherwise.
+ * @serial
+ */
+ private boolean useDaylight;
+
+ /**
+ * The daylight savings offset. This is a positive offset in
+ * milliseconds with respect to standard time. Typically this
+ * is one hour, but for some time zones this may be half an hour.
+ * @serial
+ * @since JDK1.1.4
+ */
+ private int dstSavings = 60 * 60 * 1000;
+
+ /**
+ * The first year, in which daylight savings rules applies.
+ * @serial
+ */
+ private int startYear;
+ private static final int DOM_MODE = 1;
+ private static final int DOW_IN_MONTH_MODE = 2;
+ private static final int DOW_GE_DOM_MODE = 3;
+ private static final int DOW_LE_DOM_MODE = 4;
+
+ /**
+ * The mode of the start rule. This takes one of the following values:
+ * <dl>
+ * <dt>DOM_MODE (1)</dt>
+ * <dd> startDay contains the day in month of the start date,
+ * startDayOfWeek is unused. </dd>
+ * <dt>DOW_IN_MONTH_MODE (2)</dt>
+ * <dd> The startDay gives the day of week in month, and
+ * startDayOfWeek the day of week. For example startDay=2 and
+ * startDayOfWeek=Calender.SUNDAY specifies that the change is on
+ * the second sunday in that month. You must make sure, that this
+ * day always exists (ie. don't specify the 5th sunday).
+ * </dd>
+ * <dt>DOW_GE_DOM_MODE (3)</dt>
+ * <dd> The start is on the first startDayOfWeek on or after
+ * startDay. For example startDay=13 and
+ * startDayOfWeek=Calendar.FRIDAY specifies that the daylight
+ * savings start on the first FRIDAY on or after the 13th of that
+ * Month. Make sure that the change is always in the given month, or
+ * the result is undefined.
+ * </dd>
+ * <dt>DOW_LE_DOM_MONTH (4)</dt>
+ * <dd> The start is on the first startDayOfWeek on or before the
+ * startDay. Make sure that the change is always in the given
+ * month, or the result is undefined.
+ </dd>
+ * </dl>
+ * @serial */
+ private int startMode;
+
+ /**
+ * The month in which daylight savings start. This is one of the
+ * constants Calendar.JANUARY, ..., Calendar.DECEMBER.
+ * @serial
+ */
+ private int startMonth;
+
+ /**
+ * This variable can have different meanings. See startMode for details
+ * @see #startMode
+ * @serial
+ */
+ private int startDay;
+
+ /**
+ * This variable specifies the day of week the change takes place. If
+ * startMode == DOM_MODE, this is undefined.
+ * @serial
+ * @see #startMode
+ */
+ private int startDayOfWeek;
+
+ /**
+ * This variable specifies the time of change to daylight savings.
+ * This time is given in milliseconds after midnight local
+ * standard time.
+ * @serial
+ */
+ private int startTime;
+
+ /**
+ * This variable specifies the mode that startTime is specified in. By
+ * default it is WALL_TIME, but can also be STANDARD_TIME or UTC_TIME. For
+ * startTime, STANDARD_TIME and WALL_TIME are equivalent.
+ * @serial
+ */
+ private int startTimeMode = WALL_TIME;
+
+ /**
+ * The month in which daylight savings ends. This is one of the
+ * constants Calendar.JANUARY, ..., Calendar.DECEMBER.
+ * @serial
+ */
+ private int endMonth;
+
+ /**
+ * This variable gives the mode for the end of daylight savings rule.
+ * It can take the same values as startMode.
+ * @serial
+ * @see #startMode
+ */
+ private int endMode;
+
+ /**
+ * This variable can have different meanings. See startMode for details
+ * @serial
+ * @see #startMode
+ */
+ private int endDay;
+
+ /**
+ * This variable specifies the day of week the change takes place. If
+ * endMode == DOM_MODE, this is undefined.
+ * @serial
+ * @see #startMode
+ */
+ private int endDayOfWeek;
+
+ /**
+ * This variable specifies the time of change back to standard time.
+ * This time is given in milliseconds after midnight local
+ * standard time.
+ * @serial
+ */
+ private int endTime;
+
+ /**
+ * This variable specifies the mode that endTime is specified in. By
+ * default it is WALL_TIME, but can also be STANDARD_TIME or UTC_TIME.
+ * @serial
+ */
+ private int endTimeMode = WALL_TIME;
+
+ /**
+ * This variable points to a deprecated array from JDK 1.1. It is
+ * ignored in JDK 1.2 but streamed out for compatibility with JDK 1.1.
+ * The array contains the lengths of the months in the year and is
+ * assigned from a private static final field to avoid allocating
+ * the array for every instance of the object.
+ * Note that static final fields are not serialized.
+ * @serial
+ */
+ private byte[] monthLength = monthArr;
+ private static final byte[] monthArr =
+ {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30,
+ 31, 30, 31
+ };
+
+ /**
+ * The version of the serialized data on the stream.
+ * <dl>
+ * <dt>0 or not present on stream</dt>
+ * <dd> JDK 1.1.3 or earlier, only provides this fields:
+ * rawOffset, startDay, startDayOfWeek, startMonth, startTime,
+ * startYear, endDay, endDayOfWeek, endMonth, endTime
+ * </dd>
+ * <dd> JDK 1.1.4 or later. This includes three new fields, namely
+ * startMode, endMode and dstSavings. And there is a optional section
+ * as described in writeObject.
+ * </dd>
+ * </dl>
+ *
+ * XXX - JDK 1.2 Beta 4 docu states 1.1.4, but my 1.1.5 has the old
+ * version.
+ *
+ * When streaming out this class it is always written in the latest
+ * version.
+ * @serial
+ * @since JDK1.1.4
+ */
+ private int serialVersionOnStream = 2;
+ private static final long serialVersionUID = -403250971215465050L;
+
+ /**
+ * Constant to indicate that start and end times are specified in standard
+ * time, without adjusting for daylight savings.
+ */
+ public static final int STANDARD_TIME = 1;
+
+ /**
+ * Constant to indicate that start and end times are specified in wall
+ * time, adjusting for daylight savings. This is the default.
+ */
+ public static final int WALL_TIME = 0;
+
+ /**
+ * Constant to indicate that start and end times are specified in UTC.
+ */
+ public static final int UTC_TIME = 2;
+
+ /**
+ * Create a <code>SimpleTimeZone</code> with the given time offset
+ * from GMT and without daylight savings.
+ * @param rawOffset the time offset from GMT in milliseconds.
+ * @param id The identifier of this time zone.
+ */
+ public SimpleTimeZone(int rawOffset, String id)
+ {
+ this.rawOffset = rawOffset;
+ setID(id);
+ useDaylight = false;
+ startYear = 0;
+ }
+
+ /**
+ * Create a <code>SimpleTimeZone</code> with the given time offset
+ * from GMT and with daylight savings. The start/end parameters
+ * can have different meaning (replace WEEKDAY with a real day of
+ * week). Only the first two meanings were supported by earlier
+ * versions of jdk.
+ *
+ * <dl>
+ * <dt><code>day &gt; 0, dayOfWeek = Calendar.WEEKDAY</code></dt>
+ * <dd>The start/end of daylight savings is on the <code>day</code>-th
+ * <code>WEEKDAY</code> in the given month. </dd>
+ * <dt><code>day &lt; 0, dayOfWeek = Calendar.WEEKDAY</code></dt>
+ * <dd>The start/end of daylight savings is on the <code>-day</code>-th
+ * <code>WEEKDAY</code> counted from the <i>end</i> of the month. </dd>
+ * <dt><code>day &gt; 0, dayOfWeek = 0</code></dt>
+ * <dd>The start/end of daylight is on the <code>day</code>-th day of
+ * the month. </dd>
+ * <dt><code>day &gt; 0, dayOfWeek = -Calendar.WEEKDAY</code></dt>
+ * <dd>The start/end of daylight is on the first WEEKDAY on or after
+ * the <code>day</code>-th day of the month. You must make sure that
+ * this day lies in the same month. </dd>
+ * <dt><code>day &lt; 0, dayOfWeek = -Calendar.WEEKDAY</code></dt>
+ * <dd>The start/end of daylight is on the first WEEKDAY on or
+ * <i>before</i> the <code>-day</code>-th day of the month. You
+ * must make sure that this day lies in the same month. </dd>
+ * </dl>
+ *
+ * If you give a non existing month, a day that is zero, or too big,
+ * or a dayOfWeek that is too big, the result is undefined.
+ *
+ * The start rule must have a different month than the end rule.
+ * This restriction shouldn't hurt for all possible time zones.
+ *
+ * @param rawOffset The time offset from GMT in milliseconds.
+ * @param id The identifier of this time zone.
+ * @param startMonth The start month of daylight savings; use the
+ * constants in Calendar.
+ * @param startDayOfWeekInMonth A day in month or a day of week number, as
+ * described above.
+ * @param startDayOfWeek The start rule day of week; see above.
+ * @param startTime A time in millis in standard time.
+ * @param endMonth The end month of daylight savings; use the
+ * constants in Calendar.
+ * @param endDayOfWeekInMonth A day in month or a day of week number, as
+ * described above.
+ * @param endDayOfWeek The end rule day of week; see above.
+ * @param endTime A time in millis in standard time.
+ * @throws IllegalArgumentException if parameters are invalid or out of
+ * range.
+ */
+ public SimpleTimeZone(int rawOffset, String id, int startMonth,
+ int startDayOfWeekInMonth, int startDayOfWeek,
+ int startTime, int endMonth, int endDayOfWeekInMonth,
+ int endDayOfWeek, int endTime)
+ {
+ this.rawOffset = rawOffset;
+ setID(id);
+ useDaylight = true;
+
+ setStartRule(startMonth, startDayOfWeekInMonth, startDayOfWeek, startTime);
+ setEndRule(endMonth, endDayOfWeekInMonth, endDayOfWeek, endTime);
+ if (startMonth == endMonth)
+ throw new IllegalArgumentException("startMonth and endMonth must be different");
+ this.startYear = 0;
+ }
+
+ /**
+ * This constructs a new SimpleTimeZone that supports a daylight savings
+ * rule. The parameter are the same as for the constructor above, except
+ * there is the additional dstSavaings parameter.
+ *
+ * @param dstSavings the amount of savings for daylight savings
+ * time in milliseconds. This must be positive.
+ * @since 1.2
+ */
+ public SimpleTimeZone(int rawOffset, String id, int startMonth,
+ int startDayOfWeekInMonth, int startDayOfWeek,
+ int startTime, int endMonth, int endDayOfWeekInMonth,
+ int endDayOfWeek, int endTime, int dstSavings)
+ {
+ this(rawOffset, id, startMonth, startDayOfWeekInMonth, startDayOfWeek,
+ startTime, endMonth, endDayOfWeekInMonth, endDayOfWeek, endTime);
+
+ this.dstSavings = dstSavings;
+ }
+
+ /**
+ * This constructs a new SimpleTimeZone that supports a daylight savings
+ * rule. The parameter are the same as for the constructor above, except
+ * there are the additional startTimeMode, endTimeMode, and dstSavings
+ * parameters.
+ *
+ * @param startTimeMode the mode that start times are specified in. One of
+ * WALL_TIME, STANDARD_TIME, or UTC_TIME.
+ * @param endTimeMode the mode that end times are specified in. One of
+ * WALL_TIME, STANDARD_TIME, or UTC_TIME.
+ * @param dstSavings the amount of savings for daylight savings
+ * time in milliseconds. This must be positive.
+ * @throws IllegalArgumentException if parameters are invalid or out of
+ * range.
+ * @since 1.4
+ */
+ public SimpleTimeZone(int rawOffset, String id, int startMonth,
+ int startDayOfWeekInMonth, int startDayOfWeek,
+ int startTime, int startTimeMode, int endMonth,
+ int endDayOfWeekInMonth, int endDayOfWeek,
+ int endTime, int endTimeMode, int dstSavings)
+ {
+ this.rawOffset = rawOffset;
+ setID(id);
+ useDaylight = true;
+
+ if (startTimeMode < WALL_TIME || startTimeMode > UTC_TIME)
+ throw new IllegalArgumentException("startTimeMode must be one of WALL_TIME, STANDARD_TIME, or UTC_TIME");
+ if (endTimeMode < WALL_TIME || endTimeMode > UTC_TIME)
+ throw new IllegalArgumentException("endTimeMode must be one of WALL_TIME, STANDARD_TIME, or UTC_TIME");
+ this.startTimeMode = startTimeMode;
+ this.endTimeMode = endTimeMode;
+
+ setStartRule(startMonth, startDayOfWeekInMonth, startDayOfWeek, startTime);
+ setEndRule(endMonth, endDayOfWeekInMonth, endDayOfWeek, endTime);
+ if (startMonth == endMonth)
+ throw new IllegalArgumentException("startMonth and endMonth must be different");
+ this.startYear = 0;
+
+ this.dstSavings = dstSavings;
+ }
+
+ /**
+ * Sets the first year, where daylight savings applies. The daylight
+ * savings rule never apply for years in the BC era. Note that this
+ * is gregorian calendar specific.
+ * @param year the start year.
+ */
+ public void setStartYear(int year)
+ {
+ startYear = year;
+ useDaylight = true;
+ }
+
+ /**
+ * Checks if the month, day, dayOfWeek arguments are in range and
+ * returns the mode of the rule.
+ * @param month the month parameter as in the constructor
+ * @param day the day parameter as in the constructor
+ * @param dayOfWeek the day of week parameter as in the constructor
+ * @return the mode of this rule see startMode.
+ * @exception IllegalArgumentException if parameters are out of range.
+ * @see #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)
+ * @see #startMode
+ */
+ private int checkRule(int month, int day, int dayOfWeek)
+ {
+ if (month < 0 || month > 11)
+ throw new IllegalArgumentException("month out of range");
+
+ int daysInMonth = getDaysInMonth(month, 1);
+ if (dayOfWeek == 0)
+ {
+ if (day <= 0 || day > daysInMonth)
+ throw new IllegalArgumentException("day out of range");
+ return DOM_MODE;
+ }
+ else if (dayOfWeek > 0)
+ {
+ if (Math.abs(day) > (daysInMonth + 6) / 7)
+ throw new IllegalArgumentException("dayOfWeekInMonth out of range");
+ if (dayOfWeek > Calendar.SATURDAY)
+ throw new IllegalArgumentException("dayOfWeek out of range");
+ return DOW_IN_MONTH_MODE;
+ }
+ else
+ {
+ if (day == 0 || Math.abs(day) > daysInMonth)
+ throw new IllegalArgumentException("day out of range");
+ if (dayOfWeek < -Calendar.SATURDAY)
+ throw new IllegalArgumentException("dayOfWeek out of range");
+ if (day < 0)
+ return DOW_LE_DOM_MODE;
+ else
+ return DOW_GE_DOM_MODE;
+ }
+ }
+
+ /**
+ * Sets the daylight savings start rule. You must also set the
+ * end rule with <code>setEndRule</code> or the result of
+ * getOffset is undefined. For the parameters see the ten-argument
+ * constructor above.
+ *
+ * @param month The month where daylight savings start, zero
+ * based. You should use the constants in Calendar.
+ * @param day A day of month or day of week in month.
+ * @param dayOfWeek The day of week where daylight savings start.
+ * @param time The time in milliseconds standard time where daylight
+ * savings start.
+ * @see SimpleTimeZone
+ */
+ public void setStartRule(int month, int day, int dayOfWeek, int time)
+ {
+ this.startMode = checkRule(month, day, dayOfWeek);
+ this.startMonth = month;
+ this.startDay = day;
+ this.startDayOfWeek = Math.abs(dayOfWeek);
+ if (this.startTimeMode == WALL_TIME || this.startTimeMode == STANDARD_TIME)
+ this.startTime = time;
+ else
+ // Convert from UTC to STANDARD
+ this.startTime = time + this.rawOffset;
+ useDaylight = true;
+ }
+
+ /**
+ * Sets the daylight savings start rule. You must also set the
+ * end rule with <code>setEndRule</code> or the result of
+ * getOffset is undefined. For the parameters see the ten-argument
+ * constructor above.
+ *
+ * Note that this API isn't incredibly well specified. It appears that the
+ * after flag must override the parameters, since normally, the day and
+ * dayofweek can select this. I.e., if day < 0 and dayOfWeek < 0, on or
+ * before mode is chosen. But if after == true, this implementation
+ * overrides the signs of the other arguments. And if dayOfWeek == 0, it
+ * falls back to the behavior in the other APIs. I guess this should be
+ * checked against Sun's implementation.
+ *
+ * @param month The month where daylight savings start, zero
+ * based. You should use the constants in Calendar.
+ * @param day A day of month or day of week in month.
+ * @param dayOfWeek The day of week where daylight savings start.
+ * @param time The time in milliseconds standard time where daylight
+ * savings start.
+ * @param after If true, day and dayOfWeek specify first day of week on or
+ * after day, else first day of week on or before.
+ * @since 1.2
+ * @see SimpleTimeZone
+ */
+ public void setStartRule(int month, int day, int dayOfWeek, int time,
+ boolean after)
+ {
+ // FIXME: XXX: Validate that checkRule and offset processing work with on
+ // or before mode.
+ this.startDay = after ? Math.abs(day) : -Math.abs(day);
+ this.startDayOfWeek = after ? Math.abs(dayOfWeek) : -Math.abs(dayOfWeek);
+ this.startMode = (dayOfWeek != 0)
+ ? (after ? DOW_GE_DOM_MODE : DOW_LE_DOM_MODE)
+ : checkRule(month, day, dayOfWeek);
+ this.startDay = Math.abs(this.startDay);
+ this.startDayOfWeek = Math.abs(this.startDayOfWeek);
+
+ this.startMonth = month;
+
+ if (this.startTimeMode == WALL_TIME || this.startTimeMode == STANDARD_TIME)
+ this.startTime = time;
+ else
+ // Convert from UTC to STANDARD
+ this.startTime = time + this.rawOffset;
+ useDaylight = true;
+ }
+
+ /**
+ * Sets the daylight savings start rule. You must also set the
+ * end rule with <code>setEndRule</code> or the result of
+ * getOffset is undefined. For the parameters see the ten-argument
+ * constructor above.
+ *
+ * @param month The month where daylight savings start, zero
+ * based. You should use the constants in Calendar.
+ * @param day A day of month or day of week in month.
+ * @param time The time in milliseconds standard time where daylight
+ * savings start.
+ * @see SimpleTimeZone
+ * @since 1.2
+ */
+ public void setStartRule(int month, int day, int time)
+ {
+ setStartRule(month, day, 0, time);
+ }
+
+ /**
+ * Sets the daylight savings end rule. You must also set the
+ * start rule with <code>setStartRule</code> or the result of
+ * getOffset is undefined. For the parameters see the ten-argument
+ * constructor above.
+ *
+ * @param month The end month of daylight savings.
+ * @param day A day in month, or a day of week in month.
+ * @param dayOfWeek A day of week, when daylight savings ends.
+ * @param time A time in millis in standard time.
+ * @see #setStartRule(int, int, int, int)
+ */
+ public void setEndRule(int month, int day, int dayOfWeek, int time)
+ {
+ this.endMode = checkRule(month, day, dayOfWeek);
+ this.endMonth = month;
+ this.endDay = day;
+ this.endDayOfWeek = Math.abs(dayOfWeek);
+ if (this.endTimeMode == WALL_TIME)
+ this.endTime = time;
+ else if (this.endTimeMode == STANDARD_TIME)
+ // Convert from STANDARD to DST
+ this.endTime = time + this.dstSavings;
+ else
+ // Convert from UTC to DST
+ this.endTime = time + this.rawOffset + this.dstSavings;
+ useDaylight = true;
+ }
+
+ /**
+ * Sets the daylight savings end rule. You must also set the
+ * start rule with <code>setStartRule</code> or the result of
+ * getOffset is undefined. For the parameters see the ten-argument
+ * constructor above.
+ *
+ * Note that this API isn't incredibly well specified. It appears that the
+ * after flag must override the parameters, since normally, the day and
+ * dayofweek can select this. I.e., if day < 0 and dayOfWeek < 0, on or
+ * before mode is chosen. But if after == true, this implementation
+ * overrides the signs of the other arguments. And if dayOfWeek == 0, it
+ * falls back to the behavior in the other APIs. I guess this should be
+ * checked against Sun's implementation.
+ *
+ * @param month The end month of daylight savings.
+ * @param day A day in month, or a day of week in month.
+ * @param dayOfWeek A day of week, when daylight savings ends.
+ * @param time A time in millis in standard time.
+ * @param after If true, day and dayOfWeek specify first day of week on or
+ * after day, else first day of week on or before.
+ * @since 1.2
+ * @see #setStartRule(int, int, int, int, boolean)
+ */
+ public void setEndRule(int month, int day, int dayOfWeek, int time,
+ boolean after)
+ {
+ // FIXME: XXX: Validate that checkRule and offset processing work with on
+ // or before mode.
+ this.endDay = after ? Math.abs(day) : -Math.abs(day);
+ this.endDayOfWeek = after ? Math.abs(dayOfWeek) : -Math.abs(dayOfWeek);
+ this.endMode = (dayOfWeek != 0)
+ ? (after ? DOW_GE_DOM_MODE : DOW_LE_DOM_MODE)
+ : checkRule(month, day, dayOfWeek);
+ this.endDay = Math.abs(this.endDay);
+ this.endDayOfWeek = Math.abs(endDayOfWeek);
+
+ this.endMonth = month;
+
+ if (this.endTimeMode == WALL_TIME)
+ this.endTime = time;
+ else if (this.endTimeMode == STANDARD_TIME)
+ // Convert from STANDARD to DST
+ this.endTime = time + this.dstSavings;
+ else
+ // Convert from UTC to DST
+ this.endTime = time + this.rawOffset + this.dstSavings;
+ useDaylight = true;
+ }
+
+ /**
+ * Sets the daylight savings end rule. You must also set the
+ * start rule with <code>setStartRule</code> or the result of
+ * getOffset is undefined. For the parameters see the ten-argument
+ * constructor above.
+ *
+ * @param month The end month of daylight savings.
+ * @param day A day in month, or a day of week in month.
+ * @param time A time in millis in standard time.
+ * @see #setStartRule(int, int, int)
+ */
+ public void setEndRule(int month, int day, int time)
+ {
+ setEndRule(month, day, 0, time);
+ }
+
+ /**
+ * Gets the time zone offset, for current date, modified in case of
+ * daylight savings. This is the offset to add to UTC to get the local
+ * time.
+ *
+ * In the standard JDK the results given by this method may result in
+ * inaccurate results at the end of February or the beginning of March.
+ * To avoid this, you should use Calendar instead:
+ * <code>offset = cal.get(Calendar.ZONE_OFFSET)
+ * + cal.get(Calendar.DST_OFFSET);</code>
+ *
+ * This version doesn't suffer this inaccuracy.
+ *
+ * The arguments don't follow the approach for setting start and end rules.
+ * The day must be a positive number and dayOfWeek must be a positive value
+ * from Calendar. dayOfWeek is redundant, but must match the other values
+ * or an inaccurate result may be returned.
+ *
+ * @param era the era of the given date
+ * @param year the year of the given date
+ * @param month the month of the given date, 0 for January.
+ * @param day the day of month
+ * @param dayOfWeek the day of week; this must match the other fields.
+ * @param millis the millis in the day (in local standard time)
+ * @return the time zone offset in milliseconds.
+ * @throws IllegalArgumentException if arguments are incorrect.
+ */
+ public int getOffset(int era, int year, int month, int day, int dayOfWeek,
+ int millis)
+ {
+ int daysInMonth = getDaysInMonth(month, year);
+ if (day < 1 || day > daysInMonth)
+ throw new IllegalArgumentException("day out of range");
+ if (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY)
+ throw new IllegalArgumentException("dayOfWeek out of range");
+ if (month < Calendar.JANUARY || month > Calendar.DECEMBER)
+ throw new IllegalArgumentException("month out of range:" + month);
+
+ // This method is called by Calendar, so we mustn't use that class.
+ int daylightSavings = 0;
+ if (useDaylight && era == GregorianCalendar.AD && year >= startYear)
+ {
+ // This does only work for Gregorian calendars :-(
+ // This is mainly because setStartYear doesn't take an era.
+ boolean afterStart = ! isBefore(year, month, day, dayOfWeek, millis,
+ startMode, startMonth, startDay,
+ startDayOfWeek, startTime);
+ boolean beforeEnd = isBefore(year, month, day, dayOfWeek,
+ millis + dstSavings,
+ endMode, endMonth, endDay, endDayOfWeek,
+ endTime);
+
+ if (startMonth < endMonth)
+ // use daylight savings, if the date is after the start of
+ // savings, and before the end of savings.
+ daylightSavings = afterStart && beforeEnd ? dstSavings : 0;
+ else
+ // use daylight savings, if the date is before the end of
+ // savings, or after the start of savings.
+ daylightSavings = beforeEnd || afterStart ? dstSavings : 0;
+ }
+ return rawOffset + daylightSavings;
+ }
+
+ /**
+ * Returns the time zone offset to GMT in milliseconds, ignoring
+ * day light savings.
+ * @return the time zone offset.
+ */
+ public int getRawOffset()
+ {
+ return rawOffset;
+ }
+
+ /**
+ * Sets the standard time zone offset to GMT.
+ * @param rawOffset The time offset from GMT in milliseconds.
+ */
+ public void setRawOffset(int rawOffset)
+ {
+ this.rawOffset = rawOffset;
+ }
+
+ /**
+ * Gets the daylight savings offset. This is a positive offset in
+ * milliseconds with respect to standard time. Typically this
+ * is one hour, but for some time zones this may be half an our.
+ * @return the daylight savings offset in milliseconds.
+ *
+ * @since 1.2
+ */
+ public int getDSTSavings()
+ {
+ return dstSavings;
+ }
+
+ /**
+ * Sets the daylight savings offset. This is a positive offset in
+ * milliseconds with respect to standard time.
+ *
+ * @param dstSavings the daylight savings offset in milliseconds.
+ *
+ * @since 1.2
+ */
+ public void setDSTSavings(int dstSavings)
+ {
+ if (dstSavings <= 0)
+ throw new IllegalArgumentException("illegal value for dstSavings");
+
+ this.dstSavings = dstSavings;
+ }
+
+ /**
+ * Returns if this time zone uses daylight savings time.
+ * @return true, if we use daylight savings time, false otherwise.
+ */
+ public boolean useDaylightTime()
+ {
+ return useDaylight;
+ }
+
+ /**
+ * Returns the number of days in the given month.
+ * Uses gregorian rules prior to 1582 (The default and earliest cutover)
+ * @param month The month, zero based; use one of the Calendar constants.
+ * @param year The year.
+ */
+ private int getDaysInMonth(int month, int year)
+ {
+ if (month == Calendar.FEBRUARY)
+ {
+ if ((year & 3) != 0)
+ return 28;
+
+ // Assume default Gregorian cutover,
+ // all years prior to this must be Julian
+ if (year < 1582)
+ return 29;
+
+ // Gregorian rules
+ return ((year % 100) != 0 || (year % 400) == 0) ? 29 : 28;
+ }
+ else
+ return monthArr[month];
+ }
+
+ /**
+ * Checks if the date given in calXXXX, is before the change between
+ * dst and standard time.
+ * @param calYear the year of the date to check (for leap day checking).
+ * @param calMonth the month of the date to check.
+ * @param calDay the day of month of the date to check.
+ * @param calDayOfWeek the day of week of the date to check.
+ * @param calMillis the millis of day of the date to check (standard time).
+ * @param mode the change mode; same semantic as startMode.
+ * @param month the change month; same semantic as startMonth.
+ * @param day the change day; same semantic as startDay.
+ * @param dayOfWeek the change day of week;
+ * @param millis the change time in millis since midnight standard time.
+ * same semantic as startDayOfWeek.
+ * @return true, if cal is before the change, false if cal is on
+ * or after the change.
+ */
+ private boolean isBefore(int calYear, int calMonth, int calDayOfMonth,
+ int calDayOfWeek, int calMillis, int mode,
+ int month, int day, int dayOfWeek, int millis)
+ {
+ // This method is called by Calendar, so we mustn't use that class.
+ // We have to do all calculations by hand.
+ // check the months:
+ // XXX - this is not correct:
+ // for the DOW_GE_DOM and DOW_LE_DOM modes the change date may
+ // be in a different month.
+ if (calMonth != month)
+ return calMonth < month;
+
+ // check the day:
+ switch (mode)
+ {
+ case DOM_MODE:
+ if (calDayOfMonth != day)
+ return calDayOfMonth < day;
+ break;
+ case DOW_IN_MONTH_MODE:
+ {
+ // This computes the day of month of the day of type
+ // "dayOfWeek" that lies in the same (sunday based) week as cal.
+ calDayOfMonth += (dayOfWeek - calDayOfWeek);
+
+ // Now we convert it to 7 based number (to get a one based offset
+ // after dividing by 7). If we count from the end of the
+ // month, we get want a -7 based number counting the days from
+ // the end:
+ if (day < 0)
+ calDayOfMonth -= getDaysInMonth(calMonth, calYear) + 7;
+ else
+ calDayOfMonth += 6;
+
+ // day > 0 day < 0
+ // S M T W T F S S M T W T F S
+ // 7 8 9 10 11 12 -36-35-34-33-32-31
+ // 13 14 15 16 17 18 19 -30-29-28-27-26-25-24
+ // 20 21 22 23 24 25 26 -23-22-21-20-19-18-17
+ // 27 28 29 30 31 32 33 -16-15-14-13-12-11-10
+ // 34 35 36 -9 -8 -7
+ // Now we calculate the day of week in month:
+ int week = calDayOfMonth / 7;
+
+ // day > 0 day < 0
+ // S M T W T F S S M T W T F S
+ // 1 1 1 1 1 1 -5 -5 -4 -4 -4 -4
+ // 1 2 2 2 2 2 2 -4 -4 -4 -3 -3 -3 -3
+ // 2 3 3 3 3 3 3 -3 -3 -3 -2 -2 -2 -2
+ // 3 4 4 4 4 4 4 -2 -2 -2 -1 -1 -1 -1
+ // 4 5 5 -1 -1 -1
+ if (week != day)
+ return week < day;
+
+ if (calDayOfWeek != dayOfWeek)
+ return calDayOfWeek < dayOfWeek;
+
+ // daylight savings starts/ends on the given day.
+ break;
+ }
+ case DOW_LE_DOM_MODE:
+ // The greatest sunday before or equal December, 12
+ // is the same as smallest sunday after or equal December, 6.
+ day = Math.abs(day) - 6;
+ case DOW_GE_DOM_MODE:
+ // Calculate the day of month of the day of type
+ // "dayOfWeek" that lies before (or on) the given date.
+ calDayOfMonth -= (calDayOfWeek < dayOfWeek ? 7 : 0) + calDayOfWeek
+ - dayOfWeek;
+ if (calDayOfMonth < day)
+ return true;
+ if (calDayOfWeek != dayOfWeek || calDayOfMonth >= day + 7)
+ return false;
+
+ // now we have the same day
+ break;
+ }
+
+ // the millis decides:
+ return (calMillis < millis);
+ }
+
+ /**
+ * Determines if the given date is in daylight savings time.
+ * @return true, if it is in daylight savings time, false otherwise.
+ */
+ public boolean inDaylightTime(Date date)
+ {
+ Calendar cal = Calendar.getInstance(this);
+ cal.setTime(date);
+ return (cal.get(Calendar.DST_OFFSET) != 0);
+ }
+
+ /**
+ * Generates the hashCode for the SimpleDateFormat object. It is
+ * the rawOffset, possibly, if useDaylightSavings is true, xored
+ * with startYear, startMonth, startDayOfWeekInMonth, ..., endTime.
+ */
+ public synchronized int hashCode()
+ {
+ return rawOffset
+ ^ (useDaylight
+ ? startMonth ^ startDay ^ startDayOfWeek ^ startTime ^ endMonth
+ ^ endDay ^ endDayOfWeek ^ endTime : 0);
+ }
+
+ public synchronized boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (! (o instanceof SimpleTimeZone))
+ return false;
+ SimpleTimeZone zone = (SimpleTimeZone) o;
+ if (zone.hashCode() != hashCode() || ! getID().equals(zone.getID())
+ || rawOffset != zone.rawOffset || useDaylight != zone.useDaylight)
+ return false;
+ if (! useDaylight)
+ return true;
+ return (startYear == zone.startYear && startMonth == zone.startMonth
+ && startDay == zone.startDay
+ && startDayOfWeek == zone.startDayOfWeek
+ && startTime == zone.startTime
+ && startTimeMode == zone.startTimeMode && endMonth == zone.endMonth
+ && endDay == zone.endDay && endDayOfWeek == zone.endDayOfWeek
+ && endTime == zone.endTime && endTimeMode == zone.endTimeMode);
+ }
+
+ /**
+ * Test if the other time zone uses the same rule and only
+ * possibly differs in ID. This implementation for this particular
+ * class will return true if the other object is a SimpleTimeZone,
+ * the raw offsets and useDaylight are identical and if useDaylight
+ * is true, also the start and end datas are identical.
+ * @return true if this zone uses the same rule.
+ */
+ public boolean hasSameRules(TimeZone other)
+ {
+ if (this == other)
+ return true;
+ if (! (other instanceof SimpleTimeZone))
+ return false;
+ SimpleTimeZone zone = (SimpleTimeZone) other;
+ if (zone.hashCode() != hashCode() || rawOffset != zone.rawOffset
+ || useDaylight != zone.useDaylight)
+ return false;
+ if (! useDaylight)
+ return true;
+ return (startYear == zone.startYear && startMonth == zone.startMonth
+ && startDay == zone.startDay
+ && startDayOfWeek == zone.startDayOfWeek
+ && startTime == zone.startTime
+ && startTimeMode == zone.startTimeMode && endMonth == zone.endMonth
+ && endDay == zone.endDay && endDayOfWeek == zone.endDayOfWeek
+ && endTime == zone.endTime && endTimeMode == zone.endTimeMode);
+ }
+
+ /**
+ * Returns a string representation of this SimpleTimeZone object.
+ * @return a string representation of this SimpleTimeZone object.
+ */
+ public String toString()
+ {
+ // the test for useDaylight is an incompatibility to jdk1.2, but
+ // I think this shouldn't hurt.
+ return getClass().getName() + "[" + "id=" + getID() + ",offset="
+ + rawOffset + ",dstSavings=" + dstSavings + ",useDaylight="
+ + useDaylight
+ + (useDaylight
+ ? ",startYear=" + startYear + ",startMode=" + startMode
+ + ",startMonth=" + startMonth + ",startDay=" + startDay
+ + ",startDayOfWeek=" + startDayOfWeek + ",startTime="
+ + startTime + ",startTimeMode=" + startTimeMode + ",endMode="
+ + endMode + ",endMonth=" + endMonth + ",endDay=" + endDay
+ + ",endDayOfWeek=" + endDayOfWeek + ",endTime=" + endTime
+ + ",endTimeMode=" + endTimeMode : "") + "]";
+ }
+
+ /**
+ * Reads a serialized simple time zone from stream.
+ * @see #writeObject
+ */
+ private void readObject(java.io.ObjectInputStream input)
+ throws java.io.IOException, ClassNotFoundException
+ {
+ input.defaultReadObject();
+ if (serialVersionOnStream == 0)
+ {
+ // initialize the new fields to default values.
+ dstSavings = 60 * 60 * 1000;
+ endMode = DOW_IN_MONTH_MODE;
+ startMode = DOW_IN_MONTH_MODE;
+ startTimeMode = WALL_TIME;
+ endTimeMode = WALL_TIME;
+ serialVersionOnStream = 2;
+ }
+ else
+ {
+ int length = input.readInt();
+ byte[] byteArray = new byte[length];
+ input.read(byteArray, 0, length);
+ if (length >= 4)
+ {
+ // Lets hope that Sun does extensions to the serialized
+ // form in a sane manner.
+ startDay = byteArray[0];
+ startDayOfWeek = byteArray[1];
+ endDay = byteArray[2];
+ endDayOfWeek = byteArray[3];
+ }
+ }
+ }
+
+ /**
+ * Serializes this object to a stream. @serialdata The object is
+ * first written in the old JDK 1.1 format, so that it can be read
+ * by by the old classes. This means, that the
+ * <code>start/endDay(OfWeek)</code>-Fields are written in the
+ * DOW_IN_MONTH_MODE rule, since this was the only supported rule
+ * in 1.1.
+ *
+ * In the optional section, we write first the length of an byte
+ * array as int and afterwards the byte array itself. The byte
+ * array contains in this release four elements, namely the real
+ * startDay, startDayOfWeek endDay, endDayOfWeek in that Order.
+ * These fields are needed, because for compatibility reasons only
+ * approximative values are written to the required section, as
+ * described above.
+ */
+ private void writeObject(java.io.ObjectOutputStream output)
+ throws java.io.IOException
+ {
+ byte[] byteArray = new byte[]
+ {
+ (byte) startDay, (byte) startDayOfWeek, (byte) endDay,
+ (byte) endDayOfWeek
+ };
+
+ /* calculate the approximation for JDK 1.1 */
+ switch (startMode)
+ {
+ case DOM_MODE:
+ startDayOfWeek = Calendar.SUNDAY; // random day of week
+
+ // fall through
+ case DOW_GE_DOM_MODE:
+ case DOW_LE_DOM_MODE:
+ startDay = (startDay + 6) / 7;
+ }
+ switch (endMode)
+ {
+ case DOM_MODE:
+ endDayOfWeek = Calendar.SUNDAY;
+
+ // fall through
+ case DOW_GE_DOM_MODE:
+ case DOW_LE_DOM_MODE:
+ endDay = (endDay + 6) / 7;
+ }
+
+ // the required part:
+ output.defaultWriteObject();
+ // the optional part:
+ output.writeInt(byteArray.length);
+ output.write(byteArray, 0, byteArray.length);
+ }
+}
diff --git a/libjava/classpath/java/util/SortedMap.java b/libjava/classpath/java/util/SortedMap.java
new file mode 100644
index 00000000000..acfbd0d3639
--- /dev/null
+++ b/libjava/classpath/java/util/SortedMap.java
@@ -0,0 +1,173 @@
+/* SortedMap.java -- A map that makes guarantees about the order of its keys
+ Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A map which guarantees its key's iteration order. The entries in the
+ * map are related by the <i>natural ordering</i> of the keys if they
+ * are Comparable, or by the provided Comparator. Additional operations
+ * take advantage of the sorted nature of the map.
+ * <p>
+ *
+ * All keys entered in the map must be mutually comparable; in other words,
+ * <code>k1.compareTo(k2)</code> or <code>comparator.compare(k1, k2)</code>
+ * must not throw a ClassCastException. The ordering must be <i>consistent
+ * with equals</i> (see {@link Comparator} for this definition), if the
+ * map is to obey the general contract of the Map interface. If not,
+ * the results are well-defined, but probably not what you wanted.
+ * <p>
+ *
+ * It is recommended that all implementing classes provide four constructors:
+ * 1) one that takes no arguments and builds an empty map sorted by natural
+ * order of the keys; 2) one that takes a Comparator for the sorting order;
+ * 3) one that takes a Map and sorts according to the natural order of its
+ * keys; and 4) one that takes a SortedMap and sorts by the same comparator.
+ * Unfortunately, the Java language does not provide a way to enforce this.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Map
+ * @see TreeMap
+ * @see SortedSet
+ * @see Comparable
+ * @see Comparator
+ * @see Collection
+ * @see ClassCastException
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface SortedMap extends Map
+{
+ /**
+ * Returns the comparator used in sorting this map, or null if it is
+ * the keys' natural ordering.
+ *
+ * @return the sorting comparator
+ */
+ Comparator comparator();
+
+ /**
+ * Returns the first (lowest sorted) key in the map.
+ *
+ * @return the first key
+ * @throws NoSuchElementException if this map is empty.
+ */
+ Object firstKey();
+
+ /**
+ * Returns a view of the portion of the map strictly less than toKey. The
+ * view is backed by this map, so changes in one show up in the other.
+ * The submap supports all optional operations of the original.
+ * <p>
+ *
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of toKey. Note that the endpoint, toKey,
+ * is not included; if you want this value to be included, pass its successor
+ * object in to toKey. For example, for Integers, you could request
+ * <code>headMap(new Integer(limit.intValue() + 1))</code>.
+ *
+ * @param toKey the exclusive upper range of the submap
+ * @return the submap
+ * @throws ClassCastException if toKey is not comparable to the map contents
+ * @throws IllegalArgumentException if this is a subMap, and toKey is out
+ * of range
+ * @throws NullPointerException if toKey is null but the map does not allow
+ * null keys
+ */
+ SortedMap headMap(Object toKey);
+
+ /**
+ * Returns the last (highest sorted) key in the map.
+ *
+ * @return the last key
+ * @throws NoSuchElementException if this map is empty.
+ */
+ Object lastKey();
+
+ /**
+ * Returns a view of the portion of the map greater than or equal to
+ * fromKey, and strictly less than toKey. The view is backed by this map,
+ * so changes in one show up in the other. The submap supports all
+ * optional operations of the original.
+ * <p>
+ *
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of fromKey and toKey. Note that the
+ * lower endpoint is included, but the upper is not; if you want to
+ * change the inclusion or exclusion of an endpoint, pass its successor
+ * object in instead. For example, for Integers, you could request
+ * <code>subMap(new Integer(lowlimit.intValue() + 1),
+ * new Integer(highlimit.intValue() + 1))</code> to reverse
+ * the inclusiveness of both endpoints.
+ *
+ * @param fromKey the inclusive lower range of the submap
+ * @param toKey the exclusive upper range of the submap
+ * @return the submap
+ * @throws ClassCastException if fromKey or toKey is not comparable to
+ * the map contents
+ * @throws IllegalArgumentException if this is a subMap, and fromKey or
+ * toKey is out of range
+ * @throws NullPointerException if fromKey or toKey is null but the map
+ * does not allow null keys
+ */
+ SortedMap subMap(Object fromKey, Object toKey);
+
+ /**
+ * Returns a view of the portion of the map greater than or equal to
+ * fromKey. The view is backed by this map, so changes in one show up
+ * in the other. The submap supports all optional operations of the original.
+ * <p>
+ *
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of fromKey. Note that the endpoint, fromKey, is
+ * included; if you do not want this value to be included, pass its successor object in
+ * to fromKey. For example, for Integers, you could request
+ * <code>tailMap(new Integer(limit.intValue() + 1))</code>.
+ *
+ * @param fromKey the inclusive lower range of the submap
+ * @return the submap
+ * @throws ClassCastException if fromKey is not comparable to the map
+ * contents
+ * @throws IllegalArgumentException if this is a subMap, and fromKey is out
+ * of range
+ * @throws NullPointerException if fromKey is null but the map does not allow
+ * null keys
+ */
+ SortedMap tailMap(Object fromKey);
+}
diff --git a/libjava/classpath/java/util/SortedSet.java b/libjava/classpath/java/util/SortedSet.java
new file mode 100644
index 00000000000..48a24a8e0f9
--- /dev/null
+++ b/libjava/classpath/java/util/SortedSet.java
@@ -0,0 +1,176 @@
+/* SortedSet.java -- A set that makes guarantees about the order of its
+ elements
+ Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A set which guarantees its iteration order. The elements in the set
+ * are related by the <i>natural ordering</i> if they are Comparable, or
+ * by the provided Comparator. Additional operations take advantage of
+ * the sorted nature of the set.
+ * <p>
+ *
+ * All elements entered in the set must be mutually comparable; in other words,
+ * <code>k1.compareTo(k2)</code> or <code>comparator.compare(k1, k2)</code>
+ * must not throw a ClassCastException. The ordering must be <i>consistent
+ * with equals</i> (see {@link Comparator} for this definition), if the
+ * set is to obey the general contract of the Set interface. If not,
+ * the results are well-defined, but probably not what you wanted.
+ * <p>
+ *
+ * It is recommended that all implementing classes provide four constructors:
+ * 1) one that takes no arguments and builds an empty set sorted by natural
+ * order of the elements; 2) one that takes a Comparator for the sorting order;
+ * 3) one that takes a Set and sorts according to the natural order of its
+ * elements; and 4) one that takes a SortedSet and sorts by the same
+ * comparator. Unfortunately, the Java language does not provide a way to
+ * enforce this.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Set
+ * @see TreeSet
+ * @see SortedMap
+ * @see Collection
+ * @see Comparable
+ * @see Comparator
+ * @see ClassCastException
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface SortedSet extends Set
+{
+ /**
+ * Returns the comparator used in sorting this set, or null if it is
+ * the elements' natural ordering.
+ *
+ * @return the sorting comparator
+ */
+ Comparator comparator();
+
+ /**
+ * Returns the first (lowest sorted) element in the set.
+ *
+ * @return the first element
+ * @throws NoSuchElementException if the set is empty.
+ */
+ Object first();
+
+ /**
+ * Returns a view of the portion of the set strictly less than toElement. The
+ * view is backed by this set, so changes in one show up in the other.
+ * The subset supports all optional operations of the original.
+ * <p>
+ *
+ * The returned set throws an IllegalArgumentException any time an element is
+ * used which is out of the range of toElement. Note that the endpoint, toElement,
+ * is not included; if you want this value included, pass its successor object in to
+ * toElement. For example, for Integers, you could request
+ * <code>headSet(new Integer(limit.intValue() + 1))</code>.
+ *
+ * @param toElement the exclusive upper range of the subset
+ * @return the subset
+ * @throws ClassCastException if toElement is not comparable to the set
+ * contents
+ * @throws IllegalArgumentException if this is a subSet, and toElement is out
+ * of range
+ * @throws NullPointerException if toElement is null but the set does not
+ * allow null elements
+ */
+ SortedSet headSet(Object toElement);
+
+ /**
+ * Returns the last (highest sorted) element in the set.
+ *
+ * @return the last element
+ * @throws NoSuchElementException if the set is empty.
+ */
+ Object last();
+
+ /**
+ * Returns a view of the portion of the set greater than or equal to
+ * fromElement, and strictly less than toElement. The view is backed by
+ * this set, so changes in one show up in the other. The subset supports all
+ * optional operations of the original.
+ * <p>
+ *
+ * The returned set throws an IllegalArgumentException any time an element is
+ * used which is out of the range of fromElement and toElement. Note that the
+ * lower endpoint is included, but the upper is not; if you want to
+ * change the inclusion or exclusion of an endpoint, pass its successor
+ * object in instead. For example, for Integers, you can request
+ * <code>subSet(new Integer(lowlimit.intValue() + 1),
+ * new Integer(highlimit.intValue() + 1))</code> to reverse
+ * the inclusiveness of both endpoints.
+ *
+ * @param fromElement the inclusive lower range of the subset
+ * @param toElement the exclusive upper range of the subset
+ * @return the subset
+ * @throws ClassCastException if fromElement or toElement is not comparable
+ * to the set contents
+ * @throws IllegalArgumentException if this is a subSet, and fromElement or
+ * toElement is out of range
+ * @throws NullPointerException if fromElement or toElement is null but the
+ * set does not allow null elements
+ */
+ SortedSet subSet(Object fromElement, Object toElement);
+
+ /**
+ * Returns a view of the portion of the set greater than or equal to
+ * fromElement. The view is backed by this set, so changes in one show up
+ * in the other. The subset supports all optional operations of the original.
+ * <p>
+ *
+ * The returned set throws an IllegalArgumentException any time an element is
+ * used which is out of the range of fromElement. Note that the endpoint,
+ * fromElement, is included; if you do not want this value to be included, pass its
+ * successor object in to fromElement. For example, for Integers, you could request
+ * <code>tailSet(new Integer(limit.intValue() + 1))</code>.
+ *
+ * @param fromElement the inclusive lower range of the subset
+ * @return the subset
+ * @throws ClassCastException if fromElement is not comparable to the set
+ * contents
+ * @throws IllegalArgumentException if this is a subSet, and fromElement is
+ * out of range
+ * @throws NullPointerException if fromElement is null but the set does not
+ * allow null elements
+ */
+ SortedSet tailSet(Object fromElement);
+}
diff --git a/libjava/classpath/java/util/Stack.java b/libjava/classpath/java/util/Stack.java
new file mode 100644
index 00000000000..730ce177cd1
--- /dev/null
+++ b/libjava/classpath/java/util/Stack.java
@@ -0,0 +1,158 @@
+/* Stack.java - Class that provides a Last In First Out (LIFO)
+ datatype, known more commonly as a Stack
+ Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+
+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;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status: Believed complete and correct
+
+/**
+ * Stack provides a Last In First Out (LIFO) data type, commonly known
+ * as a Stack. Stack itself extends Vector and provides the additional
+ * methods for stack manipulation (push, pop, peek). You can also seek for
+ * the 1-based position of an element on the stack.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see List
+ * @see AbstractList
+ * @see LinkedList
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Stack extends Vector
+{
+ // We could use Vector methods internally for the following methods,
+ // but have used Vector fields directly for efficiency (i.e. this
+ // often reduces out duplicate bounds checking).
+
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 1224463164541339165L;
+
+ /**
+ * This constructor creates a new Stack, initially empty
+ */
+ public Stack()
+ {
+ }
+
+ /**
+ * Pushes an Object onto the top of the stack. This method is effectively
+ * the same as addElement(item).
+ *
+ * @param item the Object to push onto the stack
+ * @return the Object pushed onto the stack
+ * @see Vector#addElement(Object)
+ */
+ public Object push(Object item)
+ {
+ // When growing the Stack, use the Vector routines in case more
+ // memory is needed.
+ // Note: spec indicates that this method *always* returns obj passed in!
+
+ addElement(item);
+ return item;
+ }
+
+ /**
+ * Pops an item from the stack and returns it. The item popped is
+ * removed from the Stack.
+ *
+ * @return the Object popped from the stack
+ * @throws EmptyStackException if the stack is empty
+ */
+ public synchronized Object pop()
+ {
+ if (elementCount == 0)
+ throw new EmptyStackException();
+
+ modCount++;
+ Object obj = elementData[--elementCount];
+
+ // Set topmost element to null to assist the gc in cleanup.
+ elementData[elementCount] = null;
+ return obj;
+ }
+
+ /**
+ * Returns the top Object on the stack without removing it.
+ *
+ * @return the top Object on the stack
+ * @throws EmptyStackException if the stack is empty
+ */
+ public synchronized Object peek()
+ {
+ if (elementCount == 0)
+ throw new EmptyStackException();
+
+ return elementData[elementCount - 1];
+ }
+
+ /**
+ * Tests if the stack is empty.
+ *
+ * @return true if the stack contains no items, false otherwise
+ */
+ public synchronized boolean empty()
+ {
+ return elementCount == 0;
+ }
+
+ /**
+ * Returns the position of an Object on the stack, with the top
+ * most Object being at position 1, and each Object deeper in the
+ * stack at depth + 1.
+ *
+ * @param o The object to search for
+ * @return The 1 based depth of the Object, or -1 if the Object
+ * is not on the stack
+ */
+ public synchronized int search(Object o)
+ {
+ int i = elementCount;
+ while (--i >= 0)
+ if (equals(o, elementData[i]))
+ return elementCount - i;
+ return -1;
+ }
+}
diff --git a/libjava/classpath/java/util/StringTokenizer.java b/libjava/classpath/java/util/StringTokenizer.java
new file mode 100644
index 00000000000..dcc192c855a
--- /dev/null
+++ b/libjava/classpath/java/util/StringTokenizer.java
@@ -0,0 +1,268 @@
+/* StringTokenizer -- breaks a String into tokens
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This class splits a string into tokens. The caller can set on which
+ * delimiters the string should be split and if the delimiters should be
+ * returned. This is much simpler than {@link java.io.StreamTokenizer}.
+ *
+ * <p>You may change the delimiter set on the fly by calling
+ * nextToken(String). But the semantic is quite difficult; it even
+ * depends on calling <code>hasMoreTokens()</code>. You should call
+ * <code>hasMoreTokens()</code> before, otherwise the old delimiters
+ * after the last token are candidates for being returned.
+ *
+ * <p>If you want to get the delimiters, you have to use the three argument
+ * constructor. The delimiters are returned as token consisting of a
+ * single character.
+ *
+ * @author Jochen Hoenicke
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see java.io.StreamTokenizer
+ * @status updated to 1.4
+ */
+public class StringTokenizer implements Enumeration
+{
+ // WARNING: StringTokenizer is a CORE class in the bootstrap cycle. See the
+ // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+ /**
+ * The position in the str, where we currently are.
+ */
+ private int pos;
+
+ /**
+ * The string that should be split into tokens.
+ */
+ private final String str;
+
+ /**
+ * The length of the string.
+ */
+ private final int len;
+
+ /**
+ * The string containing the delimiter characters.
+ */
+ private String delim;
+
+ /**
+ * Tells, if we should return the delimiters.
+ */
+ private final boolean retDelims;
+
+ /**
+ * Creates a new StringTokenizer for the string <code>str</code>,
+ * that should split on the default delimiter set (space, tab,
+ * newline, return and formfeed), and which doesn't return the
+ * delimiters.
+ *
+ * @param str The string to split
+ * @throws NullPointerException if str is null
+ */
+ public StringTokenizer(String str)
+ {
+ this(str, " \t\n\r\f", false);
+ }
+
+ /**
+ * Create a new StringTokenizer, that splits the given string on
+ * the given delimiter characters. It doesn't return the delimiter
+ * characters.
+ *
+ * @param str the string to split
+ * @param delim a string containing all delimiter characters
+ * @throws NullPointerException if either argument is null
+ */
+ public StringTokenizer(String str, String delim)
+ {
+ this(str, delim, false);
+ }
+
+ /**
+ * Create a new StringTokenizer, that splits the given string on
+ * the given delimiter characters. If you set
+ * <code>returnDelims</code> to <code>true</code>, the delimiter
+ * characters are returned as tokens of their own. The delimiter
+ * tokens always consist of a single character.
+ *
+ * @param str the string to split
+ * @param delim a string containing all delimiter characters
+ * @param returnDelims tells, if you want to get the delimiters
+ * @throws NullPointerException if str or delim is null
+ */
+ public StringTokenizer(String str, String delim, boolean returnDelims)
+ {
+ len = str.length();
+ this.str = str;
+ // The toString() hack causes the NullPointerException.
+ this.delim = delim.toString();
+ this.retDelims = returnDelims;
+ this.pos = 0;
+ }
+
+ /**
+ * Tells if there are more tokens.
+ *
+ * @return true if the next call of nextToken() will succeed
+ */
+ public boolean hasMoreTokens()
+ {
+ if (! retDelims)
+ {
+ while (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
+ pos++;
+ }
+ return pos < len;
+ }
+
+ /**
+ * Returns the nextToken, changing the delimiter set to the given
+ * <code>delim</code>. The change of the delimiter set is
+ * permanent, ie. the next call of nextToken(), uses the same
+ * delimiter set.
+ *
+ * @param delim a string containing the new delimiter characters
+ * @return the next token with respect to the new delimiter characters
+ * @throws NoSuchElementException if there are no more tokens
+ * @throws NullPointerException if delim is null
+ */
+ public String nextToken(String delim) throws NoSuchElementException
+ {
+ this.delim = delim;
+ return nextToken();
+ }
+
+ /**
+ * Returns the nextToken of the string.
+ *
+ * @return the next token with respect to the current delimiter characters
+ * @throws NoSuchElementException if there are no more tokens
+ */
+ public String nextToken() throws NoSuchElementException
+ {
+ if (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
+ {
+ if (retDelims)
+ return str.substring(pos, ++pos);
+ while (++pos < len && delim.indexOf(str.charAt(pos)) >= 0);
+ }
+ if (pos < len)
+ {
+ int start = pos;
+ while (++pos < len && delim.indexOf(str.charAt(pos)) < 0);
+
+ return str.substring(start, pos);
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * This does the same as hasMoreTokens. This is the
+ * <code>Enumeration</code> interface method.
+ *
+ * @return true, if the next call of nextElement() will succeed
+ * @see #hasMoreTokens()
+ */
+ public boolean hasMoreElements()
+ {
+ return hasMoreTokens();
+ }
+
+ /**
+ * This does the same as nextTokens. This is the
+ * <code>Enumeration</code> interface method.
+ *
+ * @return the next token with respect to the current delimiter characters
+ * @throws NoSuchElementException if there are no more tokens
+ * @see #nextToken()
+ */
+ public Object nextElement() throws NoSuchElementException
+ {
+ return nextToken();
+ }
+
+ /**
+ * This counts the number of remaining tokens in the string, with
+ * respect to the current delimiter set.
+ *
+ * @return the number of times <code>nextTokens()</code> will succeed
+ * @see #nextToken()
+ */
+ public int countTokens()
+ {
+ int count = 0;
+ int delimiterCount = 0;
+ boolean tokenFound = false; // Set when a non-delimiter is found
+ int tmpPos = pos;
+
+ // Note for efficiency, we count up the delimiters rather than check
+ // retDelims every time we encounter one. That way, we can
+ // just do the conditional once at the end of the method
+ while (tmpPos < len)
+ {
+ if (delim.indexOf(str.charAt(tmpPos++)) >= 0)
+ {
+ if (tokenFound)
+ {
+ // Got to the end of a token
+ count++;
+ tokenFound = false;
+ }
+ delimiterCount++; // Increment for this delimiter
+ }
+ else
+ {
+ tokenFound = true;
+ // Get to the end of the token
+ while (tmpPos < len
+ && delim.indexOf(str.charAt(tmpPos)) < 0)
+ ++tmpPos;
+ }
+ }
+
+ // Make sure to count the last token
+ if (tokenFound)
+ count++;
+
+ // if counting delmiters add them into the token count
+ return retDelims ? count + delimiterCount : count;
+ }
+} // class StringTokenizer
diff --git a/libjava/classpath/java/util/TimeZone.java b/libjava/classpath/java/util/TimeZone.java
new file mode 100644
index 00000000000..99df11df5f9
--- /dev/null
+++ b/libjava/classpath/java/util/TimeZone.java
@@ -0,0 +1,1523 @@
+/* java.util.TimeZone
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.DateFormatSymbols;
+
+/**
+ * This class represents a time zone offset and handles daylight savings.
+ *
+ * You can get the default time zone with <code>getDefault</code>.
+ * This represents the time zone where program is running.
+ *
+ * Another way to create a time zone is <code>getTimeZone</code>, where
+ * you can give an identifier as parameter. For instance, the identifier
+ * of the Central European Time zone is "CET".
+ *
+ * With the <code>getAvailableIDs</code> method, you can get all the
+ * supported time zone identifiers.
+ *
+ * @see Calendar
+ * @see SimpleTimeZone
+ * @author Jochen Hoenicke
+ */
+public abstract class TimeZone implements java.io.Serializable, Cloneable
+{
+
+ /**
+ * Constant used to indicate that a short timezone abbreviation should
+ * be returned, such as "EST"
+ */
+ public static final int SHORT = 0;
+
+ /**
+ * Constant used to indicate that a long timezone name should be
+ * returned, such as "Eastern Standard Time".
+ */
+ public static final int LONG = 1;
+
+ /**
+ * The time zone identifier, e.g. PST.
+ */
+ private String ID;
+
+ /**
+ * The default time zone, as returned by getDefault.
+ */
+ private static TimeZone defaultZone0;
+
+ /**
+ * Tries to get the default TimeZone for this system if not already
+ * set. It will call <code>getDefaultTimeZone(String)</code> with
+ * the result of <code>System.getProperty("user.timezone")</code>.
+ * If that fails it calls <code>VMTimeZone.getDefaultTimeZoneId()</code>.
+ * If that also fails GMT is returned.
+ */
+ private static synchronized TimeZone defaultZone()
+ {
+ /* Look up default timezone */
+ if (defaultZone0 == null)
+ {
+ defaultZone0 = (TimeZone) AccessController.doPrivileged
+ (new PrivilegedAction()
+ {
+ public Object run()
+ {
+ TimeZone zone = null;
+
+ // Prefer System property user.timezone.
+ String tzid = System.getProperty("user.timezone");
+ if (tzid != null && !tzid.equals(""))
+ zone = getDefaultTimeZone(tzid);
+
+ // Try platfom specific way.
+ if (zone == null)
+ zone = VMTimeZone.getDefaultTimeZoneId();
+
+ // Fall back on GMT.
+ if (zone == null)
+ zone = (TimeZone) timezones().get("GMT");
+
+ return zone;
+ }
+ });
+ }
+
+ return defaultZone0;
+ }
+
+ private static final long serialVersionUID = 3581463369166924961L;
+
+ /**
+ * HashMap for timezones by ID.
+ */
+ private static HashMap timezones0;
+ /* initialize this static field lazily to overhead if
+ * it is not needed:
+ */
+ // Package-private to avoid a trampoline.
+ static synchronized HashMap timezones()
+ {
+ if (timezones0 == null)
+ {
+ HashMap timezones = new HashMap();
+ timezones0 = timezones;
+
+ TimeZone tz;
+ // Automatically generated by scripts/timezones.pl
+ // XXX - Should we read this data from a file?
+ tz = new SimpleTimeZone(-11000 * 3600, "MIT");
+ timezones0.put("MIT", tz);
+ timezones0.put("Pacific/Apia", tz);
+ timezones0.put("Pacific/Midway", tz);
+ timezones0.put("Pacific/Niue", tz);
+ timezones0.put("Pacific/Pago_Pago", tz);
+ tz = new SimpleTimeZone
+ (-10000 * 3600, "America/Adak",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("America/Adak", tz);
+ tz = new SimpleTimeZone(-10000 * 3600, "HST");
+ timezones0.put("HST", tz);
+ timezones0.put("Pacific/Fakaofo", tz);
+ timezones0.put("Pacific/Honolulu", tz);
+ timezones0.put("Pacific/Johnston", tz);
+ timezones0.put("Pacific/Rarotonga", tz);
+ timezones0.put("Pacific/Tahiti", tz);
+ tz = new SimpleTimeZone(-9500 * 3600, "Pacific/Marquesas");
+ timezones0.put("Pacific/Marquesas", tz);
+ tz = new SimpleTimeZone
+ (-9000 * 3600, "AST",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("AST", tz);
+ timezones0.put("America/Anchorage", tz);
+ timezones0.put("America/Juneau", tz);
+ timezones0.put("America/Nome", tz);
+ timezones0.put("America/Yakutat", tz);
+ tz = new SimpleTimeZone(-9000 * 3600, "Pacific/Gambier");
+ timezones0.put("Pacific/Gambier", tz);
+ tz = new SimpleTimeZone
+ (-8000 * 3600, "PST",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("PST", tz);
+ timezones0.put("PST8PDT", tz);
+ timezones0.put("America/Dawson", tz);
+ timezones0.put("America/Los_Angeles", tz);
+ timezones0.put("America/Tijuana", tz);
+ timezones0.put("America/Vancouver", tz);
+ timezones0.put("America/Whitehorse", tz);
+ timezones0.put("US/Pacific-New", tz);
+ tz = new SimpleTimeZone(-8000 * 3600, "Pacific/Pitcairn");
+ timezones0.put("Pacific/Pitcairn", tz);
+ tz = new SimpleTimeZone
+ (-7000 * 3600, "MST",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("MST", tz);
+ timezones0.put("MST7MDT", tz);
+ timezones0.put("America/Boise", tz);
+ timezones0.put("America/Chihuahua", tz);
+ timezones0.put("America/Denver", tz);
+ timezones0.put("America/Edmonton", tz);
+ timezones0.put("America/Inuvik", tz);
+ timezones0.put("America/Mazatlan", tz);
+ timezones0.put("America/Shiprock", tz);
+ timezones0.put("America/Yellowknife", tz);
+ tz = new SimpleTimeZone(-7000 * 3600, "MST7");
+ timezones0.put("MST7", tz);
+ timezones0.put("PNT", tz);
+ timezones0.put("America/Dawson_Creek", tz);
+ timezones0.put("America/Hermosillo", tz);
+ timezones0.put("America/Phoenix", tz);
+ tz = new SimpleTimeZone
+ (-6000 * 3600, "CST",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("CST", tz);
+ timezones0.put("CST6CDT", tz);
+ timezones0.put("America/Cambridge_Bay", tz);
+ timezones0.put("America/Cancun", tz);
+ timezones0.put("America/Chicago", tz);
+ timezones0.put("America/Menominee", tz);
+ timezones0.put("America/Merida", tz);
+ timezones0.put("America/Mexico_City", tz);
+ timezones0.put("America/Monterrey", tz);
+ timezones0.put("America/Rainy_River", tz);
+ timezones0.put("America/Winnipeg", tz);
+ tz = new SimpleTimeZone(-6000 * 3600, "America/Belize");
+ timezones0.put("America/Belize", tz);
+ timezones0.put("America/Costa_Rica", tz);
+ timezones0.put("America/El_Salvador", tz);
+ timezones0.put("America/Guatemala", tz);
+ timezones0.put("America/Managua", tz);
+ timezones0.put("America/Regina", tz);
+ timezones0.put("America/Swift_Current", tz);
+ timezones0.put("America/Tegucigalpa", tz);
+ timezones0.put("Pacific/Galapagos", tz);
+ tz = new SimpleTimeZone
+ (-6000 * 3600, "Pacific/Easter",
+ Calendar.OCTOBER, 9, -Calendar.SUNDAY, 0 * 3600,
+ Calendar.MARCH, 9, -Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("Pacific/Easter", tz);
+ tz = new SimpleTimeZone
+ (-5000 * 3600, "America/Grand_Turk",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 0 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("America/Grand_Turk", tz);
+ timezones0.put("America/Havana", tz);
+ tz = new SimpleTimeZone(-5000 * 3600, "EST5");
+ timezones0.put("EST5", tz);
+ timezones0.put("IET", tz);
+ timezones0.put("America/Bogota", tz);
+ timezones0.put("America/Cayman", tz);
+ timezones0.put("America/Eirunepe", tz);
+ timezones0.put("America/Guayaquil", tz);
+ timezones0.put("America/Indiana/Indianapolis", tz);
+ timezones0.put("America/Indiana/Knox", tz);
+ timezones0.put("America/Indiana/Marengo", tz);
+ timezones0.put("America/Indiana/Vevay", tz);
+ timezones0.put("America/Indianapolis", tz);
+ timezones0.put("America/Iqaluit", tz);
+ timezones0.put("America/Jamaica", tz);
+ timezones0.put("America/Lima", tz);
+ timezones0.put("America/Panama", tz);
+ timezones0.put("America/Pangnirtung", tz);
+ timezones0.put("America/Port-au-Prince", tz);
+ timezones0.put("America/Porto_Acre", tz);
+ timezones0.put("America/Rankin_Inlet", tz);
+ tz = new SimpleTimeZone
+ (-5000 * 3600, "EST",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("EST", tz);
+ timezones0.put("EST5EDT", tz);
+ timezones0.put("America/Detroit", tz);
+ timezones0.put("America/Kentucky/Louisville", tz);
+ timezones0.put("America/Kentucky/Monticello", tz);
+ timezones0.put("America/Louisville", tz);
+ timezones0.put("America/Montreal", tz);
+ timezones0.put("America/Nassau", tz);
+ timezones0.put("America/New_York", tz);
+ timezones0.put("America/Nipigon", tz);
+ timezones0.put("America/Thunder_Bay", tz);
+ tz = new SimpleTimeZone(-4000 * 3600, "PRT");
+ timezones0.put("PRT", tz);
+ timezones0.put("America/Anguilla", tz);
+ timezones0.put("America/Antigua", tz);
+ timezones0.put("America/Aruba", tz);
+ timezones0.put("America/Barbados", tz);
+ timezones0.put("America/Boa_Vista", tz);
+ timezones0.put("America/Caracas", tz);
+ timezones0.put("America/Curacao", tz);
+ timezones0.put("America/Dominica", tz);
+ timezones0.put("America/Grenada", tz);
+ timezones0.put("America/Guadeloupe", tz);
+ timezones0.put("America/Guyana", tz);
+ timezones0.put("America/La_Paz", tz);
+ timezones0.put("America/Manaus", tz);
+ timezones0.put("America/Martinique", tz);
+ timezones0.put("America/Montserrat", tz);
+ timezones0.put("America/Port_of_Spain", tz);
+ timezones0.put("America/Porto_Velho", tz);
+ timezones0.put("America/Puerto_Rico", tz);
+ timezones0.put("America/Santo_Domingo", tz);
+ timezones0.put("America/St_Kitts", tz);
+ timezones0.put("America/St_Lucia", tz);
+ timezones0.put("America/St_Thomas", tz);
+ timezones0.put("America/St_Vincent", tz);
+ timezones0.put("America/Tortola", tz);
+ tz = new SimpleTimeZone
+ (-4000 * 3600, "America/Asuncion",
+ Calendar.OCTOBER, 1, Calendar.SUNDAY, 0 * 3600,
+ Calendar.FEBRUARY, -1, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("America/Asuncion", tz);
+ tz = new SimpleTimeZone
+ (-4000 * 3600, "America/Cuiaba",
+ Calendar.OCTOBER, 2, Calendar.SUNDAY, 0 * 3600,
+ Calendar.FEBRUARY, 3, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("America/Cuiaba", tz);
+ tz = new SimpleTimeZone
+ (-4000 * 3600, "America/Goose_Bay",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 60000,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 60000);
+ timezones0.put("America/Goose_Bay", tz);
+ tz = new SimpleTimeZone
+ (-4000 * 3600, "America/Glace_Bay",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("America/Glace_Bay", tz);
+ timezones0.put("America/Halifax", tz);
+ timezones0.put("America/Thule", tz);
+ timezones0.put("Atlantic/Bermuda", tz);
+ tz = new SimpleTimeZone
+ (-4000 * 3600, "America/Santiago",
+ Calendar.OCTOBER, 9, -Calendar.SUNDAY, 0 * 3600,
+ Calendar.MARCH, 9, -Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("America/Santiago", tz);
+ timezones0.put("Antarctica/Palmer", tz);
+ tz = new SimpleTimeZone
+ (-4000 * 3600, "Atlantic/Stanley",
+ Calendar.SEPTEMBER, 2, Calendar.SUNDAY, 0 * 3600,
+ Calendar.APRIL, 16, -Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("Atlantic/Stanley", tz);
+ tz = new SimpleTimeZone
+ (-3500 * 3600, "CNT",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 60000,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 60000);
+ timezones0.put("CNT", tz);
+ timezones0.put("America/St_Johns", tz);
+ tz = new SimpleTimeZone
+ (-3000 * 3600, "America/Araguaina",
+ Calendar.OCTOBER, 2, Calendar.SUNDAY, 0 * 3600,
+ Calendar.FEBRUARY, 3, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("America/Araguaina", tz);
+ timezones0.put("America/Sao_Paulo", tz);
+ tz = new SimpleTimeZone(-3000 * 3600, "AGT");
+ timezones0.put("AGT", tz);
+ timezones0.put("America/Belem", tz);
+ timezones0.put("America/Buenos_Aires", tz);
+ timezones0.put("America/Catamarca", tz);
+ timezones0.put("America/Cayenne", tz);
+ timezones0.put("America/Cordoba", tz);
+ timezones0.put("America/Fortaleza", tz);
+ timezones0.put("America/Jujuy", tz);
+ timezones0.put("America/Maceio", tz);
+ timezones0.put("America/Mendoza", tz);
+ timezones0.put("America/Montevideo", tz);
+ timezones0.put("America/Paramaribo", tz);
+ timezones0.put("America/Recife", tz);
+ timezones0.put("America/Rosario", tz);
+ tz = new SimpleTimeZone
+ (-3000 * 3600, "America/Godthab",
+ Calendar.MARCH, 30, -Calendar.SATURDAY, 22000 * 3600,
+ Calendar.OCTOBER, 30, -Calendar.SATURDAY, 22000 * 3600);
+ timezones0.put("America/Godthab", tz);
+ tz = new SimpleTimeZone
+ (-3000 * 3600, "America/Miquelon",
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("America/Miquelon", tz);
+ tz = new SimpleTimeZone(-2000 * 3600, "America/Noronha");
+ timezones0.put("America/Noronha", tz);
+ timezones0.put("Atlantic/South_Georgia", tz);
+ tz = new SimpleTimeZone
+ (-1000 * 3600, "America/Scoresbysund",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("America/Scoresbysund", tz);
+ timezones0.put("Atlantic/Azores", tz);
+ tz = new SimpleTimeZone(-1000 * 3600, "Atlantic/Cape_Verde");
+ timezones0.put("Atlantic/Cape_Verde", tz);
+ timezones0.put("Atlantic/Jan_Mayen", tz);
+ tz = new SimpleTimeZone(0 * 3600, "GMT");
+ timezones0.put("GMT", tz);
+ timezones0.put("UTC", tz);
+ timezones0.put("Africa/Abidjan", tz);
+ timezones0.put("Africa/Accra", tz);
+ timezones0.put("Africa/Bamako", tz);
+ timezones0.put("Africa/Banjul", tz);
+ timezones0.put("Africa/Bissau", tz);
+ timezones0.put("Africa/Casablanca", tz);
+ timezones0.put("Africa/Conakry", tz);
+ timezones0.put("Africa/Dakar", tz);
+ timezones0.put("Africa/El_Aaiun", tz);
+ timezones0.put("Africa/Freetown", tz);
+ timezones0.put("Africa/Lome", tz);
+ timezones0.put("Africa/Monrovia", tz);
+ timezones0.put("Africa/Nouakchott", tz);
+ timezones0.put("Africa/Ouagadougou", tz);
+ timezones0.put("Africa/Sao_Tome", tz);
+ timezones0.put("Africa/Timbuktu", tz);
+ timezones0.put("Atlantic/Reykjavik", tz);
+ timezones0.put("Atlantic/St_Helena", tz);
+ timezones0.put("Europe/Belfast", tz);
+ timezones0.put("Europe/Dublin", tz);
+ timezones0.put("Europe/London", tz);
+ tz = new SimpleTimeZone
+ (0 * 3600, "WET",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 1000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600);
+ timezones0.put("WET", tz);
+ timezones0.put("Atlantic/Canary", tz);
+ timezones0.put("Atlantic/Faeroe", tz);
+ timezones0.put("Atlantic/Madeira", tz);
+ timezones0.put("Europe/Lisbon", tz);
+ tz = new SimpleTimeZone(1000 * 3600, "Africa/Algiers");
+ timezones0.put("Africa/Algiers", tz);
+ timezones0.put("Africa/Bangui", tz);
+ timezones0.put("Africa/Brazzaville", tz);
+ timezones0.put("Africa/Douala", tz);
+ timezones0.put("Africa/Kinshasa", tz);
+ timezones0.put("Africa/Lagos", tz);
+ timezones0.put("Africa/Libreville", tz);
+ timezones0.put("Africa/Luanda", tz);
+ timezones0.put("Africa/Malabo", tz);
+ timezones0.put("Africa/Ndjamena", tz);
+ timezones0.put("Africa/Niamey", tz);
+ timezones0.put("Africa/Porto-Novo", tz);
+ timezones0.put("Africa/Tunis", tz);
+ tz = new SimpleTimeZone
+ (1000 * 3600, "Africa/Windhoek",
+ Calendar.SEPTEMBER, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Africa/Windhoek", tz);
+ tz = new SimpleTimeZone
+ (1000 * 3600, "CET",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("CET", tz);
+ timezones0.put("CEST", tz);
+ timezones0.put("ECT", tz);
+ timezones0.put("MET", tz);
+ timezones0.put("Africa/Ceuta", tz);
+ timezones0.put("Arctic/Longyearbyen", tz);
+ timezones0.put("Europe/Amsterdam", tz);
+ timezones0.put("Europe/Andorra", tz);
+ timezones0.put("Europe/Belgrade", tz);
+ timezones0.put("Europe/Berlin", tz);
+ timezones0.put("Europe/Bratislava", tz);
+ timezones0.put("Europe/Brussels", tz);
+ timezones0.put("Europe/Budapest", tz);
+ timezones0.put("Europe/Copenhagen", tz);
+ timezones0.put("Europe/Gibraltar", tz);
+ timezones0.put("Europe/Ljubljana", tz);
+ timezones0.put("Europe/Luxembourg", tz);
+ timezones0.put("Europe/Madrid", tz);
+ timezones0.put("Europe/Malta", tz);
+ timezones0.put("Europe/Monaco", tz);
+ timezones0.put("Europe/Oslo", tz);
+ timezones0.put("Europe/Paris", tz);
+ timezones0.put("Europe/Prague", tz);
+ timezones0.put("Europe/Rome", tz);
+ timezones0.put("Europe/San_Marino", tz);
+ timezones0.put("Europe/Sarajevo", tz);
+ timezones0.put("Europe/Skopje", tz);
+ timezones0.put("Europe/Stockholm", tz);
+ timezones0.put("Europe/Tirane", tz);
+ timezones0.put("Europe/Vaduz", tz);
+ timezones0.put("Europe/Vatican", tz);
+ timezones0.put("Europe/Vienna", tz);
+ timezones0.put("Europe/Warsaw", tz);
+ timezones0.put("Europe/Zagreb", tz);
+ timezones0.put("Europe/Zurich", tz);
+ tz = new SimpleTimeZone
+ (2000 * 3600, "ART",
+ Calendar.APRIL, -1, Calendar.FRIDAY, 0 * 3600,
+ Calendar.SEPTEMBER, -1, Calendar.THURSDAY, 23000 * 3600);
+ timezones0.put("ART", tz);
+ timezones0.put("Africa/Cairo", tz);
+ tz = new SimpleTimeZone(2000 * 3600, "CAT");
+ timezones0.put("CAT", tz);
+ timezones0.put("Africa/Blantyre", tz);
+ timezones0.put("Africa/Bujumbura", tz);
+ timezones0.put("Africa/Gaborone", tz);
+ timezones0.put("Africa/Harare", tz);
+ timezones0.put("Africa/Johannesburg", tz);
+ timezones0.put("Africa/Kigali", tz);
+ timezones0.put("Africa/Lubumbashi", tz);
+ timezones0.put("Africa/Lusaka", tz);
+ timezones0.put("Africa/Maputo", tz);
+ timezones0.put("Africa/Maseru", tz);
+ timezones0.put("Africa/Mbabane", tz);
+ timezones0.put("Africa/Tripoli", tz);
+ timezones0.put("Europe/Riga", tz);
+ timezones0.put("Europe/Tallinn", tz);
+ timezones0.put("Europe/Vilnius", tz);
+ tz = new SimpleTimeZone
+ (2000 * 3600, "Asia/Amman",
+ Calendar.MARCH, -1, Calendar.THURSDAY, 0 * 3600,
+ Calendar.SEPTEMBER, -1, Calendar.THURSDAY, 0 * 3600);
+ timezones0.put("Asia/Amman", tz);
+ tz = new SimpleTimeZone
+ (2000 * 3600, "Asia/Beirut",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("Asia/Beirut", tz);
+ tz = new SimpleTimeZone
+ (2000 * 3600, "Asia/Damascus",
+ Calendar.APRIL, 1, 0, 0 * 3600,
+ Calendar.OCTOBER, 1, 0, 0 * 3600);
+ timezones0.put("Asia/Damascus", tz);
+ tz = new SimpleTimeZone
+ (2000 * 3600, "Asia/Gaza",
+ Calendar.APRIL, 3, Calendar.FRIDAY, 0 * 3600,
+ Calendar.OCTOBER, 3, Calendar.FRIDAY, 0 * 3600);
+ timezones0.put("Asia/Gaza", tz);
+ tz = new SimpleTimeZone
+ (2000 * 3600, "Asia/Jerusalem",
+ Calendar.APRIL, 1, 0, 1000 * 3600,
+ Calendar.OCTOBER, 1, 0, 1000 * 3600);
+ timezones0.put("Asia/Jerusalem", tz);
+ tz = new SimpleTimeZone
+ (2000 * 3600, "EET",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+ timezones0.put("EET", tz);
+ timezones0.put("Asia/Istanbul", tz);
+ timezones0.put("Asia/Nicosia", tz);
+ timezones0.put("Europe/Athens", tz);
+ timezones0.put("Europe/Bucharest", tz);
+ timezones0.put("Europe/Chisinau", tz);
+ timezones0.put("Europe/Helsinki", tz);
+ timezones0.put("Europe/Istanbul", tz);
+ timezones0.put("Europe/Kiev", tz);
+ timezones0.put("Europe/Nicosia", tz);
+ timezones0.put("Europe/Simferopol", tz);
+ timezones0.put("Europe/Sofia", tz);
+ timezones0.put("Europe/Uzhgorod", tz);
+ timezones0.put("Europe/Zaporozhye", tz);
+ tz = new SimpleTimeZone
+ (2000 * 3600, "Europe/Kaliningrad",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Europe/Kaliningrad", tz);
+ timezones0.put("Europe/Minsk", tz);
+ tz = new SimpleTimeZone
+ (3000 * 3600, "Asia/Baghdad",
+ Calendar.APRIL, 1, 0, 3000 * 3600,
+ Calendar.OCTOBER, 1, 0, 3000 * 3600);
+ timezones0.put("Asia/Baghdad", tz);
+ tz = new SimpleTimeZone
+ (3000 * 3600, "Europe/Moscow",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Europe/Moscow", tz);
+ timezones0.put("Europe/Tiraspol", tz);
+ tz = new SimpleTimeZone(3000 * 3600, "EAT");
+ timezones0.put("EAT", tz);
+ timezones0.put("Africa/Addis_Ababa", tz);
+ timezones0.put("Africa/Asmera", tz);
+ timezones0.put("Africa/Dar_es_Salaam", tz);
+ timezones0.put("Africa/Djibouti", tz);
+ timezones0.put("Africa/Kampala", tz);
+ timezones0.put("Africa/Khartoum", tz);
+ timezones0.put("Africa/Mogadishu", tz);
+ timezones0.put("Africa/Nairobi", tz);
+ timezones0.put("Antarctica/Syowa", tz);
+ timezones0.put("Asia/Aden", tz);
+ timezones0.put("Asia/Bahrain", tz);
+ timezones0.put("Asia/Kuwait", tz);
+ timezones0.put("Asia/Qatar", tz);
+ timezones0.put("Asia/Riyadh", tz);
+ timezones0.put("Indian/Antananarivo", tz);
+ timezones0.put("Indian/Comoro", tz);
+ timezones0.put("Indian/Mayotte", tz);
+ tz = new SimpleTimeZone(3500 * 3600, "Asia/Tehran");
+ timezones0.put("Asia/Tehran", tz);
+ tz = new SimpleTimeZone
+ (4000 * 3600, "Asia/Baku",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 1000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600);
+ timezones0.put("Asia/Baku", tz);
+ tz = new SimpleTimeZone
+ (4000 * 3600, "Asia/Aqtau",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("Asia/Aqtau", tz);
+ timezones0.put("Asia/Tbilisi", tz);
+ tz = new SimpleTimeZone
+ (4000 * 3600, "Asia/Yerevan",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Yerevan", tz);
+ timezones0.put("Europe/Samara", tz);
+ tz = new SimpleTimeZone(4000 * 3600, "NET");
+ timezones0.put("NET", tz);
+ timezones0.put("Asia/Dubai", tz);
+ timezones0.put("Asia/Muscat", tz);
+ timezones0.put("Indian/Mahe", tz);
+ timezones0.put("Indian/Mauritius", tz);
+ timezones0.put("Indian/Reunion", tz);
+ tz = new SimpleTimeZone(4500 * 3600, "Asia/Kabul");
+ timezones0.put("Asia/Kabul", tz);
+ tz = new SimpleTimeZone
+ (5000 * 3600, "Asia/Aqtobe",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("Asia/Aqtobe", tz);
+ tz = new SimpleTimeZone
+ (5000 * 3600, "Asia/Bishkek",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2500 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2500 * 3600);
+ timezones0.put("Asia/Bishkek", tz);
+ tz = new SimpleTimeZone
+ (5000 * 3600, "Asia/Yekaterinburg",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Yekaterinburg", tz);
+ tz = new SimpleTimeZone(5000 * 3600, "PLT");
+ timezones0.put("PLT", tz);
+ timezones0.put("Asia/Ashgabat", tz);
+ timezones0.put("Asia/Dushanbe", tz);
+ timezones0.put("Asia/Karachi", tz);
+ timezones0.put("Asia/Samarkand", tz);
+ timezones0.put("Asia/Tashkent", tz);
+ timezones0.put("Indian/Chagos", tz);
+ timezones0.put("Indian/Kerguelen", tz);
+ timezones0.put("Indian/Maldives", tz);
+ tz = new SimpleTimeZone(5500 * 3600, "IST");
+ timezones0.put("IST", tz);
+ timezones0.put("Asia/Calcutta", tz);
+ tz = new SimpleTimeZone(5750 * 3600, "Asia/Katmandu");
+ timezones0.put("Asia/Katmandu", tz);
+ tz = new SimpleTimeZone(6000 * 3600, "BST");
+ timezones0.put("BST", tz);
+ timezones0.put("Antarctica/Mawson", tz);
+ timezones0.put("Asia/Colombo", tz);
+ timezones0.put("Asia/Dhaka", tz);
+ timezones0.put("Asia/Thimphu", tz);
+ tz = new SimpleTimeZone
+ (6000 * 3600, "Asia/Almaty",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
+ timezones0.put("Asia/Almaty", tz);
+ tz = new SimpleTimeZone
+ (6000 * 3600, "Asia/Novosibirsk",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Novosibirsk", tz);
+ timezones0.put("Asia/Omsk", tz);
+ tz = new SimpleTimeZone(6500 * 3600, "Asia/Rangoon");
+ timezones0.put("Asia/Rangoon", tz);
+ timezones0.put("Indian/Cocos", tz);
+ tz = new SimpleTimeZone(7000 * 3600, "VST");
+ timezones0.put("VST", tz);
+ timezones0.put("Antarctica/Davis", tz);
+ timezones0.put("Asia/Bangkok", tz);
+ timezones0.put("Asia/Hovd", tz);
+ timezones0.put("Asia/Jakarta", tz);
+ timezones0.put("Asia/Phnom_Penh", tz);
+ timezones0.put("Asia/Saigon", tz);
+ timezones0.put("Asia/Vientiane", tz);
+ timezones0.put("Indian/Christmas", tz);
+ tz = new SimpleTimeZone
+ (7000 * 3600, "Asia/Krasnoyarsk",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Krasnoyarsk", tz);
+ tz = new SimpleTimeZone(8000 * 3600, "CTT");
+ timezones0.put("CTT", tz);
+ timezones0.put("Antarctica/Casey", tz);
+ timezones0.put("Asia/Brunei", tz);
+ timezones0.put("Asia/Chungking", tz);
+ timezones0.put("Asia/Harbin", tz);
+ timezones0.put("Asia/Hong_Kong", tz);
+ timezones0.put("Asia/Kashgar", tz);
+ timezones0.put("Asia/Kuala_Lumpur", tz);
+ timezones0.put("Asia/Kuching", tz);
+ timezones0.put("Asia/Macao", tz);
+ timezones0.put("Asia/Manila", tz);
+ timezones0.put("Asia/Shanghai", tz);
+ timezones0.put("Asia/Singapore", tz);
+ timezones0.put("Asia/Taipei", tz);
+ timezones0.put("Asia/Ujung_Pandang", tz);
+ timezones0.put("Asia/Ulaanbaatar", tz);
+ timezones0.put("Asia/Urumqi", tz);
+ timezones0.put("Australia/Perth", tz);
+ tz = new SimpleTimeZone
+ (8000 * 3600, "Asia/Irkutsk",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Irkutsk", tz);
+ tz = new SimpleTimeZone(9000 * 3600, "JST");
+ timezones0.put("JST", tz);
+ timezones0.put("Asia/Dili", tz);
+ timezones0.put("Asia/Jayapura", tz);
+ timezones0.put("Asia/Pyongyang", tz);
+ timezones0.put("Asia/Seoul", tz);
+ timezones0.put("Asia/Tokyo", tz);
+ timezones0.put("Pacific/Palau", tz);
+ tz = new SimpleTimeZone
+ (9000 * 3600, "Asia/Yakutsk",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Yakutsk", tz);
+ tz = new SimpleTimeZone
+ (9500 * 3600, "Australia/Adelaide",
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Australia/Adelaide", tz);
+ timezones0.put("Australia/Broken_Hill", tz);
+ tz = new SimpleTimeZone(9500 * 3600, "ACT");
+ timezones0.put("ACT", tz);
+ timezones0.put("Australia/Darwin", tz);
+ tz = new SimpleTimeZone(10000 * 3600, "Antarctica/DumontDUrville");
+ timezones0.put("Antarctica/DumontDUrville", tz);
+ timezones0.put("Australia/Brisbane", tz);
+ timezones0.put("Australia/Lindeman", tz);
+ timezones0.put("Pacific/Guam", tz);
+ timezones0.put("Pacific/Port_Moresby", tz);
+ timezones0.put("Pacific/Saipan", tz);
+ timezones0.put("Pacific/Truk", tz);
+ timezones0.put("Pacific/Yap", tz);
+ tz = new SimpleTimeZone
+ (10000 * 3600, "Asia/Vladivostok",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Vladivostok", tz);
+ tz = new SimpleTimeZone
+ (10000 * 3600, "Australia/Hobart",
+ Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Australia/Hobart", tz);
+ tz = new SimpleTimeZone
+ (10000 * 3600, "AET",
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("AET", tz);
+ timezones0.put("Australia/Melbourne", tz);
+ timezones0.put("Australia/Sydney", tz);
+ tz = new SimpleTimeZone
+ (10500 * 3600, "Australia/Lord_Howe",
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, 500 * 3600);
+ timezones0.put("Australia/Lord_Howe", tz);
+ tz = new SimpleTimeZone
+ (11000 * 3600, "Asia/Magadan",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Magadan", tz);
+ tz = new SimpleTimeZone(11000 * 3600, "SST");
+ timezones0.put("SST", tz);
+ timezones0.put("Pacific/Efate", tz);
+ timezones0.put("Pacific/Guadalcanal", tz);
+ timezones0.put("Pacific/Kosrae", tz);
+ timezones0.put("Pacific/Noumea", tz);
+ timezones0.put("Pacific/Ponape", tz);
+ tz = new SimpleTimeZone(11500 * 3600, "Pacific/Norfolk");
+ timezones0.put("Pacific/Norfolk", tz);
+ tz = new SimpleTimeZone
+ (12000 * 3600, "NST",
+ Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.MARCH, 3, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("NST", tz);
+ timezones0.put("Antarctica/McMurdo", tz);
+ timezones0.put("Antarctica/South_Pole", tz);
+ timezones0.put("Pacific/Auckland", tz);
+ tz = new SimpleTimeZone
+ (12000 * 3600, "Asia/Anadyr",
+ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+ timezones0.put("Asia/Anadyr", tz);
+ timezones0.put("Asia/Kamchatka", tz);
+ tz = new SimpleTimeZone(12000 * 3600, "Pacific/Fiji");
+ timezones0.put("Pacific/Fiji", tz);
+ timezones0.put("Pacific/Funafuti", tz);
+ timezones0.put("Pacific/Kwajalein", tz);
+ timezones0.put("Pacific/Majuro", tz);
+ timezones0.put("Pacific/Nauru", tz);
+ timezones0.put("Pacific/Tarawa", tz);
+ timezones0.put("Pacific/Wake", tz);
+ timezones0.put("Pacific/Wallis", tz);
+ tz = new SimpleTimeZone
+ (12750 * 3600, "Pacific/Chatham",
+ Calendar.OCTOBER, 1, Calendar.SUNDAY, 2750 * 3600,
+ Calendar.MARCH, 3, Calendar.SUNDAY, 2750 * 3600);
+ timezones0.put("Pacific/Chatham", tz);
+ tz = new SimpleTimeZone(13000 * 3600, "Pacific/Enderbury");
+ timezones0.put("Pacific/Enderbury", tz);
+ timezones0.put("Pacific/Tongatapu", tz);
+ tz = new SimpleTimeZone(14000 * 3600, "Pacific/Kiritimati");
+ timezones0.put("Pacific/Kiritimati", tz);
+ }
+ return timezones0;
+ }
+
+ /**
+ * Maps a time zone name (with optional GMT offset and daylight time
+ * zone name) to one of the known time zones. This method called
+ * with the result of <code>System.getProperty("user.timezone")</code>
+ * or <code>getDefaultTimeZoneId()</code>. Note that giving one of
+ * the standard tz data names from ftp://elsie.nci.nih.gov/pub/ is
+ * preferred.
+ * The time zone name can be given as follows:
+ * <code>(standard zone name)[(GMT offset)[(DST zone name)[DST offset]]]
+ * </code>
+ * <p>
+ * If only a (standard zone name) is given (no numbers in the
+ * String) then it gets mapped directly to the TimeZone with that
+ * name, if that fails null is returned.
+ * <p>
+ * Alternately, a POSIX-style TZ string can be given, defining the time zone:
+ * <code>std offset dst offset,date/time,date/time</code>
+ * See the glibc manual, or the man page for <code>tzset</code> for details
+ * of this format.
+ * <p>
+ * A GMT offset is the offset to add to the local time to get GMT.
+ * If a (GMT offset) is included (either in seconds or hours) then
+ * an attempt is made to find a TimeZone name matching both the name
+ * and the offset (that doesn't observe daylight time, if the
+ * timezone observes daylight time then you must include a daylight
+ * time zone name after the offset), if that fails then a TimeZone
+ * with the given GMT offset is returned (whether or not the
+ * TimeZone observes daylight time is ignored), if that also fails
+ * the GMT TimeZone is returned.
+ * <p>
+ * If the String ends with (GMT offset)(daylight time zone name)
+ * then an attempt is made to find a TimeZone with the given name and
+ * GMT offset that also observes (the daylight time zone name is not
+ * currently used in any other way), if that fails a TimeZone with
+ * the given GMT offset that observes daylight time is returned, if
+ * that also fails the GMT TimeZone is returned.
+ * <p>
+ * Examples: In Chicago, the time zone id could be "CST6CDT", but
+ * the preferred name would be "America/Chicago". In Indianapolis
+ * (which does not have Daylight Savings Time) the string could be
+ * "EST5", but the preferred name would be "America/Indianapolis".
+ * The standard time zone name for The Netherlands is "Europe/Amsterdam",
+ * but can also be given as "CET-1CEST".
+ */
+ static TimeZone getDefaultTimeZone(String sysTimeZoneId)
+ {
+ String stdName = null;
+ String dstName;
+ int stdOffs;
+ int dstOffs;
+ try
+ {
+ int idLength = sysTimeZoneId.length();
+
+ int index = 0;
+ int prevIndex;
+ char c;
+
+ // get std
+ do
+ c = sysTimeZoneId.charAt(index++);
+ while (c != '+' && c != '-' && c != ',' && c != ':'
+ && ! Character.isDigit(c) && c != '\0' && index < idLength);
+
+ if (index >= idLength)
+ return (TimeZone)timezones().get(sysTimeZoneId);
+
+ stdName = sysTimeZoneId.substring(0, --index);
+ prevIndex = index;
+
+ // get the std offset
+ do
+ c = sysTimeZoneId.charAt(index++);
+ while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
+ && index < idLength);
+ if (index < idLength)
+ index--;
+
+ { // convert the dst string to a millis number
+ String offset = sysTimeZoneId.substring(prevIndex, index);
+ prevIndex = index;
+
+ if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
+ stdOffs = parseTime(offset.substring(1));
+ else
+ stdOffs = parseTime(offset);
+
+ if (offset.charAt(0) == '-')
+ stdOffs = -stdOffs;
+
+ // TZ timezone offsets are positive when WEST of the meridian.
+ stdOffs = -stdOffs;
+ }
+
+ // Done yet? (Format: std offset)
+ if (index >= idLength)
+ {
+ // Do we have an existing timezone with that name and offset?
+ TimeZone tz = (TimeZone) timezones().get(stdName);
+ if (tz != null)
+ if (tz.getRawOffset() == stdOffs)
+ return tz;
+
+ // Custom then.
+ return new SimpleTimeZone(stdOffs, stdName);
+ }
+
+ // get dst
+ do
+ c = sysTimeZoneId.charAt(index++);
+ while (c != '+' && c != '-' && c != ',' && c != ':'
+ && ! Character.isDigit(c) && c != '\0' && index < idLength);
+
+ // Done yet? (Format: std offset dst)
+ if (index >= idLength)
+ {
+ // Do we have an existing timezone with that name and offset
+ // which has DST?
+ TimeZone tz = (TimeZone) timezones().get(stdName);
+ if (tz != null)
+ if (tz.getRawOffset() == stdOffs && tz.useDaylightTime())
+ return tz;
+
+ // Custom then.
+ return new SimpleTimeZone(stdOffs, stdName);
+ }
+
+ // get the dst offset
+ dstName = sysTimeZoneId.substring(prevIndex, --index);
+ prevIndex = index;
+ do
+ c = sysTimeZoneId.charAt(index++);
+ while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
+ && index < idLength);
+ if (index < idLength)
+ index--;
+
+ { // convert the dst string to a millis number
+ String offset = sysTimeZoneId.substring(prevIndex, index);
+ prevIndex = index;
+
+ if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
+ dstOffs = parseTime(offset.substring(1));
+ else
+ dstOffs = parseTime(offset);
+
+ if (offset.charAt(0) == '-')
+ dstOffs = -dstOffs;
+
+ // TZ timezone offsets are positive when WEST of the meridian.
+ dstOffs = -dstOffs;
+ }
+
+ // Done yet? (Format: std offset dst offset)
+ // FIXME: We don't support DST without a rule given. Should we?
+ if (index >= idLength)
+ {
+ // Time Zone existing with same name, dst and offsets?
+ TimeZone tz = (TimeZone) timezones().get(stdName);
+ if (tz != null)
+ if (tz.getRawOffset() == stdOffs && tz.useDaylightTime()
+ && tz.getDSTSavings() == (dstOffs - stdOffs))
+ return tz;
+
+ return new SimpleTimeZone(stdOffs, stdName);
+ }
+
+ // get the DST rule
+ if (sysTimeZoneId.charAt(index) == ','
+ || sysTimeZoneId.charAt(index) == ';')
+ {
+ index++;
+ int offs = index;
+ while (sysTimeZoneId.charAt(index) != ','
+ && sysTimeZoneId.charAt(index) != ';')
+ index++;
+ String startTime = sysTimeZoneId.substring(offs, index);
+ index++;
+ String endTime = sysTimeZoneId.substring(index);
+
+ index = startTime.indexOf('/');
+ int startMillis;
+ int endMillis;
+ String startDate;
+ String endDate;
+ if (index != -1)
+ {
+ startDate = startTime.substring(0, index);
+ startMillis = parseTime(startTime.substring(index + 1));
+ }
+ else
+ {
+ startDate = startTime;
+ // if time isn't given, default to 2:00:00 AM.
+ startMillis = 2 * 60 * 60 * 1000;
+ }
+ index = endTime.indexOf('/');
+ if (index != -1)
+ {
+ endDate = endTime.substring(0, index);
+ endMillis = parseTime(endTime.substring(index + 1));
+ }
+ else
+ {
+ endDate = endTime;
+ // if time isn't given, default to 2:00:00 AM.
+ endMillis = 2 * 60 * 60 * 1000;
+ }
+
+ int[] start = getDateParams(startDate);
+ int[] end = getDateParams(endDate);
+ return new SimpleTimeZone(stdOffs, stdName, start[0], start[1],
+ start[2], startMillis, end[0], end[1],
+ end[2], endMillis, (dstOffs - stdOffs));
+ }
+ }
+
+ // FIXME: Produce a warning here?
+ catch (IndexOutOfBoundsException _)
+ {
+ }
+ catch (NumberFormatException _)
+ {
+ }
+
+ return null;
+ }
+
+ /**
+ * Parses and returns the params for a POSIX TZ date field,
+ * in the format int[]{ month, day, dayOfWeek }, following the
+ * SimpleTimeZone constructor rules.
+ */
+ private static int[] getDateParams(String date)
+ {
+ int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ int month;
+
+ if (date.charAt(0) == 'M' || date.charAt(0) == 'm')
+ {
+ int day;
+
+ // Month, week of month, day of week
+ month = Integer.parseInt(date.substring(1, date.indexOf('.')));
+ int week = Integer.parseInt(date.substring(date.indexOf('.') + 1,
+ date.lastIndexOf('.')));
+ int dayOfWeek = Integer.parseInt(date.substring(date.lastIndexOf('.')
+ + 1));
+ if (week == 5)
+ day = -1; // last day of month is -1 in java, 5 in TZ
+ else
+ // first day of week starting on or after.
+ day = (week - 1) * 7 + 1;
+
+ dayOfWeek++; // Java day of week is one-based, Sunday is first day.
+ month--; // Java month is zero-based.
+ return new int[] { month, day, dayOfWeek };
+ }
+
+ // julian day, either zero-based 0<=n<=365 (incl feb 29)
+ // or one-based 1<=n<=365 (no feb 29)
+ int julianDay; // Julian day,
+
+ if (date.charAt(0) != 'J' || date.charAt(0) != 'j')
+ {
+ julianDay = Integer.parseInt(date.substring(1));
+ julianDay++; // make 1-based
+ // Adjust day count to include feb 29.
+ dayCount = new int[]
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
+ };
+ }
+ else
+ // 1-based julian day
+ julianDay = Integer.parseInt(date);
+
+ int i = 11;
+ while (i > 0)
+ if (dayCount[i] < julianDay)
+ break;
+ else
+ i--;
+ julianDay -= dayCount[i];
+ month = i;
+ return new int[] { month, julianDay, 0 };
+ }
+
+ /**
+ * Parses a time field hh[:mm[:ss]], returning the result
+ * in milliseconds. No leading sign.
+ */
+ private static int parseTime(String time)
+ {
+ int millis = 0;
+ int i = 0;
+
+ while (i < time.length())
+ if (time.charAt(i) == ':')
+ break;
+ else
+ i++;
+ millis = 60 * 60 * 1000 * Integer.parseInt(time.substring(0, i));
+ if (i >= time.length())
+ return millis;
+
+ int iprev = ++i;
+ while (i < time.length())
+ if (time.charAt(i) == ':')
+ break;
+ else
+ i++;
+ if (i >= time.length())
+ return millis;
+
+ millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i));
+ millis += 1000 * Integer.parseInt(time.substring(++i));
+ return millis;
+ }
+
+ /**
+ * Gets the time zone offset, for current date, modified in case of
+ * daylight savings. This is the offset to add to UTC to get the local
+ * time.
+ * @param era the era of the given date
+ * @param year the year of the given date
+ * @param month the month of the given date, 0 for January.
+ * @param day the day of month
+ * @param dayOfWeek the day of week
+ * @param milliseconds the millis in the day (in local standard time)
+ * @return the time zone offset in milliseconds.
+ */
+ public abstract int getOffset(int era, int year, int month,
+ int day, int dayOfWeek, int milliseconds);
+
+ /**
+ * Get the time zone offset for the specified date, modified in case of
+ * daylight savings. This is the offset to add to UTC to get the local
+ * time.
+ * @param date the date represented in millisecends
+ * since January 1, 1970 00:00:00 GMT.
+ * @since 1.4
+ */
+ public int getOffset(long date)
+ {
+ return (inDaylightTime(new Date(date))
+ ? getRawOffset() + getDSTSavings()
+ : getRawOffset());
+ }
+
+ /**
+ * Gets the time zone offset, ignoring daylight savings. This is
+ * the offset to add to UTC to get the local time.
+ * @return the time zone offset in milliseconds.
+ */
+ public abstract int getRawOffset();
+
+ /**
+ * Sets the time zone offset, ignoring daylight savings. This is
+ * the offset to add to UTC to get the local time.
+ * @param offsetMillis the time zone offset to GMT.
+ */
+ public abstract void setRawOffset(int offsetMillis);
+
+ /**
+ * Gets the identifier of this time zone. For instance, PST for
+ * Pacific Standard Time.
+ * @returns the ID of this time zone.
+ */
+ public String getID()
+ {
+ return ID;
+ }
+
+ /**
+ * Sets the identifier of this time zone. For instance, PST for
+ * Pacific Standard Time.
+ * @param id the new time zone ID.
+ * @throws NullPointerException if <code>id</code> is <code>null</code>
+ */
+ public void setID(String id)
+ {
+ if (id == null)
+ throw new NullPointerException();
+
+ this.ID = id;
+ }
+
+ /**
+ * This method returns a string name of the time zone suitable
+ * for displaying to the user. The string returned will be the long
+ * description of the timezone in the current locale. The name
+ * displayed will assume daylight savings time is not in effect.
+ *
+ * @return The name of the time zone.
+ */
+ public final String getDisplayName()
+ {
+ return (getDisplayName(false, LONG, Locale.getDefault()));
+ }
+
+ /**
+ * This method returns a string name of the time zone suitable
+ * for displaying to the user. The string returned will be the long
+ * description of the timezone in the specified locale. The name
+ * displayed will assume daylight savings time is not in effect.
+ *
+ * @param locale The locale for this timezone name.
+ *
+ * @return The name of the time zone.
+ */
+ public final String getDisplayName(Locale locale)
+ {
+ return (getDisplayName(false, LONG, locale));
+ }
+
+ /**
+ * This method returns a string name of the time zone suitable
+ * for displaying to the user. The string returned will be of the
+ * specified type in the current locale.
+ *
+ * @param dst Whether or not daylight savings time is in effect.
+ * @param style <code>LONG</code> for a long name, <code>SHORT</code> for
+ * a short abbreviation.
+ *
+ * @return The name of the time zone.
+ */
+ public final String getDisplayName(boolean dst, int style)
+ {
+ return (getDisplayName(dst, style, Locale.getDefault()));
+ }
+
+
+ /**
+ * This method returns a string name of the time zone suitable
+ * for displaying to the user. The string returned will be of the
+ * specified type in the specified locale.
+ *
+ * @param dst Whether or not daylight savings time is in effect.
+ * @param style <code>LONG</code> for a long name, <code>SHORT</code> for
+ * a short abbreviation.
+ * @param locale The locale for this timezone name.
+ *
+ * @return The name of the time zone.
+ */
+ public String getDisplayName(boolean dst, int style, Locale locale)
+ {
+ DateFormatSymbols dfs;
+ try
+ {
+ dfs = new DateFormatSymbols(locale);
+
+ // The format of the value returned is defined by us.
+ String[][]zoneinfo = dfs.getZoneStrings();
+ for (int i = 0; i < zoneinfo.length; i++)
+ {
+ if (zoneinfo[i][0].equals(getID()))
+ {
+ if (!dst)
+ {
+ if (style == SHORT)
+ return (zoneinfo[i][2]);
+ else
+ return (zoneinfo[i][1]);
+ }
+ else
+ {
+ if (style == SHORT)
+ return (zoneinfo[i][4]);
+ else
+ return (zoneinfo[i][3]);
+ }
+ }
+ }
+ }
+ catch (MissingResourceException e)
+ {
+ }
+
+ return getDefaultDisplayName(dst);
+ }
+
+ private String getDefaultDisplayName(boolean dst)
+ {
+ int offset = getRawOffset();
+ if (dst && this instanceof SimpleTimeZone)
+ {
+ // ugly, but this is a design failure of the API:
+ // getDisplayName takes a dst parameter even though
+ // TimeZone knows nothing about daylight saving offsets.
+ offset += ((SimpleTimeZone) this).getDSTSavings();
+ }
+
+ StringBuffer sb = new StringBuffer(9);
+ sb.append("GMT");
+
+ offset = offset / (1000 * 60);
+ int hours = Math.abs(offset) / 60;
+ int minutes = Math.abs(offset) % 60;
+
+ if (minutes != 0 || hours != 0)
+ {
+ sb.append(offset >= 0 ? '+' : '-');
+ sb.append((char) ('0' + hours / 10));
+ sb.append((char) ('0' + hours % 10));
+ sb.append(':');
+ sb.append((char) ('0' + minutes / 10));
+ sb.append((char) ('0' + minutes % 10));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Returns true, if this time zone uses Daylight Savings Time.
+ */
+ public abstract boolean useDaylightTime();
+
+ /**
+ * Returns true, if the given date is in Daylight Savings Time in this
+ * time zone.
+ * @param date the given Date.
+ */
+ public abstract boolean inDaylightTime(Date date);
+
+ /**
+ * Gets the daylight savings offset. This is a positive offset in
+ * milliseconds with respect to standard time. Typically this
+ * is one hour, but for some time zones this may be half an our.
+ * <p>The default implementation returns 3600000 milliseconds
+ * (one hour) if the time zone uses daylight savings time
+ * (as specified by {@link #useDaylightTime()}), otherwise
+ * it returns 0.
+ * @return the daylight savings offset in milliseconds.
+ * @since 1.4
+ */
+ public int getDSTSavings ()
+ {
+ return useDaylightTime () ? 3600000 : 0;
+ }
+
+ /**
+ * Gets the TimeZone for the given ID.
+ * @param ID the time zone identifier.
+ * @return The time zone for the identifier or GMT, if no such time
+ * zone exists.
+ */
+ // FIXME: XXX: JCL indicates this and other methods are synchronized.
+ public static TimeZone getTimeZone(String ID)
+ {
+ // First check timezones hash
+ TimeZone tz = (TimeZone) timezones().get(ID);
+ if (tz != null)
+ {
+ if (tz.getID().equals(ID))
+ return tz;
+
+ // We always return a timezone with the requested ID.
+ // This is the same behaviour as with JDK1.2.
+ tz = (TimeZone) tz.clone();
+ tz.setID(ID);
+ // We also save the alias, so that we return the same
+ // object again if getTimeZone is called with the same
+ // alias.
+ timezones().put(ID, tz);
+ return tz;
+ }
+
+ // See if the ID is really a GMT offset form.
+ // Note that GMT is in the table so we know it is different.
+ if (ID.startsWith("GMT"))
+ {
+ int pos = 3;
+ int offset_direction = 1;
+
+ if (ID.charAt(pos) == '-')
+ {
+ offset_direction = -1;
+ pos++;
+ }
+ else if (ID.charAt(pos) == '+')
+ {
+ pos++;
+ }
+
+ try
+ {
+ int hour, minute;
+
+ String offset_str = ID.substring(pos);
+ int idx = offset_str.indexOf(":");
+ if (idx != -1)
+ {
+ hour = Integer.parseInt(offset_str.substring(0, idx));
+ minute = Integer.parseInt(offset_str.substring(idx + 1));
+ }
+ else
+ {
+ int offset_length = offset_str.length();
+ if (offset_length <= 2)
+ {
+ // Only hour
+ hour = Integer.parseInt(offset_str);
+ minute = 0;
+ }
+ else
+ {
+ // hour and minute, not separated by colon
+ hour = Integer.parseInt
+ (offset_str.substring(0, offset_length - 2));
+ minute = Integer.parseInt
+ (offset_str.substring(offset_length - 2));
+ }
+ }
+
+ return new SimpleTimeZone((hour * (60 * 60 * 1000) +
+ minute * (60 * 1000))
+ * offset_direction, ID);
+ }
+ catch (NumberFormatException e)
+ {
+ }
+ }
+
+ // Finally, return GMT per spec
+ return getTimeZone("GMT");
+ }
+
+ /**
+ * Gets the available IDs according to the given time zone
+ * offset.
+ * @param rawOffset the given time zone GMT offset.
+ * @return An array of IDs, where the time zone has the specified GMT
+ * offset. For example <code>{"Phoenix", "Denver"}</code>, since both have
+ * GMT-07:00, but differ in daylight savings behaviour.
+ */
+ public static String[] getAvailableIDs(int rawOffset)
+ {
+ int count = 0;
+ Iterator iter = timezones().entrySet().iterator();
+ while (iter.hasNext())
+ {
+ // Don't iterate the values, since we want to count
+ // doubled values (aliases)
+ Map.Entry entry = (Map.Entry) iter.next();
+ if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
+ count++;
+ }
+
+ String[] ids = new String[count];
+ count = 0;
+ iter = timezones().entrySet().iterator();
+ while (iter.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) iter.next();
+ if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
+ ids[count++] = (String) entry.getKey();
+ }
+ return ids;
+ }
+
+ /**
+ * Gets all available IDs.
+ * @return An array of all supported IDs.
+ */
+ public static String[] getAvailableIDs()
+ {
+ return (String[])
+ timezones().keySet().toArray(new String[timezones().size()]);
+ }
+
+ /**
+ * Returns the time zone under which the host is running. This
+ * can be changed with setDefault.
+ *
+ * @return A clone of the current default time zone for this host.
+ * @see #setDefault
+ */
+ public static TimeZone getDefault()
+ {
+ return (TimeZone) defaultZone().clone();
+ }
+
+ public static void setDefault(TimeZone zone)
+ {
+ // Hmmmm. No Security checks?
+ defaultZone0 = zone;
+ }
+
+ /**
+ * Test if the other time zone uses the same rule and only
+ * possibly differs in ID. This implementation for this particular
+ * class will return true if the raw offsets are identical. Subclasses
+ * should override this method if they use daylight savings.
+ * @return true if this zone has the same raw offset
+ */
+ public boolean hasSameRules(TimeZone other)
+ {
+ return other.getRawOffset() == getRawOffset();
+ }
+
+ /**
+ * Returns a clone of this object. I can't imagine, why this is
+ * useful for a time zone.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ return null;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/Timer.java b/libjava/classpath/java/util/Timer.java
new file mode 100644
index 00000000000..715f06cf641
--- /dev/null
+++ b/libjava/classpath/java/util/Timer.java
@@ -0,0 +1,615 @@
+/* Timer.java -- Timer that runs TimerTasks at a later time.
+ Copyright (C) 2000, 2001 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;
+
+/**
+ * Timer that can run TimerTasks at a later time.
+ * TimerTasks can be scheduled for one time execution at some time in the
+ * future. They can be scheduled to be rescheduled at a time period after the
+ * task was last executed. Or they can be scheduled to be executed repeatedly
+ * at a fixed rate.
+ * <p>
+ * The normal scheduling will result in a more or less even delay in time
+ * between successive executions, but the executions could drift in time if
+ * the task (or other tasks) takes a long time to execute. Fixed delay
+ * scheduling guarantees more or less that the task will be executed at a
+ * specific time, but if there is ever a delay in execution then the period
+ * between successive executions will be shorter. The first method of
+ * repeated scheduling is preferred for repeated tasks in response to user
+ * interaction, the second method of repeated scheduling is preferred for tasks
+ * that act like alarms.
+ * <p>
+ * The Timer keeps a binary heap as a task priority queue which means that
+ * scheduling and serving of a task in a queue of n tasks costs O(log n).
+ *
+ * @see TimerTask
+ * @since 1.3
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class Timer
+{
+ /**
+ * Priority Task Queue.
+ * TimerTasks are kept in a binary heap.
+ * The scheduler calls sleep() on the queue when it has nothing to do or
+ * has to wait. A sleeping scheduler can be notified by calling interrupt()
+ * which is automatically called by the enqueue(), cancel() and
+ * timerFinalized() methods.
+ */
+ private static final class TaskQueue
+ {
+ /** Default size of this queue */
+ private static final int DEFAULT_SIZE = 32;
+
+ /** Whether to return null when there is nothing in the queue */
+ private boolean nullOnEmpty;
+
+ /**
+ * The heap containing all the scheduled TimerTasks
+ * sorted by the TimerTask.scheduled field.
+ * Null when the stop() method has been called.
+ */
+ private TimerTask heap[];
+
+ /**
+ * The actual number of elements in the heap
+ * Can be less then heap.length.
+ * Note that heap[0] is used as a sentinel.
+ */
+ private int elements;
+
+ /**
+ * Creates a TaskQueue of default size without any elements in it.
+ */
+ public TaskQueue()
+ {
+ heap = new TimerTask[DEFAULT_SIZE];
+ elements = 0;
+ nullOnEmpty = false;
+ }
+
+ /**
+ * Adds a TimerTask at the end of the heap.
+ * Grows the heap if necessary by doubling the heap in size.
+ */
+ private void add(TimerTask task)
+ {
+ elements++;
+ if (elements == heap.length)
+ {
+ TimerTask new_heap[] = new TimerTask[heap.length * 2];
+ System.arraycopy(heap, 0, new_heap, 0, heap.length);
+ heap = new_heap;
+ }
+ heap[elements] = task;
+ }
+
+ /**
+ * Removes the last element from the heap.
+ * Shrinks the heap in half if
+ * elements+DEFAULT_SIZE/2 <= heap.length/4.
+ */
+ private void remove()
+ {
+ // clear the entry first
+ heap[elements] = null;
+ elements--;
+ if (elements + DEFAULT_SIZE / 2 <= (heap.length / 4))
+ {
+ TimerTask new_heap[] = new TimerTask[heap.length / 2];
+ System.arraycopy(heap, 0, new_heap, 0, elements + 1);
+ heap = new_heap;
+ }
+ }
+
+ /**
+ * Adds a task to the queue and puts it at the correct place
+ * in the heap.
+ */
+ public synchronized void enqueue(TimerTask task)
+ {
+ // Check if it is legal to add another element
+ if (heap == null)
+ {
+ throw new IllegalStateException
+ ("cannot enqueue when stop() has been called on queue");
+ }
+
+ heap[0] = task; // sentinel
+ add(task); // put the new task at the end
+ // Now push the task up in the heap until it has reached its place
+ int child = elements;
+ int parent = child / 2;
+ while (heap[parent].scheduled > task.scheduled)
+ {
+ heap[child] = heap[parent];
+ child = parent;
+ parent = child / 2;
+ }
+ // This is the correct place for the new task
+ heap[child] = task;
+ heap[0] = null; // clear sentinel
+ // Maybe sched() is waiting for a new element
+ this.notify();
+ }
+
+ /**
+ * Returns the top element of the queue.
+ * Can return null when no task is in the queue.
+ */
+ private TimerTask top()
+ {
+ if (elements == 0)
+ {
+ return null;
+ }
+ else
+ {
+ return heap[1];
+ }
+ }
+
+ /**
+ * Returns the top task in the Queue.
+ * Removes the element from the heap and reorders the heap first.
+ * Can return null when there is nothing in the queue.
+ */
+ public synchronized TimerTask serve()
+ {
+ // The task to return
+ TimerTask task = null;
+
+ while (task == null)
+ {
+ // Get the next task
+ task = top();
+
+ // return null when asked to stop
+ // or if asked to return null when the queue is empty
+ if ((heap == null) || (task == null && nullOnEmpty))
+ {
+ return null;
+ }
+
+ // Do we have a task?
+ if (task != null)
+ {
+ // The time to wait until the task should be served
+ long time = task.scheduled - System.currentTimeMillis();
+ if (time > 0)
+ {
+ // This task should not yet be served
+ // So wait until this task is ready
+ // or something else happens to the queue
+ task = null; // set to null to make sure we call top()
+ try
+ {
+ this.wait(time);
+ }
+ catch (InterruptedException _)
+ {
+ }
+ }
+ }
+ else
+ {
+ // wait until a task is added
+ // or something else happens to the queue
+ try
+ {
+ this.wait();
+ }
+ catch (InterruptedException _)
+ {
+ }
+ }
+ }
+
+ // reconstruct the heap
+ TimerTask lastTask = heap[elements];
+ remove();
+
+ // drop lastTask at the beginning and move it down the heap
+ int parent = 1;
+ int child = 2;
+ heap[1] = lastTask;
+ while (child <= elements)
+ {
+ if (child < elements)
+ {
+ if (heap[child].scheduled > heap[child + 1].scheduled)
+ {
+ child++;
+ }
+ }
+
+ if (lastTask.scheduled <= heap[child].scheduled)
+ break; // found the correct place (the parent) - done
+
+ heap[parent] = heap[child];
+ parent = child;
+ child = parent * 2;
+ }
+
+ // this is the correct new place for the lastTask
+ heap[parent] = lastTask;
+
+ // return the task
+ return task;
+ }
+
+ /**
+ * When nullOnEmpty is true the serve() method will return null when
+ * there are no tasks in the queue, otherwise it will wait until
+ * a new element is added to the queue. It is used to indicate to
+ * the scheduler that no new tasks will ever be added to the queue.
+ */
+ public synchronized void setNullOnEmpty(boolean nullOnEmpty)
+ {
+ this.nullOnEmpty = nullOnEmpty;
+ this.notify();
+ }
+
+ /**
+ * When this method is called the current and all future calls to
+ * serve() will return null. It is used to indicate to the Scheduler
+ * that it should stop executing since no more tasks will come.
+ */
+ public synchronized void stop()
+ {
+ this.heap = null;
+ this.elements = 0;
+ this.notify();
+ }
+
+ } // TaskQueue
+
+ /**
+ * The scheduler that executes all the tasks on a particular TaskQueue,
+ * reschedules any repeating tasks and that waits when no task has to be
+ * executed immediatly. Stops running when canceled or when the parent
+ * Timer has been finalized and no more tasks have to be executed.
+ */
+ private static final class Scheduler implements Runnable
+ {
+ // The priority queue containing all the TimerTasks.
+ private TaskQueue queue;
+
+ /**
+ * Creates a new Scheduler that will schedule the tasks on the
+ * given TaskQueue.
+ */
+ public Scheduler(TaskQueue queue)
+ {
+ this.queue = queue;
+ }
+
+ public void run()
+ {
+ TimerTask task;
+ while ((task = queue.serve()) != null)
+ {
+ // If this task has not been canceled
+ if (task.scheduled >= 0)
+ {
+
+ // Mark execution time
+ task.lastExecutionTime = task.scheduled;
+
+ // Repeatable task?
+ if (task.period < 0)
+ {
+ // Last time this task is executed
+ task.scheduled = -1;
+ }
+
+ // Run the task
+ try
+ {
+ task.run();
+ }
+ catch (ThreadDeath death)
+ {
+ // If an exception escapes, the Timer becomes invalid.
+ queue.stop();
+ throw death;
+ }
+ catch (Throwable t)
+ {
+ // If an exception escapes, the Timer becomes invalid.
+ queue.stop();
+ }
+ }
+
+ // Calculate next time and possibly re-enqueue.
+ if (task.scheduled >= 0)
+ {
+ if (task.fixed)
+ {
+ task.scheduled += task.period;
+ }
+ else
+ {
+ task.scheduled = task.period + System.currentTimeMillis();
+ }
+
+ try
+ {
+ queue.enqueue(task);
+ }
+ catch (IllegalStateException ise)
+ {
+ // Ignore. Apparently the Timer queue has been stopped.
+ }
+ }
+ }
+ }
+ } // Scheduler
+
+ // Number of Timers created.
+ // Used for creating nice Thread names.
+ private static int nr;
+
+ // The queue that all the tasks are put in.
+ // Given to the scheduler
+ private TaskQueue queue;
+
+ // The Scheduler that does all the real work
+ private Scheduler scheduler;
+
+ // Used to run the scheduler.
+ // Also used to checked if the Thread is still running by calling
+ // thread.isAlive(). Sometimes a Thread is suddenly killed by the system
+ // (if it belonged to an Applet).
+ private Thread thread;
+
+ // When cancelled we don't accept any more TimerTasks.
+ private boolean canceled;
+
+ /**
+ * Creates a new Timer with a non daemon Thread as Scheduler, with normal
+ * priority and a default name.
+ */
+ public Timer()
+ {
+ this(false);
+ }
+
+ /**
+ * Creates a new Timer with a daemon Thread as scheduler if daemon is true,
+ * with normal priority and a default name.
+ */
+ public Timer(boolean daemon)
+ {
+ this(daemon, Thread.NORM_PRIORITY);
+ }
+
+ /**
+ * Creates a new Timer with a daemon Thread as scheduler if daemon is true,
+ * with the priority given and a default name.
+ */
+ private Timer(boolean daemon, int priority)
+ {
+ this(daemon, priority, "Timer-" + (++nr));
+ }
+
+ /**
+ * Creates a new Timer with a daemon Thread as scheduler if daemon is true,
+ * with the priority and name given.E
+ */
+ private Timer(boolean daemon, int priority, String name)
+ {
+ canceled = false;
+ queue = new TaskQueue();
+ scheduler = new Scheduler(queue);
+ thread = new Thread(scheduler, name);
+ thread.setDaemon(daemon);
+ thread.setPriority(priority);
+ thread.start();
+ }
+
+ /**
+ * Cancels the execution of the scheduler. If a task is executing it will
+ * normally finish execution, but no other tasks will be executed and no
+ * more tasks can be scheduled.
+ */
+ public void cancel()
+ {
+ canceled = true;
+ queue.stop();
+ }
+
+ /**
+ * Schedules the task at Time time, repeating every period
+ * milliseconds if period is positive and at a fixed rate if fixed is true.
+ *
+ * @exception IllegalArgumentException if time is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ private void schedule(TimerTask task, long time, long period, boolean fixed)
+ {
+ if (time < 0)
+ throw new IllegalArgumentException("negative time");
+
+ if (task.scheduled == 0 && task.lastExecutionTime == -1)
+ {
+ task.scheduled = time;
+ task.period = period;
+ task.fixed = fixed;
+ }
+ else
+ {
+ throw new IllegalStateException
+ ("task was already scheduled or canceled");
+ }
+
+ if (!this.canceled && this.thread != null)
+ {
+ queue.enqueue(task);
+ }
+ else
+ {
+ throw new IllegalStateException
+ ("timer was canceled or scheduler thread has died");
+ }
+ }
+
+ private static void positiveDelay(long delay)
+ {
+ if (delay < 0)
+ {
+ throw new IllegalArgumentException("delay is negative");
+ }
+ }
+
+ private static void positivePeriod(long period)
+ {
+ if (period < 0)
+ {
+ throw new IllegalArgumentException("period is negative");
+ }
+ }
+
+ /**
+ * Schedules the task at the specified data for one time execution.
+ *
+ * @exception IllegalArgumentException if date.getTime() is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void schedule(TimerTask task, Date date)
+ {
+ long time = date.getTime();
+ schedule(task, time, -1, false);
+ }
+
+ /**
+ * Schedules the task at the specified date and reschedules the task every
+ * period milliseconds after the last execution of the task finishes until
+ * this timer or the task is canceled.
+ *
+ * @exception IllegalArgumentException if period or date.getTime() is
+ * negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void schedule(TimerTask task, Date date, long period)
+ {
+ positivePeriod(period);
+ long time = date.getTime();
+ schedule(task, time, period, false);
+ }
+
+ /**
+ * Schedules the task after the specified delay milliseconds for one time
+ * execution.
+ *
+ * @exception IllegalArgumentException if delay or
+ * System.currentTimeMillis + delay is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void schedule(TimerTask task, long delay)
+ {
+ positiveDelay(delay);
+ long time = System.currentTimeMillis() + delay;
+ schedule(task, time, -1, false);
+ }
+
+ /**
+ * Schedules the task after the delay milliseconds and reschedules the
+ * task every period milliseconds after the last execution of the task
+ * finishes until this timer or the task is canceled.
+ *
+ * @exception IllegalArgumentException if delay or period is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void schedule(TimerTask task, long delay, long period)
+ {
+ positiveDelay(delay);
+ positivePeriod(period);
+ long time = System.currentTimeMillis() + delay;
+ schedule(task, time, period, false);
+ }
+
+ /**
+ * Schedules the task at the specified date and reschedules the task at a
+ * fixed rate every period milliseconds until this timer or the task is
+ * canceled.
+ *
+ * @exception IllegalArgumentException if period or date.getTime() is
+ * negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void scheduleAtFixedRate(TimerTask task, Date date, long period)
+ {
+ positivePeriod(period);
+ long time = date.getTime();
+ schedule(task, time, period, true);
+ }
+
+ /**
+ * Schedules the task after the delay milliseconds and reschedules the task
+ * at a fixed rate every period milliseconds until this timer or the task
+ * is canceled.
+ *
+ * @exception IllegalArgumentException if delay or
+ * System.currentTimeMillis + delay is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void scheduleAtFixedRate(TimerTask task, long delay, long period)
+ {
+ positiveDelay(delay);
+ positivePeriod(period);
+ long time = System.currentTimeMillis() + delay;
+ schedule(task, time, period, true);
+ }
+
+ /**
+ * Tells the scheduler that the Timer task died
+ * so there will be no more new tasks scheduled.
+ */
+ protected void finalize() throws Throwable
+ {
+ queue.setNullOnEmpty(true);
+ }
+}
diff --git a/libjava/classpath/java/util/TimerTask.java b/libjava/classpath/java/util/TimerTask.java
new file mode 100644
index 00000000000..b03118ad0fe
--- /dev/null
+++ b/libjava/classpath/java/util/TimerTask.java
@@ -0,0 +1,145 @@
+/* TimerTask.java -- Task that can be run at a later time if given to a Timer.
+ Copyright (C) 2000 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;
+
+/**
+ * Task that can be run at a later time if given to a Timer.
+ * The TimerTask must implement a run method that will be called by the
+ * Timer when the task is scheduled for execution. The task can check when
+ * it should have been scheduled and cancel itself when no longer needed.
+ * <p>
+ * Example:
+ * <pre>
+ * Timer timer = new Timer();
+ * TimerTask task = new TimerTask() {
+ * public void run() {
+ * if (this.scheduledExecutionTime() &lt; System.currentTimeMillis() + 500)
+ * // Do something
+ * else
+ * // Complain: We are more then half a second late!
+ * if (someStopCondition)
+ * this.cancel(); // This was our last execution
+ * };
+ * timer.scheduleAtFixedRate(task, 1000, 1000); // schedule every second
+ * </pre>
+ * <p>
+ * Note that a TimerTask object is a one shot object and can only given once
+ * to a Timer. (The Timer will use the TimerTask object for bookkeeping,
+ * in this implementation).
+ * <p>
+ * This class also implements <code>Runnable</code> to make it possible to
+ * give a TimerTask directly as a target to a <code>Thread</code>.
+ *
+ * @see Timer
+ * @since 1.3
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public abstract class TimerTask implements Runnable
+{
+ /**
+ * If positive the next time this task should be run.
+ * If negative this TimerTask is canceled or executed for the last time.
+ */
+ long scheduled;
+
+ /**
+ * If positive the last time this task was run.
+ * If negative this TimerTask has not yet been scheduled.
+ */
+ long lastExecutionTime;
+
+ /**
+ * If positive the number of milliseconds between runs of this task.
+ * If -1 this task doesn't have to be run more then once.
+ */
+ long period;
+
+ /**
+ * If true the next time this task should be run is relative to
+ * the last scheduled time, otherwise it can drift in time.
+ */
+ boolean fixed;
+
+ /**
+ * Creates a TimerTask and marks it as not yet scheduled.
+ */
+ protected TimerTask()
+ {
+ this.scheduled = 0;
+ this.lastExecutionTime = -1;
+ }
+
+ /**
+ * Marks the task as canceled and prevents any further execution.
+ * Returns true if the task was scheduled for any execution in the future
+ * and this cancel operation prevents that execution from happening.
+ * <p>
+ * A task that has been canceled can never be scheduled again.
+ * <p>
+ * In this implementation the TimerTask it is possible that the Timer does
+ * keep a reference to the TimerTask until the first time the TimerTask
+ * is actually scheduled. But the reference will disappear immediatly when
+ * cancel is called from within the TimerTask run method.
+ */
+ public boolean cancel()
+ {
+ boolean prevented_execution = (this.scheduled >= 0);
+ this.scheduled = -1;
+ return prevented_execution;
+ }
+
+ /**
+ * Method that is called when this task is scheduled for execution.
+ */
+ public abstract void run();
+
+ /**
+ * Returns the last time this task was scheduled or (when called by the
+ * task from the run method) the time the current execution of the task
+ * was scheduled. When the task has not yet run the return value is
+ * undefined.
+ * <p>
+ * Can be used (when the task is scheduled at fixed rate) to see the
+ * difference between the requested schedule time and the actual time
+ * that can be found with <code>System.currentTimeMillis()</code>.
+ */
+ public long scheduledExecutionTime()
+ {
+ return lastExecutionTime;
+ }
+}
diff --git a/libjava/classpath/java/util/TooManyListenersException.java b/libjava/classpath/java/util/TooManyListenersException.java
new file mode 100644
index 00000000000..92ad772f2bb
--- /dev/null
+++ b/libjava/classpath/java/util/TooManyListenersException.java
@@ -0,0 +1,78 @@
+/* TooManyListenersException.java -- thrown when a unicast event can't accept
+ another Listener
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This exception is part of the java event model. It is thrown if an
+ * event listener is added via the addXyzEventListener method, but the
+ * object doesn't support any more listeners, e.g. it only supports a
+ * single event listener.
+ *
+ * @author Jochen Hoenicke
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see EventListener
+ * @see EventObject
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class TooManyListenersException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5074640544770687831L;
+
+ /**
+ * Constructs a TooManyListenersException with no detail message.
+ */
+ public TooManyListenersException()
+ {
+ }
+
+ /**
+ * Constructs a TooManyListenersException with a detail message.
+ *
+ * @param detail the detail message
+ */
+ public TooManyListenersException(String detail)
+ {
+ super(detail);
+ }
+}
diff --git a/libjava/classpath/java/util/TreeMap.java b/libjava/classpath/java/util/TreeMap.java
new file mode 100644
index 00000000000..1e8c805d908
--- /dev/null
+++ b/libjava/classpath/java/util/TreeMap.java
@@ -0,0 +1,1781 @@
+/* TreeMap.java -- a class providing a basic Red-Black Tree data structure,
+ mapping Object --> Object
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * This class provides a red-black tree implementation of the SortedMap
+ * interface. Elements in the Map will be sorted by either a user-provided
+ * Comparator object, or by the natural ordering of the keys.
+ *
+ * The algorithms are adopted from Corman, Leiserson, and Rivest's
+ * <i>Introduction to Algorithms.</i> TreeMap guarantees O(log n)
+ * insertion and deletion of elements. That being said, there is a large
+ * enough constant coefficient in front of that "log n" (overhead involved
+ * in keeping the tree balanced), that TreeMap may not be the best choice
+ * for small collections. If something is already sorted, you may want to
+ * just use a LinkedHashMap to maintain the order while providing O(1) access.
+ *
+ * TreeMap is a part of the JDK1.2 Collections API. Null keys are allowed
+ * only if a Comparator is used which can deal with them; natural ordering
+ * cannot cope with null. Null values are always allowed. Note that the
+ * ordering must be <i>consistent with equals</i> to correctly implement
+ * the Map interface. If this condition is violated, the map is still
+ * well-behaved, but you may have suprising results when comparing it to
+ * other maps.<p>
+ *
+ * This implementation is not synchronized. If you need to share this between
+ * multiple threads, do something like:<br>
+ * <code>SortedMap m
+ * = Collections.synchronizedSortedMap(new TreeMap(...));</code><p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * <code>ConcurrentModificationException</code> rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Map
+ * @see HashMap
+ * @see Hashtable
+ * @see LinkedHashMap
+ * @see Comparable
+ * @see Comparator
+ * @see Collection
+ * @see Collections#synchronizedSortedMap(SortedMap)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class TreeMap extends AbstractMap
+ implements SortedMap, Cloneable, Serializable
+{
+ // Implementation note:
+ // A red-black tree is a binary search tree with the additional properties
+ // that all paths to a leaf node visit the same number of black nodes,
+ // and no red node has red children. To avoid some null-pointer checks,
+ // we use the special node nil which is always black, has no relatives,
+ // and has key and value of null (but is not equal to a mapping of null).
+
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = 919286545866124006L;
+
+ /**
+ * Color status of a node. Package visible for use by nested classes.
+ */
+ static final int RED = -1,
+ BLACK = 1;
+
+ /**
+ * Sentinal node, used to avoid null checks for corner cases and make the
+ * delete rebalance code simpler. The rebalance code must never assign
+ * the parent, left, or right of nil, but may safely reassign the color
+ * to be black. This object must never be used as a key in a TreeMap, or
+ * it will break bounds checking of a SubMap.
+ */
+ static final Node nil = new Node(null, null, BLACK);
+ static
+ {
+ // Nil is self-referential, so we must initialize it after creation.
+ nil.parent = nil;
+ nil.left = nil;
+ nil.right = nil;
+ }
+
+ /**
+ * The root node of this TreeMap.
+ */
+ private transient Node root;
+
+ /**
+ * The size of this TreeMap. Package visible for use by nested classes.
+ */
+ transient int size;
+
+ /**
+ * The cache for {@link #entrySet()}.
+ */
+ private transient Set entries;
+
+ /**
+ * Counts the number of modifications this TreeMap has undergone, used
+ * by Iterators to know when to throw ConcurrentModificationExceptions.
+ * Package visible for use by nested classes.
+ */
+ transient int modCount;
+
+ /**
+ * This TreeMap's comparator, or null for natural ordering.
+ * Package visible for use by nested classes.
+ * @serial the comparator ordering this tree, or null
+ */
+ final Comparator comparator;
+
+ /**
+ * Class to represent an entry in the tree. Holds a single key-value pair,
+ * plus pointers to parent and child nodes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class Node extends AbstractMap.BasicMapEntry
+ {
+ // All fields package visible for use by nested classes.
+ /** The color of this node. */
+ int color;
+
+ /** The left child node. */
+ Node left = nil;
+ /** The right child node. */
+ Node right = nil;
+ /** The parent node. */
+ Node parent = nil;
+
+ /**
+ * Simple constructor.
+ * @param key the key
+ * @param value the value
+ */
+ Node(Object key, Object value, int color)
+ {
+ super(key, value);
+ this.color = color;
+ }
+ }
+
+ /**
+ * Instantiate a new TreeMap with no elements, using the keys' natural
+ * ordering to sort. All entries in the map must have a key which implements
+ * Comparable, and which are <i>mutually comparable</i>, otherwise map
+ * operations may throw a {@link ClassCastException}. Attempts to use
+ * a null key will throw a {@link NullPointerException}.
+ *
+ * @see Comparable
+ */
+ public TreeMap()
+ {
+ this((Comparator) null);
+ }
+
+ /**
+ * Instantiate a new TreeMap with no elements, using the provided comparator
+ * to sort. All entries in the map must have keys which are mutually
+ * comparable by the Comparator, otherwise map operations may throw a
+ * {@link ClassCastException}.
+ *
+ * @param c the sort order for the keys of this map, or null
+ * for the natural order
+ */
+ public TreeMap(Comparator c)
+ {
+ comparator = c;
+ fabricateTree(0);
+ }
+
+ /**
+ * Instantiate a new TreeMap, initializing it with all of the elements in
+ * the provided Map. The elements will be sorted using the natural
+ * ordering of the keys. This algorithm runs in n*log(n) time. All entries
+ * in the map must have keys which implement Comparable and are mutually
+ * comparable, otherwise map operations may throw a
+ * {@link ClassCastException}.
+ *
+ * @param map a Map, whose entries will be put into this TreeMap
+ * @throws ClassCastException if the keys in the provided Map are not
+ * comparable
+ * @throws NullPointerException if map is null
+ * @see Comparable
+ */
+ public TreeMap(Map map)
+ {
+ this((Comparator) null);
+ putAll(map);
+ }
+
+ /**
+ * Instantiate a new TreeMap, initializing it with all of the elements in
+ * the provided SortedMap. The elements will be sorted using the same
+ * comparator as in the provided SortedMap. This runs in linear time.
+ *
+ * @param sm a SortedMap, whose entries will be put into this TreeMap
+ * @throws NullPointerException if sm is null
+ */
+ public TreeMap(SortedMap sm)
+ {
+ this(sm.comparator());
+ int pos = sm.size();
+ Iterator itr = sm.entrySet().iterator();
+
+ fabricateTree(pos);
+ Node node = firstNode();
+
+ while (--pos >= 0)
+ {
+ Map.Entry me = (Map.Entry) itr.next();
+ node.key = me.getKey();
+ node.value = me.getValue();
+ node = successor(node);
+ }
+ }
+
+ /**
+ * Clears the Map so it has no keys. This is O(1).
+ */
+ public void clear()
+ {
+ if (size > 0)
+ {
+ modCount++;
+ root = nil;
+ size = 0;
+ }
+ }
+
+ /**
+ * Returns a shallow clone of this TreeMap. The Map itself is cloned,
+ * but its contents are not.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ TreeMap copy = null;
+ try
+ {
+ copy = (TreeMap) super.clone();
+ }
+ catch (CloneNotSupportedException x)
+ {
+ }
+ copy.entries = null;
+ copy.fabricateTree(size);
+
+ Node node = firstNode();
+ Node cnode = copy.firstNode();
+
+ while (node != nil)
+ {
+ cnode.key = node.key;
+ cnode.value = node.value;
+ node = successor(node);
+ cnode = copy.successor(cnode);
+ }
+ return copy;
+ }
+
+ /**
+ * Return the comparator used to sort this map, or null if it is by
+ * natural order.
+ *
+ * @return the map's comparator
+ */
+ public Comparator comparator()
+ {
+ return comparator;
+ }
+
+ /**
+ * Returns true if the map contains a mapping for the given key.
+ *
+ * @param key the key to look for
+ * @return true if the key has a mapping
+ * @throws ClassCastException if key is not comparable to map elements
+ * @throws NullPointerException if key is null and the comparator is not
+ * tolerant of nulls
+ */
+ public boolean containsKey(Object key)
+ {
+ return getNode(key) != nil;
+ }
+
+ /**
+ * Returns true if the map contains at least one mapping to the given value.
+ * This requires linear time.
+ *
+ * @param value the value to look for
+ * @return true if the value appears in a mapping
+ */
+ public boolean containsValue(Object value)
+ {
+ Node node = firstNode();
+ while (node != nil)
+ {
+ if (equals(value, node.value))
+ return true;
+ node = successor(node);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a "set view" of this TreeMap's entries. The set is backed by
+ * the TreeMap, so changes in one show up in the other. The set supports
+ * element removal, but not element addition.<p>
+ *
+ * Note that the iterators for all three views, from keySet(), entrySet(),
+ * and values(), traverse the TreeMap in sorted sequence.
+ *
+ * @return a set view of the entries
+ * @see #keySet()
+ * @see #values()
+ * @see Map.Entry
+ */
+ public Set entrySet()
+ {
+ if (entries == null)
+ // Create an AbstractSet with custom implementations of those methods
+ // that can be overriden easily and efficiently.
+ entries = new AbstractSet()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new TreeIterator(ENTRIES);
+ }
+
+ public void clear()
+ {
+ TreeMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry me = (Map.Entry) o;
+ Node n = getNode(me.getKey());
+ return n != nil && AbstractSet.equals(me.getValue(), n.value);
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry me = (Map.Entry) o;
+ Node n = getNode(me.getKey());
+ if (n != nil && AbstractSet.equals(me.getValue(), n.value))
+ {
+ removeNode(n);
+ return true;
+ }
+ return false;
+ }
+ };
+ return entries;
+ }
+
+ /**
+ * Returns the first (lowest) key in the map.
+ *
+ * @return the first key
+ * @throws NoSuchElementException if the map is empty
+ */
+ public Object firstKey()
+ {
+ if (root == nil)
+ throw new NoSuchElementException();
+ return firstNode().key;
+ }
+
+ /**
+ * Return the value in this TreeMap associated with the supplied key,
+ * or <code>null</code> if the key maps to nothing. NOTE: Since the value
+ * could also be null, you must use containsKey to see if this key
+ * actually maps to something.
+ *
+ * @param key the key for which to fetch an associated value
+ * @return what the key maps to, if present
+ * @throws ClassCastException if key is not comparable to elements in the map
+ * @throws NullPointerException if key is null but the comparator does not
+ * tolerate nulls
+ * @see #put(Object, Object)
+ * @see #containsKey(Object)
+ */
+ public Object get(Object key)
+ {
+ // Exploit fact that nil.value == null.
+ return getNode(key).value;
+ }
+
+ /**
+ * Returns a view of this Map including all entries with keys less than
+ * <code>toKey</code>. The returned map is backed by the original, so changes
+ * in one appear in the other. The submap will throw an
+ * {@link IllegalArgumentException} for any attempt to access or add an
+ * element beyond the specified cutoff. The returned map does not include
+ * the endpoint; if you want inclusion, pass the successor element.
+ *
+ * @param toKey the (exclusive) cutoff point
+ * @return a view of the map less than the cutoff
+ * @throws ClassCastException if <code>toKey</code> is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if toKey is null, but the comparator does not
+ * tolerate null elements
+ */
+ public SortedMap headMap(Object toKey)
+ {
+ return new SubMap(nil, toKey);
+ }
+
+ /**
+ * Returns a "set view" of this TreeMap's keys. The set is backed by the
+ * TreeMap, so changes in one show up in the other. The set supports
+ * element removal, but not element addition.
+ *
+ * @return a set view of the keys
+ * @see #values()
+ * @see #entrySet()
+ */
+ public Set keySet()
+ {
+ if (keys == null)
+ // Create an AbstractSet with custom implementations of those methods
+ // that can be overriden easily and efficiently.
+ keys = new AbstractSet()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new TreeIterator(KEYS);
+ }
+
+ public void clear()
+ {
+ TreeMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return containsKey(o);
+ }
+
+ public boolean remove(Object key)
+ {
+ Node n = getNode(key);
+ if (n == nil)
+ return false;
+ removeNode(n);
+ return true;
+ }
+ };
+ return keys;
+ }
+
+ /**
+ * Returns the last (highest) key in the map.
+ *
+ * @return the last key
+ * @throws NoSuchElementException if the map is empty
+ */
+ public Object lastKey()
+ {
+ if (root == nil)
+ throw new NoSuchElementException("empty");
+ return lastNode().key;
+ }
+
+ /**
+ * Puts the supplied value into the Map, mapped by the supplied key.
+ * The value may be retrieved by any object which <code>equals()</code>
+ * this key. NOTE: Since the prior value could also be null, you must
+ * first use containsKey if you want to see if you are replacing the
+ * key's mapping.
+ *
+ * @param key the key used to locate the value
+ * @param value the value to be stored in the Map
+ * @return the prior mapping of the key, or null if there was none
+ * @throws ClassCastException if key is not comparable to current map keys
+ * @throws NullPointerException if key is null, but the comparator does
+ * not tolerate nulls
+ * @see #get(Object)
+ * @see Object#equals(Object)
+ */
+ public Object put(Object key, Object value)
+ {
+ Node current = root;
+ Node parent = nil;
+ int comparison = 0;
+
+ // Find new node's parent.
+ while (current != nil)
+ {
+ parent = current;
+ comparison = compare(key, current.key);
+ if (comparison > 0)
+ current = current.right;
+ else if (comparison < 0)
+ current = current.left;
+ else // Key already in tree.
+ return current.setValue(value);
+ }
+
+ // Set up new node.
+ Node n = new Node(key, value, RED);
+ n.parent = parent;
+
+ // Insert node in tree.
+ modCount++;
+ size++;
+ if (parent == nil)
+ {
+ // Special case inserting into an empty tree.
+ root = n;
+ return null;
+ }
+ if (comparison > 0)
+ parent.right = n;
+ else
+ parent.left = n;
+
+ // Rebalance after insert.
+ insertFixup(n);
+ return null;
+ }
+
+ /**
+ * Copies all elements of the given map into this TreeMap. If this map
+ * already has a mapping for a key, the new mapping replaces the current
+ * one.
+ *
+ * @param m the map to be added
+ * @throws ClassCastException if a key in m is not comparable with keys
+ * in the map
+ * @throws NullPointerException if a key in m is null, and the comparator
+ * does not tolerate nulls
+ */
+ public void putAll(Map m)
+ {
+ Iterator itr = m.entrySet().iterator();
+ int pos = m.size();
+ while (--pos >= 0)
+ {
+ Map.Entry e = (Map.Entry) itr.next();
+ put(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * Removes from the TreeMap and returns the value which is mapped by the
+ * supplied key. If the key maps to nothing, then the TreeMap remains
+ * unchanged, and <code>null</code> is returned. NOTE: Since the value
+ * could also be null, you must use containsKey to see if you are
+ * actually removing a mapping.
+ *
+ * @param key the key used to locate the value to remove
+ * @return whatever the key mapped to, if present
+ * @throws ClassCastException if key is not comparable to current map keys
+ * @throws NullPointerException if key is null, but the comparator does
+ * not tolerate nulls
+ */
+ public Object remove(Object key)
+ {
+ Node n = getNode(key);
+ if (n == nil)
+ return null;
+ // Note: removeNode can alter the contents of n, so save value now.
+ Object result = n.value;
+ removeNode(n);
+ return result;
+ }
+
+ /**
+ * Returns the number of key-value mappings currently in this Map.
+ *
+ * @return the size
+ */
+ public int size()
+ {
+ return size;
+ }
+
+ /**
+ * Returns a view of this Map including all entries with keys greater or
+ * equal to <code>fromKey</code> and less than <code>toKey</code> (a
+ * half-open interval). The returned map is backed by the original, so
+ * changes in one appear in the other. The submap will throw an
+ * {@link IllegalArgumentException} for any attempt to access or add an
+ * element beyond the specified cutoffs. The returned map includes the low
+ * endpoint but not the high; if you want to reverse this behavior on
+ * either end, pass in the successor element.
+ *
+ * @param fromKey the (inclusive) low cutoff point
+ * @param toKey the (exclusive) high cutoff point
+ * @return a view of the map between the cutoffs
+ * @throws ClassCastException if either cutoff is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if fromKey or toKey is null, but the
+ * comparator does not tolerate null elements
+ * @throws IllegalArgumentException if fromKey is greater than toKey
+ */
+ public SortedMap subMap(Object fromKey, Object toKey)
+ {
+ return new SubMap(fromKey, toKey);
+ }
+
+ /**
+ * Returns a view of this Map including all entries with keys greater or
+ * equal to <code>fromKey</code>. The returned map is backed by the
+ * original, so changes in one appear in the other. The submap will throw an
+ * {@link IllegalArgumentException} for any attempt to access or add an
+ * element beyond the specified cutoff. The returned map includes the
+ * endpoint; if you want to exclude it, pass in the successor element.
+ *
+ * @param fromKey the (inclusive) low cutoff point
+ * @return a view of the map above the cutoff
+ * @throws ClassCastException if <code>fromKey</code> is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if fromKey is null, but the comparator
+ * does not tolerate null elements
+ */
+ public SortedMap tailMap(Object fromKey)
+ {
+ return new SubMap(fromKey, nil);
+ }
+
+ /**
+ * Returns a "collection view" (or "bag view") of this TreeMap's values.
+ * The collection is backed by the TreeMap, so changes in one show up
+ * in the other. The collection supports element removal, but not element
+ * addition.
+ *
+ * @return a bag view of the values
+ * @see #keySet()
+ * @see #entrySet()
+ */
+ public Collection values()
+ {
+ if (values == null)
+ // We don't bother overriding many of the optional methods, as doing so
+ // wouldn't provide any significant performance advantage.
+ values = new AbstractCollection()
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator iterator()
+ {
+ return new TreeIterator(VALUES);
+ }
+
+ public void clear()
+ {
+ TreeMap.this.clear();
+ }
+ };
+ return values;
+ }
+
+ /**
+ * Compares two elements by the set comparator, or by natural ordering.
+ * Package visible for use by nested classes.
+ *
+ * @param o1 the first object
+ * @param o2 the second object
+ * @throws ClassCastException if o1 and o2 are not mutually comparable,
+ * or are not Comparable with natural ordering
+ * @throws NullPointerException if o1 or o2 is null with natural ordering
+ */
+ final int compare(Object o1, Object o2)
+ {
+ return (comparator == null
+ ? ((Comparable) o1).compareTo(o2)
+ : comparator.compare(o1, o2));
+ }
+
+ /**
+ * Maintain red-black balance after deleting a node.
+ *
+ * @param node the child of the node just deleted, possibly nil
+ * @param parent the parent of the node just deleted, never nil
+ */
+ private void deleteFixup(Node node, Node parent)
+ {
+ // if (parent == nil)
+ // throw new InternalError();
+ // If a black node has been removed, we need to rebalance to avoid
+ // violating the "same number of black nodes on any path" rule. If
+ // node is red, we can simply recolor it black and all is well.
+ while (node != root && node.color == BLACK)
+ {
+ if (node == parent.left)
+ {
+ // Rebalance left side.
+ Node sibling = parent.right;
+ // if (sibling == nil)
+ // throw new InternalError();
+ if (sibling.color == RED)
+ {
+ // Case 1: Sibling is red.
+ // Recolor sibling and parent, and rotate parent left.
+ sibling.color = BLACK;
+ parent.color = RED;
+ rotateLeft(parent);
+ sibling = parent.right;
+ }
+
+ if (sibling.left.color == BLACK && sibling.right.color == BLACK)
+ {
+ // Case 2: Sibling has no red children.
+ // Recolor sibling, and move to parent.
+ sibling.color = RED;
+ node = parent;
+ parent = parent.parent;
+ }
+ else
+ {
+ if (sibling.right.color == BLACK)
+ {
+ // Case 3: Sibling has red left child.
+ // Recolor sibling and left child, rotate sibling right.
+ sibling.left.color = BLACK;
+ sibling.color = RED;
+ rotateRight(sibling);
+ sibling = parent.right;
+ }
+ // Case 4: Sibling has red right child. Recolor sibling,
+ // right child, and parent, and rotate parent left.
+ sibling.color = parent.color;
+ parent.color = BLACK;
+ sibling.right.color = BLACK;
+ rotateLeft(parent);
+ node = root; // Finished.
+ }
+ }
+ else
+ {
+ // Symmetric "mirror" of left-side case.
+ Node sibling = parent.left;
+ // if (sibling == nil)
+ // throw new InternalError();
+ if (sibling.color == RED)
+ {
+ // Case 1: Sibling is red.
+ // Recolor sibling and parent, and rotate parent right.
+ sibling.color = BLACK;
+ parent.color = RED;
+ rotateRight(parent);
+ sibling = parent.left;
+ }
+
+ if (sibling.right.color == BLACK && sibling.left.color == BLACK)
+ {
+ // Case 2: Sibling has no red children.
+ // Recolor sibling, and move to parent.
+ sibling.color = RED;
+ node = parent;
+ parent = parent.parent;
+ }
+ else
+ {
+ if (sibling.left.color == BLACK)
+ {
+ // Case 3: Sibling has red right child.
+ // Recolor sibling and right child, rotate sibling left.
+ sibling.right.color = BLACK;
+ sibling.color = RED;
+ rotateLeft(sibling);
+ sibling = parent.left;
+ }
+ // Case 4: Sibling has red left child. Recolor sibling,
+ // left child, and parent, and rotate parent right.
+ sibling.color = parent.color;
+ parent.color = BLACK;
+ sibling.left.color = BLACK;
+ rotateRight(parent);
+ node = root; // Finished.
+ }
+ }
+ }
+ node.color = BLACK;
+ }
+
+ /**
+ * Construct a perfectly balanced tree consisting of n "blank" nodes. This
+ * permits a tree to be generated from pre-sorted input in linear time.
+ *
+ * @param count the number of blank nodes, non-negative
+ */
+ private void fabricateTree(final int count)
+ {
+ if (count == 0)
+ {
+ root = nil;
+ size = 0;
+ return;
+ }
+
+ // We color every row of nodes black, except for the overflow nodes.
+ // I believe that this is the optimal arrangement. We construct the tree
+ // in place by temporarily linking each node to the next node in the row,
+ // then updating those links to the children when working on the next row.
+
+ // Make the root node.
+ root = new Node(null, null, BLACK);
+ size = count;
+ Node row = root;
+ int rowsize;
+
+ // Fill each row that is completely full of nodes.
+ for (rowsize = 2; rowsize + rowsize <= count; rowsize <<= 1)
+ {
+ Node parent = row;
+ Node last = null;
+ for (int i = 0; i < rowsize; i += 2)
+ {
+ Node left = new Node(null, null, BLACK);
+ Node right = new Node(null, null, BLACK);
+ left.parent = parent;
+ left.right = right;
+ right.parent = parent;
+ parent.left = left;
+ Node next = parent.right;
+ parent.right = right;
+ parent = next;
+ if (last != null)
+ last.right = left;
+ last = right;
+ }
+ row = row.left;
+ }
+
+ // Now do the partial final row in red.
+ int overflow = count - rowsize;
+ Node parent = row;
+ int i;
+ for (i = 0; i < overflow; i += 2)
+ {
+ Node left = new Node(null, null, RED);
+ Node right = new Node(null, null, RED);
+ left.parent = parent;
+ right.parent = parent;
+ parent.left = left;
+ Node next = parent.right;
+ parent.right = right;
+ parent = next;
+ }
+ // Add a lone left node if necessary.
+ if (i - overflow == 0)
+ {
+ Node left = new Node(null, null, RED);
+ left.parent = parent;
+ parent.left = left;
+ parent = parent.right;
+ left.parent.right = nil;
+ }
+ // Unlink the remaining nodes of the previous row.
+ while (parent != nil)
+ {
+ Node next = parent.right;
+ parent.right = nil;
+ parent = next;
+ }
+ }
+
+ /**
+ * Returns the first sorted node in the map, or nil if empty. Package
+ * visible for use by nested classes.
+ *
+ * @return the first node
+ */
+ final Node firstNode()
+ {
+ // Exploit fact that nil.left == nil.
+ Node node = root;
+ while (node.left != nil)
+ node = node.left;
+ return node;
+ }
+
+ /**
+ * Return the TreeMap.Node associated with key, or the nil node if no such
+ * node exists in the tree. Package visible for use by nested classes.
+ *
+ * @param key the key to search for
+ * @return the node where the key is found, or nil
+ */
+ final Node getNode(Object key)
+ {
+ Node current = root;
+ while (current != nil)
+ {
+ int comparison = compare(key, current.key);
+ if (comparison > 0)
+ current = current.right;
+ else if (comparison < 0)
+ current = current.left;
+ else
+ return current;
+ }
+ return current;
+ }
+
+ /**
+ * Find the "highest" node which is &lt; key. If key is nil, return last
+ * node. Package visible for use by nested classes.
+ *
+ * @param key the upper bound, exclusive
+ * @return the previous node
+ */
+ final Node highestLessThan(Object key)
+ {
+ if (key == nil)
+ return lastNode();
+
+ Node last = nil;
+ Node current = root;
+ int comparison = 0;
+
+ while (current != nil)
+ {
+ last = current;
+ comparison = compare(key, current.key);
+ if (comparison > 0)
+ current = current.right;
+ else if (comparison < 0)
+ current = current.left;
+ else // Exact match.
+ return predecessor(last);
+ }
+ return comparison <= 0 ? predecessor(last) : last;
+ }
+
+ /**
+ * Maintain red-black balance after inserting a new node.
+ *
+ * @param n the newly inserted node
+ */
+ private void insertFixup(Node n)
+ {
+ // Only need to rebalance when parent is a RED node, and while at least
+ // 2 levels deep into the tree (ie: node has a grandparent). Remember
+ // that nil.color == BLACK.
+ while (n.parent.color == RED && n.parent.parent != nil)
+ {
+ if (n.parent == n.parent.parent.left)
+ {
+ Node uncle = n.parent.parent.right;
+ // Uncle may be nil, in which case it is BLACK.
+ if (uncle.color == RED)
+ {
+ // Case 1. Uncle is RED: Change colors of parent, uncle,
+ // and grandparent, and move n to grandparent.
+ n.parent.color = BLACK;
+ uncle.color = BLACK;
+ uncle.parent.color = RED;
+ n = uncle.parent;
+ }
+ else
+ {
+ if (n == n.parent.right)
+ {
+ // Case 2. Uncle is BLACK and x is right child.
+ // Move n to parent, and rotate n left.
+ n = n.parent;
+ rotateLeft(n);
+ }
+ // Case 3. Uncle is BLACK and x is left child.
+ // Recolor parent, grandparent, and rotate grandparent right.
+ n.parent.color = BLACK;
+ n.parent.parent.color = RED;
+ rotateRight(n.parent.parent);
+ }
+ }
+ else
+ {
+ // Mirror image of above code.
+ Node uncle = n.parent.parent.left;
+ // Uncle may be nil, in which case it is BLACK.
+ if (uncle.color == RED)
+ {
+ // Case 1. Uncle is RED: Change colors of parent, uncle,
+ // and grandparent, and move n to grandparent.
+ n.parent.color = BLACK;
+ uncle.color = BLACK;
+ uncle.parent.color = RED;
+ n = uncle.parent;
+ }
+ else
+ {
+ if (n == n.parent.left)
+ {
+ // Case 2. Uncle is BLACK and x is left child.
+ // Move n to parent, and rotate n right.
+ n = n.parent;
+ rotateRight(n);
+ }
+ // Case 3. Uncle is BLACK and x is right child.
+ // Recolor parent, grandparent, and rotate grandparent left.
+ n.parent.color = BLACK;
+ n.parent.parent.color = RED;
+ rotateLeft(n.parent.parent);
+ }
+ }
+ }
+ root.color = BLACK;
+ }
+
+ /**
+ * Returns the last sorted node in the map, or nil if empty.
+ *
+ * @return the last node
+ */
+ private Node lastNode()
+ {
+ // Exploit fact that nil.right == nil.
+ Node node = root;
+ while (node.right != nil)
+ node = node.right;
+ return node;
+ }
+
+ /**
+ * Find the "lowest" node which is &gt;= key. If key is nil, return either
+ * nil or the first node, depending on the parameter first.
+ * Package visible for use by nested classes.
+ *
+ * @param key the lower bound, inclusive
+ * @param first true to return the first element instead of nil for nil key
+ * @return the next node
+ */
+ final Node lowestGreaterThan(Object key, boolean first)
+ {
+ if (key == nil)
+ return first ? firstNode() : nil;
+
+ Node last = nil;
+ Node current = root;
+ int comparison = 0;
+
+ while (current != nil)
+ {
+ last = current;
+ comparison = compare(key, current.key);
+ if (comparison > 0)
+ current = current.right;
+ else if (comparison < 0)
+ current = current.left;
+ else
+ return current;
+ }
+ return comparison > 0 ? successor(last) : last;
+ }
+
+ /**
+ * Return the node preceding the given one, or nil if there isn't one.
+ *
+ * @param node the current node, not nil
+ * @return the prior node in sorted order
+ */
+ private Node predecessor(Node node)
+ {
+ if (node.left != nil)
+ {
+ node = node.left;
+ while (node.right != nil)
+ node = node.right;
+ return node;
+ }
+
+ Node parent = node.parent;
+ // Exploit fact that nil.left == nil and node is non-nil.
+ while (node == parent.left)
+ {
+ node = parent;
+ parent = node.parent;
+ }
+ return parent;
+ }
+
+ /**
+ * Construct a tree from sorted keys in linear time. Package visible for
+ * use by TreeSet.
+ *
+ * @param s the stream to read from
+ * @param count the number of keys to read
+ * @param readValue true to read values, false to insert "" as the value
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @see #readObject(ObjectInputStream)
+ * @see TreeSet#readObject(ObjectInputStream)
+ */
+ final void putFromObjStream(ObjectInputStream s, int count,
+ boolean readValues)
+ throws IOException, ClassNotFoundException
+ {
+ fabricateTree(count);
+ Node node = firstNode();
+
+ while (--count >= 0)
+ {
+ node.key = s.readObject();
+ node.value = readValues ? s.readObject() : "";
+ node = successor(node);
+ }
+ }
+
+ /**
+ * Construct a tree from sorted keys in linear time, with values of "".
+ * Package visible for use by TreeSet.
+ *
+ * @param keys the iterator over the sorted keys
+ * @param count the number of nodes to insert
+ * @see TreeSet#TreeSet(SortedSet)
+ */
+ final void putKeysLinear(Iterator keys, int count)
+ {
+ fabricateTree(count);
+ Node node = firstNode();
+
+ while (--count >= 0)
+ {
+ node.key = keys.next();
+ node.value = "";
+ node = successor(node);
+ }
+ }
+
+ /**
+ * Deserializes this object from the given stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>size</i> (int), followed by key (Object) and value
+ * (Object) pairs in sorted order
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ int size = s.readInt();
+ putFromObjStream(s, size, true);
+ }
+
+ /**
+ * Remove node from tree. This will increment modCount and decrement size.
+ * Node must exist in the tree. Package visible for use by nested classes.
+ *
+ * @param node the node to remove
+ */
+ final void removeNode(Node node)
+ {
+ Node splice;
+ Node child;
+
+ modCount++;
+ size--;
+
+ // Find splice, the node at the position to actually remove from the tree.
+ if (node.left == nil)
+ {
+ // Node to be deleted has 0 or 1 children.
+ splice = node;
+ child = node.right;
+ }
+ else if (node.right == nil)
+ {
+ // Node to be deleted has 1 child.
+ splice = node;
+ child = node.left;
+ }
+ else
+ {
+ // Node has 2 children. Splice is node's predecessor, and we swap
+ // its contents into node.
+ splice = node.left;
+ while (splice.right != nil)
+ splice = splice.right;
+ child = splice.left;
+ node.key = splice.key;
+ node.value = splice.value;
+ }
+
+ // Unlink splice from the tree.
+ Node parent = splice.parent;
+ if (child != nil)
+ child.parent = parent;
+ if (parent == nil)
+ {
+ // Special case for 0 or 1 node remaining.
+ root = child;
+ return;
+ }
+ if (splice == parent.left)
+ parent.left = child;
+ else
+ parent.right = child;
+
+ if (splice.color == BLACK)
+ deleteFixup(child, parent);
+ }
+
+ /**
+ * Rotate node n to the left.
+ *
+ * @param node the node to rotate
+ */
+ private void rotateLeft(Node node)
+ {
+ Node child = node.right;
+ // if (node == nil || child == nil)
+ // throw new InternalError();
+
+ // Establish node.right link.
+ node.right = child.left;
+ if (child.left != nil)
+ child.left.parent = node;
+
+ // Establish child->parent link.
+ child.parent = node.parent;
+ if (node.parent != nil)
+ {
+ if (node == node.parent.left)
+ node.parent.left = child;
+ else
+ node.parent.right = child;
+ }
+ else
+ root = child;
+
+ // Link n and child.
+ child.left = node;
+ node.parent = child;
+ }
+
+ /**
+ * Rotate node n to the right.
+ *
+ * @param node the node to rotate
+ */
+ private void rotateRight(Node node)
+ {
+ Node child = node.left;
+ // if (node == nil || child == nil)
+ // throw new InternalError();
+
+ // Establish node.left link.
+ node.left = child.right;
+ if (child.right != nil)
+ child.right.parent = node;
+
+ // Establish child->parent link.
+ child.parent = node.parent;
+ if (node.parent != nil)
+ {
+ if (node == node.parent.right)
+ node.parent.right = child;
+ else
+ node.parent.left = child;
+ }
+ else
+ root = child;
+
+ // Link n and child.
+ child.right = node;
+ node.parent = child;
+ }
+
+ /**
+ * Return the node following the given one, or nil if there isn't one.
+ * Package visible for use by nested classes.
+ *
+ * @param node the current node, not nil
+ * @return the next node in sorted order
+ */
+ final Node successor(Node node)
+ {
+ if (node.right != nil)
+ {
+ node = node.right;
+ while (node.left != nil)
+ node = node.left;
+ return node;
+ }
+
+ Node parent = node.parent;
+ // Exploit fact that nil.right == nil and node is non-nil.
+ while (node == parent.right)
+ {
+ node = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>size</i> (int), followed by key (Object) and value
+ * (Object) pairs in sorted order
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+
+ Node node = firstNode();
+ s.writeInt(size);
+ while (node != nil)
+ {
+ s.writeObject(node.key);
+ s.writeObject(node.value);
+ node = successor(node);
+ }
+ }
+
+ /**
+ * Iterate over TreeMap's entries. This implementation is parameterized
+ * to give a sequential view of keys, values, or entries.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private final class TreeIterator implements Iterator
+ {
+ /**
+ * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
+ * or {@link #ENTRIES}.
+ */
+ private final int type;
+ /** The number of modifications to the backing Map that we know about. */
+ private int knownMod = modCount;
+ /** The last Entry returned by a next() call. */
+ private Node last;
+ /** The next entry that should be returned by next(). */
+ private Node next;
+ /**
+ * The last node visible to this iterator. This is used when iterating
+ * on a SubMap.
+ */
+ private final Node max;
+
+ /**
+ * Construct a new TreeIterator with the supplied type.
+ * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+ */
+ TreeIterator(int type)
+ {
+ // FIXME gcj cannot handle this. Bug java/4695
+ // this(type, firstNode(), nil);
+ this.type = type;
+ this.next = firstNode();
+ this.max = nil;
+ }
+
+ /**
+ * Construct a new TreeIterator with the supplied type. Iteration will
+ * be from "first" (inclusive) to "max" (exclusive).
+ *
+ * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+ * @param first where to start iteration, nil for empty iterator
+ * @param max the cutoff for iteration, nil for all remaining nodes
+ */
+ TreeIterator(int type, Node first, Node max)
+ {
+ this.type = type;
+ this.next = first;
+ this.max = max;
+ }
+
+ /**
+ * Returns true if the Iterator has more elements.
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the TreeMap was modified
+ */
+ public boolean hasNext()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ return next != max;
+ }
+
+ /**
+ * Returns the next element in the Iterator's sequential view.
+ * @return the next element
+ * @throws ConcurrentModificationException if the TreeMap was modified
+ * @throws NoSuchElementException if there is none
+ */
+ public Object next()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ if (next == max)
+ throw new NoSuchElementException();
+ last = next;
+ next = successor(last);
+
+ if (type == VALUES)
+ return last.value;
+ else if (type == KEYS)
+ return last.key;
+ return last;
+ }
+
+ /**
+ * Removes from the backing TreeMap the last element which was fetched
+ * with the <code>next()</code> method.
+ * @throws ConcurrentModificationException if the TreeMap was modified
+ * @throws IllegalStateException if called when there is no last element
+ */
+ public void remove()
+ {
+ if (last == null)
+ throw new IllegalStateException();
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+
+ removeNode(last);
+ last = null;
+ knownMod++;
+ }
+ } // class TreeIterator
+
+ /**
+ * Implementation of {@link #subMap(Object, Object)} and other map
+ * ranges. This class provides a view of a portion of the original backing
+ * map, and throws {@link IllegalArgumentException} for attempts to
+ * access beyond that range.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private final class SubMap extends AbstractMap implements SortedMap
+ {
+ /**
+ * The lower range of this view, inclusive, or nil for unbounded.
+ * Package visible for use by nested classes.
+ */
+ final Object minKey;
+
+ /**
+ * The upper range of this view, exclusive, or nil for unbounded.
+ * Package visible for use by nested classes.
+ */
+ final Object maxKey;
+
+ /**
+ * The cache for {@link #entrySet()}.
+ */
+ private Set entries;
+
+ /**
+ * Create a SubMap representing the elements between minKey (inclusive)
+ * and maxKey (exclusive). If minKey is nil, SubMap has no lower bound
+ * (headMap). If maxKey is nil, the SubMap has no upper bound (tailMap).
+ *
+ * @param minKey the lower bound
+ * @param maxKey the upper bound
+ * @throws IllegalArgumentException if minKey &gt; maxKey
+ */
+ SubMap(Object minKey, Object maxKey)
+ {
+ if (minKey != nil && maxKey != nil && compare(minKey, maxKey) > 0)
+ throw new IllegalArgumentException("fromKey > toKey");
+ this.minKey = minKey;
+ this.maxKey = maxKey;
+ }
+
+ /**
+ * Check if "key" is in within the range bounds for this SubMap. The
+ * lower ("from") SubMap range is inclusive, and the upper ("to") bound
+ * is exclusive. Package visible for use by nested classes.
+ *
+ * @param key the key to check
+ * @return true if the key is in range
+ */
+ boolean keyInRange(Object key)
+ {
+ return ((minKey == nil || compare(key, minKey) >= 0)
+ && (maxKey == nil || compare(key, maxKey) < 0));
+ }
+
+ public void clear()
+ {
+ Node next = lowestGreaterThan(minKey, true);
+ Node max = lowestGreaterThan(maxKey, false);
+ while (next != max)
+ {
+ Node current = next;
+ next = successor(current);
+ removeNode(current);
+ }
+ }
+
+ public Comparator comparator()
+ {
+ return comparator;
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return keyInRange(key) && TreeMap.this.containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ Node node = lowestGreaterThan(minKey, true);
+ Node max = lowestGreaterThan(maxKey, false);
+ while (node != max)
+ {
+ if (equals(value, node.getValue()))
+ return true;
+ node = successor(node);
+ }
+ return false;
+ }
+
+ public Set entrySet()
+ {
+ if (entries == null)
+ // Create an AbstractSet with custom implementations of those methods
+ // that can be overriden easily and efficiently.
+ entries = new AbstractSet()
+ {
+ public int size()
+ {
+ return SubMap.this.size();
+ }
+
+ public Iterator iterator()
+ {
+ Node first = lowestGreaterThan(minKey, true);
+ Node max = lowestGreaterThan(maxKey, false);
+ return new TreeIterator(ENTRIES, first, max);
+ }
+
+ public void clear()
+ {
+ SubMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry me = (Map.Entry) o;
+ Object key = me.getKey();
+ if (! keyInRange(key))
+ return false;
+ Node n = getNode(key);
+ return n != nil && AbstractSet.equals(me.getValue(), n.value);
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry me = (Map.Entry) o;
+ Object key = me.getKey();
+ if (! keyInRange(key))
+ return false;
+ Node n = getNode(key);
+ if (n != nil && AbstractSet.equals(me.getValue(), n.value))
+ {
+ removeNode(n);
+ return true;
+ }
+ return false;
+ }
+ };
+ return entries;
+ }
+
+ public Object firstKey()
+ {
+ Node node = lowestGreaterThan(minKey, true);
+ if (node == nil || ! keyInRange(node.key))
+ throw new NoSuchElementException();
+ return node.key;
+ }
+
+ public Object get(Object key)
+ {
+ if (keyInRange(key))
+ return TreeMap.this.get(key);
+ return null;
+ }
+
+ public SortedMap headMap(Object toKey)
+ {
+ if (! keyInRange(toKey))
+ throw new IllegalArgumentException("key outside range");
+ return new SubMap(minKey, toKey);
+ }
+
+ public Set keySet()
+ {
+ if (this.keys == null)
+ // Create an AbstractSet with custom implementations of those methods
+ // that can be overriden easily and efficiently.
+ this.keys = new AbstractSet()
+ {
+ public int size()
+ {
+ return SubMap.this.size();
+ }
+
+ public Iterator iterator()
+ {
+ Node first = lowestGreaterThan(minKey, true);
+ Node max = lowestGreaterThan(maxKey, false);
+ return new TreeIterator(KEYS, first, max);
+ }
+
+ public void clear()
+ {
+ SubMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! keyInRange(o))
+ return false;
+ return getNode(o) != nil;
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! keyInRange(o))
+ return false;
+ Node n = getNode(o);
+ if (n != nil)
+ {
+ removeNode(n);
+ return true;
+ }
+ return false;
+ }
+ };
+ return this.keys;
+ }
+
+ public Object lastKey()
+ {
+ Node node = highestLessThan(maxKey);
+ if (node == nil || ! keyInRange(node.key))
+ throw new NoSuchElementException();
+ return node.key;
+ }
+
+ public Object put(Object key, Object value)
+ {
+ if (! keyInRange(key))
+ throw new IllegalArgumentException("Key outside range");
+ return TreeMap.this.put(key, value);
+ }
+
+ public Object remove(Object key)
+ {
+ if (keyInRange(key))
+ return TreeMap.this.remove(key);
+ return null;
+ }
+
+ public int size()
+ {
+ Node node = lowestGreaterThan(minKey, true);
+ Node max = lowestGreaterThan(maxKey, false);
+ int count = 0;
+ while (node != max)
+ {
+ count++;
+ node = successor(node);
+ }
+ return count;
+ }
+
+ public SortedMap subMap(Object fromKey, Object toKey)
+ {
+ if (! keyInRange(fromKey) || ! keyInRange(toKey))
+ throw new IllegalArgumentException("key outside range");
+ return new SubMap(fromKey, toKey);
+ }
+
+ public SortedMap tailMap(Object fromKey)
+ {
+ if (! keyInRange(fromKey))
+ throw new IllegalArgumentException("key outside range");
+ return new SubMap(fromKey, maxKey);
+ }
+
+ public Collection values()
+ {
+ if (this.values == null)
+ // Create an AbstractCollection with custom implementations of those
+ // methods that can be overriden easily and efficiently.
+ this.values = new AbstractCollection()
+ {
+ public int size()
+ {
+ return SubMap.this.size();
+ }
+
+ public Iterator iterator()
+ {
+ Node first = lowestGreaterThan(minKey, true);
+ Node max = lowestGreaterThan(maxKey, false);
+ return new TreeIterator(VALUES, first, max);
+ }
+
+ public void clear()
+ {
+ SubMap.this.clear();
+ }
+ };
+ return this.values;
+ }
+ } // class SubMap
+} // class TreeMap
diff --git a/libjava/classpath/java/util/TreeSet.java b/libjava/classpath/java/util/TreeSet.java
new file mode 100644
index 00000000000..34cb39acc07
--- /dev/null
+++ b/libjava/classpath/java/util/TreeSet.java
@@ -0,0 +1,416 @@
+/* TreeSet.java -- a class providing a TreeMap-backed SortedSet
+ Copyright (C) 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * This class provides a TreeMap-backed implementation of the SortedSet
+ * interface. The elements will be sorted according to their <i>natural
+ * order</i>, or according to the provided <code>Comparator</code>.<p>
+ *
+ * Most operations are O(log n), but there is so much overhead that this
+ * makes small sets expensive. Note that the ordering must be <i>consistent
+ * with equals</i> to correctly implement the Set interface. If this
+ * condition is violated, the set is still well-behaved, but you may have
+ * suprising results when comparing it to other sets.<p>
+ *
+ * This implementation is not synchronized. If you need to share this between
+ * multiple threads, do something like:<br>
+ * <code>SortedSet s
+ * = Collections.synchronizedSortedSet(new TreeSet(...));</code><p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * <code>ConcurrentModificationException</code> rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see Set
+ * @see HashSet
+ * @see LinkedHashSet
+ * @see Comparable
+ * @see Comparator
+ * @see Collections#synchronizedSortedSet(SortedSet)
+ * @see TreeMap
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class TreeSet extends AbstractSet
+ implements SortedSet, Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = -2479143000061671589L;
+
+ /**
+ * The SortedMap which backs this Set.
+ */
+ // Not final because of readObject. This will always be one of TreeMap or
+ // TreeMap.SubMap, which both extend AbstractMap.
+ private transient SortedMap map;
+
+ /**
+ * Construct a new TreeSet whose backing TreeMap using the "natural"
+ * ordering of keys. Elements that are not mutually comparable will cause
+ * ClassCastExceptions down the road.
+ *
+ * @see Comparable
+ */
+ public TreeSet()
+ {
+ map = new TreeMap();
+ }
+
+ /**
+ * Construct a new TreeSet whose backing TreeMap uses the supplied
+ * Comparator. Elements that are not mutually comparable will cause
+ * ClassCastExceptions down the road.
+ *
+ * @param comparator the Comparator this Set will use
+ */
+ public TreeSet(Comparator comparator)
+ {
+ map = new TreeMap(comparator);
+ }
+
+ /**
+ * Construct a new TreeSet whose backing TreeMap uses the "natural"
+ * orering of the keys and which contains all of the elements in the
+ * supplied Collection. This runs in n*log(n) time.
+ *
+ * @param collection the new Set will be initialized with all
+ * of the elements in this Collection
+ * @throws ClassCastException if the elements of the collection are not
+ * comparable
+ * @throws NullPointerException if the collection is null
+ * @see Comparable
+ */
+ public TreeSet(Collection collection)
+ {
+ map = new TreeMap();
+ addAll(collection);
+ }
+
+ /**
+ * Construct a new TreeSet, using the same key ordering as the supplied
+ * SortedSet and containing all of the elements in the supplied SortedSet.
+ * This constructor runs in linear time.
+ *
+ * @param sortedSet the new TreeSet will use this SortedSet's comparator
+ * and will initialize itself with all its elements
+ * @throws NullPointerException if sortedSet is null
+ */
+ public TreeSet(SortedSet sortedSet)
+ {
+ map = new TreeMap(sortedSet.comparator());
+ Iterator itr = sortedSet.iterator();
+ ((TreeMap) map).putKeysLinear(itr, sortedSet.size());
+ }
+
+ /**
+ * This private constructor is used to implement the subSet() calls around
+ * a backing TreeMap.SubMap.
+ *
+ * @param backingMap the submap
+ */
+ private TreeSet(SortedMap backingMap)
+ {
+ map = backingMap;
+ }
+
+ /**
+ * Adds the spplied Object to the Set if it is not already in the Set;
+ * returns true if the element is added, false otherwise.
+ *
+ * @param obj the Object to be added to this Set
+ * @throws ClassCastException if the element cannot be compared with objects
+ * already in the set
+ */
+ public boolean add(Object obj)
+ {
+ return map.put(obj, "") == null;
+ }
+
+ /**
+ * Adds all of the elements in the supplied Collection to this TreeSet.
+ *
+ * @param c The collection to add
+ * @return true if the Set is altered, false otherwise
+ * @throws NullPointerException if c is null
+ * @throws ClassCastException if an element in c cannot be compared with
+ * objects already in the set
+ */
+ public boolean addAll(Collection c)
+ {
+ boolean result = false;
+ int pos = c.size();
+ Iterator itr = c.iterator();
+ while (--pos >= 0)
+ result |= (map.put(itr.next(), "") == null);
+ return result;
+ }
+
+ /**
+ * Removes all elements in this Set.
+ */
+ public void clear()
+ {
+ map.clear();
+ }
+
+ /**
+ * Returns a shallow copy of this Set. The elements are not cloned.
+ *
+ * @return the cloned set
+ */
+ public Object clone()
+ {
+ TreeSet copy = null;
+ try
+ {
+ copy = (TreeSet) super.clone();
+ // Map may be either TreeMap or TreeMap.SubMap, hence the ugly casts.
+ copy.map = (SortedMap) ((AbstractMap) map).clone();
+ }
+ catch (CloneNotSupportedException x)
+ {
+ // Impossible result.
+ }
+ return copy;
+ }
+
+ /**
+ * Returns this Set's comparator.
+ *
+ * @return the comparator, or null if the set uses natural ordering
+ */
+ public Comparator comparator()
+ {
+ return map.comparator();
+ }
+
+ /**
+ * Returns true if this Set contains the supplied Object, false otherwise.
+ *
+ * @param obj the Object to check for
+ * @return true if it is in the set
+ * @throws ClassCastException if obj cannot be compared with objects
+ * already in the set
+ */
+ public boolean contains(Object obj)
+ {
+ return map.containsKey(obj);
+ }
+
+ /**
+ * Returns the first (by order) element in this Set.
+ *
+ * @return the first element
+ * @throws NoSuchElementException if the set is empty
+ */
+ public Object first()
+ {
+ return map.firstKey();
+ }
+
+ /**
+ * Returns a view of this Set including all elements less than
+ * <code>to</code>. The returned set is backed by the original, so changes
+ * in one appear in the other. The subset will throw an
+ * {@link IllegalArgumentException} for any attempt to access or add an
+ * element beyond the specified cutoff. The returned set does not include
+ * the endpoint; if you want inclusion, pass the successor element.
+ *
+ * @param to the (exclusive) cutoff point
+ * @return a view of the set less than the cutoff
+ * @throws ClassCastException if <code>to</code> is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if to is null, but the comparator does not
+ * tolerate null elements
+ */
+ public SortedSet headSet(Object to)
+ {
+ return new TreeSet(map.headMap(to));
+ }
+
+ /**
+ * Returns true if this Set has size 0, false otherwise.
+ *
+ * @return true if the set is empty
+ */
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ /**
+ * Returns in Iterator over the elements in this TreeSet, which traverses
+ * in ascending order.
+ *
+ * @return an iterator
+ */
+ public Iterator iterator()
+ {
+ return map.keySet().iterator();
+ }
+
+ /**
+ * Returns the last (by order) element in this Set.
+ *
+ * @return the last element
+ * @throws NoSuchElementException if the set is empty
+ */
+ public Object last()
+ {
+ return map.lastKey();
+ }
+
+ /**
+ * If the supplied Object is in this Set, it is removed, and true is
+ * returned; otherwise, false is returned.
+ *
+ * @param obj the Object to remove from this Set
+ * @return true if the set was modified
+ * @throws ClassCastException if obj cannot be compared to set elements
+ */
+ public boolean remove(Object obj)
+ {
+ return map.remove(obj) != null;
+ }
+
+ /**
+ * Returns the number of elements in this Set
+ *
+ * @return the set size
+ */
+ public int size()
+ {
+ return map.size();
+ }
+
+ /**
+ * Returns a view of this Set including all elements greater or equal to
+ * <code>from</code> and less than <code>to</code> (a half-open interval).
+ * The returned set is backed by the original, so changes in one appear in
+ * the other. The subset will throw an {@link IllegalArgumentException}
+ * for any attempt to access or add an element beyond the specified cutoffs.
+ * The returned set includes the low endpoint but not the high; if you want
+ * to reverse this behavior on either end, pass in the successor element.
+ *
+ * @param from the (inclusive) low cutoff point
+ * @param to the (exclusive) high cutoff point
+ * @return a view of the set between the cutoffs
+ * @throws ClassCastException if either cutoff is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if from or to is null, but the comparator
+ * does not tolerate null elements
+ * @throws IllegalArgumentException if from is greater than to
+ */
+ public SortedSet subSet(Object from, Object to)
+ {
+ return new TreeSet(map.subMap(from, to));
+ }
+
+ /**
+ * Returns a view of this Set including all elements greater or equal to
+ * <code>from</code>. The returned set is backed by the original, so
+ * changes in one appear in the other. The subset will throw an
+ * {@link IllegalArgumentException} for any attempt to access or add an
+ * element beyond the specified cutoff. The returned set includes the
+ * endpoint; if you want to exclude it, pass in the successor element.
+ *
+ * @param from the (inclusive) low cutoff point
+ * @return a view of the set above the cutoff
+ * @throws ClassCastException if <code>from</code> is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if from is null, but the comparator
+ * does not tolerate null elements
+ */
+ public SortedSet tailSet(Object from)
+ {
+ return new TreeSet(map.tailMap(from));
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>comparator</i> (Object), followed by the set size
+ * (int), the the elements in sorted order (Object)
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ Iterator itr = map.keySet().iterator();
+ int pos = map.size();
+ s.writeObject(map.comparator());
+ s.writeInt(pos);
+ while (--pos >= 0)
+ s.writeObject(itr.next());
+ }
+
+ /**
+ * Deserializes this object from the given stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if the underlying stream fails
+ * @throws IOException if the underlying stream fails
+ * @serialData the <i>comparator</i> (Object), followed by the set size
+ * (int), the the elements in sorted order (Object)
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ Comparator comparator = (Comparator) s.readObject();
+ int size = s.readInt();
+ map = new TreeMap(comparator);
+ ((TreeMap) map).putFromObjStream(s, size, false);
+ }
+}
diff --git a/libjava/classpath/java/util/Vector.java b/libjava/classpath/java/util/Vector.java
new file mode 100644
index 00000000000..e26d7aaa4dd
--- /dev/null
+++ b/libjava/classpath/java/util/Vector.java
@@ -0,0 +1,931 @@
+/* Vector.java -- Class that provides growable arrays.
+ Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+
+/**
+ * The <code>Vector</code> classes implements growable arrays of Objects.
+ * You can access elements in a Vector with an index, just as you
+ * can in a built in array, but Vectors can grow and shrink to accommodate
+ * more or fewer objects.<p>
+ *
+ * Vectors try to mantain efficiency in growing by having a
+ * <code>capacityIncrement</code> that can be specified at instantiation.
+ * When a Vector can no longer hold a new Object, it grows by the amount
+ * in <code>capacityIncrement</code>. If this value is 0, the vector doubles in
+ * size.<p>
+ *
+ * Vector implements the JDK 1.2 List interface, and is therefore a fully
+ * compliant Collection object. The iterators are fail-fast - if external
+ * code structurally modifies the vector, any operation on the iterator will
+ * then throw a {@link ConcurrentModificationException}. The Vector class is
+ * fully synchronized, but the iterators are not. So, when iterating over a
+ * vector, be sure to synchronize on the vector itself. If you don't want the
+ * expense of synchronization, use ArrayList instead. On the other hand, the
+ * Enumeration of elements() is not thread-safe, nor is it fail-fast; so it
+ * can lead to undefined behavior even in a single thread if you modify the
+ * vector during iteration.<p>
+ *
+ * Note: Some methods, especially those specified by List, specify throwing
+ * {@link IndexOutOfBoundsException}, but it is easier to implement by
+ * throwing the subclass {@link ArrayIndexOutOfBoundsException}. Others
+ * directly specify this subclass.
+ *
+ * @author Scott G. Miller
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Collection
+ * @see List
+ * @see ArrayList
+ * @see LinkedList
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Vector extends AbstractList
+ implements List, RandomAccess, Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -2767605614048989439L;
+
+ /**
+ * The internal array used to hold members of a Vector. The elements are
+ * in positions 0 through elementCount - 1, and all remaining slots are null.
+ * @serial the elements
+ */
+ protected Object[] elementData;
+
+ /**
+ * The number of elements currently in the vector, also returned by
+ * {@link #size}.
+ * @serial the size
+ */
+ protected int elementCount;
+
+ /**
+ * The amount the Vector's internal array should be increased in size when
+ * a new element is added that exceeds the current size of the array,
+ * or when {@link #ensureCapacity} is called. If &lt;= 0, the vector just
+ * doubles in size.
+ * @serial the amount to grow the vector by
+ */
+ protected int capacityIncrement;
+
+ /**
+ * Constructs an empty vector with an initial size of 10, and
+ * a capacity increment of 0
+ */
+ public Vector()
+ {
+ this(10, 0);
+ }
+
+ /**
+ * Constructs a vector containing the contents of Collection, in the
+ * order given by the collection.
+ *
+ * @param c collection of elements to add to the new vector
+ * @throws NullPointerException if c is null
+ * @since 1.2
+ */
+ public Vector(Collection c)
+ {
+ elementCount = c.size();
+ elementData = c.toArray(new Object[elementCount]);
+ }
+
+ /**
+ * Constructs a Vector with the initial capacity and capacity
+ * increment specified.
+ *
+ * @param initialCapacity the initial size of the Vector's internal array
+ * @param capacityIncrement the amount the internal array should be
+ * increased by when necessary, 0 to double the size
+ * @throws IllegalArgumentException if initialCapacity &lt; 0
+ */
+ public Vector(int initialCapacity, int capacityIncrement)
+ {
+ if (initialCapacity < 0)
+ throw new IllegalArgumentException();
+ elementData = new Object[initialCapacity];
+ this.capacityIncrement = capacityIncrement;
+ }
+
+ /**
+ * Constructs a Vector with the initial capacity specified, and a capacity
+ * increment of 0 (double in size).
+ *
+ * @param initialCapacity the initial size of the Vector's internal array
+ * @throws IllegalArgumentException if initialCapacity &lt; 0
+ */
+ public Vector(int initialCapacity)
+ {
+ this(initialCapacity, 0);
+ }
+
+ /**
+ * Copies the contents of a provided array into the Vector. If the
+ * array is too large to fit in the Vector, an IndexOutOfBoundsException
+ * is thrown without modifying the array. Old elements in the Vector are
+ * overwritten by the new elements.
+ *
+ * @param a target array for the copy
+ * @throws IndexOutOfBoundsException the array is not large enough
+ * @throws NullPointerException the array is null
+ * @see #toArray(Object[])
+ */
+ public synchronized void copyInto(Object[] a)
+ {
+ System.arraycopy(elementData, 0, a, 0, elementCount);
+ }
+
+ /**
+ * Trims the Vector down to size. If the internal data array is larger
+ * than the number of Objects its holding, a new array is constructed
+ * that precisely holds the elements. Otherwise this does nothing.
+ */
+ public synchronized void trimToSize()
+ {
+ // Don't bother checking for the case where size() == the capacity of the
+ // vector since that is a much less likely case; it's more efficient to
+ // not do the check and lose a bit of performance in that infrequent case
+
+ Object[] newArray = new Object[elementCount];
+ System.arraycopy(elementData, 0, newArray, 0, elementCount);
+ elementData = newArray;
+ }
+
+ /**
+ * Ensures that <code>minCapacity</code> elements can fit within this Vector.
+ * If <code>elementData</code> is too small, it is expanded as follows:
+ * If the <code>elementCount + capacityIncrement</code> is adequate, that
+ * is the new size. If <code>capacityIncrement</code> is non-zero, the
+ * candidate size is double the current. If that is not enough, the new
+ * size is <code>minCapacity</code>.
+ *
+ * @param minCapacity the desired minimum capacity, negative values ignored
+ */
+ public synchronized void ensureCapacity(int minCapacity)
+ {
+ if (elementData.length >= minCapacity)
+ return;
+
+ int newCapacity;
+ if (capacityIncrement <= 0)
+ newCapacity = elementData.length * 2;
+ else
+ newCapacity = elementData.length + capacityIncrement;
+
+ Object[] newArray = new Object[Math.max(newCapacity, minCapacity)];
+
+ System.arraycopy(elementData, 0, newArray, 0, elementCount);
+ elementData = newArray;
+ }
+
+ /**
+ * Explicitly sets the size of the vector (but not necessarily the size of
+ * the internal data array). If the new size is smaller than the old one,
+ * old values that don't fit are lost. If the new size is larger than the
+ * old one, the vector is padded with null entries.
+ *
+ * @param newSize The new size of the internal array
+ * @throws ArrayIndexOutOfBoundsException if the new size is negative
+ */
+ public synchronized void setSize(int newSize)
+ {
+ // Don't bother checking for the case where size() == the capacity of the
+ // vector since that is a much less likely case; it's more efficient to
+ // not do the check and lose a bit of performance in that infrequent case
+ modCount++;
+ ensureCapacity(newSize);
+ if (newSize < elementCount)
+ Arrays.fill(elementData, newSize, elementCount, null);
+ elementCount = newSize;
+ }
+
+ /**
+ * Returns the size of the internal data array (not the amount of elements
+ * contained in the Vector).
+ *
+ * @return capacity of the internal data array
+ */
+ public synchronized int capacity()
+ {
+ return elementData.length;
+ }
+
+ /**
+ * Returns the number of elements stored in this Vector.
+ *
+ * @return the number of elements in this Vector
+ */
+ public synchronized int size()
+ {
+ return elementCount;
+ }
+
+ /**
+ * Returns true if this Vector is empty, false otherwise
+ *
+ * @return true if the Vector is empty, false otherwise
+ */
+ public synchronized boolean isEmpty()
+ {
+ return elementCount == 0;
+ }
+
+ /**
+ * Returns an Enumeration of the elements of this Vector. The enumeration
+ * visits the elements in increasing index order, but is NOT thread-safe.
+ *
+ * @return an Enumeration
+ * @see #iterator()
+ */
+ // No need to synchronize as the Enumeration is not thread-safe!
+ public Enumeration elements()
+ {
+ return new Enumeration()
+ {
+ private int i = 0;
+
+ public boolean hasMoreElements()
+ {
+ return i < elementCount;
+ }
+
+ public Object nextElement()
+ {
+ if (i >= elementCount)
+ throw new NoSuchElementException();
+ return elementData[i++];
+ }
+ };
+ }
+
+ /**
+ * Returns true when <code>elem</code> is contained in this Vector.
+ *
+ * @param elem the element to check
+ * @return true if the object is contained in this Vector, false otherwise
+ */
+ public boolean contains(Object elem)
+ {
+ return indexOf(elem, 0) >= 0;
+ }
+
+ /**
+ * Returns the first occurrence of <code>elem</code> in the Vector, or -1 if
+ * <code>elem</code> is not found.
+ *
+ * @param elem the object to search for
+ * @return the index of the first occurrence, or -1 if not found
+ */
+ public int indexOf(Object elem)
+ {
+ return indexOf(elem, 0);
+ }
+
+ /**
+ * Searches the vector starting at <code>index</code> for object
+ * <code>elem</code> and returns the index of the first occurrence of this
+ * Object. If the object is not found, or index is larger than the size
+ * of the vector, -1 is returned.
+ *
+ * @param e the Object to search for
+ * @param index start searching at this index
+ * @return the index of the next occurrence, or -1 if it is not found
+ * @throws IndexOutOfBoundsException if index &lt; 0
+ */
+ public synchronized int indexOf(Object e, int index)
+ {
+ for (int i = index; i < elementCount; i++)
+ if (equals(e, elementData[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the last index of <code>elem</code> within this Vector, or -1
+ * if the object is not within the Vector.
+ *
+ * @param elem the object to search for
+ * @return the last index of the object, or -1 if not found
+ */
+ public int lastIndexOf(Object elem)
+ {
+ return lastIndexOf(elem, elementCount - 1);
+ }
+
+ /**
+ * Returns the index of the first occurrence of <code>elem</code>, when
+ * searching backwards from <code>index</code>. If the object does not
+ * occur in this Vector, or index is less than 0, -1 is returned.
+ *
+ * @param e the object to search for
+ * @param index the index to start searching in reverse from
+ * @return the index of the Object if found, -1 otherwise
+ * @throws IndexOutOfBoundsException if index &gt;= size()
+ */
+ public synchronized int lastIndexOf(Object e, int index)
+ {
+ checkBoundExclusive(index);
+ for (int i = index; i >= 0; i--)
+ if (equals(e, elementData[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the Object stored at <code>index</code>.
+ *
+ * @param index the index of the Object to retrieve
+ * @return the object at <code>index</code>
+ * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
+ * @see #get(int)
+ */
+ public synchronized Object elementAt(int index)
+ {
+ checkBoundExclusive(index);
+ return elementData[index];
+ }
+
+ /**
+ * Returns the first element (index 0) in the Vector.
+ *
+ * @return the first Object in the Vector
+ * @throws NoSuchElementException the Vector is empty
+ */
+ public synchronized Object firstElement()
+ {
+ if (elementCount == 0)
+ throw new NoSuchElementException();
+
+ return elementData[0];
+ }
+
+ /**
+ * Returns the last element in the Vector.
+ *
+ * @return the last Object in the Vector
+ * @throws NoSuchElementException the Vector is empty
+ */
+ public synchronized Object lastElement()
+ {
+ if (elementCount == 0)
+ throw new NoSuchElementException();
+
+ return elementData[elementCount - 1];
+ }
+
+ /**
+ * Changes the element at <code>index</code> to be <code>obj</code>
+ *
+ * @param obj the object to store
+ * @param index the position in the Vector to store the object
+ * @throws ArrayIndexOutOfBoundsException the index is out of range
+ * @see #set(int, Object)
+ */
+ public void setElementAt(Object obj, int index)
+ {
+ set(index, obj);
+ }
+
+ /**
+ * Removes the element at <code>index</code>, and shifts all elements at
+ * positions greater than index to their index - 1.
+ *
+ * @param index the index of the element to remove
+ * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size();
+ * @see #remove(int)
+ */
+ public void removeElementAt(int index)
+ {
+ remove(index);
+ }
+
+ /**
+ * Inserts a new element into the Vector at <code>index</code>. Any elements
+ * at or greater than index are shifted up one position.
+ *
+ * @param obj the object to insert
+ * @param index the index at which the object is inserted
+ * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
+ * @see #add(int, Object)
+ */
+ public synchronized void insertElementAt(Object obj, int index)
+ {
+ checkBoundInclusive(index);
+ if (elementCount == elementData.length)
+ ensureCapacity(elementCount + 1);
+ modCount++;
+ System.arraycopy(elementData, index, elementData, index + 1,
+ elementCount - index);
+ elementCount++;
+ elementData[index] = obj;
+ }
+
+ /**
+ * Adds an element to the Vector at the end of the Vector. The vector
+ * is increased by ensureCapacity(size() + 1) if needed.
+ *
+ * @param obj the object to add to the Vector
+ */
+ public synchronized void addElement(Object obj)
+ {
+ if (elementCount == elementData.length)
+ ensureCapacity(elementCount + 1);
+ modCount++;
+ elementData[elementCount++] = obj;
+ }
+
+ /**
+ * Removes the first (the lowestindex) occurance 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.
+ *
+ * @param obj the object to remove from the Vector
+ * @return true if the Object was in the Vector, false otherwise
+ * @see #remove(Object)
+ */
+ public synchronized boolean removeElement(Object obj)
+ {
+ int idx = indexOf(obj, 0);
+ if (idx >= 0)
+ {
+ remove(idx);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Removes all elements from the Vector. Note that this does not
+ * resize the internal data array.
+ *
+ * @see #clear()
+ */
+ public synchronized void removeAllElements()
+ {
+ if (elementCount == 0)
+ return;
+
+ modCount++;
+ Arrays.fill(elementData, 0, elementCount, null);
+ elementCount = 0;
+ }
+
+ /**
+ * Creates a new Vector with the same contents as this one. The clone is
+ * shallow; elements are not cloned.
+ *
+ * @return the clone of this vector
+ */
+ public synchronized Object clone()
+ {
+ try
+ {
+ Vector clone = (Vector) super.clone();
+ clone.elementData = (Object[]) elementData.clone();
+ return clone;
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ // Impossible to get here.
+ throw new InternalError(ex.toString());
+ }
+ }
+
+ /**
+ * Returns an Object array with the contents of this Vector, in the order
+ * they are stored within this Vector. Note that the Object array returned
+ * is not the internal data array, and that it holds only the elements
+ * within the Vector. This is similar to creating a new Object[] with the
+ * size of this Vector, then calling Vector.copyInto(yourArray).
+ *
+ * @return an Object[] containing the contents of this Vector in order
+ * @since 1.2
+ */
+ public synchronized Object[] toArray()
+ {
+ Object[] newArray = new Object[elementCount];
+ copyInto(newArray);
+ return newArray;
+ }
+
+ /**
+ * Returns an array containing the contents of this Vector.
+ * If the provided array is large enough, the contents are copied
+ * into that array, and a null is placed in the position size().
+ * In this manner, you can obtain the size of a Vector by the position
+ * of the null element, if you know the vector does not itself contain
+ * null entries. If the array is not large enough, reflection is used
+ * to create a bigger one of the same runtime type.
+ *
+ * @param a an array to copy the Vector into if large enough
+ * @return an array with the contents of this Vector in order
+ * @throws ArrayStoreException the runtime type of the provided array
+ * cannot hold the elements of the Vector
+ * @throws NullPointerException if <code>a</code> is null
+ * @since 1.2
+ */
+ public synchronized Object[] toArray(Object[] a)
+ {
+ if (a.length < elementCount)
+ a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
+ elementCount);
+ else if (a.length > elementCount)
+ a[elementCount] = null;
+ System.arraycopy(elementData, 0, a, 0, elementCount);
+ return a;
+ }
+
+ /**
+ * Returns the element at position <code>index</code>.
+ *
+ * @param index the position from which an element will be retrieved
+ * @return the element at that position
+ * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
+ * @since 1.2
+ */
+ public Object get(int index)
+ {
+ return elementAt(index);
+ }
+
+ /**
+ * Puts <code>element</code> into the Vector at position <code>index</code>
+ * and returns the Object that previously occupied that position.
+ *
+ * @param index the index within the Vector to place the Object
+ * @param element the Object to store in the Vector
+ * @return the previous object at the specified index
+ * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
+ * @since 1.2
+ */
+ public synchronized Object set(int index, Object element)
+ {
+ checkBoundExclusive(index);
+ Object temp = elementData[index];
+ elementData[index] = element;
+ return temp;
+ }
+
+ /**
+ * Adds an object to the Vector.
+ *
+ * @param o the element to add to the Vector
+ * @return true, as specified by List
+ * @since 1.2
+ */
+ public boolean add(Object o)
+ {
+ addElement(o);
+ return true;
+ }
+
+ /**
+ * Removes the given Object from the Vector. If it exists, true
+ * is returned, if not, false is returned.
+ *
+ * @param o the object to remove from the Vector
+ * @return true if the Object existed in the Vector, false otherwise
+ * @since 1.2
+ */
+ public boolean remove(Object o)
+ {
+ return removeElement(o);
+ }
+
+ /**
+ * Adds an object at the specified index. Elements at or above
+ * index are shifted up one position.
+ *
+ * @param index the index at which to add the element
+ * @param element the element to add to the Vector
+ * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
+ * @since 1.2
+ */
+ public void add(int index, Object element)
+ {
+ insertElementAt(element, index);
+ }
+
+ /**
+ * Removes the element at the specified index, and returns it.
+ *
+ * @param index the position from which to remove the element
+ * @return the object removed
+ * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
+ * @since 1.2
+ */
+ public synchronized Object remove(int index)
+ {
+ checkBoundExclusive(index);
+ Object temp = elementData[index];
+ modCount++;
+ elementCount--;
+ if (index < elementCount)
+ System.arraycopy(elementData, index + 1, elementData, index,
+ elementCount - index);
+ elementData[elementCount] = null;
+ return temp;
+ }
+
+ /**
+ * Clears all elements in the Vector and sets its size to 0.
+ */
+ public void clear()
+ {
+ removeAllElements();
+ }
+
+ /**
+ * Returns true if this Vector contains all the elements in c.
+ *
+ * @param c the collection to compare to
+ * @return true if this vector contains all elements of c
+ * @throws NullPointerException if c is null
+ * @since 1.2
+ */
+ public synchronized boolean containsAll(Collection c)
+ {
+ // Here just for the sychronization.
+ return super.containsAll(c);
+ }
+
+ /**
+ * Appends all elements of the given collection to the end of this Vector.
+ * Behavior is undefined if the collection is modified during this operation
+ * (for example, if this == c).
+ *
+ * @param c the collection to append
+ * @return true if this vector changed, in other words c was not empty
+ * @throws NullPointerException if c is null
+ * @since 1.2
+ */
+ public synchronized boolean addAll(Collection c)
+ {
+ return addAll(elementCount, c);
+ }
+
+ /**
+ * Remove from this vector all elements contained in the given collection.
+ *
+ * @param c the collection to filter out
+ * @return true if this vector changed
+ * @throws NullPointerException if c is null
+ * @since 1.2
+ */
+ public synchronized boolean removeAll(Collection c)
+ {
+ if (c == null)
+ throw new NullPointerException();
+
+ int i;
+ int j;
+ for (i = 0; i < elementCount; i++)
+ if (c.contains(elementData[i]))
+ break;
+ if (i == elementCount)
+ return false;
+
+ modCount++;
+ for (j = i++; i < elementCount; i++)
+ if (! c.contains(elementData[i]))
+ elementData[j++] = elementData[i];
+ elementCount -= i - j;
+ return true;
+ }
+
+ /**
+ * Retain in this vector only the elements contained in the given collection.
+ *
+ * @param c the collection to filter by
+ * @return true if this vector changed
+ * @throws NullPointerException if c is null
+ * @since 1.2
+ */
+ public synchronized boolean retainAll(Collection c)
+ {
+ if (c == null)
+ throw new NullPointerException();
+
+ int i;
+ int j;
+ for (i = 0; i < elementCount; i++)
+ if (! c.contains(elementData[i]))
+ break;
+ if (i == elementCount)
+ return false;
+
+ modCount++;
+ for (j = i++; i < elementCount; i++)
+ if (c.contains(elementData[i]))
+ elementData[j++] = elementData[i];
+ elementCount -= i - j;
+ return true;
+ }
+
+ /**
+ * Inserts all elements of the given collection at the given index of
+ * this Vector. Behavior is undefined if the collection is modified during
+ * this operation (for example, if this == c).
+ *
+ * @param c the collection to append
+ * @return true if this vector changed, in other words c was not empty
+ * @throws NullPointerException if c is null
+ * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
+ * @since 1.2
+ */
+ public synchronized boolean addAll(int index, Collection c)
+ {
+ checkBoundInclusive(index);
+ Iterator itr = c.iterator();
+ int csize = c.size();
+
+ modCount++;
+ ensureCapacity(elementCount + csize);
+ int end = index + csize;
+ if (elementCount > 0 && index != elementCount)
+ System.arraycopy(elementData, index,
+ elementData, end, elementCount - index);
+ elementCount += csize;
+ for ( ; index < end; index++)
+ elementData[index] = itr.next();
+ return (csize > 0);
+ }
+
+ /**
+ * Compares this to the given object.
+ *
+ * @param o the object to compare to
+ * @return true if the two are equal
+ * @since 1.2
+ */
+ public synchronized boolean equals(Object o)
+ {
+ // Here just for the sychronization.
+ return super.equals(o);
+ }
+
+ /**
+ * Computes the hashcode of this object.
+ *
+ * @return the hashcode
+ * @since 1.2
+ */
+ public synchronized int hashCode()
+ {
+ // Here just for the sychronization.
+ return super.hashCode();
+ }
+
+ /**
+ * Returns a string representation of this Vector in the form
+ * "[element0, element1, ... elementN]".
+ *
+ * @return the String representation of this Vector
+ */
+ public synchronized String toString()
+ {
+ // Here just for the sychronization.
+ return super.toString();
+ }
+
+ /**
+ * Obtain a List view of a subsection of this list, from fromIndex
+ * (inclusive) to toIndex (exclusive). If the two indices are equal, the
+ * sublist is empty. The returned list is modifiable, and changes in one
+ * reflect in the other. If this list is structurally modified in
+ * any way other than through the returned list, the result of any subsequent
+ * operations on the returned list is undefined.
+ * <p>
+ *
+ * @param fromIndex the index that the returned list should start from
+ * (inclusive)
+ * @param toIndex the index that the returned list should go to (exclusive)
+ * @return a List backed by a subsection of this vector
+ * @throws IndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; size()
+ * @throws IllegalArgumentException if fromIndex &gt; toIndex
+ * @see ConcurrentModificationException
+ * @since 1.2
+ */
+ public synchronized List subList(int fromIndex, int toIndex)
+ {
+ List sub = super.subList(fromIndex, toIndex);
+ // We must specify the correct object to synchronize upon, hence the
+ // use of a non-public API
+ return new Collections.SynchronizedList(this, sub);
+ }
+
+ /**
+ * Removes a range of elements from this list.
+ * Does nothing when toIndex is equal to fromIndex.
+ *
+ * @param fromIndex the index to start deleting from (inclusive)
+ * @param toIndex the index to delete up to (exclusive)
+ * @throws IndexOutOfBoundsException if fromIndex &gt; toIndex
+ */
+ // This does not need to be synchronized, because it is only called through
+ // clear() of a sublist, and clear() had already synchronized.
+ protected void removeRange(int fromIndex, int toIndex)
+ {
+ int change = toIndex - fromIndex;
+ if (change > 0)
+ {
+ modCount++;
+ System.arraycopy(elementData, toIndex, elementData, fromIndex,
+ elementCount - toIndex);
+ int save = elementCount;
+ elementCount -= change;
+ Arrays.fill(elementData, elementCount, save, null);
+ }
+ else if (change < 0)
+ throw new IndexOutOfBoundsException();
+ }
+
+ /**
+ * Checks that the index is in the range of possible elements (inclusive).
+ *
+ * @param index the index to check
+ * @throws ArrayIndexOutOfBoundsException if index &gt; size
+ */
+ private void checkBoundInclusive(int index)
+ {
+ // Implementation note: we do not check for negative ranges here, since
+ // use of a negative index will cause an ArrayIndexOutOfBoundsException
+ // with no effort on our part.
+ if (index > elementCount)
+ throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount);
+ }
+
+ /**
+ * Checks that the index is in the range of existing elements (exclusive).
+ *
+ * @param index the index to check
+ * @throws ArrayIndexOutOfBoundsException if index &gt;= size
+ */
+ private void checkBoundExclusive(int index)
+ {
+ // Implementation note: we do not check for negative ranges here, since
+ // use of a negative index will cause an ArrayIndexOutOfBoundsException
+ // with no effort on our part.
+ if (index >= elementCount)
+ throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the underlying stream fails
+ * @serialData just calls default write function
+ */
+ private synchronized void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ s.defaultWriteObject();
+ }
+
+}
diff --git a/libjava/classpath/java/util/WeakHashMap.java b/libjava/classpath/java/util/WeakHashMap.java
new file mode 100644
index 00000000000..7593f7e330e
--- /dev/null
+++ b/libjava/classpath/java/util/WeakHashMap.java
@@ -0,0 +1,881 @@
+/* WeakHashMap -- a hashtable that keeps only weak references
+ to its keys, allowing the virtual machine to reclaim them
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+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.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * A weak hash map has only weak references to the key. This means that it
+ * allows the key to be garbage collected if it is not used otherwise. If
+ * this happens, the entry will eventually disappear from the map,
+ * asynchronously.
+ *
+ * <p>A weak hash map makes most sense when the keys doesn't override the
+ * <code>equals</code> method: If there is no other reference to the
+ * key nobody can ever look up the key in this table and so the entry
+ * can be removed. This table also works when the <code>equals</code>
+ * method is overloaded, such as String keys, but you should be prepared
+ * to deal with some entries disappearing spontaneously.
+ *
+ * <p>Other strange behaviors to be aware of: The size of this map may
+ * spontaneously shrink (even if you use a synchronized map and synchronize
+ * it); it behaves as if another thread removes entries from this table
+ * without synchronization. The entry set returned by <code>entrySet</code>
+ * has similar phenomenons: The size may spontaneously shrink, or an
+ * entry, that was in the set before, suddenly disappears.
+ *
+ * <p>A weak hash map is not meant for caches; use a normal map, with
+ * soft references as values instead, or try {@link LinkedHashMap}.
+ *
+ * <p>The weak hash map supports null values and null keys. The null key
+ * is never deleted from the map (except explictly of course). The
+ * performance of the methods are similar to that of a hash map.
+ *
+ * <p>The value objects are strongly referenced by this table. So if a
+ * value object maintains a strong reference to the key (either direct
+ * or indirect) the key will never be removed from this map. According
+ * to Sun, this problem may be fixed in a future release. It is not
+ * possible to do it with the jdk 1.2 reference model, though.
+ *
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @see HashMap
+ * @see WeakReference
+ * @see LinkedHashMap
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class WeakHashMap extends AbstractMap implements Map
+{
+ // WARNING: WeakHashMap is a CORE class in the bootstrap cycle. See the
+ // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+ /**
+ * The default capacity for an instance of HashMap.
+ * Sun's documentation mildly suggests that this (11) is the correct
+ * value.
+ */
+ private static final int DEFAULT_CAPACITY = 11;
+
+ /**
+ * The default load factor of a HashMap.
+ */
+ private static final float DEFAULT_LOAD_FACTOR = 0.75F;
+
+ /**
+ * This is used instead of the key value <i>null</i>. It is needed
+ * to distinguish between an null key and a removed key.
+ */
+ // Package visible for use by nested classes.
+ static final Object NULL_KEY = new Object()
+ {
+ /**
+ * Sets the hashCode to 0, since that's what null would map to.
+ * @return the hash code 0
+ */
+ public int hashCode()
+ {
+ return 0;
+ }
+
+ /**
+ * Compares this key to the given object. Normally, an object should
+ * NEVER compare equal to null, but since we don't publicize NULL_VALUE,
+ * it saves bytecode to do so here.
+ * @return true iff o is this or null
+ */
+ public boolean equals(Object o)
+ {
+ return null == o || this == o;
+ }
+ };
+
+ /**
+ * The reference queue where our buckets (which are WeakReferences) are
+ * registered to.
+ */
+ private final ReferenceQueue queue;
+
+ /**
+ * The number of entries in this hash map.
+ */
+ // Package visible for use by nested classes.
+ int size;
+
+ /**
+ * The load factor of this WeakHashMap. This is the maximum ratio of
+ * size versus number of buckets. If size grows the number of buckets
+ * must grow, too.
+ */
+ private float loadFactor;
+
+ /**
+ * The rounded product of the capacity (i.e. number of buckets) and
+ * the load factor. When the number of elements exceeds the
+ * threshold, the HashMap calls <code>rehash()</code>.
+ */
+ private int threshold;
+
+ /**
+ * The number of structural modifications. This is used by
+ * iterators, to see if they should fail. This doesn't count
+ * the silent key removals, when a weak reference is cleared
+ * by the garbage collection. Instead the iterators must make
+ * sure to have strong references to the entries they rely on.
+ */
+ // Package visible for use by nested classes.
+ int modCount;
+
+ /**
+ * The entry set. There is only one instance per hashmap, namely
+ * theEntrySet. Note that the entry set may silently shrink, just
+ * like the WeakHashMap.
+ */
+ private final class WeakEntrySet extends AbstractSet
+ {
+ /**
+ * Non-private constructor to reduce bytecode emitted.
+ */
+ WeakEntrySet()
+ {
+ }
+
+ /**
+ * Returns the size of this set.
+ *
+ * @return the set size
+ */
+ public int size()
+ {
+ return size;
+ }
+
+ /**
+ * Returns an iterator for all entries.
+ *
+ * @return an Entry iterator
+ */
+ public Iterator iterator()
+ {
+ return new Iterator()
+ {
+ /**
+ * The entry that was returned by the last
+ * <code>next()</code> call. This is also the entry whose
+ * bucket should be removed by the <code>remove</code> call. <br>
+ *
+ * It is null, if the <code>next</code> method wasn't
+ * called yet, or if the entry was already removed. <br>
+ *
+ * Remembering this entry here will also prevent it from
+ * being removed under us, since the entry strongly refers
+ * to the key.
+ */
+ WeakBucket.WeakEntry lastEntry;
+
+ /**
+ * The entry that will be returned by the next
+ * <code>next()</code> call. It is <code>null</code> if there
+ * is no further entry. <br>
+ *
+ * Remembering this entry here will also prevent it from
+ * being removed under us, since the entry strongly refers
+ * to the key.
+ */
+ WeakBucket.WeakEntry nextEntry = findNext(null);
+
+ /**
+ * The known number of modification to the list, if it differs
+ * from the real number, we throw an exception.
+ */
+ int knownMod = modCount;
+
+ /**
+ * Check the known number of modification to the number of
+ * modifications of the table. If it differs from the real
+ * number, we throw an exception.
+ * @throws ConcurrentModificationException if the number
+ * of modifications doesn't match.
+ */
+ private void checkMod()
+ {
+ // This method will get inlined.
+ cleanQueue();
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ }
+
+ /**
+ * Get a strong reference to the next entry after
+ * lastBucket.
+ * @param lastEntry the previous bucket, or null if we should
+ * get the first entry.
+ * @return the next entry.
+ */
+ private WeakBucket.WeakEntry findNext(WeakBucket.WeakEntry lastEntry)
+ {
+ int slot;
+ WeakBucket nextBucket;
+ if (lastEntry != null)
+ {
+ nextBucket = lastEntry.getBucket().next;
+ slot = lastEntry.getBucket().slot;
+ }
+ else
+ {
+ nextBucket = buckets[0];
+ slot = 0;
+ }
+
+ while (true)
+ {
+ while (nextBucket != null)
+ {
+ WeakBucket.WeakEntry entry = nextBucket.getEntry();
+ if (entry != null)
+ // This is the next entry.
+ return entry;
+
+ // Entry was cleared, try next.
+ nextBucket = nextBucket.next;
+ }
+
+ slot++;
+ if (slot == buckets.length)
+ // No more buckets, we are through.
+ return null;
+
+ nextBucket = buckets[slot];
+ }
+ }
+
+ /**
+ * Checks if there are more entries.
+ * @return true, iff there are more elements.
+ * @throws ConcurrentModificationException if the hash map was
+ * modified.
+ */
+ public boolean hasNext()
+ {
+ checkMod();
+ return nextEntry != null;
+ }
+
+ /**
+ * Returns the next entry.
+ * @return the next entry.
+ * @throws ConcurrentModificationException if the hash map was
+ * modified.
+ * @throws NoSuchElementException if there is no entry.
+ */
+ public Object next()
+ {
+ checkMod();
+ if (nextEntry == null)
+ throw new NoSuchElementException();
+ lastEntry = nextEntry;
+ nextEntry = findNext(lastEntry);
+ return lastEntry;
+ }
+
+ /**
+ * Removes the last returned entry from this set. This will
+ * also remove the bucket of the underlying weak hash map.
+ * @throws ConcurrentModificationException if the hash map was
+ * modified.
+ * @throws IllegalStateException if <code>next()</code> was
+ * never called or the element was already removed.
+ */
+ public void remove()
+ {
+ checkMod();
+ if (lastEntry == null)
+ throw new IllegalStateException();
+ modCount++;
+ internalRemove(lastEntry.getBucket());
+ lastEntry = null;
+ knownMod++;
+ }
+ };
+ }
+ }
+
+ /**
+ * A bucket is a weak reference to the key, that contains a strong
+ * reference to the value, a pointer to the next bucket and its slot
+ * number. <br>
+ *
+ * It would be cleaner to have a WeakReference as field, instead of
+ * extending it, but if a weak reference gets cleared, we only get
+ * the weak reference (by queue.poll) and wouldn't know where to
+ * look for this reference in the hashtable, to remove that entry.
+ *
+ * @author Jochen Hoenicke
+ */
+ private static class WeakBucket extends WeakReference
+ {
+ /**
+ * The value of this entry. The key is stored in the weak
+ * reference that we extend.
+ */
+ Object value;
+
+ /**
+ * The next bucket describing another entry that uses the same
+ * slot.
+ */
+ WeakBucket next;
+
+ /**
+ * The slot of this entry. This should be
+ * <code>Math.abs(key.hashCode() % buckets.length)</code>.
+ *
+ * But since the key may be silently removed we have to remember
+ * the slot number.
+ *
+ * If this bucket was removed the slot is -1. This marker will
+ * prevent the bucket from being removed twice.
+ */
+ int slot;
+
+ /**
+ * Creates a new bucket for the given key/value pair and the specified
+ * slot.
+ * @param key the key
+ * @param queue the queue the weak reference belongs to
+ * @param value the value
+ * @param slot the slot. This must match the slot where this bucket
+ * will be enqueued.
+ */
+ public WeakBucket(Object key, ReferenceQueue queue, Object value,
+ int slot)
+ {
+ super(key, queue);
+ this.value = value;
+ this.slot = slot;
+ }
+
+ /**
+ * This class gives the <code>Entry</code> representation of the
+ * current bucket. It also keeps a strong reference to the
+ * key; bad things may happen otherwise.
+ */
+ class WeakEntry implements Map.Entry
+ {
+ /**
+ * The strong ref to the key.
+ */
+ Object key;
+
+ /**
+ * Creates a new entry for the key.
+ * @param key the key
+ */
+ public WeakEntry(Object key)
+ {
+ this.key = key;
+ }
+
+ /**
+ * Returns the underlying bucket.
+ * @return the owning bucket
+ */
+ public WeakBucket getBucket()
+ {
+ return WeakBucket.this;
+ }
+
+ /**
+ * Returns the key.
+ * @return the key
+ */
+ public Object getKey()
+ {
+ return key == NULL_KEY ? null : key;
+ }
+
+ /**
+ * Returns the value.
+ * @return the value
+ */
+ public Object getValue()
+ {
+ return value;
+ }
+
+ /**
+ * This changes the value. This change takes place in
+ * the underlying hash map.
+ * @param newVal the new value
+ * @return the old value
+ */
+ public Object setValue(Object newVal)
+ {
+ Object oldVal = value;
+ value = newVal;
+ return oldVal;
+ }
+
+ /**
+ * The hashCode as specified in the Entry interface.
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return key.hashCode() ^ WeakHashMap.hashCode(value);
+ }
+
+ /**
+ * The equals method as specified in the Entry interface.
+ * @param o the object to compare to
+ * @return true iff o represents the same key/value pair
+ */
+ public boolean equals(Object o)
+ {
+ if (o instanceof Map.Entry)
+ {
+ Map.Entry e = (Map.Entry) o;
+ return key.equals(e.getKey())
+ && WeakHashMap.equals(value, e.getValue());
+ }
+ return false;
+ }
+
+ public String toString()
+ {
+ return key + "=" + value;
+ }
+ }
+
+ /**
+ * This returns the entry stored in this bucket, or null, if the
+ * bucket got cleared in the mean time.
+ * @return the Entry for this bucket, if it exists
+ */
+ WeakEntry getEntry()
+ {
+ final Object key = this.get();
+ if (key == null)
+ return null;
+ return new WeakEntry(key);
+ }
+ }
+
+ /**
+ * The entry set returned by <code>entrySet()</code>.
+ */
+ private final WeakEntrySet theEntrySet;
+
+ /**
+ * The hash buckets. These are linked lists. Package visible for use in
+ * nested classes.
+ */
+ WeakBucket[] buckets;
+
+ /**
+ * Creates a new weak hash map with default load factor and default
+ * capacity.
+ */
+ public WeakHashMap()
+ {
+ this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Creates a new weak hash map with default load factor and the given
+ * capacity.
+ * @param initialCapacity the initial capacity
+ * @throws IllegalArgumentException if initialCapacity is negative
+ */
+ public WeakHashMap(int initialCapacity)
+ {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Creates a new weak hash map with the given initial capacity and
+ * load factor.
+ * @param initialCapacity the initial capacity.
+ * @param loadFactor the load factor (see class description of HashMap).
+ * @throws IllegalArgumentException if initialCapacity is negative, or
+ * loadFactor is non-positive
+ */
+ public WeakHashMap(int initialCapacity, float loadFactor)
+ {
+ // Check loadFactor for NaN as well.
+ if (initialCapacity < 0 || ! (loadFactor > 0))
+ throw new IllegalArgumentException();
+ if (initialCapacity == 0)
+ initialCapacity = 1;
+ this.loadFactor = loadFactor;
+ threshold = (int) (initialCapacity * loadFactor);
+ theEntrySet = new WeakEntrySet();
+ queue = new ReferenceQueue();
+ buckets = new WeakBucket[initialCapacity];
+ }
+
+ /**
+ * Construct a new WeakHashMap with the same mappings as the given map.
+ * The WeakHashMap has a default load factor of 0.75.
+ *
+ * @param m the map to copy
+ * @throws NullPointerException if m is null
+ * @since 1.3
+ */
+ public WeakHashMap(Map m)
+ {
+ this(m.size(), DEFAULT_LOAD_FACTOR);
+ putAll(m);
+ }
+
+ /**
+ * Simply hashes a non-null Object to its array index.
+ * @param key the key to hash
+ * @return its slot number
+ */
+ private int hash(Object key)
+ {
+ return Math.abs(key.hashCode() % buckets.length);
+ }
+
+ /**
+ * Cleans the reference queue. This will poll all references (which
+ * are WeakBuckets) from the queue and remove them from this map.
+ * This will not change modCount, even if it modifies the map. The
+ * iterators have to make sure that nothing bad happens. <br>
+ *
+ * Currently the iterator maintains a strong reference to the key, so
+ * that is no problem.
+ */
+ // Package visible for use by nested classes.
+ void cleanQueue()
+ {
+ Object bucket = queue.poll();
+ while (bucket != null)
+ {
+ internalRemove((WeakBucket) bucket);
+ bucket = queue.poll();
+ }
+ }
+
+ /**
+ * Rehashes this hashtable. This will be called by the
+ * <code>add()</code> method if the size grows beyond the threshold.
+ * It will grow the bucket size at least by factor two and allocates
+ * new buckets.
+ */
+ private void rehash()
+ {
+ WeakBucket[] oldBuckets = buckets;
+ int newsize = buckets.length * 2 + 1; // XXX should be prime.
+ threshold = (int) (newsize * loadFactor);
+ buckets = new WeakBucket[newsize];
+
+ // Now we have to insert the buckets again.
+ for (int i = 0; i < oldBuckets.length; i++)
+ {
+ WeakBucket bucket = oldBuckets[i];
+ WeakBucket nextBucket;
+ while (bucket != null)
+ {
+ nextBucket = bucket.next;
+
+ Object key = bucket.get();
+ if (key == null)
+ {
+ // This bucket should be removed; it is probably
+ // already on the reference queue. We don't insert it
+ // at all, and mark it as cleared.
+ bucket.slot = -1;
+ size--;
+ }
+ else
+ {
+ // Add this bucket to its new slot.
+ int slot = hash(key);
+ bucket.slot = slot;
+ bucket.next = buckets[slot];
+ buckets[slot] = bucket;
+ }
+ bucket = nextBucket;
+ }
+ }
+ }
+
+ /**
+ * Finds the entry corresponding to key. Since it returns an Entry
+ * it will also prevent the key from being removed under us.
+ * @param key the key, may be null
+ * @return The WeakBucket.WeakEntry or null, if the key wasn't found.
+ */
+ private WeakBucket.WeakEntry internalGet(Object key)
+ {
+ if (key == null)
+ key = NULL_KEY;
+ int slot = hash(key);
+ WeakBucket bucket = buckets[slot];
+ while (bucket != null)
+ {
+ WeakBucket.WeakEntry entry = bucket.getEntry();
+ if (entry != null && key.equals(entry.key))
+ return entry;
+
+ bucket = bucket.next;
+ }
+ return null;
+ }
+
+ /**
+ * Adds a new key/value pair to the hash map.
+ * @param key the key. This mustn't exists in the map. It may be null.
+ * @param value the value.
+ */
+ private void internalAdd(Object key, Object value)
+ {
+ if (key == null)
+ key = NULL_KEY;
+ int slot = hash(key);
+ WeakBucket bucket = new WeakBucket(key, queue, value, slot);
+ bucket.next = buckets[slot];
+ buckets[slot] = bucket;
+ size++;
+ }
+
+ /**
+ * Removes a bucket from this hash map, if it wasn't removed before
+ * (e.g. one time through rehashing and one time through reference queue).
+ * Package visible for use in nested classes.
+ *
+ * @param bucket the bucket to remove.
+ */
+ void internalRemove(WeakBucket bucket)
+ {
+ int slot = bucket.slot;
+ if (slot == -1)
+ // This bucket was already removed.
+ return;
+
+ // Mark the bucket as removed. This is necessary, since the
+ // bucket may be enqueued later by the garbage collection, and
+ // internalRemove will be called a second time.
+ bucket.slot = -1;
+ if (buckets[slot] == bucket)
+ buckets[slot] = bucket.next;
+ else
+ {
+ WeakBucket prev = buckets[slot];
+ /* This may throw a NullPointerException. It shouldn't but if
+ * a race condition occurred (two threads removing the same
+ * bucket at the same time) it may happen. <br>
+ * But with race condition many much worse things may happen
+ * anyway.
+ */
+ while (prev.next != bucket)
+ prev = prev.next;
+ prev.next = bucket.next;
+ }
+ size--;
+ }
+
+ /**
+ * Returns the size of this hash map. Note that the size() may shrink
+ * spontaneously, if the some of the keys were only weakly reachable.
+ * @return the number of entries in this hash map.
+ */
+ public int size()
+ {
+ cleanQueue();
+ return size;
+ }
+
+ /**
+ * Tells if the map is empty. Note that the result may change
+ * spontanously, if all of the keys were only weakly reachable.
+ * @return true, iff the map is empty.
+ */
+ public boolean isEmpty()
+ {
+ cleanQueue();
+ return size == 0;
+ }
+
+ /**
+ * Tells if the map contains the given key. Note that the result
+ * may change spontanously, if the key was only weakly
+ * reachable.
+ * @param key the key to look for
+ * @return true, iff the map contains an entry for the given key.
+ */
+ public boolean containsKey(Object key)
+ {
+ cleanQueue();
+ return internalGet(key) != null;
+ }
+
+ /**
+ * Gets the value the key is mapped to.
+ * @return the value the key was mapped to. It returns null if
+ * the key wasn't in this map, or if the mapped value was
+ * explicitly set to null.
+ */
+ public Object get(Object key)
+ {
+ cleanQueue();
+ WeakBucket.WeakEntry entry = internalGet(key);
+ return entry == null ? null : entry.getValue();
+ }
+
+ /**
+ * Adds a new key/value mapping to this map.
+ * @param key the key, may be null
+ * @param value the value, may be null
+ * @return the value the key was mapped to previously. It returns
+ * null if the key wasn't in this map, or if the mapped value
+ * was explicitly set to null.
+ */
+ public Object put(Object key, Object value)
+ {
+ cleanQueue();
+ WeakBucket.WeakEntry entry = internalGet(key);
+ if (entry != null)
+ return entry.setValue(value);
+
+ modCount++;
+ if (size >= threshold)
+ rehash();
+
+ internalAdd(key, value);
+ return null;
+ }
+
+ /**
+ * Removes the key and the corresponding value from this map.
+ * @param key the key. This may be null.
+ * @return the value the key was mapped to previously. It returns
+ * null if the key wasn't in this map, or if the mapped value was
+ * explicitly set to null.
+ */
+ public Object remove(Object key)
+ {
+ cleanQueue();
+ WeakBucket.WeakEntry entry = internalGet(key);
+ if (entry == null)
+ return null;
+
+ modCount++;
+ internalRemove(entry.getBucket());
+ return entry.getValue();
+ }
+
+ /**
+ * Returns a set representation of the entries in this map. This
+ * set will not have strong references to the keys, so they can be
+ * silently removed. The returned set has therefore the same
+ * strange behaviour (shrinking size(), disappearing entries) as
+ * this weak hash map.
+ * @return a set representation of the entries.
+ */
+ public Set entrySet()
+ {
+ cleanQueue();
+ return theEntrySet;
+ }
+
+ /**
+ * Clears all entries from this map.
+ */
+ public void clear()
+ {
+ super.clear();
+ }
+
+ /**
+ * Returns true if the map contains at least one key which points to
+ * the specified object as a value. Note that the result
+ * may change spontanously, if its key was only weakly reachable.
+ * @param value the value to search for
+ * @return true if it is found in the set.
+ */
+ public boolean containsValue(Object value)
+ {
+ cleanQueue();
+ return super.containsValue(value);
+ }
+
+ /**
+ * Returns a set representation of the keys in this map. This
+ * set will not have strong references to the keys, so they can be
+ * silently removed. The returned set has therefore the same
+ * strange behaviour (shrinking size(), disappearing entries) as
+ * this weak hash map.
+ * @return a set representation of the keys.
+ */
+ public Set keySet()
+ {
+ cleanQueue();
+ return super.keySet();
+ }
+
+ /**
+ * Puts all of the mappings from the given map into this one. If the
+ * key already exists in this map, its value is replaced.
+ * @param m the map to copy in
+ */
+ public void putAll(Map m)
+ {
+ super.putAll(m);
+ }
+
+ /**
+ * Returns a collection representation of the values in this map. This
+ * collection will not have strong references to the keys, so mappings
+ * can be silently removed. The returned collection has therefore the same
+ * strange behaviour (shrinking size(), disappearing entries) as
+ * this weak hash map.
+ * @return a collection representation of the values.
+ */
+ public Collection values()
+ {
+ cleanQueue();
+ return super.values();
+ }
+} // class WeakHashMap
diff --git a/libjava/classpath/java/util/class-dependencies.conf b/libjava/classpath/java/util/class-dependencies.conf
new file mode 100644
index 00000000000..39f96062744
--- /dev/null
+++ b/libjava/classpath/java/util/class-dependencies.conf
@@ -0,0 +1,78 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+
+# All calendars supported are loaded via java/util/Calendar.getBundle or
+# java/util/GregorianCalendar.getBundle from class
+# gnu/java/locale/Calendar_{locale_id}
+#
+# This introduces a dependency for the localized calendars. To allow an easy
+# selection and addition of locales, the library variable {calendar_locales}
+# can be set to the set of supported calendar locales.
+#
+
+{calendar_locales}: de en nl
+
+java/util/Calendar.getBundle(Ljava/util/Locale;)Ljava/util/ResourceBundle;: \
+ gnu/java/locale/Calendar.* \
+ gnu/java/locale/Calendar_{calendar_locales}.*
+
+java/util/GregorianCalendar.getBundle(Ljava/util/Locale;)Ljava/util/ResourceBundle;: \
+ gnu/java/locale/Calendar.* \
+ gnu/java/locale/Calendar_{calendar_locales}.*
+
+# end of file
diff --git a/libjava/classpath/java/util/jar/Attributes.java b/libjava/classpath/java/util/jar/Attributes.java
new file mode 100644
index 00000000000..4db2c72e75b
--- /dev/null
+++ b/libjava/classpath/java/util/jar/Attributes.java
@@ -0,0 +1,630 @@
+/* Attributes.java -- Represents attribute name/value pairs from a Manifest
+ Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.jar;
+
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Represents attribute name/value pairs from a Manifest as a Map.
+ * The names of an attribute are represented by the
+ * <code>Attributes.Name</code> class and should confirm to the restrictions
+ * described in that class. Note that the Map interface that Attributes
+ * implements allows you to put names and values into the attribute that don't
+ * follow these restriction (and are not really Atrribute.Names, but if you do
+ * that it might cause undefined behaviour later).
+ * <p>
+ * If you use the constants defined in the inner class Name then you can be
+ * sure that you always access the right attribute names. This makes
+ * manipulating the Attributes more or less type safe.
+ * <p>
+ * Most of the methods are wrappers to implement the Map interface. The really
+ * useful and often used methods are <code>getValue(Name)</code> and
+ * <code>getValue(String)</code>. If you actually want to set attributes you
+ * may want to use the <code>putValue(String, String)</code> method
+ * (sorry there is no public type safe <code>putValue(Name, String)</code>
+ * method).
+ *
+ * @see java.util.jar.Attributes.Name
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class Attributes implements Cloneable, Map
+{
+
+ // Fields
+
+ /**
+ * The map that holds all the attribute name/value pairs. In this
+ * implementation it is actually a Hashtable, but that can be different in
+ * other implementations.
+ */
+ protected Map map;
+
+ // Inner class
+
+ /**
+ * Represents a name of a Manifest Attribute. Defines a couple of well
+ * know names for the general main attributes, stand alone application
+ * attributes, applet attributes, extension identification attributes,
+ * package versioning and sealing attributes, file contents attributes,
+ * bean objects attribute and signing attributes. See the
+ *
+ * <p>The characters of a Name must obey the following restrictions:</p>
+ *
+ * <ul>
+ * <li>Must contain at least one character</li>
+ * <li>The first character must be alphanumeric (a-z, A-Z, 0-9)</li>
+ * <li>All other characters must be alphanumeric, a '-' or a '_'</li>
+ * </ul>
+ *
+ * <p>When comparing Names (with <code>equals</code>) all characters are
+ * converted to lowercase. But you can get the original case sensitive
+ * string with the <code>toString()</code> method.</p>
+ *
+ * <p>Most important attributes have a constant defined in this
+ * class. Some other attributes used in Manifest files are:
+ * <ul>
+ * <li> "Created-By" - General main attribute, tool and version
+ * that created this Manifest file.</li>
+ * <li> "Java-Bean" - Bean objects attribute, whether the entry is a Bean.
+ * Value is either "true" or "false".</li>
+ * <li> "Magic" - Signing attribute, application specific signing attribute.
+ * Must be understood by the manifest parser when present to validate the
+ * jar (entry).</li>
+ * </ul>
+ *
+ * @since 1.2
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+ public static class Name
+ {
+ // General Main Attributes
+
+ /**
+ * General main attribute -
+ * the version of this Manifest file.
+ */
+ public static final Name MANIFEST_VERSION = new Name("Manifest-Version");
+
+ /**
+ * General main attribute -
+ * the version of the jar file signature.
+ */
+ public static final Name SIGNATURE_VERSION
+ = new Name("Signature-Version");
+
+ /**
+ * General main attribute -
+ * (relative) file paths of the libraries/classpaths that the Classes in
+ * this jar file depend on. Paths are separated by spaces.
+ */
+ public static final Name CLASS_PATH = new Name("Class-Path");
+
+ /**
+ * Stand alone application attribute -
+ * the entry (without the .class ending) that is the main
+ * class of this jar file.
+ */
+ public static final Name MAIN_CLASS = new Name("Main-Class");
+
+ /**
+ * Applet attribute -
+ * a list of extension libraries that the applet in this
+ * jar file depends on.
+ * For every named extension there should be some Attributes in the
+ * Manifest manifest file with the following Names:
+ * <ul>
+ * <li> &lt;extension&gt;-Extension-Name:
+ * unique name of the extension</li>
+ * <li> &lt;extension&gt;-Specification-Version:
+ * minimum specification version</li>
+ * <li> &lt;extension&gt;-Implementation-Version:
+ * minimum implementation version</li>
+ * <li> &lt;extension&gt;-Implementation-Vendor-Id:
+ * unique id of implementation vendor</li>
+ * <li> &lt;extension&gt;-Implementation-URL:
+ * where the latest version of the extension library can be found</li>
+ * </ul>
+ */
+ public static final Name EXTENSION_LIST = new Name("Extension-List");
+
+ /**
+ * Extension identification attribute -
+ * the name if the extension library contained in the jar.
+ */
+ public static final Name EXTENSION_NAME = new Name("Extension-Name");
+
+ /**
+ * Extension identification attribute -
+ * synonym for <code>EXTENSTION_NAME</code>.
+ */
+ public static final Name EXTENSION_INSTALLATION = EXTENSION_NAME;
+
+ // Package versioning and sealing attributes
+
+ /**
+ * Package versioning -
+ * name of extension library contained in this jar.
+ */
+ public static final Name IMPLEMENTATION_TITLE
+ = new Name("Implementation-Title");
+
+ /**
+ * Package versioning -
+ * version of the extension library contained in this jar.
+ */
+ public static final Name IMPLEMENTATION_VERSION
+ = new Name("Implementation-Version");
+
+ /**
+ * Package versioning -
+ * name of extension library creator contained in this jar.
+ */
+ public static final Name IMPLEMENTATION_VENDOR
+ = new Name("Implementation-Vendor");
+
+ /**
+ * Package versioning -
+ * unique id of extension library creator.
+ */
+ public static final Name IMPLEMENTATION_VENDOR_ID
+ = new Name("Implementation-Vendor-Id");
+
+ /**
+ * Package versioning -
+ * location where this implementation can be downloaded.
+ */
+ public static final Name IMPLEMENTATION_URL
+ = new Name("Implementation-URL");
+
+ /**
+ * Package versioning -
+ * title of the specification contained in this jar.
+ */
+ public static final Name SPECIFICATION_TITLE
+ = new Name("Specification-Title");
+
+ /**
+ * Package versioning -
+ * version of the specification contained in this jar.
+ */
+ public static final Name SPECIFICATION_VERSION
+ = new Name("Specification-Version");
+
+ /**
+ * Package versioning -
+ * organisation that maintains the specification contains in this
+ * jar.
+ */
+ public static final Name SPECIFICATION_VENDOR
+ = new Name("Specification-Vendor");
+
+ /**
+ * Package sealing -
+ * whether (all) package(s) is(/are) sealed. Value is either "true"
+ * or "false".
+ */
+ public static final Name SEALED = new Name("Sealed");
+
+ /**
+ * File contents attribute -
+ * Mime type and subtype for the jar entry.
+ */
+ public static final Name CONTENT_TYPE = new Name("Content-Type");
+
+ /** The (lowercase) String representation of this Name */
+ private final String name;
+
+ /** The original String given to the constructor */
+ private final String origName;
+
+ // Constructor
+
+ /**
+ * Creates a new Name from the given String.
+ * Throws an IllegalArgumentException if the given String is empty or
+ * contains any illegal Name characters.
+ *
+ * @param name the name of the new Name
+ * @exception IllegalArgumentException if name isn't a valid String
+ * representation of a Name
+ * @exception NullPointerException if name is null
+ */
+ public Name(String name) throws IllegalArgumentException,
+ NullPointerException
+ {
+ // name must not be null
+ // this will throw a NullPointerException if it is
+ char chars[] = name.toCharArray();
+
+ // there must be at least one character
+ if (chars.length == 0)
+ throw new
+ IllegalArgumentException
+ ("There must be at least one character in a name");
+
+ // first character must be alphanum
+ char c = chars[0];
+ if (!((c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')))
+ throw new
+ IllegalArgumentException("First character must be alphanum");
+
+ // all other characters must be alphanums, '-' or '_'
+ for (int i = 1; i < chars.length; i++)
+ {
+ c = chars[i];
+ if (!((c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || (c == '-') || (c == '_')))
+ throw new
+ IllegalArgumentException
+ ("Characters must be alphanums, '-' or '_'");
+ }
+
+ // Still here? Then convert to lower case and be done.
+ // Store the original name for toString();
+ this.origName = name;
+ this.name = name.toLowerCase();
+ }
+
+ /**
+ * Returns the hash code of the (lowercase) String representation of
+ * this Name.
+ */
+ public int hashCode()
+ {
+ return name.hashCode();
+ }
+
+ /**
+ * Checks if another object is equal to this Name object.
+ * Another object is equal to this Name object if it is an instance of
+ * Name and the (lowercase) string representation of the name is equal.
+ */
+ public boolean equals(Object o)
+ {
+ // Quick and dirty check
+ if (name == o)
+ return true;
+
+ try
+ {
+ // Note that the constructor already converts the strings to
+ // lowercase.
+ String otherName = ((Name) o).name;
+ return name.equals(otherName);
+ }
+ catch (ClassCastException cce)
+ {
+ return false;
+ }
+ catch (NullPointerException npe)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the string representation of this Name as given to the
+ * constructor (not neccesarily the lower case representation).
+ */
+ public String toString()
+ {
+ return origName;
+ }
+ }
+
+ // Constructors
+
+ /**
+ * Creates an empty Attributes map.
+ */
+ public Attributes()
+ {
+ map = new Hashtable();
+ }
+
+ /**
+ * Creates an empty Attributes map with the given initial size.
+ * @param size the initial size of the underlying map
+ */
+ public Attributes(int size)
+ {
+ map = new Hashtable(size);
+ }
+
+ /**
+ * Creates an Attributes map with the initial values taken from another
+ * Attributes map.
+ * @param attr Attributes map to take the initial values from
+ */
+ public Attributes(Attributes attr)
+ {
+ map = new Hashtable(attr.map);
+ }
+
+ // Methods
+
+ /**
+ * Gets the value of an attribute name given as a String.
+ *
+ * @param name a String describing the Name to look for
+ * @return the value gotten from the map of null when not found
+ */
+ public String getValue(String name)
+ {
+ return (String) get(new Name(name));
+ }
+
+ /**
+ * Gets the value of the given attribute name.
+ *
+ * @param name the Name to look for
+ * @return the value gotten from the map of null when not found
+ */
+ public String getValue(Name name)
+ {
+ return (String) get(name);
+ }
+
+ /**
+ * Stores an attribute name (represented by a String) and value in this
+ * Attributes map.
+ * When the (case insensitive string) name already exists the value is
+ * replaced and the old value is returned.
+ *
+ * @param name a (case insensitive) String representation of the attribite
+ * name to add/replace
+ * @param value the (new) value of the attribute name
+ * @returns the old value of the attribute name or null if it didn't exist
+ * yet
+ */
+ public String putValue(String name, String value)
+ {
+ return putValue(new Name(name), value);
+ }
+
+ /**
+ * Stores an attribute name (represented by a String) and value in this
+ * Attributes map.
+ * When the name already exists the value is replaced and the old value
+ * is returned.
+ * <p>
+ * I don't know why there is no public method with this signature. I think
+ * there should be one.
+ *
+ * @param name the attribite name to add/replace
+ * @param value the (new) value of the attribute name
+ * @returns the old value of the attribute name or null if it didn't exist
+ * yet
+ */
+ String putValue(Name name, String value)
+ {
+ return (String) put(name, value);
+ }
+
+ // Methods from Cloneable interface
+
+ /**
+ * Return a clone of this attribute map.
+ */
+ public Object clone()
+ {
+ return new Attributes(this);
+ }
+
+ // Methods from Map interface
+
+ /**
+ * Removes all attributes.
+ */
+ public void clear()
+ {
+ map.clear();
+ }
+
+ /**
+ * Checks to see if there is an attribute with the specified name.
+ * XXX - what if the object is a String?
+ *
+ * @param attrName the name of the attribute to check
+ * @return true if there is an attribute with the specified name, false
+ * otherwise
+ */
+ public boolean containsKey(Object attrName)
+ {
+ return map.containsKey(attrName);
+ }
+
+ /**
+ * Checks to see if there is an attribute name with the specified value.
+ *
+ * @param attrValue the value of a attribute to check
+ * @return true if there is an attribute name with the specified value,
+ * false otherwise
+ */
+ public boolean containsValue(Object attrValue)
+ {
+ return map.containsValue(attrValue);
+ }
+
+ /**
+ * Gives a Set of attribute name and values pairs as MapEntries.
+ * @see java.util.Map.Entry
+ * @see java.util.Map#entrySet()
+ *
+ * @return a set of attribute name value pairs
+ */
+ public Set entrySet()
+ {
+ return map.entrySet();
+ }
+
+ /**
+ * Checks to see if two Attributes are equal. The supplied object must be
+ * a real instance of Attributes and contain the same attribute name/value
+ * pairs.
+ *
+ * @param o another Attribute object which should be checked for equality
+ * @return true if the object is an instance of Attributes and contains the
+ * same name/value pairs, false otherwise
+ */
+ public boolean equals(Object o)
+ {
+ // quick and dirty check
+ if (this == o)
+ return true;
+
+ try
+ {
+ return map.equals(((Attributes) o).map);
+ }
+ catch (ClassCastException cce)
+ {
+ return false;
+ }
+ catch (NullPointerException npe)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Gets the value of a specified attribute name.
+ * XXX - what if the object is a String?
+ *
+ * @param attrName the name of the attribute we want the value of
+ * @return the value of the specified attribute name or null when there is
+ * no such attribute name
+ */
+ public Object get(Object attrName)
+ {
+ return map.get(attrName);
+ }
+
+ /**
+ * Returns the hashcode of the attribute name/value map.
+ */
+ public int hashCode()
+ {
+ return map.hashCode();
+ }
+
+ /**
+ * Returns true if there are no attributes set, false otherwise.
+ */
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ /**
+ * Gives a Set of all the values of defined attribute names.
+ */
+ public Set keySet()
+ {
+ return map.keySet();
+ }
+
+ /**
+ * Adds or replaces a attribute name/value pair.
+ * XXX - What if the name is a string? What if the name is neither a Name
+ * nor a String? What if the value is not a string?
+ *
+ * @param name the name of the attribute
+ * @param value the (new) value of the attribute
+ * @return the old value of the attribute or null when there was no old
+ * attribute with this name
+ */
+ public Object put(Object name, Object value)
+ {
+ return map.put(name, value);
+ }
+
+ /**
+ * Adds or replaces all attribute name/value pairs from another
+ * Attributes object to this one. The supplied Map must be an instance of
+ * Attributes.
+ *
+ * @param attr the Attributes object to merge with this one
+ * @exception ClassCastException if the supplied map is not an instance of
+ * Attributes
+ */
+ public void putAll(Map attr)
+ {
+ if (!(attr instanceof Attributes))
+ {
+ throw new
+ ClassCastException("Supplied Map is not an instance of Attributes");
+ }
+ map.putAll(attr);
+ }
+
+ /**
+ * Remove a attribute name/value pair.
+ * XXX - What if the name is a String?
+ *
+ * @param name the name of the attribute name/value pair to remove
+ * @return the old value of the attribute or null if the attribute didn't
+ * exist
+ */
+ public Object remove(Object name)
+ {
+ return map.remove(name);
+ }
+
+ /**
+ * Returns the number of defined attribute name/value pairs.
+ */
+ public int size()
+ {
+ return map.size();
+ }
+
+ /**
+ * Returns all the values of the defined attribute name/value pairs as a
+ * Collection.
+ */
+ public Collection values()
+ {
+ return map.values();
+ }
+}
diff --git a/libjava/classpath/java/util/jar/JarEntry.java b/libjava/classpath/java/util/jar/JarEntry.java
new file mode 100644
index 00000000000..722a283bba3
--- /dev/null
+++ b/libjava/classpath/java/util/jar/JarEntry.java
@@ -0,0 +1,165 @@
+/* JarEntry.java - Represents an entry in a jar file
+ Copyright (C) 2000 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.jar;
+
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.util.zip.ZipEntry;
+
+/**
+ * Extension to a ZipEntry that contains manifest attributes and certificates.
+ * Both the Atrributes and the Certificates can be null when not set.
+ * Note that the <code>getCertificates()</code> method only returns a
+ * valid value after all of the data of the entry has been read.
+ * <p>
+ * There are no public methods to set the attributes or certificate of an
+ * Entru. Only JarEntries created by the classes in <code>java.util.jar</code>
+ * will have these properties set.
+ *
+ * @since 1.2
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+
+public class JarEntry extends ZipEntry
+{
+ // (Package local) fields
+
+ Attributes attr;
+ Certificate certs[];
+
+ // Constructors
+
+ /**
+ * Creates a new JarEntry with the specified name and no attributes or
+ * or certificates. Calls <code>super(name)</code> so all other (zip)entry
+ * fields are null or -1.
+ *
+ * @param name the name of the new jar entry
+ * @exception NullPointerException when the supplied name is null
+ * @exception IllegalArgumentException when the supplied name is longer
+ * than 65535 bytes
+ */
+ public JarEntry(String name) throws NullPointerException,
+ IllegalArgumentException
+ {
+ super(name);
+ attr = null;
+ certs = null;
+ }
+
+ /**
+ * Creates a new JarEntry with the specified ZipEntry as template for
+ * all properties of the entry. Both attributes and certificates will be
+ * null.
+ *
+ * @param entry the ZipEntry whose fields should be copied
+ */
+ public JarEntry(ZipEntry entry)
+ {
+ super(entry);
+ attr = null;
+ certs = null;
+ }
+
+ /**
+ * Creates a new JarEntry with the specified JarEntry as template for
+ * all properties of the entry.
+ *
+ * @param entry the jarEntry whose fields should be copied
+ */
+ public JarEntry(JarEntry entry)
+ {
+ super(entry);
+ try
+ {
+ attr = entry.getAttributes();
+ }
+ catch (IOException _)
+ {
+ }
+ certs = entry.getCertificates();
+ }
+
+ // Methods
+
+ /**
+ * Returns a copy of the Attributes set for this entry.
+ * When no Attributes are set in the manifest null is returned.
+ *
+ * @return a copy of the Attributes set for this entry
+ * @exception IOException This will never be thrown. It is here for
+ * binary compatibility.
+ */
+ public Attributes getAttributes() throws IOException
+ {
+ if (attr != null)
+ {
+ return (Attributes) attr.clone();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns a copy of the certificates set for this entry.
+ * When no certificates are set or when not all data of this entry has
+ * been read null is returned.
+ * <p>
+ * To make sure that this call returns a valid value you must read all
+ * data from the JarInputStream for this entry.
+ * When you don't need the data for an entry but want to know the
+ * certificates that are set for the entry then you can skip all data by
+ * calling <code>skip(entry.getSize())</code> on the JarInputStream for
+ * the entry.
+ *
+ * @return a copy of the certificates set for this entry
+ */
+ public Certificate[] getCertificates()
+ {
+ if (certs != null)
+ {
+ return (Certificate[])certs.clone();
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/jar/JarException.java b/libjava/classpath/java/util/jar/JarException.java
new file mode 100644
index 00000000000..d6f0634fe71
--- /dev/null
+++ b/libjava/classpath/java/util/jar/JarException.java
@@ -0,0 +1,77 @@
+/* JarException.java -- thrown to indicate an problem with a jar file
+ Copyright (C) 2000, 2002 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.jar;
+
+import java.util.zip.ZipException;
+
+/**
+ * This exception is thrown to indicate an problem with a jar file.
+ * Note that none of the methods in the java.util.jar package actually declare
+ * to throw this exception, most just declare that they throw an IOException
+ * which is super class of JarException.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @since 1.2
+ */
+public class JarException extends ZipException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 7159778400963954473L;
+
+ /**
+ * Create a new JarException without a descriptive error message.
+ */
+ public JarException()
+ {
+ }
+
+ /**
+ * Create a new JarException with a descriptive error message indicating
+ * what went wrong. This message can later be retrieved by calling the
+ * <code>getMessage()</code> method.
+ *
+ * @param message The descriptive error message
+ * @see #getMessage()
+ */
+ public JarException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/libjava/classpath/java/util/jar/JarFile.java b/libjava/classpath/java/util/jar/JarFile.java
new file mode 100644
index 00000000000..a9ad21ecc1d
--- /dev/null
+++ b/libjava/classpath/java/util/jar/JarFile.java
@@ -0,0 +1,1059 @@
+/* JarFile.java - Representation of a jar file
+ Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.jar;
+
+import gnu.java.io.Base64InputStream;
+import gnu.java.security.OID;
+import gnu.java.security.pkcs.PKCS7SignedData;
+import gnu.java.security.pkcs.SignerInfo;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.CRLException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+/**
+ * Representation of a jar file.
+ * <p>
+ * Note that this class is not a subclass of java.io.File but a subclass of
+ * java.util.zip.ZipFile and you can only read JarFiles with it (although
+ * there are constructors that take a File object).
+ *
+ * @since 1.2
+ * @author Mark Wielaard (mark@klomp.org)
+ * @author Casey Marshall (csm@gnu.org) wrote the certificate and entry
+ * verification code.
+ */
+public class JarFile extends ZipFile
+{
+ // Fields
+
+ /** The name of the manifest entry: META-INF/MANIFEST.MF */
+ public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
+
+ /** The META-INF directory entry. */
+ private static final String META_INF = "META-INF/";
+
+ /** The suffix for PKCS7 DSA signature entries. */
+ private static final String PKCS7_DSA_SUFFIX = ".DSA";
+
+ /** The suffix for PKCS7 RSA signature entries. */
+ private static final String PKCS7_RSA_SUFFIX = ".RSA";
+
+ /** The suffix for digest attributes. */
+ private static final String DIGEST_KEY_SUFFIX = "-Digest";
+
+ /** The suffix for signature files. */
+ private static final String SF_SUFFIX = ".SF";
+
+ // Signature OIDs.
+ private static final OID MD2_OID = new OID("1.2.840.113549.2.2");
+ private static final OID MD4_OID = new OID("1.2.840.113549.2.4");
+ private static final OID MD5_OID = new OID("1.2.840.113549.2.5");
+ private static final OID SHA1_OID = new OID("1.3.14.3.2.26");
+ private static final OID DSA_ENCRYPTION_OID = new OID("1.2.840.10040.4.1");
+ private static final OID RSA_ENCRYPTION_OID = new OID("1.2.840.113549.1.1.1");
+
+ /**
+ * The manifest of this file, if any, otherwise null.
+ * Read when first needed.
+ */
+ private Manifest manifest;
+
+ /** Whether to verify the manifest and all entries. */
+ boolean verify;
+
+ /** Whether the has already been loaded. */
+ private boolean manifestRead = false;
+
+ /** Whether the signature files have been loaded. */
+ boolean signaturesRead = false;
+
+ /**
+ * A map between entry names and booleans, signaling whether or
+ * not that entry has been verified.
+ * Only be accessed with lock on this JarFile*/
+ HashMap verified = new HashMap();
+
+ /**
+ * A mapping from entry name to certificates, if any.
+ * Only accessed with lock on this JarFile.
+ */
+ HashMap entryCerts;
+
+ static boolean DEBUG = false;
+ static void debug(Object msg)
+ {
+ System.err.print(JarFile.class.getName());
+ System.err.print(" >>> ");
+ System.err.println(msg);
+ }
+
+ // Constructors
+
+ /**
+ * Creates a new JarFile. All jar entries are verified (when a Manifest file
+ * for this JarFile exists). You need to actually open and read the complete
+ * jar entry (with <code>getInputStream()</code>) to check its signature.
+ *
+ * @param fileName the name of the file to open
+ * @exception FileNotFoundException if the fileName cannot be found
+ * @exception IOException if another IO exception occurs while reading
+ */
+ public JarFile(String fileName) throws FileNotFoundException, IOException
+ {
+ this(fileName, true);
+ }
+
+ /**
+ * Creates a new JarFile. If verify is true then all jar entries are
+ * verified (when a Manifest file for this JarFile exists). You need to
+ * actually open and read the complete jar entry
+ * (with <code>getInputStream()</code>) to check its signature.
+ *
+ * @param fileName the name of the file to open
+ * @param verify checks manifest and entries when true and a manifest
+ * exists, when false no checks are made
+ * @exception FileNotFoundException if the fileName cannot be found
+ * @exception IOException if another IO exception occurs while reading
+ */
+ public JarFile(String fileName, boolean verify) throws
+ FileNotFoundException, IOException
+ {
+ super(fileName);
+ if (verify)
+ {
+ manifest = readManifest();
+ verify();
+ }
+ }
+
+ /**
+ * Creates a new JarFile. All jar entries are verified (when a Manifest file
+ * for this JarFile exists). You need to actually open and read the complete
+ * jar entry (with <code>getInputStream()</code>) to check its signature.
+ *
+ * @param file the file to open as a jar file
+ * @exception FileNotFoundException if the file does not exits
+ * @exception IOException if another IO exception occurs while reading
+ */
+ public JarFile(File file) throws FileNotFoundException, IOException
+ {
+ this(file, true);
+ }
+
+ /**
+ * Creates a new JarFile. If verify is true then all jar entries are
+ * verified (when a Manifest file for this JarFile exists). You need to
+ * actually open and read the complete jar entry
+ * (with <code>getInputStream()</code>) to check its signature.
+ *
+ * @param file the file to open to open as a jar file
+ * @param verify checks manifest and entries when true and a manifest
+ * exists, when false no checks are made
+ * @exception FileNotFoundException if file does not exist
+ * @exception IOException if another IO exception occurs while reading
+ */
+ public JarFile(File file, boolean verify) throws FileNotFoundException,
+ IOException
+ {
+ super(file);
+ if (verify)
+ {
+ manifest = readManifest();
+ verify();
+ }
+ }
+
+ /**
+ * Creates a new JarFile with the indicated mode. If verify is true then
+ * all jar entries are verified (when a Manifest file for this JarFile
+ * exists). You need to actually open and read the complete jar entry
+ * (with <code>getInputStream()</code>) to check its signature.
+ * manifest and if the manifest exists and verify is true verfies it.
+ *
+ * @param file the file to open to open as a jar file
+ * @param verify checks manifest and entries when true and a manifest
+ * exists, when false no checks are made
+ * @param mode either ZipFile.OPEN_READ or
+ * (ZipFile.OPEN_READ | ZipFile.OPEN_DELETE)
+ * @exception FileNotFoundException if the file does not exist
+ * @exception IOException if another IO exception occurs while reading
+ * @exception IllegalArgumentException when given an illegal mode
+ *
+ * @since 1.3
+ */
+ public JarFile(File file, boolean verify, int mode) throws
+ FileNotFoundException, IOException, IllegalArgumentException
+ {
+ super(file, mode);
+ if (verify)
+ {
+ manifest = readManifest();
+ verify();
+ }
+ }
+
+ // Methods
+
+ /**
+ * XXX - should verify the manifest file
+ */
+ private void verify()
+ {
+ // only check if manifest is not null
+ if (manifest == null)
+ {
+ verify = false;
+ return;
+ }
+
+ verify = true;
+ // XXX - verify manifest
+ }
+
+ /**
+ * Parses and returns the manifest if it exists, otherwise returns null.
+ */
+ private Manifest readManifest()
+ {
+ try
+ {
+ ZipEntry manEntry = super.getEntry(MANIFEST_NAME);
+ if (manEntry != null)
+ {
+ InputStream in = super.getInputStream(manEntry);
+ manifestRead = true;
+ return new Manifest(in);
+ }
+ else
+ {
+ manifestRead = true;
+ return null;
+ }
+ }
+ catch (IOException ioe)
+ {
+ manifestRead = true;
+ return null;
+ }
+ }
+
+ /**
+ * Returns a enumeration of all the entries in the JarFile.
+ * Note that also the Jar META-INF entries are returned.
+ *
+ * @exception IllegalStateException when the JarFile is already closed
+ */
+ public Enumeration entries() throws IllegalStateException
+ {
+ return new JarEnumeration(super.entries(), this);
+ }
+
+ /**
+ * Wraps a given Zip Entries Enumeration. For every zip entry a
+ * JarEntry is created and the corresponding Attributes are looked up.
+ */
+ private static class JarEnumeration implements Enumeration
+ {
+
+ private final Enumeration entries;
+ private final JarFile jarfile;
+
+ JarEnumeration(Enumeration e, JarFile f)
+ {
+ entries = e;
+ jarfile = f;
+ }
+
+ public boolean hasMoreElements()
+ {
+ return entries.hasMoreElements();
+ }
+
+ public Object nextElement()
+ {
+ ZipEntry zip = (ZipEntry) entries.nextElement();
+ JarEntry jar = new JarEntry(zip);
+ Manifest manifest;
+ try
+ {
+ manifest = jarfile.getManifest();
+ }
+ catch (IOException ioe)
+ {
+ manifest = null;
+ }
+
+ if (manifest != null)
+ {
+ jar.attr = manifest.getAttributes(jar.getName());
+ }
+
+ synchronized(jarfile)
+ {
+ if (!jarfile.signaturesRead)
+ try
+ {
+ jarfile.readSignatures();
+ }
+ catch (IOException ioe)
+ {
+ if (JarFile.DEBUG)
+ {
+ JarFile.debug(ioe);
+ ioe.printStackTrace();
+ }
+ jarfile.signaturesRead = true; // fudge it.
+ }
+
+ // Include the certificates only if we have asserted that the
+ // signatures are valid. This means the certificates will not be
+ // available if the entry hasn't been read yet.
+ if (jarfile.entryCerts != null
+ && jarfile.verified.get(zip.getName()) == Boolean.TRUE)
+ {
+ Set certs = (Set) jarfile.entryCerts.get(jar.getName());
+ if (certs != null)
+ jar.certs = (Certificate[])
+ certs.toArray(new Certificate[certs.size()]);
+ }
+ }
+ return jar;
+ }
+ }
+
+ /**
+ * XXX
+ * It actually returns a JarEntry not a zipEntry
+ * @param name XXX
+ */
+ public synchronized ZipEntry getEntry(String name)
+ {
+ ZipEntry entry = super.getEntry(name);
+ if (entry != null)
+ {
+ JarEntry jarEntry = new JarEntry(entry);
+ Manifest manifest;
+ try
+ {
+ manifest = getManifest();
+ }
+ catch (IOException ioe)
+ {
+ manifest = null;
+ }
+
+ if (manifest != null)
+ {
+ jarEntry.attr = manifest.getAttributes(name);
+ }
+
+ if (!signaturesRead)
+ try
+ {
+ readSignatures();
+ }
+ catch (IOException ioe)
+ {
+ if (DEBUG)
+ {
+ debug(ioe);
+ ioe.printStackTrace();
+ }
+ signaturesRead = true;
+ }
+ // See the comments in the JarEnumeration for why we do this
+ // check.
+ if (DEBUG)
+ debug("entryCerts=" + entryCerts + " verified " + name
+ + " ? " + verified.get(name));
+ if (entryCerts != null && verified.get(name) == Boolean.TRUE)
+ {
+ Set certs = (Set) entryCerts.get(name);
+ if (certs != null)
+ jarEntry.certs = (Certificate[])
+ certs.toArray(new Certificate[certs.size()]);
+ }
+ return jarEntry;
+ }
+ return null;
+ }
+
+ /**
+ * Returns an input stream for the given entry. If configured to
+ * verify entries, the input stream returned will verify them while
+ * the stream is read, but only on the first time.
+ *
+ * @param entry The entry to get the input stream for.
+ * @exception ZipException XXX
+ * @exception IOException XXX
+ */
+ public synchronized InputStream getInputStream(ZipEntry entry) throws
+ ZipException, IOException
+ {
+ // If we haven't verified the hash, do it now.
+ if (!verified.containsKey(entry.getName()) && verify)
+ {
+ if (DEBUG)
+ debug("reading and verifying " + entry);
+ return new EntryInputStream(entry, super.getInputStream(entry), this);
+ }
+ else
+ {
+ if (DEBUG)
+ debug("reading already verified entry " + entry);
+ if (verify && verified.get(entry.getName()) == Boolean.FALSE)
+ throw new ZipException("digest for " + entry + " is invalid");
+ return super.getInputStream(entry);
+ }
+ }
+
+ /**
+ * Returns the JarEntry that belongs to the name if such an entry
+ * exists in the JarFile. Returns null otherwise
+ * Convenience method that just casts the result from <code>getEntry</code>
+ * to a JarEntry.
+ *
+ * @param name the jar entry name to look up
+ * @return the JarEntry if it exists, null otherwise
+ */
+ public JarEntry getJarEntry(String name)
+ {
+ return (JarEntry) getEntry(name);
+ }
+
+ /**
+ * Returns the manifest for this JarFile or null when the JarFile does not
+ * contain a manifest file.
+ */
+ public synchronized Manifest getManifest() throws IOException
+ {
+ if (!manifestRead)
+ manifest = readManifest();
+
+ return manifest;
+ }
+
+ // Only called with lock on this JarFile.
+ // Package private for use in inner classes.
+ void readSignatures() throws IOException
+ {
+ Map pkcs7Dsa = new HashMap();
+ Map pkcs7Rsa = new HashMap();
+ Map sigFiles = new HashMap();
+
+ // Phase 1: Read all signature files. These contain the user
+ // certificates as well as the signatures themselves.
+ for (Enumeration e = super.entries(); e.hasMoreElements(); )
+ {
+ ZipEntry ze = (ZipEntry) e.nextElement();
+ String name = ze.getName();
+ if (name.startsWith(META_INF))
+ {
+ String alias = name.substring(META_INF.length());
+ if (alias.lastIndexOf('.') >= 0)
+ alias = alias.substring(0, alias.lastIndexOf('.'));
+
+ if (name.endsWith(PKCS7_DSA_SUFFIX) || name.endsWith(PKCS7_RSA_SUFFIX))
+ {
+ if (DEBUG)
+ debug("reading PKCS7 info from " + name + ", alias=" + alias);
+ PKCS7SignedData sig = null;
+ try
+ {
+ sig = new PKCS7SignedData(super.getInputStream(ze));
+ }
+ catch (CertificateException ce)
+ {
+ IOException ioe = new IOException("certificate parsing error");
+ ioe.initCause(ce);
+ throw ioe;
+ }
+ catch (CRLException crle)
+ {
+ IOException ioe = new IOException("CRL parsing error");
+ ioe.initCause(crle);
+ throw ioe;
+ }
+ if (name.endsWith(PKCS7_DSA_SUFFIX))
+ pkcs7Dsa.put(alias, sig);
+ else if (name.endsWith(PKCS7_RSA_SUFFIX))
+ pkcs7Rsa.put(alias, sig);
+ }
+ else if (name.endsWith(SF_SUFFIX))
+ {
+ if (DEBUG)
+ debug("reading signature file for " + alias + ": " + name);
+ Manifest sf = new Manifest(super.getInputStream(ze));
+ sigFiles.put(alias, sf);
+ if (DEBUG)
+ debug("result: " + sf);
+ }
+ }
+ }
+
+ // Phase 2: verify the signatures on any signature files.
+ Set validCerts = new HashSet();
+ Map entryCerts = new HashMap();
+ for (Iterator it = sigFiles.entrySet().iterator(); it.hasNext(); )
+ {
+ int valid = 0;
+ Map.Entry e = (Map.Entry) it.next();
+ String alias = (String) e.getKey();
+
+ PKCS7SignedData sig = (PKCS7SignedData) pkcs7Dsa.get(alias);
+ if (sig != null)
+ {
+ Certificate[] certs = sig.getCertificates();
+ Set signerInfos = sig.getSignerInfos();
+ for (Iterator it2 = signerInfos.iterator(); it2.hasNext(); )
+ verify(certs, (SignerInfo) it2.next(), alias, validCerts);
+ }
+
+ sig = (PKCS7SignedData) pkcs7Rsa.get(alias);
+ if (sig != null)
+ {
+ Certificate[] certs = sig.getCertificates();
+ Set signerInfos = sig.getSignerInfos();
+ for (Iterator it2 = signerInfos.iterator(); it2.hasNext(); )
+ verify(certs, (SignerInfo) it2.next(), alias, validCerts);
+ }
+
+ // It isn't a signature for anything. Punt it.
+ if (validCerts.isEmpty())
+ {
+ it.remove();
+ continue;
+ }
+
+ entryCerts.put(e.getValue(), new HashSet(validCerts));
+ validCerts.clear();
+ }
+
+ // Phase 3: verify the signature file signatures against the manifest,
+ // mapping the entry name to the target certificates.
+ this.entryCerts = new HashMap();
+ for (Iterator it = entryCerts.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry) it.next();
+ Manifest sigfile = (Manifest) e.getKey();
+ Map entries = sigfile.getEntries();
+ Set certificates = (Set) e.getValue();
+
+ for (Iterator it2 = entries.entrySet().iterator(); it2.hasNext(); )
+ {
+ Map.Entry e2 = (Map.Entry) it2.next();
+ String entryname = String.valueOf(e2.getKey());
+ Attributes attr = (Attributes) e2.getValue();
+ if (verifyHashes(entryname, attr))
+ {
+ if (DEBUG)
+ debug("entry " + entryname + " has certificates " + certificates);
+ Set s = (Set) this.entryCerts.get(entryname);
+ if (s != null)
+ s.addAll(certificates);
+ else
+ this.entryCerts.put(entryname, new HashSet(certificates));
+ }
+ }
+ }
+
+ signaturesRead = true;
+ }
+
+ /**
+ * Tell if the given signer info is over the given alias's signature file,
+ * given one of the certificates specified.
+ */
+ private void verify(Certificate[] certs, SignerInfo signerInfo,
+ String alias, Set validCerts)
+ {
+ Signature sig = null;
+ try
+ {
+ OID alg = signerInfo.getDigestEncryptionAlgorithmId();
+ if (alg.equals(DSA_ENCRYPTION_OID))
+ {
+ if (!signerInfo.getDigestAlgorithmId().equals(SHA1_OID))
+ return;
+ sig = Signature.getInstance("SHA1withDSA");
+ }
+ else if (alg.equals(RSA_ENCRYPTION_OID))
+ {
+ OID hash = signerInfo.getDigestAlgorithmId();
+ if (hash.equals(MD2_OID))
+ sig = Signature.getInstance("md2WithRsaEncryption");
+ else if (hash.equals(MD4_OID))
+ sig = Signature.getInstance("md4WithRsaEncryption");
+ else if (hash.equals(MD5_OID))
+ sig = Signature.getInstance("md5WithRsaEncryption");
+ else if (hash.equals(SHA1_OID))
+ sig = Signature.getInstance("sha1WithRsaEncryption");
+ else
+ return;
+ }
+ else
+ {
+ if (DEBUG)
+ debug("unsupported signature algorithm: " + alg);
+ return;
+ }
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ if (DEBUG)
+ {
+ debug(nsae);
+ nsae.printStackTrace();
+ }
+ return;
+ }
+ ZipEntry sigFileEntry = super.getEntry(META_INF + alias + SF_SUFFIX);
+ if (sigFileEntry == null)
+ return;
+ for (int i = 0; i < certs.length; i++)
+ {
+ if (!(certs[i] instanceof X509Certificate))
+ continue;
+ X509Certificate cert = (X509Certificate) certs[i];
+ if (!cert.getIssuerX500Principal().equals(signerInfo.getIssuer()) ||
+ !cert.getSerialNumber().equals(signerInfo.getSerialNumber()))
+ continue;
+ try
+ {
+ sig.initVerify(cert.getPublicKey());
+ InputStream in = super.getInputStream(sigFileEntry);
+ if (in == null)
+ continue;
+ byte[] buf = new byte[1024];
+ int len = 0;
+ while ((len = in.read(buf)) != -1)
+ sig.update(buf, 0, len);
+ if (sig.verify(signerInfo.getEncryptedDigest()))
+ {
+ if (DEBUG)
+ debug("signature for " + cert.getSubjectDN() + " is good");
+ validCerts.add(cert);
+ }
+ }
+ catch (IOException ioe)
+ {
+ continue;
+ }
+ catch (InvalidKeyException ike)
+ {
+ continue;
+ }
+ catch (SignatureException se)
+ {
+ continue;
+ }
+ }
+ }
+
+ /**
+ * Verifies that the digest(s) in a signature file were, in fact, made
+ * over the manifest entry for ENTRY.
+ *
+ * @param entry The entry name.
+ * @param attr The attributes from the signature file to verify.
+ */
+ private boolean verifyHashes(String entry, Attributes attr)
+ {
+ int verified = 0;
+
+ // The bytes for ENTRY's manifest entry, which are signed in the
+ // signature file.
+ byte[] entryBytes = null;
+ try
+ {
+ ZipEntry e = super.getEntry(entry);
+ if (e == null)
+ {
+ if (DEBUG)
+ debug("verifyHashes: no entry '" + entry + "'");
+ return false;
+ }
+ entryBytes = readManifestEntry(e);
+ }
+ catch (IOException ioe)
+ {
+ if (DEBUG)
+ {
+ debug(ioe);
+ ioe.printStackTrace();
+ }
+ return false;
+ }
+
+ for (Iterator it = attr.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry) it.next();
+ String key = String.valueOf(e.getKey());
+ if (!key.endsWith(DIGEST_KEY_SUFFIX))
+ continue;
+ String alg = key.substring(0, key.length() - DIGEST_KEY_SUFFIX.length());
+ try
+ {
+ byte[] hash = Base64InputStream.decode((String) e.getValue());
+ MessageDigest md = MessageDigest.getInstance(alg);
+ md.update(entryBytes);
+ byte[] hash2 = md.digest();
+ if (DEBUG)
+ debug("verifying SF entry " + entry + " alg: " + md.getAlgorithm()
+ + " expect=" + new java.math.BigInteger(hash).toString(16)
+ + " comp=" + new java.math.BigInteger(hash2).toString(16));
+ if (!Arrays.equals(hash, hash2))
+ return false;
+ verified++;
+ }
+ catch (IOException ioe)
+ {
+ if (DEBUG)
+ {
+ debug(ioe);
+ ioe.printStackTrace();
+ }
+ return false;
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ if (DEBUG)
+ {
+ debug(nsae);
+ nsae.printStackTrace();
+ }
+ return false;
+ }
+ }
+
+ // We have to find at least one valid digest.
+ return verified > 0;
+ }
+
+ /**
+ * Read the raw bytes that comprise a manifest entry. We can't use the
+ * Manifest object itself, because that loses information (such as line
+ * endings, and order of entries).
+ */
+ private byte[] readManifestEntry(ZipEntry entry) throws IOException
+ {
+ InputStream in = super.getInputStream(super.getEntry(MANIFEST_NAME));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] target = ("Name: " + entry.getName()).getBytes();
+ int t = 0, c, prev = -1, state = 0, l = -1;
+
+ while ((c = in.read()) != -1)
+ {
+// if (DEBUG)
+// debug("read "
+// + (c == '\n' ? "\\n" : (c == '\r' ? "\\r" : String.valueOf((char) c)))
+// + " state=" + state + " prev="
+// + (prev == '\n' ? "\\n" : (prev == '\r' ? "\\r" : String.valueOf((char) prev)))
+// + " t=" + t + (t < target.length ? (" target[t]=" + (char) target[t]) : "")
+// + " l=" + l);
+ switch (state)
+ {
+
+ // Step 1: read until we find the "target" bytes: the start
+ // of the entry we need to read.
+ case 0:
+ if (((byte) c) != target[t])
+ t = 0;
+ else
+ {
+ t++;
+ if (t == target.length)
+ {
+ out.write(target);
+ state = 1;
+ }
+ }
+ break;
+
+ // Step 2: assert that there is a newline character after
+ // the "target" bytes.
+ case 1:
+ if (c != '\n' && c != '\r')
+ {
+ out.reset();
+ t = 0;
+ state = 0;
+ }
+ else
+ {
+ out.write(c);
+ state = 2;
+ }
+ break;
+
+ // Step 3: read this whole entry, until we reach an empty
+ // line.
+ case 2:
+ if (c == '\n')
+ {
+ out.write(c);
+ // NL always terminates a line.
+ if (l == 0 || (l == 1 && prev == '\r'))
+ return out.toByteArray();
+ l = 0;
+ }
+ else
+ {
+ // Here we see a blank line terminated by a CR,
+ // followed by the next entry. Technically, `c' should
+ // always be 'N' at this point.
+ if (l == 1 && prev == '\r')
+ return out.toByteArray();
+ out.write(c);
+ l++;
+ }
+ prev = c;
+ break;
+
+ default:
+ throw new RuntimeException("this statement should be unreachable");
+ }
+ }
+
+ // The last entry, with a single CR terminating the line.
+ if (state == 2 && prev == '\r' && l == 0)
+ return out.toByteArray();
+
+ // We should not reach this point, we didn't find the entry (or, possibly,
+ // it is the last entry and is malformed).
+ throw new IOException("could not find " + entry + " in manifest");
+ }
+
+ /**
+ * A utility class that verifies jar entries as they are read.
+ */
+ private static class EntryInputStream extends FilterInputStream
+ {
+ private final JarFile jarfile;
+ private final long length;
+ private long pos;
+ private final ZipEntry entry;
+ private final byte[][] hashes;
+ private final MessageDigest[] md;
+ private boolean checked;
+
+ EntryInputStream(final ZipEntry entry,
+ final InputStream in,
+ final JarFile jar)
+ throws IOException
+ {
+ super(in);
+ this.entry = entry;
+ this.jarfile = jar;
+
+ length = entry.getSize();
+ pos = 0;
+ checked = false;
+
+ Attributes attr;
+ Manifest manifest = jarfile.getManifest();
+ if (manifest != null)
+ attr = manifest.getAttributes(entry.getName());
+ else
+ attr = null;
+ if (DEBUG)
+ debug("verifying entry " + entry + " attr=" + attr);
+ if (attr == null)
+ {
+ hashes = new byte[0][];
+ md = new MessageDigest[0];
+ }
+ else
+ {
+ List hashes = new LinkedList();
+ List md = new LinkedList();
+ for (Iterator it = attr.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry) it.next();
+ String key = String.valueOf(e.getKey());
+ if (key == null)
+ continue;
+ if (!key.endsWith(DIGEST_KEY_SUFFIX))
+ continue;
+ hashes.add(Base64InputStream.decode((String) e.getValue()));
+ try
+ {
+ md.add(MessageDigest.getInstance
+ (key.substring(0, key.length() - DIGEST_KEY_SUFFIX.length())));
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ IOException ioe = new IOException("no such message digest: " + key);
+ ioe.initCause(nsae);
+ throw ioe;
+ }
+ }
+ if (DEBUG)
+ debug("digests=" + md);
+ this.hashes = (byte[][]) hashes.toArray(new byte[hashes.size()][]);
+ this.md = (MessageDigest[]) md.toArray(new MessageDigest[md.size()]);
+ }
+ }
+
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ public void mark(int readLimit)
+ {
+ }
+
+ public void reset()
+ {
+ }
+
+ public int read() throws IOException
+ {
+ int b = super.read();
+ if (b == -1)
+ {
+ eof();
+ return -1;
+ }
+ for (int i = 0; i < md.length; i++)
+ md[i].update((byte) b);
+ pos++;
+ if (length > 0 && pos >= length)
+ eof();
+ return b;
+ }
+
+ public int read(byte[] buf, int off, int len) throws IOException
+ {
+ int count = super.read(buf, off, (int) Math.min(len, (length != 0
+ ? length - pos
+ : Integer.MAX_VALUE)));
+ if (count == -1 || (length > 0 && pos >= length))
+ {
+ eof();
+ return -1;
+ }
+ for (int i = 0; i < md.length; i++)
+ md[i].update(buf, off, count);
+ pos += count;
+ if (length != 0 && pos >= length)
+ eof();
+ return count;
+ }
+
+ public int read(byte[] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public long skip(long bytes) throws IOException
+ {
+ byte[] b = new byte[1024];
+ long amount = 0;
+ while (amount < bytes)
+ {
+ int l = read(b, 0, (int) Math.min(b.length, bytes - amount));
+ if (l == -1)
+ break;
+ amount += l;
+ }
+ return amount;
+ }
+
+ private void eof() throws IOException
+ {
+ if (checked)
+ return;
+ checked = true;
+ for (int i = 0; i < md.length; i++)
+ {
+ byte[] hash = md[i].digest();
+ if (DEBUG)
+ debug("verifying " + md[i].getAlgorithm() + " expect="
+ + new java.math.BigInteger(hashes[i]).toString(16)
+ + " comp=" + new java.math.BigInteger(hash).toString(16));
+ if (!Arrays.equals(hash, hashes[i]))
+ {
+ synchronized(jarfile)
+ {
+ if (DEBUG)
+ debug(entry + " could NOT be verified");
+ jarfile.verified.put(entry.getName(), Boolean.FALSE);
+ }
+ return;
+ // XXX ??? what do we do here?
+ // throw new ZipException("message digest mismatch");
+ }
+ }
+
+ synchronized(jarfile)
+ {
+ if (DEBUG)
+ debug(entry + " has been VERIFIED");
+ jarfile.verified.put(entry.getName(), Boolean.TRUE);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/jar/JarInputStream.java b/libjava/classpath/java/util/jar/JarInputStream.java
new file mode 100644
index 00000000000..1788af6add5
--- /dev/null
+++ b/libjava/classpath/java/util/jar/JarInputStream.java
@@ -0,0 +1,200 @@
+/* JarInputStream.java - InputStream for reading jar files
+ Copyright (C) 2000, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.jar;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * InputStream for reading jar files.
+ * XXX - verification of the signatures in the Manifest file is not yet
+ * implemented.
+ *
+ * @since 1.2
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+
+public class JarInputStream extends ZipInputStream
+{
+ // Fields
+
+ /** The manifest for this file or null when there was no manifest. */
+ private Manifest manifest;
+
+ /** The first real JarEntry for this file. Used by readManifest() to store
+ an entry that isn't the manifest but that should be returned by
+ getNextEntry next time it is called. Null when no firstEntry was read
+ while searching for the manifest entry, or when it has already been
+ returned by getNextEntry(). */
+ private JarEntry firstEntry;
+
+ // Constructors
+
+ /**
+ * Creates a new JarInputStream and tries to read the manifest.
+ * If such a manifest is present the JarInputStream tries to verify all
+ * the entry signatures while reading.
+ *
+ * @param in InputStream to read the jar from
+ * @exception IOException when an error occurs when opening or reading
+ */
+ public JarInputStream(InputStream in) throws IOException
+ {
+ this(in, true);
+ }
+
+ /**
+ * Creates a new JarInputStream and tries to read the manifest.
+ * If such a manifest is present and verify is true, the JarInputStream
+ * tries to verify all the entry signatures while reading.
+ *
+ * @param in InputStream to read the jar from
+ * @param verify whether or not to verify the manifest entries
+ * @exception IOException when an error occurs when opening or reading
+ */
+ public JarInputStream(InputStream in, boolean verify) throws IOException
+ {
+ super(in);
+ readManifest(verify);
+ }
+
+ // Methods
+
+ /**
+ * Set the manifest if found. Skips all entries that start with "META-INF/"
+ *
+ * @param verify when true (and a Manifest is found) checks the Manifest,
+ * when false no check is performed
+ * @exception IOException if an error occurs while reading
+ */
+ private void readManifest(boolean verify) throws IOException
+ {
+ firstEntry = (JarEntry) super.getNextEntry();
+ while ((firstEntry != null) &&
+ firstEntry.getName().startsWith("META-INF/"))
+ {
+ if (firstEntry.getName().equals(JarFile.MANIFEST_NAME))
+ {
+ manifest = new Manifest(this);
+ }
+ firstEntry = (JarEntry) super.getNextEntry();
+ }
+
+ if (verify)
+ {
+ // XXX
+ }
+ }
+
+ /**
+ * Creates a JarEntry for a particular name and consults the manifest
+ * for the Attributes of the entry.
+ * Used by <code>ZipEntry.getNextEntry()</code>
+ *
+ * @param name the name of the new entry
+ */
+ protected ZipEntry createZipEntry(String name)
+ {
+ ZipEntry zipEntry = super.createZipEntry(name);
+ JarEntry jarEntry = new JarEntry(zipEntry);
+ if (manifest != null)
+ {
+ jarEntry.attr = manifest.getAttributes(name);
+ }
+ return jarEntry;
+ }
+
+ /**
+ * Returns the Manifest for the jar file or null if there was no Manifest.
+ */
+ public Manifest getManifest()
+ {
+ return manifest;
+ }
+
+ /**
+ * Returns the next entry or null when there are no more entries.
+ * Does actually return a JarEntry, if you don't want to cast it yourself
+ * use <code>getNextJarEntry()</code>. Does not return any entries found
+ * at the beginning of the ZipFile that are special
+ * (those that start with "META-INF/").
+ *
+ * @exception IOException if an IO error occurs when reading the entry
+ */
+ public ZipEntry getNextEntry() throws IOException
+ {
+ ZipEntry entry;
+ if (firstEntry != null)
+ {
+ entry = firstEntry;
+ firstEntry = null;
+ }
+ else
+ {
+ entry = super.getNextEntry();
+ }
+ return entry;
+ }
+
+ /**
+ * Returns the next jar entry or null when there are no more entries.
+ *
+ * @exception IOException if an IO error occurs when reading the entry
+ */
+ public JarEntry getNextJarEntry() throws IOException
+ {
+ return (JarEntry) getNextEntry();
+ }
+
+ /**
+ * XXX
+ *
+ * @param buf XXX
+ * @param off XXX
+ * @param len XXX
+ * @return XXX
+ * @exception IOException XXX
+ */
+ public int read(byte[]buf, int off, int len) throws IOException
+ {
+ // XXX if (verify) {}
+ return super.read(buf, off, len);
+ }
+}
diff --git a/libjava/classpath/java/util/jar/JarOutputStream.java b/libjava/classpath/java/util/jar/JarOutputStream.java
new file mode 100644
index 00000000000..2c8c2f08d8f
--- /dev/null
+++ b/libjava/classpath/java/util/jar/JarOutputStream.java
@@ -0,0 +1,113 @@
+/* JarOutputStream.java - OutputStream for writing jar files
+ Copyright (C) 2000, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.jar;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * OutputStream for writing jar files.
+ * A special ZipOutputStream that can take JarEntries and can have a optional
+ * Manifest as first entry.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+
+public class JarOutputStream extends ZipOutputStream
+{
+ // Constructors
+
+ /**
+ * Creates a new JarOutputStream without a manifest entry.
+ *
+ * @param out the stream to create the new jar on
+ * @exception IOException if something unexpected happend
+ */
+ public JarOutputStream(OutputStream out) throws IOException
+ {
+ this(out, null);
+ }
+
+ /**
+ * Creates a new JarOutputStream with a manifest entry.
+ * The manifest will be the first entry in the jar.
+ *
+ * @param out the stream to create the new jar on
+ * @param man the manifest that should be put in the jar file or null
+ * for no manifest entry
+ * @exception IOException if something unexpected happend
+ */
+ public JarOutputStream(OutputStream out, Manifest man) throws IOException
+ {
+ super(out);
+ if (man != null)
+ writeManifest(man);
+ }
+
+ // Methods
+
+ /**
+ * Writes the manifest to a new JarEntry in this JarOutputStream with as
+ * name JarFile.MANIFEST_NAME.
+ *
+ * @param manifest the non null manifest to be written
+ * @exception IOException if something unexpected happend
+ */
+ private void writeManifest(Manifest manifest) throws IOException
+ {
+ // Create a new Jar Entry for the Manifest
+ JarEntry entry = new JarEntry(JarFile.MANIFEST_NAME);
+ putNextEntry(entry);
+ manifest.write(this);
+ closeEntry();
+ }
+
+ /**
+ * Prepares the JarOutputStream for writing the next entry.
+ * This implementation just calls <code>super.putNextEntre()</code>.
+ *
+ * @param entry The information for the next entry
+ * @exception IOException when some unexpected I/O exception occurred
+ */
+ public void putNextEntry(ZipEntry entry) throws IOException
+ {
+ super.putNextEntry(entry); // XXX
+ }
+}
diff --git a/libjava/classpath/java/util/jar/Manifest.java b/libjava/classpath/java/util/jar/Manifest.java
new file mode 100644
index 00000000000..fdc76ff97ee
--- /dev/null
+++ b/libjava/classpath/java/util/jar/Manifest.java
@@ -0,0 +1,472 @@
+/* Manifest.java -- Reads, writes and manipulaties jar manifest files
+ Copyright (C) 2000, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.jar;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Reads, writes and manipulaties jar manifest files.
+ * XXX
+ *
+ * @since 1.2
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class Manifest implements Cloneable
+{
+ // Fields
+
+ /** The main attributes of the manifest (jar file). */
+ private final Attributes mainAttr;
+
+ /** A map of atrributes for all entries described in this Manifest. */
+ private final Map entries;
+
+ // Constructors
+
+ /**
+ * Creates a new empty Manifest.
+ */
+ public Manifest()
+ {
+ mainAttr = new Attributes();
+ entries = new Hashtable();
+ }
+
+ /**
+ * Creates a Manifest from the supplied input stream.
+ *
+ * @see read(Inputstream)
+ * @see write(OutputStream)
+ *
+ * @param InputStream the input stream to read the manifest from
+ * @exception IOException when an i/o exception occurs or the input stream
+ * does not describe a valid manifest
+ */
+ public Manifest(InputStream in) throws IOException
+ {
+ this();
+ read(in);
+ }
+
+ /**
+ * Creates a Manifest from another Manifest.
+ * Makes a deep copy of the main attributes, but a shallow copy of
+ * the other entries. This means that you can freely add, change or remove
+ * the main attributes or the entries of the new manifest without effecting
+ * the original manifest, but adding, changing or removing attributes from
+ * a particular entry also changes the attributes of that entry in the
+ * original manifest.
+ *
+ * @see clone()
+ * @param man the Manifest to copy from
+ */
+ public Manifest(Manifest man)
+ {
+ mainAttr = new Attributes(man.getMainAttributes());
+ entries = new Hashtable(man.getEntries());
+ }
+
+ // Methods
+
+ /**
+ * Gets the main attributes of this Manifest.
+ */
+ public Attributes getMainAttributes()
+ {
+ return mainAttr;
+ }
+
+ /**
+ * Gets a map of entry Strings to Attributes for all the entries described
+ * in this manifest. Adding, changing or removing from this entries map
+ * changes the entries of this manifest.
+ */
+ public Map getEntries()
+ {
+ return entries;
+ }
+
+ /**
+ * Returns the Attributes associated with the Entry.
+ * <p>
+ * Implemented as:
+ * <code>return (Attributes)getEntries().get(entryName)</code>
+ *
+ * @param entryName the name of the entry to look up
+ * @return the attributes associated with the entry or null when none
+ */
+ public Attributes getAttributes(String entryName)
+ {
+ return (Attributes) getEntries().get(entryName);
+ }
+
+ /**
+ * Clears the main attributes and removes all the entries from the
+ * manifest.
+ */
+ public void clear()
+ {
+ mainAttr.clear();
+ entries.clear();
+ }
+
+ /**
+ * XXX
+ */
+ public void read(InputStream in) throws IOException
+ {
+ BufferedReader br =
+ new BufferedReader(new InputStreamReader(in, "8859_1"));
+ read_main_section(getMainAttributes(), br);
+ read_individual_sections(getEntries(), br);
+ }
+
+ // Private Static methods for reading the Manifest file from BufferedReader
+
+ private static void read_main_section(Attributes attr,
+ BufferedReader br) throws IOException
+ {
+ // According to the spec we should actually call read_version_info() here.
+ read_attributes(attr, br);
+ // Explicitly set Manifest-Version attribute if not set in Main
+ // attributes of Manifest.
+ if (attr.getValue(Attributes.Name.MANIFEST_VERSION) == null)
+ attr.putValue(Attributes.Name.MANIFEST_VERSION, "0.0");
+ }
+
+ /**
+ * Pedantic method that requires the next attribute in the Manifest to be
+ * the "Manifest-Version". This follows the Manifest spec closely but
+ * reject some jar Manifest files out in the wild.
+ */
+ private static void read_version_info(Attributes attr,
+ BufferedReader br) throws IOException
+ {
+ String version_header = Attributes.Name.MANIFEST_VERSION.toString();
+ try
+ {
+ String value = expect_header(version_header, br);
+ attr.putValue(Attributes.Name.MANIFEST_VERSION, value);
+ }
+ catch (IOException ioe)
+ {
+ throw new JarException("Manifest should start with a " +
+ version_header + ": " + ioe.getMessage());
+ }
+ }
+
+ private static String expect_header(String header, BufferedReader br)
+ throws IOException
+ {
+ String s = br.readLine();
+ if (s == null)
+ {
+ throw new JarException("unexpected end of file");
+ }
+ return expect_header(header, br, s);
+ }
+
+ private static String expect_header(String header, BufferedReader br,
+ String s) throws IOException
+ {
+ try
+ {
+ String name = s.substring(0, header.length() + 1);
+ if (name.equalsIgnoreCase(header + ":"))
+ {
+ String value_start = s.substring(header.length() + 2);
+ return read_header_value(value_start, br);
+ }
+ }
+ catch (IndexOutOfBoundsException iobe)
+ {
+ }
+ // If we arrive here, something went wrong
+ throw new JarException("unexpected '" + s + "'");
+ }
+
+ private static String read_header_value(String s, BufferedReader br)
+ throws IOException
+ {
+ boolean try_next = true;
+ while (try_next)
+ {
+ // Lets see if there is something on the next line
+ br.mark(1);
+ if (br.read() == ' ')
+ {
+ s += br.readLine();
+ }
+ else
+ {
+ br.reset();
+ try_next = false;
+ }
+ }
+ return s;
+ }
+
+ private static void read_attributes(Attributes attr,
+ BufferedReader br) throws IOException
+ {
+ String s = br.readLine();
+ while (s != null && (!s.equals("")))
+ {
+ read_attribute(attr, s, br);
+ s = br.readLine();
+ }
+ }
+
+ private static void read_attribute(Attributes attr, String s,
+ BufferedReader br) throws IOException
+ {
+ try
+ {
+ int colon = s.indexOf(": ");
+ String name = s.substring(0, colon);
+ String value_start = s.substring(colon + 2);
+ String value = read_header_value(value_start, br);
+ attr.putValue(name, value);
+ }
+ catch (IndexOutOfBoundsException iobe)
+ {
+ throw new JarException("Manifest contains a bad header: " + s);
+ }
+ }
+
+ private static void read_individual_sections(Map entries,
+ BufferedReader br) throws
+ IOException
+ {
+ String s = br.readLine();
+ while (s != null && (!s.equals("")))
+ {
+ Attributes attr = read_section_name(s, br, entries);
+ read_attributes(attr, br);
+ s = br.readLine();
+ }
+ }
+
+ private static Attributes read_section_name(String s, BufferedReader br,
+ Map entries) throws JarException
+ {
+ try
+ {
+ String name = expect_header("Name", br, s);
+ Attributes attr = new Attributes();
+ entries.put(name, attr);
+ return attr;
+ }
+ catch (IOException ioe)
+ {
+ throw new JarException
+ ("Section should start with a Name header: " + ioe.getMessage());
+ }
+ }
+
+ /**
+ * XXX
+ */
+ public void write(OutputStream out) throws IOException
+ {
+ PrintWriter pw =
+ new PrintWriter(new
+ BufferedWriter(new OutputStreamWriter(out, "8859_1")));
+ write_main_section(getMainAttributes(), pw);
+ pw.println();
+ write_individual_sections(getEntries(), pw);
+ if (pw.checkError())
+ {
+ throw new JarException("Error while writing manifest");
+ }
+ }
+
+ // Private Static functions for writing the Manifest file to a PrintWriter
+
+ private static void write_main_section(Attributes attr,
+ PrintWriter pw) throws JarException
+ {
+ write_version_info(attr, pw);
+ write_main_attributes(attr, pw);
+ }
+
+ private static void write_version_info(Attributes attr, PrintWriter pw)
+ {
+ // First check if there is already a version attribute set
+ String version = attr.getValue(Attributes.Name.MANIFEST_VERSION);
+ if (version == null)
+ {
+ version = "1.0";
+ }
+ write_header(Attributes.Name.MANIFEST_VERSION.toString(), version, pw);
+ }
+
+ private static void write_header(String name, String value, PrintWriter pw)
+ {
+ pw.print(name + ": ");
+
+ int last = 68 - name.length();
+ if (last > value.length())
+ {
+ pw.println(value);
+ }
+ else
+ {
+ pw.println(value.substring(0, last));
+ }
+ while (last < value.length())
+ {
+ pw.print(" ");
+ int end = (last + 69);
+ if (end > value.length())
+ {
+ pw.println(value.substring(last));
+ }
+ else
+ {
+ pw.println(value.substring(last, end));
+ }
+ last = end;
+ }
+ }
+
+ private static void write_main_attributes(Attributes attr, PrintWriter pw)
+ throws JarException
+ {
+ Iterator it = attr.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ // Don't print the manifest version again
+ if (!Attributes.Name.MANIFEST_VERSION.equals(entry.getKey()))
+ {
+ write_attribute_entry(entry, pw);
+ }
+ }
+ }
+
+ private static void write_attribute_entry(Map.Entry entry, PrintWriter pw)
+ throws JarException
+ {
+ String name = entry.getKey().toString();
+ String value = entry.getValue().toString();
+
+ if (name.equalsIgnoreCase("Name"))
+ {
+ throw new JarException("Attributes cannot be called 'Name'");
+ }
+ if (name.startsWith("From"))
+ {
+ throw new
+ JarException("Header cannot start with the four letters 'From'" +
+ name);
+ }
+ write_header(name, value, pw);
+ }
+
+ private static void write_individual_sections(Map entries, PrintWriter pw)
+ throws JarException
+ {
+
+ Iterator it = entries.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ write_header("Name", entry.getKey().toString(), pw);
+ write_entry_attributes((Attributes) entry.getValue(), pw);
+ pw.println();
+ }
+ }
+
+ private static void write_entry_attributes(Attributes attr, PrintWriter pw)
+ throws JarException
+ {
+ Iterator it = attr.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ write_attribute_entry(entry, pw);
+ }
+ }
+
+ /**
+ * Makes a deep copy of the main attributes, but a shallow copy of
+ * the other entries. This means that you can freely add, change or remove
+ * the main attributes or the entries of the new manifest without effecting
+ * the original manifest, but adding, changing or removing attributes from
+ * a particular entry also changes the attributes of that entry in the
+ * original manifest. Calls <CODE>new Manifest(this)</CODE>.
+ */
+ public Object clone()
+ {
+ return new Manifest(this);
+ }
+
+ /**
+ * Checks if another object is equal to this Manifest object.
+ * Another Object is equal to this Manifest object if it is an instance of
+ * Manifest and the main attributes and the entries of the other manifest
+ * are equal to this one.
+ */
+ public boolean equals(Object o)
+ {
+ return (o instanceof Manifest) &&
+ (mainAttr.equals(((Manifest) o).mainAttr)) &&
+ (entries.equals(((Manifest) o).entries));
+ }
+
+ /**
+ * Calculates the hash code of the manifest. Implemented by a xor of the
+ * hash code of the main attributes with the hash code of the entries map.
+ */
+ public int hashCode()
+ {
+ return mainAttr.hashCode() ^ entries.hashCode();
+ }
+
+}
diff --git a/libjava/classpath/java/util/jar/package.html b/libjava/classpath/java/util/jar/package.html
new file mode 100644
index 00000000000..7fd87878dd8
--- /dev/null
+++ b/libjava/classpath/java/util/jar/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.util.jar package.
+ Copyright (C) 2002 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 - java.util.jar</title></head>
+
+<body>
+<p>Utility classes for manipulating java archives
+(zip files with a manifest file with attributes).</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/util/logging/ConsoleHandler.java b/libjava/classpath/java/util/logging/ConsoleHandler.java
new file mode 100644
index 00000000000..3cf4bca3354
--- /dev/null
+++ b/libjava/classpath/java/util/logging/ConsoleHandler.java
@@ -0,0 +1,125 @@
+/* ConsoleHandler.java -- a class for publishing log messages to System.err
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+/**
+ * A <code>ConsoleHandler</code> publishes log records to
+ * <code>System.err</code>.
+ *
+ * <p><strong>Configuration:</strong> Values of the subsequent
+ * <code>LogManager</code> properties are taken into consideration
+ * when a <code>ConsoleHandler</code> is initialized.
+ * If a property is not defined, or if it has an invalid
+ * value, a default is taken without an exception being thrown.
+ *
+ * <ul>
+ *
+ * <li><code>java.util.logging.ConsoleHandler.level</code> - specifies
+ * the initial severity level threshold. Default value:
+ * <code>Level.INFO</code>.</li>
+ *
+ * <li><code>java.util.logging.ConsoleHandler.filter</code> - specifies
+ * the name of a Filter class. Default value: No Filter.</li>
+ *
+ * <li><code>java.util.logging.ConsoleHandler.formatter</code> - specifies
+ * the name of a Formatter class. Default value:
+ * <code>java.util.logging.SimpleFormatter</code>.</li>
+ *
+ * <li><code>java.util.logging.ConsoleHandler.encoding</code> - specifies
+ * the name of the character encoding. Default value:
+ * the default platform encoding.</li>
+ *
+ * </ul>
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class ConsoleHandler
+ extends StreamHandler
+{
+ /**
+ * Constructs a <code>StreamHandler</code> that publishes
+ * log records to <code>System.err</code>. The initial
+ * configuration is determined by the <code>LogManager</code>
+ * properties described above.
+ */
+ public ConsoleHandler()
+ {
+ super(System.err, "java.util.logging.ConsoleHandler", Level.INFO,
+ /* formatter */ null, SimpleFormatter.class);
+ }
+
+
+ /**
+ * Forces any data that may have been buffered to the underlying
+ * output device, but does <i>not</i> close <code>System.err</code>.
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>ConsoleHandler</code> will be informed, but the caller
+ * of this method will not receive an exception.
+ */
+ public void close()
+ {
+ flush();
+ }
+
+
+ /**
+ * Publishes a <code>LogRecord</code> to the console, provided the
+ * record passes all tests for being loggable.
+ *
+ * <p>Most applications do not need to call this method directly.
+ * Instead, they will use use a <code>Logger</code>, which will
+ * create LogRecords and distribute them to registered handlers.
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>SocketHandler</code> will be informed, but the caller
+ * of this method will not receive an exception.
+ *
+ * <p>The GNU implementation of <code>ConsoleHandler.publish</code>
+ * calls flush() for every request to publish a record, so
+ * they appear immediately on the console.
+ *
+ * @param record the log event to be published.
+ */
+ public void publish(LogRecord record)
+ {
+ super.publish(record);
+ flush();
+ }
+}
diff --git a/libjava/classpath/java/util/logging/ErrorManager.java b/libjava/classpath/java/util/logging/ErrorManager.java
new file mode 100644
index 00000000000..57c079fe25b
--- /dev/null
+++ b/libjava/classpath/java/util/logging/ErrorManager.java
@@ -0,0 +1,194 @@
+/* ErrorManager.java --
+ A class for dealing with errors that a Handler encounters
+ during logging
+ Copyright (C) 2002, 2003 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.logging;
+
+/**
+ * An <code>ErrorManager</code> deals with errors that a <code>Handler</code>
+ * encounters while logging.
+ *
+ * @see Handler#setErrorManager(ErrorManager)
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class ErrorManager
+{
+ /* The values have been taken from Sun's public J2SE 1.4 API
+ * documentation.
+ * See http://java.sun.com/j2se/1.4/docs/api/constant-values.html
+ */
+
+ /**
+ * Indicates that there was a failure that does not readily
+ * fall into any of the other categories.
+ */
+ public static final int GENERIC_FAILURE = 0;
+
+
+ /**
+ * Indicates that there was a problem upon writing to
+ * an output stream.
+ */
+ public static final int WRITE_FAILURE = 1;
+
+
+ /**
+ * Indicates that there was a problem upon flushing
+ * an output stream.
+ */
+ public static final int FLUSH_FAILURE = 2;
+
+
+ /**
+ * Indicates that there was a problem upon closing
+ * an output stream.
+ */
+ public static final int CLOSE_FAILURE = 3;
+
+
+ /**
+ * Indicates that there was a problem upon opening
+ * an output stream.
+ */
+ public static final int OPEN_FAILURE = 4;
+
+
+ /**
+ * Indicates that there was a problem upon formatting
+ * the message of a log record.
+ */
+ public static final int FORMAT_FAILURE = 5;
+
+
+ /**
+ * Indicates whether the {@link #error} method of this ErrorManager
+ * has ever been used.
+ *
+ * Declared volatile in order to correctly support the
+ * double-checked locking idiom (once the revised Java Memory Model
+ * gets adopted); see Classpath bug #2944.
+ */
+ private volatile boolean everUsed = false;
+
+
+ public ErrorManager()
+ {
+ }
+
+
+ /**
+ * Reports an error that occured upon logging. The default implementation
+ * emits the very first error to System.err, ignoring subsequent errors.
+ *
+ * @param message a message describing the error, or <code>null</code> if
+ * there is no suitable description.
+ *
+ * @param ex an exception, or <code>null</code> if the error is not
+ * related to an exception.
+ *
+ * @param errorCode one of the defined error codes, for example
+ * <code>ErrorManager.CLOSE_FAILURE</code>.
+ */
+ public void error(String message, Exception ex, int errorCode)
+ {
+ if (everUsed)
+ return;
+
+ synchronized (this)
+ {
+ /* The double check is intentional. If the first check was
+ * omitted, the monitor would have to be entered every time
+ * error() method was called. If the second check was
+ * omitted, the code below could be executed by multiple
+ * threads simultaneously.
+ *
+ * This is the 'double-checked locking' idiom, which is broken
+ * with the current version of the Java memory model. However,
+ * we assume that JVMs will have adopted a revised version of
+ * the Java Memory Model by the time GNU Classpath gains
+ * widespread acceptance. See Classpath bug #2944.
+ */
+ if (everUsed)
+ return;
+
+ everUsed = true;
+ }
+
+ String codeMsg;
+ switch (errorCode)
+ {
+ case GENERIC_FAILURE:
+ codeMsg = "GENERIC_FAILURE";
+ break;
+
+ case WRITE_FAILURE:
+ codeMsg = "WRITE_FAILURE";
+ break;
+
+ case FLUSH_FAILURE:
+ codeMsg = "FLUSH_FAILURE";
+ break;
+
+ case CLOSE_FAILURE:
+ codeMsg = "CLOSE_FAILURE";
+ break;
+
+ case OPEN_FAILURE:
+ codeMsg = "OPEN_FAILURE";
+ break;
+
+ case FORMAT_FAILURE:
+ codeMsg = "FORMAT_FAILURE";
+ break;
+
+ default:
+ codeMsg = String.valueOf(errorCode);
+ break;
+ }
+
+ System.err.println("Error upon logging: " + codeMsg);
+ if ((message != null) && (message.length() > 0))
+ System.err.println(message);
+
+ if (ex != null)
+ ex.printStackTrace();
+ }
+}
+
diff --git a/libjava/classpath/java/util/logging/FileHandler.java b/libjava/classpath/java/util/logging/FileHandler.java
new file mode 100644
index 00000000000..3d958b7d760
--- /dev/null
+++ b/libjava/classpath/java/util/logging/FileHandler.java
@@ -0,0 +1,646 @@
+/* FileHandler.java -- a class for publishing log messages to log files
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+/**
+ * A <code>FileHandler</code> publishes log records to a set of log
+ * files. A maximum file size can be specified; as soon as a log file
+ * reaches the size limit, it is closed and the next file in the set
+ * is taken.
+ *
+ * <p><strong>Configuration:</strong> Values of the subsequent
+ * <code>LogManager</code> properties are taken into consideration
+ * when a <code>FileHandler</code> is initialized. If a property is
+ * not defined, or if it has an invalid value, a default is taken
+ * without an exception being thrown.
+ *
+ * <ul>
+ *
+ * <li><code>java.util.FileHandler.level</code> - specifies
+ * the initial severity level threshold. Default value:
+ * <code>Level.ALL</code>.</li>
+ *
+ * <li><code>java.util.FileHandler.filter</code> - specifies
+ * the name of a Filter class. Default value: No Filter.</li>
+ *
+ * <li><code>java.util.FileHandler.formatter</code> - specifies
+ * the name of a Formatter class. Default value:
+ * <code>java.util.logging.XMLFormatter</code>.</li>
+ *
+ * <li><code>java.util.FileHandler.encoding</code> - specifies
+ * the name of the character encoding. Default value:
+ * the default platform encoding.</li>
+ *
+ * <li><code>java.util.FileHandler.limit</code> - specifies the number
+ * of bytes a log file is approximately allowed to reach before it
+ * is closed and the handler switches to the next file in the
+ * rotating set. A value of zero means that files can grow
+ * without limit. Default value: 0 (unlimited growth).</li>
+ *
+ * <li><code>java.util.FileHandler.count</code> - specifies the number
+ * of log files through which this handler cycles. Default value:
+ * 1.</li>
+ *
+ * <li><code>java.util.FileHandler.pattern</code> - specifies a
+ * pattern for the location and name of the produced log files.
+ * See the section on <a href="#filePatterns">file name
+ * patterns</a> for details. Default value:
+ * <code>"%h/java%u.log"</code>.</li>
+ *
+ * <li><code>java.util.FileHandler.append</code> - specifies
+ * whether the handler will append log records to existing
+ * files, or whether the handler will clear log files
+ * upon switching to them. Default value: <code>false</code>,
+ * indicating that files will be cleared.</li>
+ *
+ * </ul>
+ *
+ * <p><a name="filePatterns"><strong>File Name Patterns:</strong></a>
+ * The name and location and log files are specified with pattern
+ * strings. The handler will replace the following character sequences
+ * when opening log files:
+ *
+ * <p><ul>
+ * <li><code>/</code> - replaced by the platform-specific path name
+ * separator. This value is taken from the system property
+ * <code>file.separator</code>.</li>
+ *
+ * <li><code>%t</code> - replaced by the platform-specific location of
+ * the directory intended for temporary files. This value is
+ * taken from the system property <code>java.io.tmpdir</code>.</li>
+ *
+ * <li><code>%h</code> - replaced by the location of the home
+ * directory of the current user. This value is taken from the
+ * system property <code>file.separator</code>.</li>
+ *
+ * <li><code>%g</code> - replaced by a generation number for
+ * distinguisthing the individual items in the rotating set
+ * of log files. The generation number cycles through the
+ * sequence 0, 1, ..., <code>count</code> - 1.</li>
+ *
+ * <li><code>%u</code> - replaced by a unique number for
+ * distinguisthing the output files of several concurrently
+ * running processes. The <code>FileHandler</code> starts
+ * with 0 when it tries to open a log file. If the file
+ * cannot be opened because it is currently in use,
+ * the unique number is incremented by one and opening
+ * is tried again. These steps are repeated until the
+ * opening operation succeeds.
+ *
+ * <p>FIXME: Is the following correct? Please review. The unique
+ * number is determined for each log file individually when it is
+ * opened upon switching to the next file. Therefore, it is not
+ * correct to assume that all log files in a rotating set bear the
+ * same unique number.
+ *
+ * <p>FIXME: The Javadoc for the Sun reference implementation
+ * says: "Note that the use of unique ids to avoid conflicts is
+ * only guaranteed to work reliably when using a local disk file
+ * system." Why? This needs to be mentioned as well, in case
+ * the reviewers decide the statement is true. Otherwise,
+ * file a bug report with Sun.</li>
+ *
+ * <li><code>%%</code> - replaced by a single percent sign.</li>
+ * </ul>
+ *
+ * <p>If the pattern string does not contain <code>%g</code> and
+ * <code>count</code> is greater than one, the handler will append
+ * the string <code>.%g</code> to the specified pattern.
+ *
+ * <p>If the handler attempts to open a log file, this log file
+ * is being used at the time of the attempt, and the pattern string
+ * does not contain <code>%u</code>, the handler will append
+ * the string <code>.%u</code> to the specified pattern. This
+ * step is performed after any generation number has been
+ * appended.
+ *
+ * <p><em>Examples for the GNU platform:</em>
+ *
+ * <p><ul>
+ *
+ * <li><code>%h/java%u.log</code> will lead to a single log file
+ * <code>/home/janet/java0.log</code>, assuming <code>count</code>
+ * equals 1, the user's home directory is
+ * <code>/home/janet</code>, and the attempt to open the file
+ * succeeds.</li>
+ *
+ * <li><code>%h/java%u.log</code> will lead to three log files
+ * <code>/home/janet/java0.log.0</code>,
+ * <code>/home/janet/java0.log.1</code>, and
+ * <code>/home/janet/java0.log.2</code>,
+ * assuming <code>count</code> equals 3, the user's home
+ * directory is <code>/home/janet</code>, and all attempts
+ * to open files succeed.</li>
+ *
+ * <li><code>%h/java%u.log</code> will lead to three log files
+ * <code>/home/janet/java0.log.0</code>,
+ * <code>/home/janet/java1.log.1</code>, and
+ * <code>/home/janet/java0.log.2</code>,
+ * assuming <code>count</code> equals 3, the user's home
+ * directory is <code>/home/janet</code>, and the attempt
+ * to open <code>/home/janet/java0.log.1</code> fails.</li>
+ *
+ * </ul>
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class FileHandler
+ extends StreamHandler
+{
+ /**
+ * The number of bytes a log file is approximately allowed to reach
+ * before it is closed and the handler switches to the next file in
+ * the rotating set. A value of zero means that files can grow
+ * without limit.
+ */
+ private final int limit;
+
+
+ /**
+ * The number of log files through which this handler cycles.
+ */
+ private final int count;
+
+
+ /**
+ * The pattern for the location and name of the produced log files.
+ * See the section on <a href="#filePatterns">file name patterns</a>
+ * for details.
+ */
+ private final String pattern;
+
+
+ /**
+ * Indicates whether the handler will append log records to existing
+ * files (<code>true</code>), or whether the handler will clear log files
+ * upon switching to them (<code>false</code>).
+ */
+ private final boolean append;
+
+
+ /**
+ * The number of bytes that have currently been written to the stream.
+ * Package private for use in inner classes.
+ */
+ long written;
+
+
+ /**
+ * A linked list of files we are, or have written to. The entries
+ * are file path strings, kept in the order
+ */
+ private LinkedList logFiles;
+
+
+ /**
+ * Constructs a <code>FileHandler</code>, taking all property values
+ * from the current {@link LogManager LogManager} configuration.
+ *
+ * @throws java.io.IOException FIXME: The Sun Javadoc says: "if
+ * there are IO problems opening the files." This conflicts
+ * with the general principle that configuration errors do
+ * not prohibit construction. Needs review.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ */
+ public FileHandler()
+ throws IOException, SecurityException
+ {
+ this(/* pattern: use configiguration */ null,
+
+ LogManager.getIntProperty("java.util.logging.FileHandler.limit",
+ /* default */ 0),
+
+ LogManager.getIntProperty("java.util.logging.FileHandler.count",
+ /* default */ 1),
+
+ LogManager.getBooleanProperty("java.util.logging.FileHandler.append",
+ /* default */ false));
+ }
+
+
+ /* FIXME: Javadoc missing. */
+ public FileHandler(String pattern)
+ throws IOException, SecurityException
+ {
+ this(pattern,
+ /* limit */ 0,
+ /* count */ 1,
+ /* append */ false);
+ }
+
+
+ /* FIXME: Javadoc missing. */
+ public FileHandler(String pattern, boolean append)
+ throws IOException, SecurityException
+ {
+ this(pattern,
+ /* limit */ 0,
+ /* count */ 1,
+ append);
+ }
+
+
+ /* FIXME: Javadoc missing. */
+ public FileHandler(String pattern, int limit, int count)
+ throws IOException, SecurityException
+ {
+ this(pattern, limit, count,
+ LogManager.getBooleanProperty(
+ "java.util.logging.FileHandler.append",
+ /* default */ false));
+ }
+
+
+ /**
+ * Constructs a <code>FileHandler</code> given the pattern for the
+ * location and name of the produced log files, the size limit, the
+ * number of log files thorough which the handler will rotate, and
+ * the <code>append</code> property. All other property values are
+ * taken from the current {@link LogManager LogManager}
+ * configuration.
+ *
+ * @param pattern The pattern for the location and name of the
+ * produced log files. See the section on <a
+ * href="#filePatterns">file name patterns</a> for details.
+ * If <code>pattern</code> is <code>null</code>, the value is
+ * taken from the {@link LogManager LogManager} configuration
+ * property
+ * <code>java.util.logging.FileHandler.pattern</code>.
+ * However, this is a pecularity of the GNU implementation,
+ * and Sun's API specification does not mention what behavior
+ * is to be expected for <code>null</code>. Therefore,
+ * applications should not rely on this feature.
+ *
+ * @param limit specifies the number of bytes a log file is
+ * approximately allowed to reach before it is closed and the
+ * handler switches to the next file in the rotating set. A
+ * value of zero means that files can grow without limit.
+ *
+ * @param count specifies the number of log files through which this
+ * handler cycles.
+ *
+ * @param append specifies whether the handler will append log
+ * records to existing files (<code>true</code>), or whether the
+ * handler will clear log files upon switching to them
+ * (<code>false</code>).
+ *
+ * @throws java.io.IOException FIXME: The Sun Javadoc says: "if
+ * there are IO problems opening the files." This conflicts
+ * with the general principle that configuration errors do
+ * not prohibit construction. Needs review.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ * <p>FIXME: This seems in contrast to all other handler
+ * constructors -- verify this by running tests against
+ * the Sun reference implementation.
+ */
+ public FileHandler(String pattern,
+ int limit,
+ int count,
+ boolean append)
+ throws IOException, SecurityException
+ {
+ super(/* output stream, created below */ null,
+ "java.util.logging.FileHandler",
+ /* default level */ Level.ALL,
+ /* formatter */ null,
+ /* default formatter */ XMLFormatter.class);
+
+ if ((limit <0) || (count < 1))
+ throw new IllegalArgumentException();
+
+ this.pattern = pattern;
+ this.limit = limit;
+ this.count = count;
+ this.append = append;
+ this.written = 0;
+ this.logFiles = new LinkedList ();
+
+ setOutputStream (createFileStream (pattern, limit, count, append,
+ /* generation */ 0));
+ }
+
+
+ /* FIXME: Javadoc missing. */
+ private OutputStream createFileStream(String pattern,
+ int limit,
+ int count,
+ boolean append,
+ int generation)
+ {
+ String path;
+ int unique = 0;
+
+ /* Throws a SecurityException if the caller does not have
+ * LoggingPermission("control").
+ */
+ LogManager.getLogManager().checkAccess();
+
+ /* Default value from the java.util.logging.FileHandler.pattern
+ * LogManager configuration property.
+ */
+ if (pattern == null)
+ pattern = LogManager.getLogManager().getProperty(
+ "java.util.logging.FileHandler.pattern");
+ if (pattern == null)
+ pattern = "%h/java%u.log";
+
+ if (count > 1 && !has (pattern, 'g'))
+ pattern = pattern + ".%g";
+
+ do
+ {
+ path = replaceFileNameEscapes(pattern, generation, unique, count);
+
+ try
+ {
+ File file = new File(path);
+ if (!file.exists () || append)
+ {
+ FileOutputStream fout = new FileOutputStream (file, append);
+ // FIXME we need file locks for this to work properly, but they
+ // are not implemented yet in Classpath! Madness!
+// FileChannel channel = fout.getChannel ();
+// FileLock lock = channel.tryLock ();
+// if (lock != null) // We've locked the file.
+// {
+ if (logFiles.isEmpty ())
+ logFiles.addFirst (path);
+ return new ostr (fout);
+// }
+ }
+ }
+ catch (Exception ex)
+ {
+ reportError (null, ex, ErrorManager.OPEN_FAILURE);
+ }
+
+ unique = unique + 1;
+ if (!has (pattern, 'u'))
+ pattern = pattern + ".%u";
+ }
+ while (true);
+ }
+
+
+ /**
+ * Replaces the substrings <code>"/"</code> by the value of the
+ * system property <code>"file.separator"</code>, <code>"%t"</code>
+ * by the value of the system property
+ * <code>"java.io.tmpdir"</code>, <code>"%h"</code> by the value of
+ * the system property <code>"user.home"</code>, <code>"%g"</code>
+ * by the value of <code>generation</code>, <code>"%u"</code> by the
+ * value of <code>uniqueNumber</code>, and <code>"%%"</code> by a
+ * single percent character. If <code>pattern</code> does
+ * <em>not</em> contain the sequence <code>"%g"</code>,
+ * the value of <code>generation</code> will be appended to
+ * the result.
+ *
+ * @throws NullPointerException if one of the system properties
+ * <code>"file.separator"</code>,
+ * <code>"java.io.tmpdir"</code>, or
+ * <code>"user.home"</code> has no value and the
+ * corresponding escape sequence appears in
+ * <code>pattern</code>.
+ */
+ private static String replaceFileNameEscapes(String pattern,
+ int generation,
+ int uniqueNumber,
+ int count)
+ {
+ StringBuffer buf = new StringBuffer(pattern);
+ String replaceWith;
+ boolean foundGeneration = false;
+
+ int pos = 0;
+ do
+ {
+ // Uncomment the next line for finding bugs.
+ // System.out.println(buf.substring(0,pos) + '|' + buf.substring(pos));
+
+ if (buf.charAt(pos) == '/')
+ {
+ /* The same value is also provided by java.io.File.separator. */
+ replaceWith = System.getProperty("file.separator");
+ buf.replace(pos, pos + 1, replaceWith);
+ pos = pos + replaceWith.length() - 1;
+ continue;
+ }
+
+ if (buf.charAt(pos) == '%')
+ {
+ switch (buf.charAt(pos + 1))
+ {
+ case 't':
+ replaceWith = System.getProperty("java.io.tmpdir");
+ break;
+
+ case 'h':
+ replaceWith = System.getProperty("user.home");
+ break;
+
+ case 'g':
+ replaceWith = Integer.toString(generation);
+ foundGeneration = true;
+ break;
+
+ case 'u':
+ replaceWith = Integer.toString(uniqueNumber);
+ break;
+
+ case '%':
+ replaceWith = "%";
+ break;
+
+ default:
+ replaceWith = "??";
+ break; // FIXME: Throw exception?
+ }
+
+ buf.replace(pos, pos + 2, replaceWith);
+ pos = pos + replaceWith.length() - 1;
+ continue;
+ }
+ }
+ while (++pos < buf.length() - 1);
+
+ if (!foundGeneration && (count > 1))
+ {
+ buf.append('.');
+ buf.append(generation);
+ }
+
+ return buf.toString();
+ }
+
+
+ /* FIXME: Javadoc missing. */
+ public void publish(LogRecord record)
+ {
+ if (limit > 0 && written >= limit)
+ rotate ();
+ super.publish(record);
+ flush ();
+ }
+
+ /**
+ * Rotates the current log files, possibly removing one if we
+ * exceed the file count.
+ */
+ private synchronized void rotate ()
+ {
+ if (logFiles.size () > 0)
+ {
+ File f1 = null;
+ ListIterator lit = null;
+
+ // If we reach the file count, ditch the oldest file.
+ if (logFiles.size () == count)
+ {
+ f1 = new File ((String) logFiles.getLast ());
+ f1.delete ();
+ lit = logFiles.listIterator (logFiles.size () - 1);
+ }
+ // Otherwise, move the oldest to a new location.
+ else
+ {
+ String path = replaceFileNameEscapes (pattern, logFiles.size (),
+ /* unique */ 0, count);
+ f1 = new File (path);
+ logFiles.addLast (path);
+ lit = logFiles.listIterator (logFiles.size () - 1);
+ }
+
+ // Now rotate the files.
+ while (lit.hasPrevious ())
+ {
+ String s = (String) lit.previous ();
+ File f2 = new File (s);
+ f2.renameTo (f1);
+ f1 = f2;
+ }
+ }
+
+ setOutputStream (createFileStream (pattern, limit, count, append,
+ /* generation */ 0));
+
+ // Reset written count.
+ written = 0;
+ }
+
+ /**
+ * Tell if <code>pattern</code> contains the pattern sequence
+ * with character <code>escape</code>. That is, if <code>escape</code>
+ * is 'g', this method returns true if the given pattern contains
+ * "%g", and not just the substring "%g" (for example, in the case of
+ * "%%g").
+ *
+ * @param pattern The pattern to test.
+ * @param escape The escape character to search for.
+ * @return True iff the pattern contains the escape sequence with the
+ * given character.
+ */
+ private static boolean has (final String pattern, final char escape)
+ {
+ final int len = pattern.length ();
+ boolean sawPercent = false;
+ for (int i = 0; i < len; i++)
+ {
+ char c = pattern.charAt (i);
+ if (sawPercent)
+ {
+ if (c == escape)
+ return true;
+ if (c == '%') // Double percent
+ {
+ sawPercent = false;
+ continue;
+ }
+ }
+ sawPercent = (c == '%');
+ }
+ return false;
+ }
+
+ /**
+ * An output stream that tracks the number of bytes written to it.
+ */
+ private final class ostr extends FilterOutputStream
+ {
+ private ostr (OutputStream out)
+ {
+ super (out);
+ }
+
+ public void write (final int b) throws IOException
+ {
+ out.write (b);
+ FileHandler.this.written++; // FIXME: synchronize?
+ }
+
+ public void write (final byte[] b) throws IOException
+ {
+ write (b, 0, b.length);
+ }
+
+ public void write (final byte[] b, final int offset, final int length)
+ throws IOException
+ {
+ out.write (b, offset, length);
+ FileHandler.this.written += length; // FIXME: synchronize?
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/logging/Filter.java b/libjava/classpath/java/util/logging/Filter.java
new file mode 100644
index 00000000000..ec4597670d5
--- /dev/null
+++ b/libjava/classpath/java/util/logging/Filter.java
@@ -0,0 +1,64 @@
+/* Filter.java -- an interface for filters that decide whether a
+ LogRecord should be published or discarded
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+/**
+ * By implementing the <code>Filter</code> interface, applications
+ * can control what is being logged based on arbitrary properties,
+ * not just the severity level. Both <code>Handler</code> and
+ * <code>Logger</code> allow to register Filters whose
+ * <code>isLoggable</code> method will be called when a
+ * <code>LogRecord</code> has passed the test based on the
+ * severity level.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public interface Filter
+{
+ /**
+ * Determines whether a LogRecord should be published or discarded.
+ *
+ * @param record the <code>LogRecord</code> to be inspected.
+ *
+ * @return <code>true</code> if the record should be published,
+ * <code>false</code> if it should be discarded.
+ */
+ boolean isLoggable(LogRecord record);
+}
diff --git a/libjava/classpath/java/util/logging/Formatter.java b/libjava/classpath/java/util/logging/Formatter.java
new file mode 100644
index 00000000000..ee747b0b978
--- /dev/null
+++ b/libjava/classpath/java/util/logging/Formatter.java
@@ -0,0 +1,171 @@
+/* Formatter.java --
+ A class for formatting log messages by localizing message texts
+ and performing substitution of parameters
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+/**
+ * A <code>Formatter</code> supports handlers by localizing
+ * message texts and by subsituting parameter values for their
+ * placeholders.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public abstract class Formatter
+{
+ /**
+ * Constructs a new Formatter.
+ */
+ protected Formatter()
+ {
+ }
+
+
+ /**
+ * Formats a LogRecord into a string. Usually called by handlers
+ * which need a string for a log record, for example to append
+ * a record to a log file or to transmit a record over the network.
+ *
+ * @param record the log record for which a string form is requested.
+ */
+ public abstract String format(LogRecord record);
+
+
+ /**
+ * Returns a string that handlers are supposed to emit before
+ * the first log record. The base implementation returns an
+ * empty string, but subclasses such as {@link XMLFormatter}
+ * override this method in order to provide a suitable header.
+ *
+ * @return a string for the header.
+ *
+ * @param handler the handler which will prepend the returned
+ * string in front of the first log record. This method
+ * may inspect certain properties of the handler, for
+ * example its encoding, in order to construct the header.
+ */
+ public String getHead(Handler handler)
+ {
+ return "";
+ }
+
+
+ /**
+ * Returns a string that handlers are supposed to emit after
+ * the last log record. The base implementation returns an
+ * empty string, but subclasses such as {@link XMLFormatter}
+ * override this method in order to provide a suitable tail.
+ *
+ * @return a string for the header.
+ *
+ * @param handler the handler which will append the returned
+ * string after the last log record. This method
+ * may inspect certain properties of the handler
+ * in order to construct the tail.
+ */
+ public String getTail(Handler handler)
+ {
+ return "";
+ }
+
+
+ /**
+ * Formats the message part of a log record.
+ *
+ * <p>First, the Formatter localizes the record message to the
+ * default locale by looking up the message in the record's
+ * localization resource bundle. If this step fails because there
+ * is no resource bundle associated with the record, or because the
+ * record message is not a key in the bundle, the raw message is
+ * used instead.
+ *
+ * <p>Second, the Formatter substitutes appropriate strings for
+ * the message parameters. If the record returns a non-empty
+ * array for <code>getParameters()</code> and the localized
+ * message string contains the character sequence "{0", the
+ * formatter uses <code>java.text.MessageFormat</code> to format
+ * the message. Otherwise, no parameter substitution is performed.
+ *
+ * @param record the log record to be localized and formatted.
+ *
+ * @return the localized message text where parameters have been
+ * substituted by suitable strings.
+ *
+ * @throws NullPointerException if <code>record</code>
+ * is <code>null</code>.
+ */
+ public String formatMessage(LogRecord record)
+ {
+ String msg;
+ ResourceBundle bundle;
+ Object[] params;
+
+ /* This will throw a NullPointerExceptionif record is null. */
+ msg = record.getMessage();
+ if (msg == null)
+ msg = "";
+
+ /* Try to localize the message. */
+ bundle = record.getResourceBundle();
+ if (bundle != null)
+ {
+ try
+ {
+ msg = bundle.getString(msg);
+ }
+ catch (java.util.MissingResourceException _)
+ {
+ }
+ }
+
+ /* Format the message if there are parameters. */
+ params = record.getParameters();
+ if ((params != null)
+ && (params.length > 0)
+ && (msg.indexOf("{0") >= 0))
+ {
+ msg = MessageFormat.format(msg, params);
+ }
+
+ return msg;
+ }
+}
diff --git a/libjava/classpath/java/util/logging/Handler.java b/libjava/classpath/java/util/logging/Handler.java
new file mode 100644
index 00000000000..c3227d6f531
--- /dev/null
+++ b/libjava/classpath/java/util/logging/Handler.java
@@ -0,0 +1,386 @@
+/* Handler.java -- a class for publishing log messages
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * A <code>Handler</code> publishes <code>LogRecords</code> to
+ * a sink, for example a file, the console or a network socket.
+ * There are different subclasses of <code>Handler</code>
+ * to deal with different kinds of sinks.
+ *
+ * <p>FIXME: Are handlers thread-safe, or is the assumption that only
+ * loggers are, and a handler can belong only to one single logger? If
+ * the latter, should we enforce it? (Spec not clear). In any
+ * case, it needs documentation.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public abstract class Handler
+{
+ Formatter formatter;
+ Filter filter;
+ Level level;
+ ErrorManager errorManager;
+ String encoding;
+
+ /**
+ * Constructs a Handler with a logging severity level of
+ * <code>Level.ALL</code>, no formatter, no filter, and
+ * an instance of <code>ErrorManager</code> managing errors.
+ *
+ * <p><strong>Specification Note:</strong> The specification of the
+ * Java<sup>TM</sup> Logging API does not mention which character
+ * encoding is to be used by freshly constructed Handlers. The GNU
+ * implementation uses the default platform encoding, but other
+ * Java implementations might behave differently.
+ *
+ * <p><strong>Specification Note:</strong> While a freshly constructed
+ * Handler is required to have <em>no filter</em> according to the
+ * specification, <code>null</code> is not a valid parameter for
+ * <code>Handler.setFormatter</code>. Therefore, the following
+ * code will throw a <code>java.lang.NullPointerException</code>:
+ *
+ * <p><pre>Handler h = new MyConcreteSubclassOfHandler();
+h.setFormatter(h.getFormatter());</pre>
+ *
+ * It seems strange that a freshly constructed Handler is not
+ * supposed to provide a Formatter, but this is what the specification
+ * says.
+ */
+ protected Handler()
+ {
+ level = Level.ALL;
+ }
+
+
+ /**
+ * Publishes a <code>LogRecord</code> to an appropriate sink,
+ * provided the record passes all tests for being loggable. The
+ * <code>Handler</code> will localize the message of the log
+ * record and substitute any message parameters.
+ *
+ * <p>Most applications do not need to call this method directly.
+ * Instead, they will use use a {@link Logger}, which will
+ * create LogRecords and distribute them to registered handlers.
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>Handler</code> will be informed, but the caller
+ * of this method will not receive an exception.
+ *
+ * @param record the log event to be published.
+ */
+ public abstract void publish(LogRecord record);
+
+
+ /**
+ * Forces any data that may have been buffered to the underlying
+ * output device.
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>Handler</code> will be informed, but the caller
+ * of this method will not receive an exception.
+ */
+ public abstract void flush();
+
+
+ /**
+ * Closes this <code>Handler</code> after having flushed
+ * the buffers. As soon as <code>close</code> has been called,
+ * a <code>Handler</code> should not be used anymore. Attempts
+ * to publish log records, to flush buffers, or to modify the
+ * <code>Handler</code> in any other way may throw runtime
+ * exceptions after calling <code>close</code>.
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>Handler</code> will be informed, but the caller
+ * of this method will not receive an exception.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ */
+ public abstract void close()
+ throws SecurityException;
+
+
+ /**
+ * Returns the <code>Formatter</code> which will be used to
+ * localize the text of log messages and to substitute
+ * message parameters. A <code>Handler</code> is encouraged,
+ * but not required to actually use an assigned
+ * <code>Formatter</code>.
+ *
+ * @return the <code>Formatter</code> being used, or
+ * <code>null</code> if this <code>Handler</code>
+ * does not use formatters and no formatter has
+ * ever been set by calling <code>setFormatter</code>.
+ */
+ public Formatter getFormatter()
+ {
+ return formatter;
+ }
+
+
+ /**
+ * Sets the <code>Formatter</code> which will be used to
+ * localize the text of log messages and to substitute
+ * message parameters. A <code>Handler</code> is encouraged,
+ * but not required to actually use an assigned
+ * <code>Formatter</code>.
+ *
+ * @param formatter the new <code>Formatter</code> to use.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ *
+ * @throws NullPointerException if <code>formatter</code> is
+ * <code>null</code>.
+ */
+ public void setFormatter(Formatter formatter)
+ throws SecurityException
+ {
+ LogManager.getLogManager().checkAccess();
+
+ /* Throws a NullPointerException if formatter is null. */
+ formatter.getClass();
+
+ this.formatter = formatter;
+ }
+
+
+ /**
+ * Returns the character encoding which this handler uses for publishing
+ * log records.
+ *
+ * @param encoding the name of a character encoding, or <code>null</code>
+ * for the default platform encoding.
+ */
+ public String getEncoding()
+ {
+ return encoding;
+ }
+
+
+ /**
+ * Sets the character encoding which this handler uses for publishing
+ * log records. The encoding of a <code>Handler</code> must be
+ * set before any log records have been published.
+ *
+ * @param encoding the name of a character encoding, or <code>null</code>
+ * for the default encoding.
+ *
+ * @exception SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ *
+ */
+ public void setEncoding(String encoding)
+ throws SecurityException, UnsupportedEncodingException
+ {
+ /* Should any developer ever change this implementation, they are
+ * advised to have a look at StreamHandler.setEncoding(String),
+ * which overrides this method without calling super.setEncoding.
+ */
+ LogManager.getLogManager().checkAccess();
+
+ /* Simple check for supported encodings. This is more expensive
+ * than it could be, but this method is overwritten by StreamHandler
+ * anyway.
+ */
+ if (encoding != null)
+ new String(new byte[0], encoding);
+
+ this.encoding = encoding;
+ }
+
+
+ /**
+ * Returns the <code>Filter</code> that currently controls which
+ * log records are being published by this <code>Handler</code>.
+ *
+ * @return the currently active <code>Filter</code>, or
+ * <code>null</code> if no filter has been associated.
+ * In the latter case, log records are filtered purely
+ * based on their severity level.
+ */
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+
+ /**
+ * Sets the <code>Filter</code> for controlling which
+ * log records will be published by this <code>Handler</code>.
+ *
+ * @return the <code>Filter</code> to use, or
+ * <code>null</code> to filter log records purely based
+ * on their severity level.
+ */
+ public void setFilter(Filter filter)
+ throws SecurityException
+ {
+ LogManager.getLogManager().checkAccess();
+ this.filter = filter;
+ }
+
+
+ /**
+ * Returns the <code>ErrorManager</code> that currently deals
+ * with errors originating from this Handler.
+ *
+ * @exception SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ */
+ public ErrorManager getErrorManager()
+ {
+ LogManager.getLogManager().checkAccess();
+
+ /* Developers wanting to change the subsequent code should
+ * have a look at Handler.reportError -- it also can create
+ * an ErrorManager, but does so without checking permissions
+ * to control the logging infrastructure.
+ */
+ if (errorManager == null)
+ errorManager = new ErrorManager();
+
+ return errorManager;
+ }
+
+
+ public void setErrorManager(ErrorManager manager)
+ {
+ LogManager.getLogManager().checkAccess();
+
+ /* Make sure manager is not null. */
+ manager.getClass();
+
+ this.errorManager = manager;
+ }
+
+
+ protected void reportError(String message, Exception ex, int code)
+ {
+ if (errorManager == null)
+ errorManager = new ErrorManager();
+
+ errorManager.error(message, ex, code);
+ }
+
+
+ /**
+ * Returns the severity level threshold for this <code>Handler</code>
+ * All log records with a lower severity level will be discarded;
+ * a log record of the same or a higher level will be published
+ * unless an installed <code>Filter</code> decides to discard it.
+ *
+ * @return the severity level below which all log messages
+ * will be discarded.
+ */
+ public Level getLevel()
+ {
+ return level;
+ }
+
+
+ /**
+ * Sets the severity level threshold for this <code>Handler</code>.
+ * All log records with a lower severity level will be discarded;
+ * a log record of the same or a higher level will be published
+ * unless an installed <code>Filter</code> decides to discard it.
+ *
+ * @param level the severity level below which all log messages
+ * will be discarded.
+ *
+ * @exception SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ *
+ * @exception NullPointerException if <code>level</code> is
+ * <code>null</code>.
+ */
+ public void setLevel(Level level)
+ {
+ LogManager.getLogManager().checkAccess();
+
+ /* Throw NullPointerException if level is null. */
+ level.getClass();
+ this.level = level;
+ }
+
+
+ /**
+ * Checks whether a <code>LogRecord</code> would be logged
+ * if it was passed to this <code>Handler</code> for publication.
+ *
+ * <p>The <code>Handler</code> implementation considers a record as
+ * loggable if its level is greater than or equal to the severity
+ * level threshold. In a second step, if a {@link Filter} has
+ * been installed, its {@link Filter#isLoggable(LogRecord) isLoggable}
+ * method is invoked. Subclasses of <code>Handler</code> can override
+ * this method to impose their own constraints.
+ *
+ * @param record the <code>LogRecord</code> to be checked.
+ *
+ * @return <code>true</code> if <code>record</code> would
+ * be published by {@link #publish(LogRecord) publish},
+ * <code>false</code> if it would be discarded.
+ *
+ * @see #setLevel(Level)
+ * @see #setFilter(Filter)
+ * @see Filter#isLoggable(LogRecord)
+ *
+ * @throws NullPointerException if <code>record</code>
+ * is <code>null</code>.
+ */
+ public boolean isLoggable(LogRecord record)
+ {
+ if (record.getLevel().intValue() < level.intValue())
+ return false;
+
+ if (filter != null)
+ return filter.isLoggable(record);
+ else
+ return true;
+ }
+}
diff --git a/libjava/classpath/java/util/logging/Level.java b/libjava/classpath/java/util/logging/Level.java
new file mode 100644
index 00000000000..2c400dc3a90
--- /dev/null
+++ b/libjava/classpath/java/util/logging/Level.java
@@ -0,0 +1,414 @@
+/* Level.java -- a class for indicating logging levels
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.io.Serializable;
+import java.util.ResourceBundle;
+
+/**
+ * A class for indicating logging levels. A number of commonly used
+ * levels is pre-defined (such as <code>java.util.logging.Level.INFO</code>),
+ * and applications should utilize those whenever possible. For specialized
+ * purposes, however, applications can sub-class Level in order to define
+ * custom logging levels.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class Level implements Serializable
+{
+ /* The integer values are the same as in the Sun J2SE 1.4.
+ * They have been obtained with a test program. In J2SE 1.4.1,
+ * Sun has amended the API documentation; these values are now
+ * publicly documented.
+ */
+
+ /**
+ * The <code>OFF</code> level is used as a threshold for filtering
+ * log records, meaning that no message should be logged.
+ *
+ * @see Logger#setLevel(java.util.logging.Level)
+ */
+ public static final Level OFF = new Level ("OFF", Integer.MAX_VALUE);
+
+ /**
+ * Log records whose level is <code>SEVERE</code> indicate a serious
+ * failure that prevents normal program execution. Messages at this
+ * level should be understandable to an inexperienced, non-technical
+ * end user. Ideally, they explain in simple words what actions the
+ * user can take in order to resolve the problem.
+ */
+ public static final Level SEVERE = new Level ("SEVERE", 1000);
+
+
+ /**
+ * Log records whose level is <code>WARNING</code> indicate a
+ * potential problem that does not prevent normal program execution.
+ * Messages at this level should be understandable to an
+ * inexperienced, non-technical end user. Ideally, they explain in
+ * simple words what actions the user can take in order to resolve
+ * the problem.
+ */
+ public static final Level WARNING = new Level ("WARNING", 900);
+
+
+ /**
+ * Log records whose level is <code>INFO</code> are used in purely
+ * informational situations that do not constitute serious errors or
+ * potential problems. In the default logging configuration, INFO
+ * messages will be written to the system console. For this reason,
+ * the INFO level should be used only for messages that are
+ * important to end users and system administrators. Messages at
+ * this level should be understandable to an inexperienced,
+ * non-technical user.
+ */
+ public static final Level INFO = new Level ("INFO", 800);
+
+
+ /**
+ * Log records whose level is <code>CONFIG</code> are used for
+ * describing the static configuration, for example the windowing
+ * environment, the operating system version, etc.
+ */
+ public static final Level CONFIG = new Level ("CONFIG", 700);
+
+
+ /**
+ * Log records whose level is <code>FINE</code> are typically used
+ * for messages that are relevant for developers using
+ * the component generating log messages. Examples include minor,
+ * recoverable failures, or possible inefficiencies.
+ */
+ public static final Level FINE = new Level ("FINE", 500);
+
+
+ /**
+ * Log records whose level is <code>FINER</code> are intended for
+ * rather detailed tracing, for example entering a method, returning
+ * from a method, or throwing an exception.
+ */
+ public static final Level FINER = new Level ("FINER", 400);
+
+
+ /**
+ * Log records whose level is <code>FINEST</code> are used for
+ * highly detailed tracing, for example to indicate that a certain
+ * point inside the body of a method has been reached.
+ */
+ public static final Level FINEST = new Level ("FINEST", 300);
+
+
+ /**
+ * The <code>ALL</code> level is used as a threshold for filtering
+ * log records, meaning that every message should be logged.
+ *
+ * @see Logger#setLevel(java.util.logging.Level)
+ */
+ public static final Level ALL = new Level ("ALL", Integer.MIN_VALUE);
+
+
+ private static final Level[] knownLevels = {
+ ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF
+ };
+
+
+ /**
+ * The name of the Level without localizing it, for example
+ * "WARNING".
+ */
+ private String name;
+
+
+ /**
+ * The integer value of this <code>Level</code>.
+ */
+ private int value;
+
+
+ /**
+ * The name of the resource bundle used for localizing the level
+ * name, or <code>null</code> if the name does not undergo
+ * localization.
+ */
+ private String resourceBundleName;
+
+
+ /**
+ * Creates a logging level given a name and an integer value.
+ * It rarely is necessary to create custom levels,
+ * as most applications should be well served with one of the
+ * standard levels such as <code>Level.CONFIG</code>,
+ * <code>Level.INFO</code>, or <code>Level.FINE</code>.
+ *
+ * @param name the name of the level.
+ *
+ * @param value the integer value of the level. Please note
+ * that the Java<small><sup>TM</sup></small>
+ * Logging API does not specify integer
+ * values for standard levels (such as
+ * Level.FINE). Therefore, a custom
+ * level should pass an integer value that
+ * is calculated at run-time, e.g.
+ * <code>(Level.FINE.intValue() + Level.CONFIG.intValue())
+ * / 2</code> for a level between FINE and CONFIG.
+ */
+ protected Level(String name, int value)
+ {
+ this(name, value, null);
+ }
+
+
+ /**
+ * Create a logging level given a name, an integer value and a name
+ * of a resource bundle for localizing the level name. It rarely
+ * is necessary to create custom levels, as most applications
+ * should be well served with one of the standard levels such as
+ * <code>Level.CONFIG</code>, <code>Level.INFO</code>, or
+ * <code>Level.FINE</code>.
+ *
+ * @param name the name of the level.
+ *
+ * @param value the integer value of the level. Please note
+ * that the Java<small><sup>TM</sup></small>
+ * Logging API does not specify integer
+ * values for standard levels (such as
+ * Level.FINE). Therefore, a custom
+ * level should pass an integer value that
+ * is calculated at run-time, e.g.
+ * <code>(Level.FINE.intValue() + Level.CONFIG.intValue())
+ * / 2</code> for a level between FINE and CONFIG.
+ *
+ * @param resourceBundleName the name of a resource bundle
+ * for localizing the level name, or <code>null</code>
+ * if the name does not need to be localized.
+ */
+ protected Level(String name, int value, String resourceBundleName)
+ {
+ this.name = name;
+ this.value = value;
+ this.resourceBundleName = resourceBundleName;
+ }
+
+
+ static final long serialVersionUID = -8176160795706313070L;
+
+
+ /**
+ * Checks whether the Level has the same intValue as one of the
+ * pre-defined levels. If so, the pre-defined level object is
+ * returned.
+ *
+ * <br/>Since the resource bundle name is not taken into
+ * consideration, it is possible to resolve Level objects that have
+ * been de-serialized by another implementation, even if the other
+ * implementation uses a different resource bundle for localizing
+ * the names of pre-defined levels.
+ */
+ private Object readResolve()
+ {
+ for (int i = 0; i < knownLevels.length; i++)
+ if (value == knownLevels[i].intValue())
+ return knownLevels[i];
+
+ return this;
+ }
+
+
+ /**
+ * Returns the name of the resource bundle used for localizing the
+ * level name.
+ *
+ * @return the name of the resource bundle used for localizing the
+ * level name, or <code>null</code> if the name does not undergo
+ * localization.
+ */
+ public String getResourceBundleName()
+ {
+ return resourceBundleName;
+ }
+
+
+ /**
+ * Returns the name of the Level without localizing it, for example
+ * "WARNING".
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+
+ /**
+ * Returns the name of the Level after localizing it, for example
+ * "WARNUNG".
+ */
+ public String getLocalizedName()
+ {
+ String localizedName = null;
+
+ if (resourceBundleName != null)
+ {
+ try
+ {
+ ResourceBundle b = ResourceBundle.getBundle(resourceBundleName);
+ localizedName = b.getString(name);
+ }
+ catch (Exception _)
+ {
+ }
+ }
+
+ if (localizedName != null)
+ return localizedName;
+ else
+ return name;
+ }
+
+
+ /**
+ * Returns the name of the Level without localizing it, for example
+ * "WARNING".
+ */
+ public final String toString()
+ {
+ return getName();
+ }
+
+
+ /**
+ * Returns the integer value of the Level.
+ */
+ public final int intValue()
+ {
+ return value;
+ }
+
+
+ /**
+ * Returns one of the standard Levels given either its name or its
+ * integer value. Custom subclasses of Level will not be returned
+ * by this method.
+ *
+ * @throws IllegalArgumentException if <code>name</code> is neither
+ * the name nor the integer value of one of the pre-defined standard
+ * logging levels.
+ *
+ * @throws NullPointerException if <code>name</code> is null.
+ *
+ */
+ public static Level parse(String name)
+ throws IllegalArgumentException
+ {
+ /* This will throw a NullPointerException if name is null,
+ * as required by the API specification.
+ */
+ name = name.intern();
+
+ for (int i = 0; i < knownLevels.length; i++)
+ {
+ if (name == knownLevels[i].name)
+ return knownLevels[i];
+ }
+
+ try
+ {
+ int num = Integer.parseInt(name);
+ for (int i = 0; i < knownLevels.length; i++)
+ if (num == knownLevels[i].value)
+ return knownLevels[i];
+ }
+ catch (NumberFormatException _)
+ {
+ }
+
+ String msg = "Not the name of a standard logging level: \"" + name + "\"";
+ throw new IllegalArgumentException(msg);
+ }
+
+
+ /**
+ * Checks whether this Level's integer value is equal to that of
+ * another object.
+ *
+ * @return <code>true</code> if <code>other</code> is an instance of
+ * <code>java.util.logging.Level</code> and has the same integer
+ * value, <code>false</code> otherwise.
+ */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof Level))
+ return false;
+
+ return value == ((Level) other).value;
+ }
+
+
+ /**
+ * Returns a hash code for this Level which is based on its numeric
+ * value.
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+
+ /**
+ * Determines whether or not this Level is one of the standard
+ * levels specified in the Logging API.
+ *
+ * <p>This method is package-private because it is not part
+ * of the logging API specification. However, an XMLFormatter
+ * is supposed to emit the numeric value for a custom log
+ * level, but the name for a pre-defined level. It seems
+ * cleaner to put this method to Level than to write some
+ * procedural code for XMLFormatter.
+ *
+ * @return <code>true</code> if this Level is a standard level,
+ * <code>false</code> otherwise.
+ */
+ final boolean isStandardLevel()
+ {
+ for (int i = 0; i < knownLevels.length; i++)
+ if (knownLevels[i] == this)
+ return true;
+
+ return false;
+ }
+}
+
diff --git a/libjava/classpath/java/util/logging/LogManager.java b/libjava/classpath/java/util/logging/LogManager.java
new file mode 100644
index 00000000000..7e3fd97d01f
--- /dev/null
+++ b/libjava/classpath/java/util/logging/LogManager.java
@@ -0,0 +1,829 @@
+/* LogManager.java -- a class for maintaining Loggers and managing
+ configuration properties
+ Copyright (C) 2002,2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ * The <code>LogManager</code> maintains a hierarchical namespace
+ * of Logger objects and manages properties for configuring the logging
+ * framework. There exists only one single <code>LogManager</code>
+ * per virtual machine. This instance can be retrieved using the
+ * static method {@link #getLogManager()}.
+ *
+ * <p><strong>Configuration Process:</strong> The global LogManager
+ * object is created and configured when the class
+ * <code>java.util.logging.LogManager</code> is initialized.
+ * The configuration process includes the subsequent steps:
+ *
+ * <ul>
+ * <li>If the system property <code>java.util.logging.manager</code>
+ * is set to the name of a subclass of
+ * <code>java.util.logging.LogManager</code>, an instance of
+ * that subclass is created and becomes the global LogManager.
+ * Otherwise, a new instance of LogManager is created.</li>
+ * <li>The <code>LogManager</code> constructor tries to create
+ * a new instance of the class specified by the system
+ * property <code>java.util.logging.config.class</code>.
+ * Typically, the constructor of this class will call
+ * <code>LogManager.getLogManager().readConfiguration(java.io.InputStream)</code>
+ * for configuring the logging framework.
+ * The configuration process stops at this point if
+ * the system property <code>java.util.logging.config.class</code>
+ * is set (irrespective of whether the class constructor
+ * could be called or an exception was thrown).</li>
+ *
+ * <li>If the system property <code>java.util.logging.config.class</code>
+ * is <em>not</em> set, the configuration parameters are read in from
+ * a file and passed to
+ * {@link #readConfiguration(java.io.InputStream)}.
+ * The name and location of this file are specified by the system
+ * property <code>java.util.logging.config.file</code>.</li>
+ * <li>If the system property <code>java.util.logging.config.file</code>
+ * is not set, however, the contents of the URL
+ * "{gnu.classpath.home.url}/logging.properties" are passed to
+ * {@link #readConfiguration(java.io.InputStream)}.
+ * Here, "{gnu.classpath.home.url}" stands for the value of
+ * the system property <code>gnu.classpath.home.url</code>.</li>
+ * </ul>
+ *
+ * <p>The <code>LogManager</code> has a level of <code>INFO</code> by
+ * default, and this will be inherited by <code>Logger</code>s unless they
+ * override it either by properties or programmatically.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class LogManager
+{
+ /**
+ * The singleton LogManager instance.
+ */
+ private static LogManager logManager;
+
+ /**
+ * The registered named loggers; maps the name of a Logger to
+ * a WeakReference to it.
+ */
+ private Map loggers;
+ final Logger rootLogger;
+
+ /**
+ * The properties for the logging framework which have been
+ * read in last.
+ */
+ private Properties properties;
+
+ /**
+ * A delegate object that provides support for handling
+ * PropertyChangeEvents. The API specification does not
+ * mention which bean should be the source in the distributed
+ * PropertyChangeEvents, but Mauve test code has determined that
+ * the Sun J2SE 1.4 reference implementation uses the LogManager
+ * class object. This is somewhat strange, as the class object
+ * is not the bean with which listeners have to register, but
+ * there is no reason for the GNU Classpath implementation to
+ * behave differently from the reference implementation in
+ * this case.
+ */
+ private final PropertyChangeSupport pcs = new PropertyChangeSupport( /* source bean */
+ LogManager.class);
+
+ protected LogManager()
+ {
+ if (logManager != null)
+ throw new IllegalStateException("there can be only one LogManager; use LogManager.getLogManager()");
+
+ logManager = this;
+ loggers = new java.util.HashMap();
+ rootLogger = new Logger("", null);
+ rootLogger.setLevel(Level.INFO);
+ addLogger(rootLogger);
+
+ /* Make sure that Logger.global has the rootLogger as its parent.
+ *
+ * Logger.global is set during class initialization of Logger,
+ * which may or may not be before this code is being executed.
+ * For example, on the Sun 1.3.1 and 1.4.0 JVMs, Logger.global
+ * has been set before this code is being executed. In contrast,
+ * Logger.global still is null on GCJ 3.2. Since the LogManager
+ * and Logger classes are mutually dependent, both behaviors are
+ * correct.
+ *
+ * This means that we cannot depend on Logger.global to have its
+ * value when this code executes, although that variable is final.
+ * Since Logger.getLogger will always return the same logger for
+ * the same name, the subsequent line works fine irrespective of
+ * the order in which classes are initialized.
+ */
+ Logger.getLogger("global").setParent(rootLogger);
+ Logger.getLogger("global").setUseParentHandlers(true);
+ }
+
+ /**
+ * Returns the globally shared LogManager instance.
+ */
+ public static LogManager getLogManager()
+ {
+ return logManager;
+ }
+
+ static
+ {
+ makeLogManager();
+
+ /* The Javadoc description of the class explains
+ * what is going on here.
+ */
+ Object configurator = createInstance(System.getProperty("java.util.logging.config.class"),
+ /* must be instance of */ Object.class);
+
+ try
+ {
+ if (configurator == null)
+ getLogManager().readConfiguration();
+ }
+ catch (IOException ex)
+ {
+ /* FIXME: Is it ok to ignore exceptions here? */
+ }
+ }
+
+ private static LogManager makeLogManager()
+ {
+ String managerClassName;
+ LogManager manager;
+
+ managerClassName = System.getProperty("java.util.logging.manager");
+ manager = (LogManager) createInstance(managerClassName, LogManager.class);
+ if (manager != null)
+ return manager;
+
+ if (managerClassName != null)
+ System.err.println("WARNING: System property \"java.util.logging.manager\""
+ + " should be the name of a subclass of java.util.logging.LogManager");
+
+ return new LogManager();
+ }
+
+ /**
+ * Registers a listener which will be notified when the
+ * logging properties are re-read.
+ */
+ public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ /* do not register null. */
+ listener.getClass();
+
+ pcs.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * Unregisters a listener.
+ *
+ * If <code>listener</code> has not been registered previously,
+ * nothing happens. Also, no exception is thrown if
+ * <code>listener</code> is <code>null</code>.
+ */
+ public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (listener != null)
+ pcs.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Adds a named logger. If a logger with the same name has
+ * already been registered, the method returns <code>false</code>
+ * without adding the logger.
+ *
+ * <p>The <code>LogManager</code> only keeps weak references
+ * to registered loggers. Therefore, names can become available
+ * after automatic garbage collection.
+ *
+ * @param logger the logger to be added.
+ *
+ * @return <code>true</code>if <code>logger</code> was added,
+ * <code>false</code> otherwise.
+ *
+ * @throws NullPointerException if <code>name</code> is
+ * <code>null</code>.
+ */
+ public synchronized boolean addLogger(Logger logger)
+ {
+ /* To developers thinking about to remove the 'synchronized'
+ * declaration from this method: Please read the comment
+ * in java.util.logging.Logger.getLogger(String, String)
+ * and make sure that whatever you change wrt. synchronization
+ * does not endanger thread-safety of Logger.getLogger.
+ * The current implementation of Logger.getLogger assumes
+ * that LogManager does its synchronization on the globally
+ * shared instance of LogManager.
+ */
+ String name;
+ WeakReference ref;
+
+ /* This will throw a NullPointerException if logger is null,
+ * as required by the API specification.
+ */
+ name = logger.getName();
+
+ ref = (WeakReference) loggers.get(name);
+ if (ref != null)
+ {
+ if (ref.get() != null)
+ return false;
+
+ /* There has been a logger under this name in the past,
+ * but it has been garbage collected.
+ */
+ loggers.remove(ref);
+ }
+
+ /* Adding a named logger requires a security permission. */
+ if ((name != null) && ! name.equals(""))
+ checkAccess();
+
+ Logger parent = findAncestor(logger);
+ loggers.put(name, new WeakReference(logger));
+ if (parent != logger.getParent())
+ logger.setParent(parent);
+
+ /* It can happen that existing loggers should be children of
+ * the newly added logger. For example, assume that there
+ * already exist loggers under the names "", "foo", and "foo.bar.baz".
+ * When adding "foo.bar", the logger "foo.bar.baz" should change
+ * its parent to "foo.bar".
+ */
+ if (parent != rootLogger)
+ {
+ for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
+ {
+ Logger possChild = (Logger) ((WeakReference) loggers.get(iter.next()))
+ .get();
+ if ((possChild == null) || (possChild == logger)
+ || (possChild.getParent() != parent))
+ continue;
+
+ if (! possChild.getName().startsWith(name))
+ continue;
+
+ if (possChild.getName().charAt(name.length()) != '.')
+ continue;
+
+ possChild.setParent(logger);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Finds the closest ancestor for a logger among the currently
+ * registered ones. For example, if the currently registered
+ * loggers have the names "", "foo", and "foo.bar", the result for
+ * "foo.bar.baz" will be the logger whose name is "foo.bar".
+ *
+ * @param child a logger for whose name no logger has been
+ * registered.
+ *
+ * @return the closest ancestor for <code>child</code>,
+ * or <code>null</code> if <code>child</code>
+ * is the root logger.
+ *
+ * @throws NullPointerException if <code>child</code>
+ * is <code>null</code>.
+ */
+ private synchronized Logger findAncestor(Logger child)
+ {
+ String childName = child.getName();
+ int childNameLength = childName.length();
+ Logger best = rootLogger;
+ int bestNameLength = 0;
+
+ Logger cand;
+ String candName;
+ int candNameLength;
+
+ if (child == rootLogger)
+ return null;
+
+ for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
+ {
+ candName = (String) iter.next();
+ candNameLength = candName.length();
+
+ if (candNameLength > bestNameLength
+ && childNameLength > candNameLength
+ && childName.startsWith(candName)
+ && childName.charAt(candNameLength) == '.')
+ {
+ cand = (Logger) ((WeakReference) loggers.get(candName)).get();
+ if ((cand == null) || (cand == child))
+ continue;
+
+ bestNameLength = candName.length();
+ best = cand;
+ }
+ }
+
+ return best;
+ }
+
+ /**
+ * Returns a Logger given its name.
+ *
+ * @param name the name of the logger.
+ *
+ * @return a named Logger, or <code>null</code> if there is no
+ * logger with that name.
+ *
+ * @throw java.lang.NullPointerException if <code>name</code>
+ * is <code>null</code>.
+ */
+ public synchronized Logger getLogger(String name)
+ {
+ WeakReference ref;
+
+ /* Throw a NullPointerException if name is null. */
+ name.getClass();
+
+ ref = (WeakReference) loggers.get(name);
+ if (ref != null)
+ return (Logger) ref.get();
+ else
+ return null;
+ }
+
+ /**
+ * Returns an Enumeration of currently registered Logger names.
+ * Since other threads can register loggers at any time, the
+ * result could be different any time this method is called.
+ *
+ * @return an Enumeration with the names of the currently
+ * registered Loggers.
+ */
+ public synchronized Enumeration getLoggerNames()
+ {
+ return Collections.enumeration(loggers.keySet());
+ }
+
+ /**
+ * Resets the logging configuration by removing all handlers for
+ * registered named loggers and setting their level to <code>null</code>.
+ * The level of the root logger will be set to <code>Level.INFO</code>.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ */
+ public synchronized void reset() throws SecurityException
+ {
+ /* Throw a SecurityException if the caller does not have the
+ * permission to control the logging infrastructure.
+ */
+ checkAccess();
+
+ properties = new Properties();
+
+ Iterator iter = loggers.values().iterator();
+ while (iter.hasNext())
+ {
+ WeakReference ref;
+ Logger logger;
+
+ ref = (WeakReference) iter.next();
+ if (ref != null)
+ {
+ logger = (Logger) ref.get();
+
+ if (logger == null)
+ iter.remove();
+ else if (logger != rootLogger)
+ {
+ logger.resetLogger();
+ logger.setLevel(null);
+ }
+ }
+ }
+
+ rootLogger.setLevel(Level.INFO);
+ rootLogger.resetLogger();
+ }
+
+ /**
+ * Configures the logging framework by reading a configuration file.
+ * The name and location of this file are specified by the system
+ * property <code>java.util.logging.config.file</code>. If this
+ * property is not set, the URL
+ * "{gnu.classpath.home.url}/logging.properties" is taken, where
+ * "{gnu.classpath.home.url}" stands for the value of the system
+ * property <code>gnu.classpath.home.url</code>.
+ *
+ * <p>The task of configuring the framework is then delegated to
+ * {@link #readConfiguration(java.io.InputStream)}, which will
+ * notify registered listeners after having read the properties.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure, or if the caller is
+ * not granted the permission to read the configuration
+ * file.
+ *
+ * @throws IOException if there is a problem reading in the
+ * configuration file.
+ */
+ public synchronized void readConfiguration()
+ throws IOException, SecurityException
+ {
+ String path;
+ InputStream inputStream;
+
+ path = System.getProperty("java.util.logging.config.file");
+ if ((path == null) || (path.length() == 0))
+ {
+ String url = (System.getProperty("gnu.classpath.home.url")
+ + "/logging.properties");
+ inputStream = new URL(url).openStream();
+ }
+ else
+ inputStream = new java.io.FileInputStream(path);
+
+ try
+ {
+ readConfiguration(inputStream);
+ }
+ finally
+ {
+ /* Close the stream in order to save
+ * resources such as file descriptors.
+ */
+ inputStream.close();
+ }
+ }
+
+ public synchronized void readConfiguration(InputStream inputStream)
+ throws IOException, SecurityException
+ {
+ Properties newProperties;
+ Enumeration keys;
+
+ checkAccess();
+ newProperties = new Properties();
+ newProperties.load(inputStream);
+ reset();
+ this.properties = newProperties;
+ keys = newProperties.propertyNames();
+
+ while (keys.hasMoreElements())
+ {
+ String key = ((String) keys.nextElement()).trim();
+ String value = newProperties.getProperty(key);
+
+ if (value == null)
+ continue;
+
+ value = value.trim();
+
+ if ("handlers".equals(key))
+ {
+ StringTokenizer tokenizer = new StringTokenizer(value);
+ while (tokenizer.hasMoreTokens())
+ {
+ String handlerName = tokenizer.nextToken();
+ try
+ {
+ Class handlerClass = ClassLoader.getSystemClassLoader().loadClass(handlerName);
+ getLogger("").addHandler((Handler) handlerClass
+ .newInstance());
+ }
+ catch (ClassCastException ex)
+ {
+ System.err.println("[LogManager] class " + handlerName
+ + " is not subclass of java.util.logging.Handler");
+ }
+ catch (Exception ex)
+ {
+ //System.out.println("[LogManager.readConfiguration]"+ex);
+ }
+ }
+ }
+
+ if (key.endsWith(".level"))
+ {
+ String loggerName = key.substring(0, key.length() - 6);
+ Logger logger = getLogger(loggerName);
+
+ if (logger == null)
+ {
+ logger = Logger.getLogger(loggerName);
+ addLogger(logger);
+ }
+ try
+ {
+ logger.setLevel(Level.parse(value));
+ }
+ catch (Exception _)
+ {
+ //System.out.println("[LogManager.readConfiguration] "+_);
+ }
+ continue;
+ }
+ }
+
+ /* The API specification does not talk about the
+ * property name that is distributed with the
+ * PropertyChangeEvent. With test code, it could
+ * be determined that the Sun J2SE 1.4 reference
+ * implementation uses null for the property name.
+ */
+ pcs.firePropertyChange(null, null, null);
+ }
+
+ /**
+ * Returns the value of a configuration property as a String.
+ */
+ public synchronized String getProperty(String name)
+ {
+ if (properties != null)
+ return properties.getProperty(name);
+ else
+ return null;
+ }
+
+ /**
+ * Returns the value of a configuration property as an integer.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param name the name of the configuration property.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if its value is not an integer
+ * number.
+ */
+ static int getIntProperty(String name, int defaultValue)
+ {
+ try
+ {
+ return Integer.parseInt(getLogManager().getProperty(name));
+ }
+ catch (Exception ex)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value of a configuration property as an integer,
+ * provided it is inside the acceptable range.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param name the name of the configuration property.
+ *
+ * @param minValue the lowest acceptable value.
+ *
+ * @param maxValue the highest acceptable value.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if its value is not an integer
+ * number, or if it is less than the minimum value,
+ * or if it is greater than the maximum value.
+ */
+ static int getIntPropertyClamped(String name, int defaultValue,
+ int minValue, int maxValue)
+ {
+ int val = getIntProperty(name, defaultValue);
+ if ((val < minValue) || (val > maxValue))
+ val = defaultValue;
+ return val;
+ }
+
+ /**
+ * Returns the value of a configuration property as a boolean.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param name the name of the configuration property.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if its value is neither
+ * <code>"true"</code> nor <code>"false"</code>.
+ */
+ static boolean getBooleanProperty(String name, boolean defaultValue)
+ {
+ try
+ {
+ return (new Boolean(getLogManager().getProperty(name))).booleanValue();
+ }
+ catch (Exception ex)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value of a configuration property as a Level.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param propertyName the name of the configuration property.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if
+ * {@link Level.parse(java.lang.String)} does not like
+ * the property value.
+ */
+ static Level getLevelProperty(String propertyName, Level defaultValue)
+ {
+ try
+ {
+ return Level.parse(getLogManager().getProperty(propertyName));
+ }
+ catch (Exception ex)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value of a configuration property as a Class.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param propertyName the name of the configuration property.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if it does not specify
+ * the name of a loadable class.
+ */
+ static final Class getClassProperty(String propertyName, Class defaultValue)
+ {
+ Class usingClass = null;
+
+ try
+ {
+ String propertyValue = logManager.getProperty(propertyName);
+ if (propertyValue != null)
+ usingClass = Class.forName(propertyValue);
+ if (usingClass != null)
+ return usingClass;
+ }
+ catch (Exception _)
+ {
+ }
+
+ return defaultValue;
+ }
+
+ static final Object getInstanceProperty(String propertyName, Class ofClass,
+ Class defaultClass)
+ {
+ Class klass = getClassProperty(propertyName, defaultClass);
+ if (klass == null)
+ return null;
+
+ try
+ {
+ Object obj = klass.newInstance();
+ if (ofClass.isInstance(obj))
+ return obj;
+ }
+ catch (Exception _)
+ {
+ }
+
+ if (defaultClass == null)
+ return null;
+
+ try
+ {
+ return defaultClass.newInstance();
+ }
+ catch (java.lang.InstantiationException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ catch (java.lang.IllegalAccessException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ /**
+ * An instance of <code>LoggingPermission("control")</code>
+ * that is shared between calls to <code>checkAccess()</code>.
+ */
+ private static final LoggingPermission controlPermission = new LoggingPermission("control",
+ null);
+
+ /**
+ * Checks whether the current security context allows changing
+ * the configuration of the logging framework. For the security
+ * context to be trusted, it has to be granted
+ * a LoggingPermission("control").
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ */
+ public void checkAccess() throws SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(controlPermission);
+ }
+
+ /**
+ * Creates a new instance of a class specified by name.
+ *
+ * @param className the name of the class of which a new instance
+ * should be created.
+ *
+ * @param ofClass the class to which the new instance should
+ * be either an instance or an instance of a subclass.
+ * FIXME: This description is just terrible.
+ *
+ * @return the new instance, or <code>null</code> if
+ * <code>className</code> is <code>null</code>, if no class
+ * with that name could be found, if there was an error
+ * loading that class, or if the constructor of the class
+ * has thrown an exception.
+ */
+ static final Object createInstance(String className, Class ofClass)
+ {
+ Class klass;
+
+ if ((className == null) || (className.length() == 0))
+ return null;
+
+ try
+ {
+ klass = Class.forName(className);
+ if (! ofClass.isAssignableFrom(klass))
+ return null;
+
+ return klass.newInstance();
+ }
+ catch (Exception _)
+ {
+ return null;
+ }
+ catch (java.lang.LinkageError _)
+ {
+ return null;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/logging/LogRecord.java b/libjava/classpath/java/util/logging/LogRecord.java
new file mode 100644
index 00000000000..af7f2058dbe
--- /dev/null
+++ b/libjava/classpath/java/util/logging/LogRecord.java
@@ -0,0 +1,672 @@
+/* LogRecord.java --
+ A class for the state associated with individual logging events
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.util.ResourceBundle;
+
+
+/**
+ * A <code>LogRecord</code> contains the state for an individual
+ * event to be logged.
+ *
+ * <p>As soon as a LogRecord instance has been handed over to the
+ * logging framework, applications should not manipulate it anymore.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class LogRecord
+ implements java.io.Serializable
+{
+ /**
+ * The severity level of this <code>LogRecord</code>.
+ */
+ private Level level;
+
+
+ /**
+ * The sequence number of this <code>LogRecord</code>.
+ */
+ private long sequenceNumber;
+
+
+ /**
+ * The name of the class that issued the logging request, or
+ * <code>null</code> if this information could not be obtained.
+ */
+ private String sourceClassName;
+
+
+ /**
+ * The name of the method that issued the logging request, or
+ * <code>null</code> if this information could not be obtained.
+ */
+ private String sourceMethodName;
+
+
+ /**
+ * The message for this <code>LogRecord</code> before
+ * any localization or formatting.
+ */
+ private String message;
+
+
+ /**
+ * An identifier for the thread in which this <code>LogRecord</code>
+ * was created. The identifier is not necessarily related to any
+ * thread identifiers used by the operating system.
+ */
+ private int threadID;
+
+
+ /**
+ * The time when this <code>LogRecord</code> was created,
+ * in milliseconds since the beginning of January 1, 1970.
+ */
+ private long millis;
+
+
+ /**
+ * The Throwable associated with this <code>LogRecord</code>, or
+ * <code>null</code> if the logged event is not related to an
+ * exception or error.
+ */
+ private Throwable thrown;
+
+
+ /**
+ * The name of the logger where this <code>LogRecord</code> has
+ * originated, or <code>null</code> if this <code>LogRecord</code>
+ * does not originate from a <code>Logger</code>.
+ */
+ private String loggerName;
+
+
+ /**
+ * The name of the resource bundle used for localizing log messages,
+ * or <code>null</code> if no bundle has been specified.
+ */
+ private String resourceBundleName;
+
+ private transient Object[] parameters;
+
+ private transient ResourceBundle bundle;
+
+
+ /**
+ * Constructs a <code>LogRecord</code> given a severity level and
+ * an unlocalized message text. In addition, the sequence number,
+ * creation time (as returned by <code>getMillis()</code>) and
+ * thread ID are assigned. All other properties are set to
+ * <code>null</code>.
+ *
+ * @param level the severity level, for example <code>Level.WARNING</code>.
+ *
+ * @param message the message text (which will be used as key
+ * for looking up the localized message text
+ * if a resource bundle has been associated).
+ */
+ public LogRecord(Level level, String message)
+ {
+ this.level = level;
+ this.message = message;
+ this.millis = System.currentTimeMillis();
+
+ /* A subclass of java.lang.Thread could override hashCode(),
+ * in which case the result would not be guaranteed anymore
+ * to be unique among all threads. While System.identityHashCode
+ * is not necessarily unique either, it at least cannot be
+ * overridden by user code. However, is might be a good idea
+ * to use something better for generating thread IDs.
+ */
+ this.threadID = System.identityHashCode(Thread.currentThread());
+
+ sequenceNumber = allocateSeqNum();
+ }
+
+
+ /**
+ * Determined with the serialver tool of the Sun J2SE 1.4.
+ */
+ static final long serialVersionUID = 5372048053134512534L;
+
+ private void readObject(java.io.ObjectInputStream in)
+ throws java.io.IOException, java.lang.ClassNotFoundException
+ {
+ in.defaultReadObject();
+
+ /* We assume that future versions will be downwards compatible,
+ * so we can ignore the versions.
+ */
+ byte majorVersion = in.readByte();
+ byte minorVersion = in.readByte();
+
+ int numParams = in.readInt();
+ if (numParams >= 0)
+ {
+ parameters = new Object[numParams];
+ for (int i = 0; i < numParams; i++)
+ parameters[i] = in.readObject();
+ }
+ }
+
+
+ /**
+ * @serialData The default fields, followed by a major byte version
+ * number, followed by a minor byte version number, followed by
+ * information about the log record parameters. If
+ * <code>parameters</code> is <code>null</code>, the integer -1 is
+ * written, otherwise the length of the <code>parameters</code>
+ * array (which can be zero), followed by the result of calling
+ * {@link Object#toString() toString()} on the parameter (or
+ * <code>null</code> if the parameter is <code>null</code>).
+ *
+ * <p><strong>Specification Note:</strong> The Javadoc for the
+ * Sun reference implementation does not specify the version
+ * number. FIXME: Reverse-engineer the JDK and file a bug
+ * report with Sun, asking for amendment of the specification.
+ */
+ private void writeObject(java.io.ObjectOutputStream out)
+ throws java.io.IOException
+ {
+ out.defaultWriteObject();
+
+ /* Major, minor version number: The Javadoc for J2SE1.4 does not
+ * specify the values.
+ */
+ out.writeByte(0);
+ out.writeByte(0);
+
+ if (parameters == null)
+ out.writeInt(-1);
+ else
+ {
+ out.writeInt(parameters.length);
+ for (int i = 0; i < parameters.length; i++)
+ {
+ if (parameters[i] == null)
+ out.writeObject(null);
+ else
+ out.writeObject(parameters[i].toString());
+ }
+ }
+ }
+
+
+ /**
+ * Returns the name of the logger where this <code>LogRecord</code>
+ * has originated.
+ *
+ * @return the name of the source {@link Logger}, or
+ * <code>null</code> if this <code>LogRecord</code>
+ * does not originate from a <code>Logger</code>.
+ */
+ public String getLoggerName()
+ {
+ return loggerName;
+ }
+
+
+ /**
+ * Sets the name of the logger where this <code>LogRecord</code>
+ * has originated.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param name the name of the source logger, or <code>null</code> to
+ * indicate that this <code>LogRecord</code> does not
+ * originate from a <code>Logger</code>.
+ */
+ public void setLoggerName(String name)
+ {
+ loggerName = name;
+ }
+
+
+ /**
+ * Returns the resource bundle that is used when the message
+ * of this <code>LogRecord</code> needs to be localized.
+ *
+ * @return the resource bundle used for localization,
+ * or <code>null</code> if this message does not need
+ * to be localized.
+ */
+ public ResourceBundle getResourceBundle()
+ {
+ return bundle;
+ }
+
+
+ /**
+ * Sets the resource bundle that is used when the message
+ * of this <code>LogRecord</code> needs to be localized.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param bundle the resource bundle to be used, or
+ * <code>null</code> to indicate that this
+ * message does not need to be localized.
+ */
+ public void setResourceBundle(ResourceBundle bundle)
+ {
+ this.bundle = bundle;
+
+ /* FIXME: Is there a way to infer the name
+ * of a resource bundle from a ResourceBundle object?
+ */
+ this.resourceBundleName = null;
+ }
+
+
+ /**
+ * Returns the name of the resource bundle that is used when the
+ * message of this <code>LogRecord</code> needs to be localized.
+ *
+ * @return the name of the resource bundle used for localization,
+ * or <code>null</code> if this message does not need
+ * to be localized.
+ */
+ public String getResourceBundleName()
+ {
+ return resourceBundleName;
+ }
+
+
+ /**
+ * Sets the name of the resource bundle that is used when the
+ * message of this <code>LogRecord</code> needs to be localized.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param name the name of the resource bundle to be used, or
+ * <code>null</code> to indicate that this message
+ * does not need to be localized.
+ */
+ public void setResourceBundleName(String name)
+ {
+ resourceBundleName = name;
+ bundle = null;
+
+ try
+ {
+ if (resourceBundleName != null)
+ bundle = ResourceBundle.getBundle(resourceBundleName);
+ }
+ catch (java.util.MissingResourceException _)
+ {
+ }
+ }
+
+
+ /**
+ * Returns the level of the LogRecord.
+ *
+ * <p>Applications should be aware of the possibility that the
+ * result is not necessarily one of the standard logging levels,
+ * since the logging framework allows to create custom subclasses
+ * of <code>java.util.logging.Level</code>. Therefore, filters
+ * should perform checks like <code>theRecord.getLevel().intValue()
+ * == Level.INFO.intValue()</code> instead of <code>theRecord.getLevel()
+ * == Level.INFO</code>.
+ */
+ public Level getLevel()
+ {
+ return level;
+ }
+
+
+ /**
+ * Sets the severity level of this <code>LogRecord</code> to a new
+ * value.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param level the new severity level, for example
+ * <code>Level.WARNING</code>.
+ */
+ public void setLevel(Level level)
+ {
+ this.level = level;
+ }
+
+
+ /**
+ * The last used sequence number for any LogRecord.
+ */
+ private static long lastSeqNum;
+
+
+ /**
+ * Allocates a sequence number for a new LogRecord. This class
+ * method is only called by the LogRecord constructor.
+ */
+ private static synchronized long allocateSeqNum()
+ {
+ lastSeqNum += 1;
+ return lastSeqNum;
+ }
+
+
+ /**
+ * Returns the sequence number of this <code>LogRecord</code>.
+ */
+ public long getSequenceNumber()
+ {
+ return sequenceNumber;
+ }
+
+
+ /**
+ * Sets the sequence number of this <code>LogRecord</code> to a new
+ * value.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param seqNum the new sequence number.
+ */
+ public void setSequenceNumber(long seqNum)
+ {
+ this.sequenceNumber = seqNum;
+ }
+
+
+ /**
+ * Returns the name of the class where the event being logged
+ * has had its origin. This information can be passed as
+ * parameter to some logging calls, and in certain cases, the
+ * logging framework tries to determine an approximation
+ * (which may or may not be accurate).
+ *
+ * @return the name of the class that issued the logging request,
+ * or <code>null</code> if this information could not
+ * be obtained.
+ */
+ public String getSourceClassName()
+ {
+ if (sourceClassName != null)
+ return sourceClassName;
+
+ /* FIXME: Should infer this information from the call stack. */
+ return null;
+ }
+
+
+ /**
+ * Sets the name of the class where the event being logged
+ * has had its origin.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param sourceClassName the name of the class that issued the
+ * logging request, or <code>null</code> to indicate that
+ * this information could not be obtained.
+ */
+ public void setSourceClassName(String sourceClassName)
+ {
+ this.sourceClassName = sourceClassName;
+ }
+
+
+ /**
+ * Returns the name of the method where the event being logged
+ * has had its origin. This information can be passed as
+ * parameter to some logging calls, and in certain cases, the
+ * logging framework tries to determine an approximation
+ * (which may or may not be accurate).
+ *
+ * @return the name of the method that issued the logging request,
+ * or <code>null</code> if this information could not
+ * be obtained.
+ */
+ public String getSourceMethodName()
+ {
+ if (sourceMethodName != null)
+ return sourceMethodName;
+
+ /* FIXME: Should infer this information from the call stack. */
+ return null;
+ }
+
+
+ /**
+ * Sets the name of the method where the event being logged
+ * has had its origin.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param sourceMethodName the name of the method that issued the
+ * logging request, or <code>null</code> to indicate that
+ * this information could not be obtained.
+ */
+ public void setSourceMethodName(String sourceMethodName)
+ {
+ this.sourceMethodName = sourceMethodName;
+ }
+
+
+ /**
+ * Returns the message for this <code>LogRecord</code> before
+ * any localization or parameter substitution.
+ *
+ * <p>A {@link Logger} will try to localize the message
+ * if a resource bundle has been associated with this
+ * <code>LogRecord</code>. In this case, the logger will call
+ * <code>getMessage()</code> and use the result as the key
+ * for looking up the localized message in the bundle.
+ * If no bundle has been associated, or if the result of
+ * <code>getMessage()</code> is not a valid key in the
+ * bundle, the logger will use the raw message text as
+ * returned by this method.
+ *
+ * @return the message text, or <code>null</code> if there
+ * is no message text.
+ */
+ public String getMessage()
+ {
+ return message;
+ }
+
+
+ /**
+ * Sets the message for this <code>LogRecord</code>.
+ *
+ * <p>A <code>Logger</code> will try to localize the message
+ * if a resource bundle has been associated with this
+ * <code>LogRecord</code>. In this case, the logger will call
+ * <code>getMessage()</code> and use the result as the key
+ * for looking up the localized message in the bundle.
+ * If no bundle has been associated, or if the result of
+ * <code>getMessage()</code> is not a valid key in the
+ * bundle, the logger will use the raw message text as
+ * returned by this method.
+ *
+ * <p>It is possible to set the message to either an empty String or
+ * <code>null</code>, although this does not make the the message
+ * very helpful to human users.
+ *
+ * @param message the message text (which will be used as key
+ * for looking up the localized message text
+ * if a resource bundle has been associated).
+ */
+ public void setMessage(String message)
+ {
+ this.message = message;
+ }
+
+
+ /**
+ * Returns the parameters to the log message.
+ *
+ * @return the parameters to the message, or <code>null</code> if
+ * the message has no parameters.
+ */
+ public Object[] getParameters()
+ {
+ return parameters;
+ }
+
+
+ /**
+ * Sets the parameters to the log message.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param parameters the parameters to the message, or <code>null</code>
+ * to indicate that the message has no parameters.
+ */
+ public void setParameters(Object[] parameters)
+ {
+ this.parameters = parameters;
+ }
+
+
+ /**
+ * Returns an identifier for the thread in which this
+ * <code>LogRecord</code> was created. The identifier is not
+ * necessarily related to any thread identifiers used by the
+ * operating system.
+ *
+ * @return an identifier for the source thread.
+ */
+ public int getThreadID()
+ {
+ return threadID;
+ }
+
+
+ /**
+ * Sets the identifier indicating in which thread this
+ * <code>LogRecord</code> was created. The identifier is not
+ * necessarily related to any thread identifiers used by the
+ * operating system.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param threadID the identifier for the source thread.
+ */
+ public void setThreadID(int threadID)
+ {
+ this.threadID = threadID;
+ }
+
+
+ /**
+ * Returns the time when this <code>LogRecord</code> was created.
+ *
+ * @return the time of creation in milliseconds since the beginning
+ * of January 1, 1970.
+ */
+ public long getMillis()
+ {
+ return millis;
+ }
+
+
+ /**
+ * Sets the time when this <code>LogRecord</code> was created.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param millis the time of creation in milliseconds since the
+ * beginning of January 1, 1970.
+ */
+ public void setMillis(long millis)
+ {
+ this.millis = millis;
+ }
+
+
+ /**
+ * Returns the Throwable associated with this <code>LogRecord</code>,
+ * or <code>null</code> if the logged event is not related to an exception
+ * or error.
+ */
+ public Throwable getThrown()
+ {
+ return thrown;
+ }
+
+
+ /**
+ * Associates this <code>LogRecord</code> with an exception or error.
+ *
+ * <p>As soon as a <code>LogRecord</code> has been handed over
+ * to the logging framework, applications should not modify it
+ * anymore. Therefore, this method should only be called on
+ * freshly constructed LogRecords.
+ *
+ * @param thrown the exception or error to associate with, or
+ * <code>null</code> if this <code>LogRecord</code>
+ * should be made unrelated to an exception or error.
+ */
+ public void setThrown(Throwable thrown)
+ {
+ this.thrown = thrown;
+ }
+}
diff --git a/libjava/classpath/java/util/logging/Logger.java b/libjava/classpath/java/util/logging/Logger.java
new file mode 100644
index 00000000000..ae985a93cbc
--- /dev/null
+++ b/libjava/classpath/java/util/logging/Logger.java
@@ -0,0 +1,1199 @@
+/* Logger.java -- a class for logging messages
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * A Logger is used for logging information about events. Usually, there
+ * is a seprate logger for each subsystem or component, although there
+ * is a shared instance for components that make only occasional use of
+ * the logging framework.
+ *
+ * <p>It is common to name a logger after the name of a corresponding
+ * Java package. Loggers are organized into a hierarchical namespace;
+ * for example, the logger <code>"org.gnu.foo"</code> is the
+ * <em>parent</em> of logger <code>"org.gnu.foo.bar"</code>.
+ *
+ * <p>A logger for a named subsystem can be obtained through {@link
+ * java.util.logging.Logger#getLogger(java.lang.String)}. However,
+ * only code which has been granted the permission to control the
+ * logging infrastructure will be allowed to customize that logger.
+ * Untrusted code can obtain a private, anonymous logger through
+ * {@link #getAnonymousLogger()} if it wants to perform any
+ * modifications to the logger.
+ *
+ * <p>FIXME: Write more documentation.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class Logger
+{
+ /**
+ * A logger provided to applications that make only occasional use
+ * of the logging framework, typically early prototypes. Serious
+ * products are supposed to create and use their own Loggers, so
+ * they can be controlled individually.
+ */
+ public static final Logger global = getLogger("global");
+
+
+ /**
+ * The name of the Logger, or <code>null</code> if the logger is
+ * anonymous.
+ *
+ * <p>A previous version of the GNU Classpath implementation granted
+ * untrusted code the permission to control any logger whose name
+ * was null. However, test code revealed that the Sun J2SE 1.4
+ * reference implementation enforces the security control for any
+ * logger that was not created through getAnonymousLogger, even if
+ * it has a null name. Therefore, a separate flag {@link
+ * Logger#anonymous} was introduced.
+ */
+ private final String name;
+
+
+ /**
+ * The name of the resource bundle used for localization.
+ *
+ * <p>This variable cannot be declared as <code>final</code>
+ * because its value can change as a result of calling
+ * getLogger(String,String).
+ */
+ private String resourceBundleName;
+
+
+ /**
+ * The resource bundle used for localization.
+ *
+ * <p>This variable cannot be declared as <code>final</code>
+ * because its value can change as a result of calling
+ * getLogger(String,String).
+ */
+ private ResourceBundle resourceBundle;
+
+ private Filter filter;
+
+ private final List handlerList = new java.util.ArrayList(4);
+ private Handler[] handlers = new Handler[0];
+
+ /**
+ * Indicates whether or not this logger is anonymous. While
+ * a LoggingPermission is required for any modifications to
+ * a normal logger, untrusted code can obtain an anonymous logger
+ * and modify it according to its needs.
+ *
+ * <p>A previous version of the GNU Classpath implementation
+ * granted access to every logger whose name was null.
+ * However, test code revealed that the Sun J2SE 1.4 reference
+ * implementation enforces the security control for any logger
+ * that was not created through getAnonymousLogger, even
+ * if it has a null name.
+ */
+ private boolean anonymous;
+
+
+ private boolean useParentHandlers;
+
+ private Level level;
+
+ private Logger parent;
+
+ /**
+ * Constructs a Logger for a subsystem. Most applications do not
+ * need to create new Loggers explicitly; instead, they should call
+ * the static factory methods
+ * {@link #getLogger(java.lang.String,java.lang.String) getLogger}
+ * (with ResourceBundle for localization) or
+ * {@link #getLogger(java.lang.String) getLogger} (without
+ * ResourceBundle), respectively.
+ *
+ * @param name the name for the logger, for example "java.awt"
+ * or "com.foo.bar". The name should be based on
+ * the name of the package issuing log records
+ * and consist of dot-separated Java identifiers.
+ *
+ * @param resourceBundleName the name of a resource bundle
+ * for localizing messages, or <code>null</code>
+ * to indicate that messages do not need to be localized.
+ *
+ * @throws java.util.MissingResourceException if
+ * <code>resourceBundleName</code> is not <code>null</code>
+ * and no such bundle could be located.
+ */
+ protected Logger(String name, String resourceBundleName)
+ throws MissingResourceException
+ {
+ this.name = name;
+ this.resourceBundleName = resourceBundleName;
+
+ if (resourceBundleName == null)
+ resourceBundle = null;
+ else
+ resourceBundle = ResourceBundle.getBundle(resourceBundleName);
+
+ level = null;
+
+ /* This is null when the root logger is being constructed,
+ * and the root logger afterwards.
+ */
+ parent = LogManager.getLogManager().rootLogger;
+
+ useParentHandlers = (parent != null);
+ }
+
+
+
+ /**
+ * Finds a registered logger for a subsystem, or creates one in
+ * case no logger has been registered yet.
+ *
+ * @param name the name for the logger, for example "java.awt"
+ * or "com.foo.bar". The name should be based on
+ * the name of the package issuing log records
+ * and consist of dot-separated Java identifiers.
+ *
+ * @throws IllegalArgumentException if a logger for the subsystem
+ * identified by <code>name</code> has already been created,
+ * but uses a a resource bundle for localizing messages.
+ *
+ * @throws NullPointerException if <code>name</code> is
+ * <code>null</code>.
+ *
+ * @return a logger for the subsystem specified by <code>name</code>
+ * that does not localize messages.
+ */
+ public static Logger getLogger(String name)
+ {
+ return getLogger(name, null);
+ }
+
+
+ /**
+ * Finds a registered logger for a subsystem, or creates one in case
+ * no logger has been registered yet.
+ *
+ * <p>If a logger with the specified name has already been
+ * registered, the behavior depends on the resource bundle that is
+ * currently associated with the existing logger.
+ *
+ * <ul><li>If the existing logger uses the same resource bundle as
+ * specified by <code>resourceBundleName</code>, the existing logger
+ * is returned.</li>
+ *
+ * <li>If the existing logger currently does not localize messages,
+ * the existing logger is modified to use the bundle specified by
+ * <code>resourceBundleName</code>. The existing logger is then
+ * returned. Therefore, all subsystems currently using this logger
+ * will produce localized messages from now on.</li>
+ *
+ * <li>If the existing logger already has an associated resource
+ * bundle, but a different one than specified by
+ * <code>resourceBundleName</code>, an
+ * <code>IllegalArgumentException</code> is thrown.</li></ul>
+ *
+ * @param name the name for the logger, for example "java.awt"
+ * or "org.gnu.foo". The name should be based on
+ * the name of the package issuing log records
+ * and consist of dot-separated Java identifiers.
+ *
+ * @param resourceBundleName the name of a resource bundle
+ * for localizing messages, or <code>null</code>
+ * to indicate that messages do not need to be localized.
+ *
+ * @return a logger for the subsystem specified by <code>name</code>.
+ *
+ * @throws java.util.MissingResourceException if
+ * <code>resourceBundleName</code> is not <code>null</code>
+ * and no such bundle could be located.
+ *
+ * @throws IllegalArgumentException if a logger for the subsystem
+ * identified by <code>name</code> has already been created,
+ * but uses a different resource bundle for localizing
+ * messages.
+ *
+ * @throws NullPointerException if <code>name</code> is
+ * <code>null</code>.
+ */
+ public static Logger getLogger(String name, String resourceBundleName)
+ {
+ LogManager lm = LogManager.getLogManager();
+ Logger result;
+
+ /* Throw NullPointerException if name is null. */
+ name.getClass();
+
+ /* Without synchronized(lm), it could happen that another thread
+ * would create a logger between our calls to getLogger and
+ * addLogger. While addLogger would indicate this by returning
+ * false, we could not be sure that this other logger was still
+ * existing when we called getLogger a second time in order
+ * to retrieve it -- note that LogManager is only allowed to
+ * keep weak references to registered loggers, so Loggers
+ * can be garbage collected at any time in general, and between
+ * our call to addLogger and our second call go getLogger
+ * in particular.
+ *
+ * Of course, we assume here that LogManager.addLogger etc.
+ * are synchronizing on the global LogManager object. There
+ * is a comment in the implementation of LogManager.addLogger
+ * referring to this comment here, so that any change in
+ * the synchronization of LogManager will be reflected here.
+ */
+ synchronized (lm)
+ {
+ result = lm.getLogger(name);
+ if (result == null)
+ {
+ boolean couldBeAdded;
+
+ result = new Logger(name, resourceBundleName);
+ couldBeAdded = lm.addLogger(result);
+ if (!couldBeAdded)
+ throw new IllegalStateException("cannot register new logger");
+ }
+ else
+ {
+ /* The logger already exists. Make sure it uses
+ * the same resource bundle for localizing messages.
+ */
+ String existingBundleName = result.getResourceBundleName();
+
+ /* The Sun J2SE 1.4 reference implementation will return the
+ * registered logger object, even if it does not have a resource
+ * bundle associated with it. However, it seems to change the
+ * resourceBundle of the registered logger to the bundle
+ * whose name was passed to getLogger.
+ */
+ if ((existingBundleName == null) && (resourceBundleName != null))
+ {
+ /* If ResourceBundle.getBundle throws an exception, the
+ * existing logger will be unchanged. This would be
+ * different if the assignment to resourceBundleName
+ * came first.
+ */
+ result.resourceBundle = ResourceBundle.getBundle(resourceBundleName);
+ result.resourceBundleName = resourceBundleName;
+ return result;
+ }
+
+ if ((existingBundleName != resourceBundleName)
+ && ((existingBundleName == null)
+ || !existingBundleName.equals(resourceBundleName)))
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ /**
+ * Creates a new, unnamed logger. Unnamed loggers are not
+ * registered in the namespace of the LogManager, and no special
+ * security permission is required for changing their state.
+ * Therefore, untrusted applets are able to modify their private
+ * logger instance obtained through this method.
+ *
+ * <p>The parent of the newly created logger will the the root
+ * logger, from which the level threshold and the handlers are
+ * inherited.
+ */
+ public static Logger getAnonymousLogger()
+ {
+ return getAnonymousLogger(null);
+ }
+
+
+ /**
+ * Creates a new, unnamed logger. Unnamed loggers are not
+ * registered in the namespace of the LogManager, and no special
+ * security permission is required for changing their state.
+ * Therefore, untrusted applets are able to modify their private
+ * logger instance obtained through this method.
+ *
+ * <p>The parent of the newly created logger will the the root
+ * logger, from which the level threshold and the handlers are
+ * inherited.
+ *
+ * @param resourceBundleName the name of a resource bundle
+ * for localizing messages, or <code>null</code>
+ * to indicate that messages do not need to be localized.
+ *
+ * @throws java.util.MissingResourceException if
+ * <code>resourceBundleName</code> is not <code>null</code>
+ * and no such bundle could be located.
+ */
+ public static Logger getAnonymousLogger(String resourceBundleName)
+ throws MissingResourceException
+ {
+ Logger result;
+
+ result = new Logger(null, resourceBundleName);
+ result.anonymous = true;
+ return result;
+ }
+
+
+ /**
+ * Returns the name of the resource bundle that is being used for
+ * localizing messages.
+ *
+ * @return the name of the resource bundle used for localizing messages,
+ * or <code>null</code> if the parent's resource bundle
+ * is used for this purpose.
+ */
+ public synchronized String getResourceBundleName()
+ {
+ return resourceBundleName;
+ }
+
+
+ /**
+ * Returns the resource bundle that is being used for localizing
+ * messages.
+ *
+ * @return the resource bundle used for localizing messages,
+ * or <code>null</code> if the parent's resource bundle
+ * is used for this purpose.
+ */
+ public synchronized ResourceBundle getResourceBundle()
+ {
+ return resourceBundle;
+ }
+
+
+ /**
+ * Returns the severity level threshold for this <code>Handler</code>.
+ * All log records with a lower severity level will be discarded;
+ * a log record of the same or a higher level will be published
+ * unless an installed <code>Filter</code> decides to discard it.
+ *
+ * @return the severity level below which all log messages will be
+ * discarded, or <code>null</code> if the logger inherits
+ * the threshold from its parent.
+ */
+ public synchronized Level getLevel()
+ {
+ return level;
+ }
+
+
+ /**
+ * Returns whether or not a message of the specified level
+ * would be logged by this logger.
+ *
+ * @throws NullPointerException if <code>level</code>
+ * is <code>null</code>.
+ */
+ public synchronized boolean isLoggable(Level level)
+ {
+ if (this.level != null)
+ return this.level.intValue() <= level.intValue();
+
+ if (parent != null)
+ return parent.isLoggable(level);
+ else
+ return false;
+ }
+
+
+ /**
+ * Sets the severity level threshold for this <code>Handler</code>.
+ * All log records with a lower severity level will be discarded
+ * immediately. A log record of the same or a higher level will be
+ * published unless an installed <code>Filter</code> decides to
+ * discard it.
+ *
+ * @param level the severity level below which all log messages
+ * will be discarded, or <code>null</code> to
+ * indicate that the logger should inherit the
+ * threshold from its parent.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ */
+ public synchronized void setLevel(Level level)
+ {
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ this.level = level;
+ }
+
+
+ public synchronized Filter getFilter()
+ {
+ return filter;
+ }
+
+
+ /**
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ */
+ public synchronized void setFilter(Filter filter)
+ throws SecurityException
+ {
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ this.filter = filter;
+ }
+
+
+
+
+ /**
+ * Returns the name of this logger.
+ *
+ * @return the name of this logger, or <code>null</code> if
+ * the logger is anonymous.
+ */
+ public String getName()
+ {
+ /* Note that the name of a logger cannot be changed during
+ * its lifetime, so no synchronization is needed.
+ */
+ return name;
+ }
+
+
+ /**
+ * Passes a record to registered handlers, provided the record
+ * is considered as loggable both by {@link #isLoggable(Level)}
+ * and a possibly installed custom {@link #setFilter(Filter) filter}.
+ *
+ * <p>If the logger has been configured to use parent handlers,
+ * the record will be forwarded to the parent of this logger
+ * in addition to being processed by the handlers registered with
+ * this logger.
+ *
+ * <p>The other logging methods in this class are convenience methods
+ * that merely create a new LogRecord and pass it to this method.
+ * Therefore, subclasses usually just need to override this single
+ * method for customizing the logging behavior.
+ *
+ * @param record the log record to be inspected and possibly forwarded.
+ */
+ public synchronized void log(LogRecord record)
+ {
+ if (!isLoggable(record.getLevel()))
+ return;
+
+ if ((filter != null) && !filter.isLoggable(record))
+ return;
+
+ /* If no logger name has been set for the log record,
+ * use the name of this logger.
+ */
+ if (record.getLoggerName() == null)
+ record.setLoggerName(name);
+
+ /* Avoid that some other thread is changing the logger hierarchy
+ * while we are traversing it.
+ */
+ synchronized (LogManager.getLogManager())
+ {
+ Logger curLogger = this;
+
+ do
+ {
+ /* The Sun J2SE 1.4 reference implementation seems to call the
+ * filter only for the logger whose log method is called,
+ * never for any of its parents. Also, parent loggers publish
+ * log record whatever their level might be. This is pretty
+ * weird, but GNU Classpath tries to be as compatible as
+ * possible to the reference implementation.
+ */
+ for (int i = 0; i < curLogger.handlers.length; i++)
+ curLogger.handlers[i].publish(record);
+
+ if (curLogger.getUseParentHandlers() == false)
+ break;
+
+ curLogger = curLogger.getParent();
+ }
+ while (parent != null);
+ }
+ }
+
+
+ public void log(Level level, String message)
+ {
+ log(level, message, (Object[]) null);
+ }
+
+
+ public synchronized void log(Level level,
+ String message,
+ Object param)
+ {
+ StackTraceElement caller = getCallerStackFrame();
+ logp(level,
+ caller != null ? caller.getClassName() : "<unknown>",
+ caller != null ? caller.getMethodName() : "<unknown>",
+ message,
+ param);
+ }
+
+
+ public synchronized void log(Level level,
+ String message,
+ Object[] params)
+ {
+ StackTraceElement caller = getCallerStackFrame();
+ logp(level,
+ caller != null ? caller.getClassName() : "<unknown>",
+ caller != null ? caller.getMethodName() : "<unknown>",
+ message,
+ params);
+ }
+
+
+ public synchronized void log(Level level,
+ String message,
+ Throwable thrown)
+ {
+ StackTraceElement caller = getCallerStackFrame();
+ logp(level,
+ caller != null ? caller.getClassName() : "<unknown>",
+ caller != null ? caller.getMethodName() : "<unknown>",
+ message,
+ thrown);
+ }
+
+
+ public synchronized void logp(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message)
+ {
+ logp(level, sourceClass, sourceMethod, message,
+ (Object[]) null);
+ }
+
+
+ public synchronized void logp(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message,
+ Object param)
+ {
+ logp(level, sourceClass, sourceMethod, message,
+ new Object[] { param });
+ }
+
+
+ private synchronized ResourceBundle findResourceBundle()
+ {
+ if (resourceBundle != null)
+ return resourceBundle;
+
+ if (parent != null)
+ return parent.findResourceBundle();
+
+ return null;
+ }
+
+
+ private synchronized void logImpl(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message,
+ Object[] params)
+ {
+ LogRecord rec = new LogRecord(level, message);
+
+ rec.setResourceBundle(findResourceBundle());
+ rec.setSourceClassName(sourceClass);
+ rec.setSourceMethodName(sourceMethod);
+ rec.setParameters(params);
+
+ log(rec);
+ }
+
+
+ public synchronized void logp(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message,
+ Object[] params)
+ {
+ logImpl(level, sourceClass, sourceMethod, message, params);
+ }
+
+
+ public synchronized void logp(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message,
+ Throwable thrown)
+ {
+ LogRecord rec = new LogRecord(level, message);
+
+ rec.setResourceBundle(resourceBundle);
+ rec.setSourceClassName(sourceClass);
+ rec.setSourceMethodName(sourceMethod);
+ rec.setThrown(thrown);
+
+ log(rec);
+ }
+
+
+ public synchronized void logrb(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String bundleName,
+ String message)
+ {
+ logrb(level, sourceClass, sourceMethod, bundleName,
+ message, (Object[]) null);
+ }
+
+
+ public synchronized void logrb(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String bundleName,
+ String message,
+ Object param)
+ {
+ logrb(level, sourceClass, sourceMethod, bundleName,
+ message, new Object[] { param });
+ }
+
+
+ public synchronized void logrb(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String bundleName,
+ String message,
+ Object[] params)
+ {
+ LogRecord rec = new LogRecord(level, message);
+
+ rec.setResourceBundleName(bundleName);
+ rec.setSourceClassName(sourceClass);
+ rec.setSourceMethodName(sourceMethod);
+ rec.setParameters(params);
+
+ log(rec);
+ }
+
+
+ public synchronized void logrb(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String bundleName,
+ String message,
+ Throwable thrown)
+ {
+ LogRecord rec = new LogRecord(level, message);
+
+ rec.setResourceBundleName(bundleName);
+ rec.setSourceClassName(sourceClass);
+ rec.setSourceMethodName(sourceMethod);
+ rec.setThrown(thrown);
+
+ log(rec);
+ }
+
+
+ public synchronized void entering(String sourceClass,
+ String sourceMethod)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
+ }
+
+
+ public synchronized void entering(String sourceClass,
+ String sourceMethod,
+ Object param)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param);
+ }
+
+
+ public synchronized void entering(String sourceClass,
+ String sourceMethod,
+ Object[] params)
+ {
+ if (isLoggable(Level.FINER))
+ {
+ StringBuffer buf = new StringBuffer(80);
+ buf.append("ENTRY");
+ for (int i = 0; i < params.length; i++)
+ {
+ buf.append(" {");
+ buf.append(i);
+ buf.append('}');
+ }
+
+ logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params);
+ }
+ }
+
+
+ public synchronized void exiting(String sourceClass,
+ String sourceMethod)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
+ }
+
+
+ public synchronized void exiting(String sourceClass,
+ String sourceMethod,
+ Object result)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
+ }
+
+
+ public synchronized void throwing(String sourceClass,
+ String sourceMethod,
+ Throwable thrown)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown);
+ }
+
+
+ /**
+ * Logs a message with severity level SEVERE, indicating a serious
+ * failure that prevents normal program execution. Messages at this
+ * level should be understandable to an inexperienced, non-technical
+ * end user. Ideally, they explain in simple words what actions the
+ * user can take in order to resolve the problem.
+ *
+ * @see Level#SEVERE
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void severe(String message)
+ {
+ if (isLoggable(Level.SEVERE))
+ log(Level.SEVERE, message);
+ }
+
+
+ /**
+ * Logs a message with severity level WARNING, indicating a
+ * potential problem that does not prevent normal program execution.
+ * Messages at this level should be understandable to an
+ * inexperienced, non-technical end user. Ideally, they explain in
+ * simple words what actions the user can take in order to resolve
+ * the problem.
+ *
+ * @see Level#WARNING
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void warning(String message)
+ {
+ if (isLoggable(Level.WARNING))
+ log(Level.WARNING, message);
+ }
+
+
+ /**
+ * Logs a message with severity level INFO. {@link Level#INFO} is
+ * intended for purely informational messages that do not indicate
+ * error or warning situations. In the default logging
+ * configuration, INFO messages will be written to the system
+ * console. For this reason, the INFO level should be used only for
+ * messages that are important to end users and system
+ * administrators. Messages at this level should be understandable
+ * to an inexperienced, non-technical user.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void info(String message)
+ {
+ if (isLoggable(Level.INFO))
+ log(Level.INFO, message);
+ }
+
+
+ /**
+ * Logs a message with severity level CONFIG. {@link Level#CONFIG} is
+ * intended for static configuration messages, for example about the
+ * windowing environment, the operating system version, etc.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource bundle. While
+ * it is possible to pass <code>null</code>, this is not
+ * recommended, since a logging message without text is unlikely
+ * to be helpful.
+ */
+ public synchronized void config(String message)
+ {
+ if (isLoggable(Level.CONFIG))
+ log(Level.CONFIG, message);
+ }
+
+
+ /**
+ * Logs a message with severity level FINE. {@link Level#FINE} is
+ * intended for messages that are relevant for developers using
+ * the component generating log messages. Examples include minor,
+ * recoverable failures, or possible inefficiencies.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void fine(String message)
+ {
+ if (isLoggable(Level.FINE))
+ log(Level.FINE, message);
+ }
+
+
+ /**
+ * Logs a message with severity level FINER. {@link Level#FINER} is
+ * intended for rather detailed tracing, for example entering a
+ * method, returning from a method, or throwing an exception.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void finer(String message)
+ {
+ if (isLoggable(Level.FINER))
+ log(Level.FINER, message);
+ }
+
+
+ /**
+ * Logs a message with severity level FINEST. {@link Level#FINEST}
+ * is intended for highly detailed tracing, for example reaching a
+ * certain point inside the body of a method.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void finest(String message)
+ {
+ if (isLoggable(Level.FINEST))
+ log(Level.FINEST, message);
+ }
+
+
+ /**
+ * Adds a handler to the set of handlers that get notified
+ * when a log record is to be published.
+ *
+ * @param handler the handler to be added.
+ *
+ * @throws NullPointerException if <code>handler</code>
+ * is <code>null</code>.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ */
+ public synchronized void addHandler(Handler handler)
+ throws SecurityException
+ {
+ /* Throw a new NullPointerException if handler is null. */
+ handler.getClass();
+
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ if (!handlerList.contains(handler))
+ {
+ handlerList.add(handler);
+ handlers = getHandlers();
+ }
+ }
+
+
+ /**
+ * Removes a handler from the set of handlers that get notified
+ * when a log record is to be published.
+ *
+ * @param handler the handler to be removed.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted the
+ * permission to control the logging infrastructure by having
+ * LoggingPermission("control"). Untrusted code can obtain an
+ * anonymous logger through the static factory method {@link
+ * #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ *
+ * @throws NullPointerException if <code>handler</code>
+ * is <code>null</code>.
+ */
+ public synchronized void removeHandler(Handler handler)
+ throws SecurityException
+ {
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ /* Throw a new NullPointerException if handler is null. */
+ handler.getClass();
+
+ handlerList.remove(handler);
+ handlers = getHandlers();
+ }
+
+
+ /**
+ * Returns the handlers currently registered for this Logger.
+ * When a log record has been deemed as being loggable,
+ * it will be passed to all registered handlers for
+ * publication. In addition, if the logger uses parent handlers
+ * (see {@link #getUseParentHandlers() getUseParentHandlers}
+ * and {@link #setUseParentHandlers(boolean) setUseParentHandlers},
+ * the log record will be passed to the parent's handlers.
+ */
+ public synchronized Handler[] getHandlers()
+ {
+ /* We cannot return our internal handlers array
+ * because we do not have any guarantee that the
+ * caller would not change the array entries.
+ */
+ return (Handler[]) handlerList.toArray(new Handler[handlerList.size()]);
+ }
+
+
+ /**
+ * Returns whether or not this Logger forwards log records to
+ * handlers registered for its parent loggers.
+ *
+ * @return <code>false</code> if this Logger sends log records
+ * merely to Handlers registered with itself;
+ * <code>true</code> if this Logger sends log records
+ * not only to Handlers registered with itself, but also
+ * to those Handlers registered with parent loggers.
+ */
+ public synchronized boolean getUseParentHandlers()
+ {
+ return useParentHandlers;
+ }
+
+
+ /**
+ * Sets whether or not this Logger forwards log records to
+ * handlers registered for its parent loggers.
+ *
+ * @param useParentHandlers <code>false</code> to let this
+ * Logger send log records merely to Handlers registered
+ * with itself; <code>true</code> to let this Logger
+ * send log records not only to Handlers registered
+ * with itself, but also to those Handlers registered with
+ * parent loggers.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ *
+ */
+ public synchronized void setUseParentHandlers(boolean useParentHandlers)
+ {
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ this.useParentHandlers = useParentHandlers;
+ }
+
+
+ /**
+ * Returns the parent of this logger. By default, the parent is
+ * assigned by the LogManager by inspecting the logger's name.
+ *
+ * @return the parent of this logger (as detemined by the LogManager
+ * by inspecting logger names), the root logger if no other
+ * logger has a name which is a prefix of this logger's name, or
+ * <code>null</code> for the root logger.
+ */
+ public synchronized Logger getParent()
+ {
+ return parent;
+ }
+
+
+ /**
+ * Sets the parent of this logger. Usually, applications do not
+ * call this method directly. Instead, the LogManager will ensure
+ * that the tree of loggers reflects the hierarchical logger
+ * namespace. Basically, this method should not be public at all,
+ * but the GNU implementation follows the API specification.
+ *
+ * @throws NullPointerException if <code>parent</code> is
+ * <code>null</code>.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ */
+ public synchronized void setParent(Logger parent)
+ {
+ LogManager lm;
+
+ /* Throw a new NullPointerException if parent is null. */
+ parent.getClass();
+
+ lm = LogManager.getLogManager();
+
+ if (this == lm.rootLogger)
+ throw new IllegalArgumentException(
+ "only the root logger can have a null parent");
+
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ this.parent = parent;
+ }
+
+ /**
+ * Gets the StackTraceElement of the first class that is not this class.
+ * That should be the initial caller of a logging method.
+ * @return caller of the initial logging method or null if unknown.
+ */
+ private StackTraceElement getCallerStackFrame()
+ {
+ Throwable t = new Throwable();
+ StackTraceElement[] stackTrace = t.getStackTrace();
+ int index = 0;
+
+ // skip to stackentries until this class
+ while(index < stackTrace.length
+ && !stackTrace[index].getClassName().equals(getClass().getName()))
+ index++;
+
+ // skip the stackentries of this class
+ while(index < stackTrace.length
+ && stackTrace[index].getClassName().equals(getClass().getName()))
+ index++;
+
+ return index < stackTrace.length ? stackTrace[index] : null;
+ }
+
+ /**
+ * Reset and close handlers attached to this logger. This function is package
+ * private because it must only be avaiable to the LogManager.
+ */
+ void resetLogger()
+ {
+ for (int i = 0; i < handlers.length; i++)
+ {
+ handlers[i].close();
+ handlerList.remove(handlers[i]);
+ }
+ handlers = getHandlers();
+ }
+}
diff --git a/libjava/classpath/java/util/logging/LoggingPermission.java b/libjava/classpath/java/util/logging/LoggingPermission.java
new file mode 100644
index 00000000000..c7a2255ecea
--- /dev/null
+++ b/libjava/classpath/java/util/logging/LoggingPermission.java
@@ -0,0 +1,73 @@
+/* LoggingPermission.java -- a class for logging permissions.
+ Copyright (C) 2002 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.logging;
+
+public final class LoggingPermission
+ extends java.security.BasicPermission
+{
+ /**
+ * Creates a new LoggingPermission.
+ *
+ * @param name the name of the permission, which must be "control".
+ *
+ * @param actions the list of actions for the permission, which
+ * must be either <code>null</code> or an empty
+ * string.
+ *
+ * @exception IllegalArgumentException if <code>name</code>
+ * is not "control", or <code>actions</code> is
+ * neither <code>null</code> nor empty.
+ */
+ public LoggingPermission(String name, String actions)
+ {
+ super("control", "");
+
+ if (!"control".equals(name))
+ {
+ throw new IllegalArgumentException(
+ "name of LoggingPermission must be \"control\"");
+ }
+
+ if ((actions != null) && (actions.length() != 0))
+ {
+ throw new IllegalArgumentException(
+ "actions of LoggingPermissions must be null or empty");
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/logging/MemoryHandler.java b/libjava/classpath/java/util/logging/MemoryHandler.java
new file mode 100644
index 00000000000..ffa589f1668
--- /dev/null
+++ b/libjava/classpath/java/util/logging/MemoryHandler.java
@@ -0,0 +1,345 @@
+/* MemoryHandler.java -- a class for buffering log messages in a memory buffer
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.logging;
+
+/**
+ * A <code>MemoryHandler</code> maintains a circular buffer of
+ * log records.
+ *
+ * <p><strong>Configuration:</strong> Values of the subsequent
+ * <code>LogManager</code> properties are taken into consideration
+ * when a <code>MemoryHandler</code> is initialized.
+ * If a property is not defined, or if it has an invalid
+ * value, a default is taken without an exception being thrown.
+ *
+ * <ul>
+ * <li><code>java.util.MemoryHandler.level</code> - specifies
+ * the initial severity level threshold. Default value:
+ * <code>Level.ALL</code>.</li>
+ * <li><code>java.util.MemoryHandler.filter</code> - specifies
+ * the name of a Filter class. Default value: No Filter.</li>
+ * <li><code>java.util.MemoryHandler.size</code> - specifies the
+ * maximum number of log records that are kept in the circular
+ * buffer. Default value: 1000.</li>
+ * <li><code>java.util.MemoryHandler.push</code> - specifies the
+ * <code>pushLevel</code>. Default value:
+ * <code>Level.SEVERE</code>.</li>
+ * <li><code>java.util.MemoryHandler.target</code> - specifies the
+ * name of a subclass of {@link Handler} that will be used as the
+ * target handler. There is no default value for this property;
+ * if it is not set, the no-argument MemoryHandler constructor
+ * will throw an exception.</li>
+ * </ul>
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class MemoryHandler
+ extends Handler
+{
+ /**
+ * The storage area used for buffering the unpushed log records in
+ * memory.
+ */
+ private final LogRecord[] buffer;
+
+
+ /**
+ * The current position in the circular buffer. For a new
+ * MemoryHandler, or immediately after {@link #push()} was called,
+ * the value of this variable is zero. Each call to {@link
+ * #publish(LogRecord)} will store the published LogRecord into
+ * <code>buffer[position]</code> before position is incremented by
+ * one. If position becomes greater than the size of the buffer, it
+ * is reset to zero.
+ */
+ private int position;
+
+
+ /**
+ * The number of log records which have been published, but not
+ * pushed yet to the target handler.
+ */
+ private int numPublished;
+
+
+ /**
+ * The push level threshold for this <code>Handler</code>. When a
+ * record is published whose severity level is greater than or equal
+ * to the <code>pushLevel</code> of this <code>MemoryHandler</code>,
+ * the {@link #push()} method will be invoked for pushing the buffer
+ * contents to the target <code>Handler</code>.
+ */
+ private Level pushLevel;
+
+
+ /**
+ * The Handler to which log records are forwarded for actual
+ * publication.
+ */
+ private final Handler target;
+
+
+ /**
+ * Constructs a <code>MemoryHandler</code> for keeping a circular
+ * buffer of LogRecords; the initial configuration is determined by
+ * the <code>LogManager</code> properties described above.
+ */
+ public MemoryHandler()
+ {
+ this((Handler) LogManager.getInstanceProperty(
+ "java.util.logging.MemoryHandler.target",
+ Handler.class, /* default */ null),
+ LogManager.getIntPropertyClamped(
+ "java.util.logging.MemoryHandler.size",
+ /* default */ 1000,
+ /* minimum value */ 1,
+ /* maximum value */ Integer.MAX_VALUE),
+ LogManager.getLevelProperty(
+ "java.util.logging.MemoryHandler.push",
+ /* default push level */ Level.SEVERE));
+ }
+
+
+ /**
+ * Constructs a <code>MemoryHandler</code> for keeping a circular
+ * buffer of LogRecords, given some parameters. The values of the
+ * other parameters are taken from LogManager properties, as
+ * described above.
+ *
+ * @param target the target handler that will receive those
+ * log records that are passed on for publication.
+ *
+ * @param size the number of log records that are kept in the buffer.
+ * The value must be a at least one.
+ *
+ * @param pushLevel the push level threshold for this
+ * <code>MemoryHandler</code>. When a record is published whose
+ * severity level is greater than or equal to
+ * <code>pushLevel</code>, the {@link #push()} method will be
+ * invoked in order to push the bufffer contents to
+ * <code>target</code>.
+ *
+ * @throws java.lang.IllegalArgumentException if <code>size</code>
+ * is negative or zero. The GNU implementation also throws
+ * an IllegalArgumentException if <code>target</code> or
+ * <code>pushLevel</code> are <code>null</code>, but the
+ * API specification does not prescribe what should happen
+ * in those cases.
+ */
+ public MemoryHandler(Handler target, int size, Level pushLevel)
+ {
+ if ((target == null) || (size <= 0) || (pushLevel == null))
+ throw new IllegalArgumentException();
+
+ buffer = new LogRecord[size];
+ this.pushLevel = pushLevel;
+ this.target = target;
+
+ setLevel(LogManager.getLevelProperty(
+ "java.util.logging.MemoryHandler.level",
+ /* default value */ Level.ALL));
+
+ setFilter((Filter) LogManager.getInstanceProperty(
+ "java.util.logging.MemoryHandler.filter",
+ /* must be instance of */ Filter.class,
+ /* default value */ null));
+ }
+
+
+ /**
+ * Stores a <code>LogRecord</code> in a fixed-size circular buffer,
+ * provided the record passes all tests for being loggable. If the
+ * buffer is full, the oldest record will be discarded.
+ *
+ * <p>If the record has a severity level which is greater than or
+ * equal to the <code>pushLevel</code> of this
+ * <code>MemoryHandler</code>, the {@link #push()} method will be
+ * invoked for pushing the buffer contents to the target
+ * <code>Handler</code>.
+ *
+ * <p>Most applications do not need to call this method directly.
+ * Instead, they will use use a {@link Logger}, which will create
+ * LogRecords and distribute them to registered handlers.
+ *
+ * @param record the log event to be published.
+ */
+ public void publish(LogRecord record)
+ {
+ if (!isLoggable(record))
+ return;
+
+ buffer[position] = record;
+ position = (position + 1) % buffer.length;
+ numPublished = numPublished + 1;
+
+ if (record.getLevel().intValue() >= pushLevel.intValue())
+ push();
+ }
+
+
+ /**
+ * Pushes the contents of the memory buffer to the target
+ * <code>Handler</code> and clears the buffer. Note that
+ * the target handler will discard those records that do
+ * not satisfy its own severity level threshold, or that are
+ * not considered loggable by an installed {@link Filter}.
+ *
+ * <p>In case of an I/O failure, the {@link ErrorManager} of the
+ * target <code>Handler</code> will be notified, but the caller of
+ * this method will not receive an exception.
+ */
+ public void push()
+ {
+ int i;
+
+ if (numPublished < buffer.length)
+ {
+ for (i = 0; i < position; i++)
+ target.publish(buffer[i]);
+ }
+ else
+ {
+ for (i = position; i < buffer.length; i++)
+ target.publish(buffer[i]);
+ for (i = 0; i < position; i++)
+ target.publish(buffer[i]);
+ }
+
+ numPublished = 0;
+ position = 0;
+ }
+
+
+ /**
+ * Forces any data that may have been buffered by the target
+ * <code>Handler</code> to the underlying output device, but
+ * does <em>not</em> push the contents of the circular memory
+ * buffer to the target handler.
+ *
+ * <p>In case of an I/O failure, the {@link ErrorManager} of the
+ * target <code>Handler</code> will be notified, but the caller of
+ * this method will not receive an exception.
+ *
+ * @see #push()
+ */
+ public void flush()
+ {
+ target.flush();
+ }
+
+
+ /**
+ * Closes this <code>MemoryHandler</code> and its associated target
+ * handler, discarding the contents of the memory buffer. However,
+ * any data that may have been buffered by the target
+ * <code>Handler</code> is forced to the underlying output device.
+ *
+ * <p>As soon as <code>close</code> has been called,
+ * a <code>Handler</code> should not be used anymore. Attempts
+ * to publish log records, to flush buffers, or to modify the
+ * <code>Handler</code> in any other way may throw runtime
+ * exceptions after calling <code>close</code>.</p>
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code> of
+ * the associated target <code>Handler</code> will be informed, but
+ * the caller of this method will not receive an exception.</p>
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ *
+ * @see #push()
+ */
+ public void close()
+ throws SecurityException
+ {
+ push();
+
+ /* This will check for LoggingPermission("control"). If the
+ * current security context does not grant this permission,
+ * push() has been executed, but this does not impose a
+ * security risk.
+ */
+ target.close();
+ }
+
+
+
+ /**
+ * Returns the push level threshold for this <code>Handler</code>.
+ * When a record is published whose severity level is greater
+ * than or equal to the <code>pushLevel</code> of this
+ * <code>MemoryHandler</code>, the {@link #push()} method will be
+ * invoked for pushing the buffer contents to the target
+ * <code>Handler</code>.
+ *
+ * @return the push level threshold for automatic pushing.
+ */
+ public Level getPushLevel()
+ {
+ return pushLevel;
+ }
+
+
+ /**
+ * Sets the push level threshold for this <code>Handler</code>.
+ * When a record is published whose severity level is greater
+ * than or equal to the <code>pushLevel</code> of this
+ * <code>MemoryHandler</code>, the {@link #push()} method will be
+ * invoked for pushing the buffer contents to the target
+ * <code>Handler</code>.
+ *
+ * @param pushLevel the push level threshold for automatic pushing.
+ *
+ * @exception SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ *
+ * @exception NullPointerException if <code>pushLevel</code> is
+ * <code>null</code>.
+ */
+ public void setPushLevel(Level pushLevel)
+ {
+ LogManager.getLogManager().checkAccess();
+
+ /* Throws a NullPointerException if pushLevel is null. */
+ pushLevel.getClass();
+
+ this.pushLevel = pushLevel;
+ }
+}
diff --git a/libjava/classpath/java/util/logging/SimpleFormatter.java b/libjava/classpath/java/util/logging/SimpleFormatter.java
new file mode 100644
index 00000000000..f7a442792f9
--- /dev/null
+++ b/libjava/classpath/java/util/logging/SimpleFormatter.java
@@ -0,0 +1,119 @@
+/* SimpleFormatter.java --
+ A class for formatting log records into short human-readable messages
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * A <code>SimpleFormatter</code> formats log records into
+ * short human-readable messages, typically one or two lines.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class SimpleFormatter
+ extends Formatter
+{
+ /**
+ * Constructs a SimpleFormatter.
+ */
+ public SimpleFormatter()
+ {
+ }
+
+
+ /**
+ * An instance of a DateFormatter that is used for formatting
+ * the time of a log record into a human-readable string,
+ * according to the rules of the current locale. The value
+ * is set after the first invocation of format, since it is
+ * common that a JVM will instantiate a SimpleFormatter without
+ * ever using it.
+ */
+ private DateFormat dateFormat;
+
+ /**
+ * The character sequence that is used to separate lines in the
+ * generated stream. Somewhat surprisingly, the Sun J2SE 1.4
+ * reference implementation always uses UNIX line endings, even on
+ * platforms that have different line ending conventions (i.e.,
+ * DOS). The GNU implementation does not replicate this bug.
+ *
+ * @see Sun bug parade, bug #4462871,
+ * "java.util.logging.SimpleFormatter uses hard-coded line separator".
+ */
+ static final String lineSep = System.getProperty("line.separator");
+
+
+ /**
+ * Formats a log record into a String.
+ *
+ * @param the log record to be formatted.
+ *
+ * @return a short human-readable message, typically one or two
+ * lines. Lines are separated using the default platform line
+ * separator.
+ *
+ * @throws NullPointerException if <code>record</code>
+ * is <code>null</code>.
+ */
+ public String format(LogRecord record)
+ {
+ StringBuffer buf = new StringBuffer(180);
+
+ if (dateFormat == null)
+ dateFormat = DateFormat.getDateTimeInstance();
+
+ buf.append(dateFormat.format(new Date(record.getMillis())));
+ buf.append(' ');
+ buf.append(record.getSourceClassName());
+ buf.append(' ');
+ buf.append(record.getSourceMethodName());
+ buf.append(lineSep);
+
+ buf.append(record.getLevel());
+ buf.append(": ");
+ buf.append(formatMessage(record));
+
+ buf.append(lineSep);
+
+ return buf.toString();
+ }
+}
diff --git a/libjava/classpath/java/util/logging/SocketHandler.java b/libjava/classpath/java/util/logging/SocketHandler.java
new file mode 100644
index 00000000000..002dfdbbe5e
--- /dev/null
+++ b/libjava/classpath/java/util/logging/SocketHandler.java
@@ -0,0 +1,221 @@
+/* SocketHandler.java -- a class for publishing log messages to network sockets
+ Copyright (C) 2002 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.logging;
+
+
+/**
+ * A <code>SocketHandler</code> publishes log records to
+ * a TCP/IP socket.
+ *
+ * <p><strong>Configuration:</strong> Values of the subsequent
+ * <code>LogManager</code> properties are taken into consideration
+ * when a <code>SocketHandler</code> is initialized.
+ * If a property is not defined, or if it has an invalid
+ * value, a default is taken without an exception being thrown.
+ *
+ * <ul>
+ *
+ * <li><code>java.util.SocketHandler.level</code> - specifies
+ * the initial severity level threshold. Default value:
+ * <code>Level.ALL</code>.</li>
+ *
+ * <li><code>java.util.SocketHandler.filter</code> - specifies
+ * the name of a Filter class. Default value: No Filter.</li>
+ *
+ * <li><code>java.util.SocketHandler.formatter</code> - specifies
+ * the name of a Formatter class. Default value:
+ * <code>java.util.logging.XMLFormatter</code>.</li>
+ *
+ * <li><code>java.util.SocketHandler.encoding</code> - specifies
+ * the name of the character encoding. Default value:
+ * the default platform encoding.</li>
+ *
+ * <li><code>java.util.SocketHandler.host</code> - specifies
+ * the name of the host to which records are published.
+ * There is no default value for this property; if it is
+ * not set, the SocketHandler constructor will throw
+ * an exception.</li>
+ *
+ * <li><code>java.util.SocketHandler.port</code> - specifies
+ * the TCP/IP port to which records are published.
+ * There is no default value for this property; if it is
+ * not set, the SocketHandler constructor will throw
+ * an exception.</li>
+ *
+ * </ul>
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class SocketHandler
+ extends StreamHandler
+{
+ /**
+ * Constructs a <code>SocketHandler</code> that publishes log
+ * records to a TCP/IP socket. Tthe initial configuration is
+ * determined by the <code>LogManager</code> properties described
+ * above.
+ *
+ * @throws java.io.IOException if the connection to the specified
+ * network host and port cannot be established.
+ *
+ * @throws java.lang.IllegalArgumentException if either the
+ * <code>java.util.logging.SocketHandler.host</code>
+ * or <code>java.util.logging.SocketHandler.port</code>
+ * LogManager properties is not defined, or specifies
+ * an invalid value.
+ */
+ public SocketHandler()
+ throws java.io.IOException
+ {
+ this(LogManager.getLogManager().getProperty("java.util.logging.SocketHandler.host"),
+ getPortNumber());
+ }
+
+
+ /**
+ * Constructs a <code>SocketHandler</code> that publishes log
+ * records to a TCP/IP socket. With the exception of the internet
+ * host and port, the initial configuration is determined by the
+ * <code>LogManager</code> properties described above.
+ *
+ * @param host the Internet host to which log records will be
+ * forwarded.
+ *
+ * @param port the port at the host which will accept a request
+ * for a TCP/IP connection.
+ *
+ * @throws java.io.IOException if the connection to the specified
+ * network host and port cannot be established.
+ *
+ * @throws java.lang.IllegalArgumentException if either
+ * <code>host</code> or <code>port</code> specify
+ * an invalid value.
+ */
+ public SocketHandler(String host, int port)
+ throws java.io.IOException
+ {
+ super(createSocket(host, port),
+ "java.util.logging.SocketHandler",
+ /* default level */ Level.ALL,
+ /* formatter */ null,
+ /* default formatter */ XMLFormatter.class);
+ }
+
+
+ /**
+ * Retrieves the port number from the java.util.logging.SocketHandler.port
+ * LogManager property.
+ *
+ * @throws IllegalArgumentException if the property is not defined or
+ * does not specify an integer value.
+ */
+ private static int getPortNumber()
+ {
+ try {
+ return Integer.parseInt(LogManager.getLogManager().getProperty("java.util.logging.SocketHandler.port"));
+ } catch (Exception ex) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+
+ /**
+ * Creates an OutputStream for publishing log records to an Internet
+ * host and port. This private method is a helper for use by the
+ * constructor of SocketHandler.
+ *
+ * @param host the Internet host to which log records will be
+ * forwarded.
+ *
+ * @param port the port at the host which will accept a request
+ * for a TCP/IP connection.
+ *
+ * @throws java.io.IOException if the connection to the specified
+ * network host and port cannot be established.
+ *
+ * @throws java.lang.IllegalArgumentException if either
+ * <code>host</code> or <code>port</code> specify
+ * an invalid value.
+ */
+ private static java.io.OutputStream createSocket(String host, int port)
+ throws java.io.IOException, java.lang.IllegalArgumentException
+ {
+ java.net.Socket socket;
+
+ if ((host == null) || (port < 1))
+ throw new IllegalArgumentException();
+
+ socket = new java.net.Socket(host, port);
+
+ socket.shutdownInput();
+
+ /* The architecture of the logging framework provides replaceable
+ * formatters. Because these formatters perform their task by
+ * returning one single String for each LogRecord to be formatted,
+ * there is no need to buffer.
+ */
+ socket.setTcpNoDelay(true);
+
+ return socket.getOutputStream();
+ }
+
+
+ /**
+ * Publishes a <code>LogRecord</code> to the network socket,
+ * provided the record passes all tests for being loggable.
+ * In addition, all data that may have been buffered will
+ * be forced to the network stream.
+ *
+ * <p>Most applications do not need to call this method directly.
+ * Instead, they will use a {@link Logger} instance, which will
+ * create LogRecords and distribute them to registered handlers.
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>SocketHandler</code> will be informed, but the caller
+ * of this method will not receive an exception.
+ *
+ * @param record the log event to be published.
+ */
+ public void publish(LogRecord record)
+ {
+ super.publish(record);
+ flush();
+ }
+}
+
diff --git a/libjava/classpath/java/util/logging/StreamHandler.java b/libjava/classpath/java/util/logging/StreamHandler.java
new file mode 100644
index 00000000000..5c35c1e481d
--- /dev/null
+++ b/libjava/classpath/java/util/logging/StreamHandler.java
@@ -0,0 +1,521 @@
+/* StreamHandler.java --
+ A class for publishing log messages to instances of java.io.OutputStream
+ Copyright (C) 2002 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.logging;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+
+/**
+ * A <code>StreamHandler</code> publishes <code>LogRecords</code> to
+ * a instances of <code>java.io.OutputStream</code>.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class StreamHandler
+ extends Handler
+{
+ private OutputStream out;
+ private Writer writer;
+
+
+ /**
+ * Indicates the current state of this StreamHandler. The value
+ * should be one of STATE_FRESH, STATE_PUBLISHED, or STATE_CLOSED.
+ */
+ private int streamState = STATE_FRESH;
+
+
+ /**
+ * streamState having this value indicates that the StreamHandler
+ * has been created, but the publish(LogRecord) method has not been
+ * called yet. If the StreamHandler has been constructed without an
+ * OutputStream, writer will be null, otherwise it is set to a
+ * freshly created OutputStreamWriter.
+ */
+ private static final int STATE_FRESH = 0;
+
+
+ /**
+ * streamState having this value indicates that the publish(LocRecord)
+ * method has been called at least once.
+ */
+ private static final int STATE_PUBLISHED = 1;
+
+
+ /**
+ * streamState having this value indicates that the close() method
+ * has been called.
+ */
+ private static final int STATE_CLOSED = 2;
+
+
+ /**
+ * Creates a <code>StreamHandler</code> without an output stream.
+ * Subclasses can later use {@link
+ * #setOutputStream(java.io.OutputStream)} to associate an output
+ * stream with this StreamHandler.
+ */
+ public StreamHandler()
+ {
+ this(null, null);
+ }
+
+
+ /**
+ * Creates a <code>StreamHandler</code> that formats log messages
+ * with the specified Formatter and publishes them to the specified
+ * output stream.
+ *
+ * @param out the output stream to which the formatted log messages
+ * are published.
+ *
+ * @param formatter the <code>Formatter</code> that will be used
+ * to format log messages.
+ */
+ public StreamHandler(OutputStream out, Formatter formatter)
+ {
+ this(out, "java.util.logging.StreamHandler", Level.INFO,
+ formatter, SimpleFormatter.class);
+ }
+
+
+ StreamHandler(
+ OutputStream out,
+ String propertyPrefix,
+ Level defaultLevel,
+ Formatter formatter, Class defaultFormatterClass)
+ {
+ this.level = LogManager.getLevelProperty(propertyPrefix + ".level",
+ defaultLevel);
+
+ this.filter = (Filter) LogManager.getInstanceProperty(
+ propertyPrefix + ".filter",
+ /* must be instance of */ Filter.class,
+ /* default: new instance of */ null);
+
+ if (formatter != null)
+ this.formatter = formatter;
+ else
+ this.formatter = (Formatter) LogManager.getInstanceProperty(
+ propertyPrefix + ".formatter",
+ /* must be instance of */ Formatter.class,
+ /* default: new instance of */ defaultFormatterClass);
+
+ try
+ {
+ String enc = LogManager.getLogManager().getProperty(propertyPrefix
+ + ".encoding");
+
+ /* make sure enc actually is a valid encoding */
+ if ((enc != null) && (enc.length() > 0))
+ new String(new byte[0], enc);
+
+ this.encoding = enc;
+ }
+ catch (Exception _)
+ {
+ }
+
+ if (out != null)
+ {
+ try
+ {
+ changeWriter(out, getEncoding());
+ }
+ catch (UnsupportedEncodingException uex)
+ {
+ /* This should never happen, since the validity of the encoding
+ * name has been checked above.
+ */
+ throw new RuntimeException(uex.getMessage());
+ }
+ }
+ }
+
+
+ private void checkOpen()
+ {
+ if (streamState == STATE_CLOSED)
+ throw new IllegalStateException(this.toString() + " has been closed");
+ }
+
+ private void checkFresh()
+ {
+ checkOpen();
+ if (streamState != STATE_FRESH)
+ throw new IllegalStateException("some log records have been published to " + this);
+ }
+
+
+ private void changeWriter(OutputStream out, String encoding)
+ throws UnsupportedEncodingException
+ {
+ OutputStreamWriter writer;
+
+ /* The logging API says that a null encoding means the default
+ * platform encoding. However, java.io.OutputStreamWriter needs
+ * another constructor for the default platform encoding,
+ * passing null would throw an exception.
+ */
+ if (encoding == null)
+ writer = new OutputStreamWriter(out);
+ else
+ writer = new OutputStreamWriter(out, encoding);
+
+ /* Closing the stream has side effects -- do this only after
+ * creating a new writer has been successful.
+ */
+ if ((streamState != STATE_FRESH) || (this.writer != null))
+ close();
+
+ this.writer = writer;
+ this.out = out;
+ this.encoding = encoding;
+ streamState = STATE_FRESH;
+ }
+
+
+ /**
+ * Sets the character encoding which this handler uses for publishing
+ * log records. The encoding of a <code>StreamHandler</code> must be
+ * set before any log records have been published.
+ *
+ * @param encoding the name of a character encoding, or <code>null</code>
+ * for the default encoding.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control the
+ * the logging infrastructure.
+ *
+ * @exception IllegalStateException if any log records have been
+ * published to this <code>StreamHandler</code> before. Please
+ * be aware that this is a pecularity of the GNU implementation.
+ * While the API specification indicates that it is an error
+ * if the encoding is set after records have been published,
+ * it does not mandate any specific behavior for that case.
+ */
+ public void setEncoding(String encoding)
+ throws SecurityException, UnsupportedEncodingException
+ {
+ /* The inherited implementation first checks whether the invoking
+ * code indeed has the permission to control the logging infra-
+ * structure, and throws a SecurityException if this was not the
+ * case.
+ *
+ * Next, it verifies that the encoding is supported and throws
+ * an UnsupportedEncodingExcpetion otherwise. Finally, it remembers
+ * the name of the encoding.
+ */
+ super.setEncoding(encoding);
+
+ checkFresh();
+
+ /* If out is null, setEncoding is being called before an output
+ * stream has been set. In that case, we need to check that the
+ * encoding is valid, and remember it if this is the case. Since
+ * this is exactly what the inherited implementation of
+ * Handler.setEncoding does, we can delegate.
+ */
+ if (out != null)
+ {
+ /* The logging API says that a null encoding means the default
+ * platform encoding. However, java.io.OutputStreamWriter needs
+ * another constructor for the default platform encoding, passing
+ * null would throw an exception.
+ */
+ if (encoding == null)
+ writer = new OutputStreamWriter(out);
+ else
+ writer = new OutputStreamWriter(out, encoding);
+ }
+ }
+
+
+ /**
+ * Changes the output stream to which this handler publishes
+ * logging records.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ *
+ * @throws NullPointerException if <code>out</code>
+ * is <code>null</code>.
+ */
+ protected void setOutputStream(OutputStream out)
+ throws SecurityException
+ {
+ LogManager.getLogManager().checkAccess();
+
+ /* Throw a NullPointerException if out is null. */
+ out.getClass();
+
+ try
+ {
+ changeWriter(out, getEncoding());
+ }
+ catch (UnsupportedEncodingException ex)
+ {
+ /* This seems quite unlikely to happen, unless the underlying
+ * implementation of java.io.OutputStreamWriter changes its
+ * mind (at runtime) about the set of supported character
+ * encodings.
+ */
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+
+ /**
+ * Publishes a <code>LogRecord</code> to the associated output
+ * stream, provided the record passes all tests for being loggable.
+ * The <code>StreamHandler</code> will localize the message of the
+ * log record and substitute any message parameters.
+ *
+ * <p>Most applications do not need to call this method directly.
+ * Instead, they will use use a {@link Logger}, which will create
+ * LogRecords and distribute them to registered handlers.
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>Handler</code> will be informed, but the caller
+ * of this method will not receive an exception.
+ *
+ * <p>If a log record is being published to a
+ * <code>StreamHandler</code> that has been closed earlier, the Sun
+ * J2SE 1.4 reference can be observed to silently ignore the
+ * call. The GNU implementation, however, intentionally behaves
+ * differently by informing the <code>ErrorManager</code> associated
+ * with this <code>StreamHandler</code>. Since the condition
+ * indicates a programming error, the programmer should be
+ * informed. It also seems extremely unlikely that any application
+ * would depend on the exact behavior in this rather obscure,
+ * erroneous case -- especially since the API specification does not
+ * prescribe what is supposed to happen.
+ *
+ * @param record the log event to be published.
+ */
+ public void publish(LogRecord record)
+ {
+ String formattedMessage;
+
+ if (!isLoggable(record))
+ return;
+
+ if (streamState == STATE_FRESH)
+ {
+ try
+ {
+ writer.write(formatter.getHead(this));
+ }
+ catch (java.io.IOException ex)
+ {
+ reportError(null, ex, ErrorManager.WRITE_FAILURE);
+ return;
+ }
+ catch (Exception ex)
+ {
+ reportError(null, ex, ErrorManager.GENERIC_FAILURE);
+ return;
+ }
+
+ streamState = STATE_PUBLISHED;
+ }
+
+ try
+ {
+ formattedMessage = formatter.format(record);
+ }
+ catch (Exception ex)
+ {
+ reportError(null, ex, ErrorManager.FORMAT_FAILURE);
+ return;
+ }
+
+ try
+ {
+ writer.write(formattedMessage);
+ }
+ catch (Exception ex)
+ {
+ reportError(null, ex, ErrorManager.WRITE_FAILURE);
+ }
+ }
+
+
+ /**
+ * Checks whether or not a <code>LogRecord</code> would be logged
+ * if it was passed to this <code>StreamHandler</code> for publication.
+ *
+ * <p>The <code>StreamHandler</code> implementation first checks
+ * whether a writer is present and the handler's level is greater
+ * than or equal to the severity level threshold. In a second step,
+ * if a {@link Filter} has been installed, its {@link
+ * Filter#isLoggable(LogRecord) isLoggable} method is
+ * invoked. Subclasses of <code>StreamHandler</code> can override
+ * this method to impose their own constraints.
+ *
+ * @param record the <code>LogRecord</code> to be checked.
+ *
+ * @return <code>true</code> if <code>record</code> would
+ * be published by {@link #publish(LogRecord) publish},
+ * <code>false</code> if it would be discarded.
+ *
+ * @see #setLevel(Level)
+ * @see #setFilter(Filter)
+ * @see Filter#isLoggable(LogRecord)
+ *
+ * @throws NullPointerException if <code>record</code> is
+ * <code>null</code>. */
+ public boolean isLoggable(LogRecord record)
+ {
+ return (writer != null) && super.isLoggable(record);
+ }
+
+
+ /**
+ * Forces any data that may have been buffered to the underlying
+ * output device.
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>Handler</code> will be informed, but the caller
+ * of this method will not receive an exception.
+ *
+ * <p>If a <code>StreamHandler</code> that has been closed earlier
+ * is closed a second time, the Sun J2SE 1.4 reference can be
+ * observed to silently ignore the call. The GNU implementation,
+ * however, intentionally behaves differently by informing the
+ * <code>ErrorManager</code> associated with this
+ * <code>StreamHandler</code>. Since the condition indicates a
+ * programming error, the programmer should be informed. It also
+ * seems extremely unlikely that any application would depend on the
+ * exact behavior in this rather obscure, erroneous case --
+ * especially since the API specification does not prescribe what is
+ * supposed to happen.
+ */
+ public void flush()
+ {
+ try
+ {
+ checkOpen();
+ if (writer != null)
+ writer.flush();
+ }
+ catch (Exception ex)
+ {
+ reportError(null, ex, ErrorManager.FLUSH_FAILURE);
+ }
+ }
+
+
+ /**
+ * Closes this <code>StreamHandler</code> after having forced any
+ * data that may have been buffered to the underlying output
+ * device.
+ *
+ * <p>As soon as <code>close</code> has been called,
+ * a <code>Handler</code> should not be used anymore. Attempts
+ * to publish log records, to flush buffers, or to modify the
+ * <code>Handler</code> in any other way may throw runtime
+ * exceptions after calling <code>close</code>.</p>
+ *
+ * <p>In case of an I/O failure, the <code>ErrorManager</code>
+ * of this <code>Handler</code> will be informed, but the caller
+ * of this method will not receive an exception.</p>
+ *
+ * <p>If a <code>StreamHandler</code> that has been closed earlier
+ * is closed a second time, the Sun J2SE 1.4 reference can be
+ * observed to silently ignore the call. The GNU implementation,
+ * however, intentionally behaves differently by informing the
+ * <code>ErrorManager</code> associated with this
+ * <code>StreamHandler</code>. Since the condition indicates a
+ * programming error, the programmer should be informed. It also
+ * seems extremely unlikely that any application would depend on the
+ * exact behavior in this rather obscure, erroneous case --
+ * especially since the API specification does not prescribe what is
+ * supposed to happen.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ */
+ public void close()
+ throws SecurityException
+ {
+ LogManager.getLogManager().checkAccess();
+
+ try
+ {
+ /* Although flush also calls checkOpen, it catches
+ * any exceptions and reports them to the ErrorManager
+ * as flush failures. However, we want to report
+ * a closed stream as a close failure, not as a
+ * flush failure here. Therefore, we call checkOpen()
+ * before flush().
+ */
+ checkOpen();
+ flush();
+
+ if (writer != null)
+ {
+ if (formatter != null)
+ {
+ /* Even if the StreamHandler has never published a record,
+ * it emits head and tail upon closing. An earlier version
+ * of the GNU Classpath implementation did not emitted
+ * anything. However, this had caused XML log files to be
+ * entirely empty instead of containing no log records.
+ */
+ if (streamState == STATE_FRESH)
+ writer.write(formatter.getHead(this));
+ if (streamState != STATE_CLOSED)
+ writer.write(formatter.getTail(this));
+ }
+ streamState = STATE_CLOSED;
+ writer.close();
+ }
+ }
+ catch (Exception ex)
+ {
+ reportError(null, ex, ErrorManager.CLOSE_FAILURE);
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/logging/XMLFormatter.java b/libjava/classpath/java/util/logging/XMLFormatter.java
new file mode 100644
index 00000000000..4dd63281727
--- /dev/null
+++ b/libjava/classpath/java/util/logging/XMLFormatter.java
@@ -0,0 +1,387 @@
+/* XMLFormatter.java --
+ A class for formatting log messages into a standard XML format
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.ResourceBundle;
+
+/**
+ * An <code>XMLFormatter</code> formats LogRecords into
+ * a standard XML format.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class XMLFormatter
+ extends Formatter
+{
+ /**
+ * Constructs a new XMLFormatter.
+ */
+ public XMLFormatter()
+ {
+ }
+
+
+ /**
+ * The character sequence that is used to separate lines in the
+ * generated XML stream. Somewhat surprisingly, the Sun J2SE 1.4
+ * reference implementation always uses UNIX line endings, even on
+ * platforms that have different line ending conventions (i.e.,
+ * DOS). The GNU Classpath implementation does not replicates this
+ * bug.
+ *
+ * See also the Sun bug parade, bug #4462871,
+ * "java.util.logging.SimpleFormatter uses hard-coded line separator".
+ */
+ private static final String lineSep = SimpleFormatter.lineSep;
+
+
+ /**
+ * A DateFormat for emitting time in the ISO 8601 format.
+ * Since the API specification of SimpleDateFormat does not talk
+ * about its thread-safety, we cannot share a singleton instance.
+ */
+ private final SimpleDateFormat iso8601
+ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+
+
+ /**
+ * Appends a line consisting of indentation, opening element tag,
+ * element content, closing element tag and line separator to
+ * a StringBuffer, provided that the element content is
+ * actually existing.
+ *
+ * @param buf the StringBuffer to which the line will be appended.
+ *
+ * @param indent the indentation level.
+ *
+ * @param tag the element tag name, for instance <code>method</code>.
+ *
+ * @param content the element content, or <code>null</code> to
+ * have no output whatsoever appended to <code>buf</code>.
+ */
+ private static void appendTag(StringBuffer buf, int indent,
+ String tag, String content)
+ {
+ int i;
+
+ if (content == null)
+ return;
+
+ for (i = 0; i < indent * 2; i++)
+ buf.append(' ');
+
+ buf.append("<");
+ buf.append(tag);
+ buf.append('>');
+
+ /* Append the content, but escape for XML by replacing
+ * '&', '<', '>' and all non-ASCII characters with
+ * appropriate escape sequences.
+ * The Sun J2SE 1.4 reference implementation does not
+ * escape non-ASCII characters. This is a bug in their
+ * implementation which has been reported in the Java
+ * bug parade as bug number (FIXME: Insert number here).
+ */
+ for (i = 0; i < content.length(); i++)
+ {
+ char c = content.charAt(i);
+ switch (c)
+ {
+ case '&':
+ buf.append("&amp;");
+ break;
+
+ case '<':
+ buf.append("&lt;");
+ break;
+
+ case '>':
+ buf.append("&gt;");
+ break;
+
+ default:
+ if (((c >= 0x20) && (c <= 0x7e))
+ || (c == /* line feed */ 10)
+ || (c == /* carriage return */ 13))
+ buf.append(c);
+ else
+ {
+ buf.append("&#");
+ buf.append((int) c);
+ buf.append(';');
+ }
+ break;
+ } /* switch (c) */
+ } /* for i */
+
+ buf.append("</");
+ buf.append(tag);
+ buf.append(">");
+ buf.append(lineSep);
+ }
+
+
+ /**
+ * Appends a line consisting of indentation, opening element tag,
+ * numeric element content, closing element tag and line separator
+ * to a StringBuffer.
+ *
+ * @param buf the StringBuffer to which the line will be appended.
+ *
+ * @param indent the indentation level.
+ *
+ * @param tag the element tag name, for instance <code>method</code>.
+ *
+ * @param content the element content.
+ */
+ private static void appendTag(StringBuffer buf, int indent,
+ String tag, long content)
+ {
+ appendTag(buf, indent, tag, Long.toString(content));
+ }
+
+
+ public String format(LogRecord record)
+ {
+ StringBuffer buf = new StringBuffer(400);
+ Level level = record.getLevel();
+ long millis = record.getMillis();
+ Object[] params = record.getParameters();
+ ResourceBundle bundle = record.getResourceBundle();
+ String message;
+
+ buf.append("<record>");
+ buf.append(lineSep);
+
+
+ appendTag(buf, 1, "date", iso8601.format(new Date(millis)));
+ appendTag(buf, 1, "millis", record.getMillis());
+ appendTag(buf, 1, "sequence", record.getSequenceNumber());
+ appendTag(buf, 1, "logger", record.getLoggerName());
+
+ if (level.isStandardLevel())
+ appendTag(buf, 1, "level", level.toString());
+ else
+ appendTag(buf, 1, "level", level.intValue());
+
+ appendTag(buf, 1, "class", record.getSourceClassName());
+ appendTag(buf, 1, "method", record.getSourceMethodName());
+ appendTag(buf, 1, "thread", record.getThreadID());
+
+ /* The Sun J2SE 1.4 reference implementation does not emit the
+ * message in localized form. This is in violation of the API
+ * specification. The GNU Classpath implementation intentionally
+ * replicates the buggy behavior of the Sun implementation, as
+ * different log files might be a big nuisance to users.
+ */
+ try
+ {
+ record.setResourceBundle(null);
+ message = formatMessage(record);
+ }
+ finally
+ {
+ record.setResourceBundle(bundle);
+ }
+ appendTag(buf, 1, "message", message);
+
+ /* The Sun J2SE 1.4 reference implementation does not
+ * emit key, catalog and param tags. This is in violation
+ * of the API specification. The Classpath implementation
+ * intentionally replicates the buggy behavior of the
+ * Sun implementation, as different log files might be
+ * a big nuisance to users.
+ *
+ * FIXME: File a bug report with Sun. Insert bug number here.
+ *
+ *
+ * key = record.getMessage();
+ * if (key == null)
+ * key = "";
+ *
+ * if ((bundle != null) && !key.equals(message))
+ * {
+ * appendTag(buf, 1, "key", key);
+ * appendTag(buf, 1, "catalog", record.getResourceBundleName());
+ * }
+ *
+ * if (params != null)
+ * {
+ * for (int i = 0; i < params.length; i++)
+ * appendTag(buf, 1, "param", params[i].toString());
+ * }
+ */
+
+ /* FIXME: We have no way to obtain the stacktrace before free JVMs
+ * support the corresponding method in java.lang.Throwable. Well,
+ * it would be possible to parse the output of printStackTrace,
+ * but this would be pretty kludgy. Instead, we postpose the
+ * implementation until Throwable has made progress.
+ */
+ Throwable thrown = record.getThrown();
+ if (thrown != null)
+ {
+ buf.append(" <exception>");
+ buf.append(lineSep);
+
+ /* The API specification is not clear about what exactly
+ * goes into the XML record for a thrown exception: It
+ * could be the result of getMessage(), getLocalizedMessage(),
+ * or toString(). Therefore, it was necessary to write a
+ * Mauve testlet and run it with the Sun J2SE 1.4 reference
+ * implementation. It turned out that the we need to call
+ * toString().
+ *
+ * FIXME: File a bug report with Sun, asking for clearer
+ * specs.
+ */
+ appendTag(buf, 2, "message", thrown.toString());
+
+ /* FIXME: The Logging DTD specifies:
+ *
+ * <!ELEMENT exception (message?, frame+)>
+ *
+ * However, java.lang.Throwable.getStackTrace() is
+ * allowed to return an empty array. So, what frame should
+ * be emitted for an empty stack trace? We probably
+ * should file a bug report with Sun, asking for the DTD
+ * to be changed.
+ */
+
+ buf.append(" </exception>");
+ buf.append(lineSep);
+ }
+
+
+ buf.append("</record>");
+ buf.append(lineSep);
+
+ return buf.toString();
+ }
+
+
+ /**
+ * Returns a string that handlers are supposed to emit before
+ * the first log record. The base implementation returns an
+ * empty string, but subclasses such as {@link XMLFormatter}
+ * override this method in order to provide a suitable header.
+ *
+ * @return a string for the header.
+ *
+ * @param handler the handler which will prepend the returned
+ * string in front of the first log record. This method
+ * will inspect certain properties of the handler, for
+ * example its encoding, in order to construct the header.
+ */
+ public String getHead(Handler h)
+ {
+ StringBuffer buf;
+ String encoding;
+
+ buf = new StringBuffer(80);
+ buf.append("<?xml version=\"1.0\" encoding=\"");
+
+ encoding = h.getEncoding();
+
+ /* file.encoding is a system property with the Sun JVM, indicating
+ * the platform-default file encoding. Unfortunately, the API
+ * specification for java.lang.System.getProperties() does not
+ * list this property.
+ */
+ if (encoding == null)
+ encoding = System.getProperty("file.encoding");
+
+ /* Since file.encoding is not listed with the API specification of
+ * java.lang.System.getProperties(), there might be some VMs that
+ * do not define this system property. Therefore, we use UTF-8 as
+ * a reasonable default. Please note that if the platform encoding
+ * uses the same codepoints as US-ASCII for the US-ASCII character
+ * set (e.g, 65 for A), it does not matter whether we emit the
+ * wrong encoding into the XML header -- the GNU Classpath will
+ * emit XML escape sequences like &#1234; for any non-ASCII
+ * character. Virtually all character encodings use the same code
+ * points as US-ASCII for ASCII characters. Probably, EBCDIC is
+ * the only exception.
+ */
+ if (encoding == null)
+ encoding = "UTF-8";
+
+ /* On Windows XP localized for Swiss German (this is one of
+ * my [Sascha Brawer's] test machines), the default encoding
+ * has the canonical name "windows-1252". The "historical" name
+ * of this encoding is "Cp1252" (see the Javadoc for the class
+ * java.nio.charset.Charset for the distinction). Now, that class
+ * does have a method for mapping historical to canonical encoding
+ * names. However, if we used it here, we would be come dependent
+ * on java.nio.*, which was only introduced with J2SE 1.4.
+ * Thus, we do this little hack here. As soon as Classpath supports
+ * java.nio.charset.CharSet, this hack should be replaced by
+ * code that correctly canonicalizes the encoding name.
+ */
+ if ((encoding.length() > 2) && encoding.startsWith("Cp"))
+ encoding = "windows-" + encoding.substring(2);
+
+ buf.append(encoding);
+
+ buf.append("\" standalone=\"no\"?>");
+ buf.append(lineSep);
+
+ /* SYSTEM is not a fully qualified URL so that validating
+ * XML parsers do not need to connect to the Internet in
+ * order to read in a log file. See also the Sun Bug Parade,
+ * bug #4372790, "Logging APIs: need to use relative URL for XML
+ * doctype".
+ */
+ buf.append("<!DOCTYPE log SYSTEM \"logger.dtd\">");
+ buf.append(lineSep);
+ buf.append("<log>");
+ buf.append(lineSep);
+
+ return buf.toString();
+ }
+
+
+ public String getTail(Handler h)
+ {
+ return "</log>" + lineSep;
+ }
+}
diff --git a/libjava/classpath/java/util/logging/package.html b/libjava/classpath/java/util/logging/package.html
new file mode 100644
index 00000000000..31f0494fcd7
--- /dev/null
+++ b/libjava/classpath/java/util/logging/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.util.logging package.
+ Copyright (C) 2002 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 - java.util.logging</title></head>
+
+<body>
+<p>Utility classes for logging events.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/util/package.html b/libjava/classpath/java/util/package.html
new file mode 100644
index 00000000000..ff2919c550c
--- /dev/null
+++ b/libjava/classpath/java/util/package.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.util package.
+ Copyright (C) 2002 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 - java.util</title></head>
+
+<body>
+<p>Utility classes such as collections (maps, sets, lists, dictionaries and
+stacks), calendars, dates, locales, properties, timers, resource bundles and
+event objects.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/util/prefs/AbstractPreferences.java b/libjava/classpath/java/util/prefs/AbstractPreferences.java
new file mode 100644
index 00000000000..3f70400f5d1
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/AbstractPreferences.java
@@ -0,0 +1,1272 @@
+/* AbstractPreferences -- Partial implementation of a Preference node
+ Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.prefs;
+
+import gnu.java.util.prefs.NodeWriter;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+/**
+ * Partial implementation of a Preference node.
+ *
+ * @since 1.4
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public abstract class AbstractPreferences extends Preferences {
+
+ // protected fields
+
+ /**
+ * Object used to lock this preference node. Any thread only locks nodes
+ * downwards when it has the lock on the current node. No method should
+ * synchronize on the lock of any of its parent nodes while holding the
+ * lock on the current node.
+ */
+ protected final Object lock = new Object();
+
+ /**
+ * Set to true in the contructor if the node did not exist in the backing
+ * store when this preference node object was created. Should be set in
+ * the contructor of a subclass. Defaults to false. Used to fire node
+ * changed events.
+ */
+ protected boolean newNode = false;
+
+ // private fields
+
+ /**
+ * The parent preferences node or null when this is the root node.
+ */
+ private final AbstractPreferences parent;
+
+ /**
+ * The name of this node.
+ * Only when this is a root node (parent == null) the name is empty.
+ * It has a maximum of 80 characters and cannot contain any '/' characters.
+ */
+ private final String name;
+
+ /** True when this node has been remove, false otherwise. */
+ private boolean removed = false;
+
+ /**
+ * Holds all the child names and nodes of this node that have been
+ * accessed by earlier <code>getChild()</code> or <code>childSpi()</code>
+ * invocations and that have not been removed.
+ */
+ private HashMap childCache = new HashMap();
+
+ // constructor
+
+ /**
+ * Creates a new AbstractPreferences node with the given parent and name.
+ *
+ * @param parent the parent of this node or null when this is the root node
+ * @param name the name of this node, can not be null, only 80 characters
+ * maximum, must be empty when parent is null and cannot
+ * contain any '/' characters
+ * @exception IllegalArgumentException when name is null, greater then 80
+ * characters, not the empty string but parent is null or
+ * contains a '/' character
+ */
+ protected AbstractPreferences(AbstractPreferences parent, String name) {
+ if ( (name == null) // name should be given
+ || (name.length() > MAX_NAME_LENGTH) // 80 characters max
+ || (parent == null && name.length() != 0) // root has no name
+ || (parent != null && name.length() == 0) // all other nodes do
+ || (name.indexOf('/') != -1)) // must not contain '/'
+ throw new IllegalArgumentException("Illegal name argument '"
+ + name
+ + "' (parent is "
+ + (parent == null ? "" : "not ")
+ + "null)");
+ this.parent = parent;
+ this.name = name;
+ }
+
+ // identification methods
+
+ /**
+ * Returns the absolute path name of this preference node.
+ * The absolute path name of a node is the path name of its parent node
+ * plus a '/' plus its own name. If the node is the root node and has no
+ * parent then its path name is "" and its absolute path name is "/".
+ */
+ public String absolutePath() {
+ if (parent == null)
+ return "/";
+ else
+ return parent.path() + '/' + name;
+ }
+
+ /**
+ * Private helper method for absolutePath. Returns the empty string for a
+ * root node and otherwise the parentPath of its parent plus a '/'.
+ */
+ private String path() {
+ if (parent == null)
+ return "";
+ else
+ return parent.path() + '/' + name;
+ }
+
+ /**
+ * Returns true if this node comes from the user preferences tree, false
+ * if it comes from the system preferences tree.
+ */
+ public boolean isUserNode() {
+ AbstractPreferences root = this;
+ while (root.parent != null)
+ root = root.parent;
+ return root == Preferences.userRoot();
+ }
+
+ /**
+ * Returns the name of this preferences node. The name of the node cannot
+ * be null, can be mostly 80 characters and cannot contain any '/'
+ * characters. The root node has as name "".
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the String given by
+ * <code>
+ * (isUserNode() ? "User":"System") + " Preference Node: " + absolutePath()
+ * </code>
+ */
+ public String toString() {
+ return (isUserNode() ? "User":"System")
+ + " Preference Node: "
+ + absolutePath();
+ }
+
+ /**
+ * Returns all known unremoved children of this node.
+ *
+ * @return All known unremoved children of this node
+ */
+ protected final AbstractPreferences[] cachedChildren()
+ {
+ return (AbstractPreferences[]) childCache.values().toArray();
+ }
+
+ /**
+ * Returns all the direct sub nodes of this preferences node.
+ * Needs access to the backing store to give a meaningfull answer.
+ * <p>
+ * This implementation locks this node, checks if the node has not yet
+ * been removed and throws an <code>IllegalStateException</code> when it
+ * has been. Then it creates a new <code>TreeSet</code> and adds any
+ * already cached child nodes names. To get any uncached names it calls
+ * <code>childrenNamesSpi()</code> and adds the result to the set. Finally
+ * it calls <code>toArray()</code> on the created set. When the call to
+ * <code>childrenNamesSpi</code> thows an <code>BackingStoreException</code>
+ * this method will not catch that exception but propagate the exception
+ * to the caller.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException when this node has been removed
+ */
+ public String[] childrenNames() throws BackingStoreException {
+ synchronized(lock) {
+ if (isRemoved())
+ throw new IllegalStateException("Node removed");
+
+ TreeSet childrenNames = new TreeSet();
+
+ // First get all cached node names
+ childrenNames.addAll(childCache.keySet());
+
+ // Then add any others
+ String names[] = childrenNamesSpi();
+ for (int i = 0; i < names.length; i++) {
+ childrenNames.add(names[i]);
+ }
+
+ // And return the array of names
+ String[] children = new String[childrenNames.size()];
+ childrenNames.toArray(children);
+ return children;
+
+ }
+ }
+
+ /**
+ * Returns a sub node of this preferences node if the given path is
+ * relative (does not start with a '/') or a sub node of the root
+ * if the path is absolute (does start with a '/').
+ * <p>
+ * This method first locks this node and checks if the node has not been
+ * removed, if it has been removed it throws an exception. Then if the
+ * path is relative (does not start with a '/') it checks if the path is
+ * legal (does not end with a '/' and has no consecutive '/' characters).
+ * Then it recursively gets a name from the path, gets the child node
+ * from the child-cache of this node or calls the <code>childSpi()</code>
+ * method to create a new child sub node. This is done recursively on the
+ * newly created sub node with the rest of the path till the path is empty.
+ * If the path is absolute (starts with a '/') the lock on this node is
+ * droped and this method is called on the root of the preferences tree
+ * with as argument the complete path minus the first '/'.
+ *
+ * @exception IllegalStateException if this node has been removed
+ * @exception IllegalArgumentException if the path contains two or more
+ * consecutive '/' characters, ends with a '/' charactor and is not the
+ * string "/" (indicating the root node) or any name on the path is more
+ * then 80 characters long
+ */
+ public Preferences node(String path) {
+ synchronized(lock) {
+ if (isRemoved())
+ throw new IllegalStateException("Node removed");
+
+ // Is it a relative path?
+ if (!path.startsWith("/")) {
+
+ // Check if it is a valid path
+ if (path.indexOf("//") != -1 || path.endsWith("/"))
+ throw new IllegalArgumentException(path);
+
+ return getNode(path);
+ }
+ }
+
+ // path started with a '/' so it is absolute
+ // we drop the lock and start from the root (omitting the first '/')
+ Preferences root = isUserNode() ? userRoot() : systemRoot();
+ return root.node(path.substring(1));
+
+ }
+
+ /**
+ * Private helper method for <code>node()</code>. Called with this node
+ * locked. Returns this node when path is the empty string, if it is not
+ * empty the next node name is taken from the path (all chars till the
+ * next '/' or end of path string) and the node is either taken from the
+ * child-cache of this node or the <code>childSpi()</code> method is called
+ * on this node with the name as argument. Then this method is called
+ * recursively on the just constructed child node with the rest of the
+ * path.
+ *
+ * @param path should not end with a '/' character and should not contain
+ * consecutive '/' characters
+ * @exception IllegalArgumentException if path begins with a name that is
+ * larger then 80 characters.
+ */
+ private Preferences getNode(String path) {
+ // if mark is dom then goto end
+
+ // Empty String "" indicates this node
+ if (path.length() == 0)
+ return this;
+
+ // Calculate child name and rest of path
+ String childName;
+ String childPath;
+ int nextSlash = path.indexOf('/');
+ if (nextSlash == -1) {
+ childName = path;
+ childPath = "";
+ } else {
+ childName = path.substring(0, nextSlash);
+ childPath = path.substring(nextSlash+1);
+ }
+
+ // Get the child node
+ AbstractPreferences child;
+ child = (AbstractPreferences)childCache.get(childName);
+ if (child == null) {
+
+ if (childName.length() > MAX_NAME_LENGTH)
+ throw new IllegalArgumentException(childName);
+
+ // Not in childCache yet so create a new sub node
+ child = childSpi(childName);
+ // XXX - check if node is new
+ childCache.put(childName, child);
+ }
+
+ // Lock the child and go down
+ synchronized(child.lock) {
+ return child.getNode(childPath);
+ }
+ }
+
+ /**
+ * Returns true if the node that the path points to exists in memory or
+ * in the backing store. Otherwise it returns false or an exception is
+ * thrown. When this node is removed the only valid parameter is the
+ * empty string (indicating this node), the return value in that case
+ * will be false.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ * and the path is not the empty string (indicating this node)
+ * @exception IllegalArgumentException if the path contains two or more
+ * consecutive '/' characters, ends with a '/' charactor and is not the
+ * string "/" (indicating the root node) or any name on the path is more
+ * then 80 characters long
+ */
+ public boolean nodeExists(String path) throws BackingStoreException {
+ synchronized(lock) {
+ if (isRemoved() && path.length() != 0)
+ throw new IllegalStateException("Node removed");
+
+ // Is it a relative path?
+ if (!path.startsWith("/")) {
+
+ // Check if it is a valid path
+ if (path.indexOf("//") != -1 || path.endsWith("/"))
+ throw new IllegalArgumentException(path);
+
+ return existsNode(path);
+ }
+ }
+
+ // path started with a '/' so it is absolute
+ // we drop the lock and start from the root (omitting the first '/')
+ Preferences root = isUserNode() ? userRoot() : systemRoot();
+ return root.nodeExists(path.substring(1));
+
+ }
+
+ private boolean existsNode(String path) throws BackingStoreException {
+
+ // Empty String "" indicates this node
+ if (path.length() == 0)
+ return(!isRemoved());
+
+ // Calculate child name and rest of path
+ String childName;
+ String childPath;
+ int nextSlash = path.indexOf('/');
+ if (nextSlash == -1) {
+ childName = path;
+ childPath = "";
+ } else {
+ childName = path.substring(0, nextSlash);
+ childPath = path.substring(nextSlash+1);
+ }
+
+ // Get the child node
+ AbstractPreferences child;
+ child = (AbstractPreferences)childCache.get(childName);
+ if (child == null) {
+
+ if (childName.length() > MAX_NAME_LENGTH)
+ throw new IllegalArgumentException(childName);
+
+ // Not in childCache yet so create a new sub node
+ child = getChild(childName);
+
+ if (child == null)
+ return false;
+
+ childCache.put(childName, child);
+ }
+
+ // Lock the child and go down
+ synchronized(child.lock) {
+ return child.existsNode(childPath);
+ }
+ }
+
+ /**
+ * Returns the child sub node if it exists in the backing store or null
+ * if it does not exist. Called (indirectly) by <code>nodeExists()</code>
+ * when a child node name can not be found in the cache.
+ * <p>
+ * Gets the lock on this node, calls <code>childrenNamesSpi()</code> to
+ * get an array of all (possibly uncached) children and compares the
+ * given name with the names in the array. If the name is found in the
+ * array <code>childSpi()</code> is called to get an instance, otherwise
+ * null is returned.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ */
+ protected AbstractPreferences getChild(String name)
+ throws BackingStoreException
+ {
+ synchronized(lock) {
+ // Get all the names (not yet in the cache)
+ String[] names = childrenNamesSpi();
+ for (int i=0; i < names.length; i++)
+ if (name.equals(names[i]))
+ return childSpi(name);
+
+ // No child with that name found
+ return null;
+ }
+ }
+
+ /**
+ * Returns true if this node has been removed with the
+ * <code>removeNode()</code> method, false otherwise.
+ * <p>
+ * Gets the lock on this node and then returns a boolean field set by
+ * <code>removeNode</code> methods.
+ */
+ protected boolean isRemoved() {
+ synchronized(lock) {
+ return removed;
+ }
+ }
+
+ /**
+ * Returns the parent preferences node of this node or null if this is
+ * the root of the preferences tree.
+ * <p>
+ * Gets the lock on this node, checks that the node has not been removed
+ * and returns the parent given to the constructor.
+ *
+ * @exception IllegalStateException if this node has been removed
+ */
+ public Preferences parent() {
+ synchronized(lock) {
+ if (isRemoved())
+ throw new IllegalStateException("Node removed");
+
+ return parent;
+ }
+ }
+
+ // export methods
+
+ /**
+ * XXX
+ */
+ public void exportNode(OutputStream os)
+ throws BackingStoreException,
+ IOException
+ {
+ NodeWriter nodeWriter = new NodeWriter(this, os);
+ nodeWriter.writePrefs();
+ }
+
+ /**
+ * XXX
+ */
+ public void exportSubtree(OutputStream os)
+ throws BackingStoreException,
+ IOException
+ {
+ NodeWriter nodeWriter = new NodeWriter(this, os);
+ nodeWriter.writePrefsTree();
+ }
+
+ // preference entry manipulation methods
+
+ /**
+ * Returns an (possibly empty) array with all the keys of the preference
+ * entries of this node.
+ * <p>
+ * This method locks this node and checks if the node has not been
+ * removed, if it has been removed it throws an exception, then it returns
+ * the result of calling <code>keysSpi()</code>.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ */
+ public String[] keys() throws BackingStoreException {
+ synchronized(lock) {
+ if (isRemoved())
+ throw new IllegalStateException("Node removed");
+
+ return keysSpi();
+ }
+ }
+
+
+ /**
+ * Returns the value associated with the key in this preferences node. If
+ * the default value of the key cannot be found in the preferences node
+ * entries or something goes wrong with the backing store the supplied
+ * default value is returned.
+ * <p>
+ * Checks that key is not null and not larger then 80 characters,
+ * locks this node, and checks that the node has not been removed.
+ * Then it calls <code>keySpi()</code> and returns
+ * the result of that method or the given default value if it returned
+ * null or throwed an exception.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public String get(String key, String defaultVal) {
+ if (key.length() > MAX_KEY_LENGTH)
+ throw new IllegalArgumentException(key);
+
+ synchronized(lock) {
+ if (isRemoved())
+ throw new IllegalStateException("Node removed");
+
+ String value;
+ try {
+ value = getSpi(key);
+ } catch (ThreadDeath death) {
+ throw death;
+ } catch (Throwable t) {
+ value = null;
+ }
+
+ if (value != null) {
+ return value;
+ } else {
+ return defaultVal;
+ }
+ }
+ }
+
+ /**
+ * Convenience method for getting the given entry as a boolean.
+ * When the string representation of the requested entry is either
+ * "true" or "false" (ignoring case) then that value is returned,
+ * otherwise the given default boolean value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public boolean getBoolean(String key, boolean defaultVal) {
+ String value = get(key, null);
+
+ if ("true".equalsIgnoreCase(value))
+ return true;
+
+ if ("false".equalsIgnoreCase(value))
+ return false;
+
+ return defaultVal;
+ }
+
+ /**
+ * Convenience method for getting the given entry as a byte array.
+ * When the string representation of the requested entry is a valid
+ * Base64 encoded string (without any other characters, such as newlines)
+ * then the decoded Base64 string is returned as byte array,
+ * otherwise the given default byte array value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public byte[] getByteArray(String key, byte[] defaultVal) {
+ String value = get(key, null);
+
+ byte[] b = null;
+ if (value != null) {
+ b = decode64(value);
+ }
+
+ if (b != null)
+ return b;
+ else
+ return defaultVal;
+ }
+
+ /**
+ * Helper method for decoding a Base64 string as an byte array.
+ * Returns null on encoding error. This method does not allow any other
+ * characters present in the string then the 65 special base64 chars.
+ */
+ private static byte[] decode64(String s) {
+ ByteArrayOutputStream bs = new ByteArrayOutputStream((s.length()/4)*3);
+ char[] c = new char[s.length()];
+ s.getChars(0, s.length(), c, 0);
+
+ // Convert from base64 chars
+ int endchar = -1;
+ for(int j = 0; j < c.length && endchar == -1; j++) {
+ if (c[j] >= 'A' && c[j] <= 'Z') {
+ c[j] -= 'A';
+ } else if (c[j] >= 'a' && c[j] <= 'z') {
+ c[j] = (char) (c[j] + 26 - 'a');
+ } else if (c[j] >= '0' && c[j] <= '9') {
+ c[j] = (char) (c[j] + 52 - '0');
+ } else if (c[j] == '+') {
+ c[j] = 62;
+ } else if (c[j] == '/') {
+ c[j] = 63;
+ } else if (c[j] == '=') {
+ endchar = j;
+ } else {
+ return null; // encoding exception
+ }
+ }
+
+ int remaining = endchar == -1 ? c.length : endchar;
+ int i = 0;
+ while (remaining > 0) {
+ // Four input chars (6 bits) are decoded as three bytes as
+ // 000000 001111 111122 222222
+
+ byte b0 = (byte) (c[i] << 2);
+ if (remaining >= 2) {
+ b0 += (c[i+1] & 0x30) >> 4;
+ }
+ bs.write(b0);
+
+ if (remaining >= 3) {
+ byte b1 = (byte) ((c[i+1] & 0x0F) << 4);
+ b1 += (byte) ((c[i+2] & 0x3C) >> 2);
+ bs.write(b1);
+ }
+
+ if (remaining >= 4) {
+ byte b2 = (byte) ((c[i+2] & 0x03) << 6);
+ b2 += c[i+3];
+ bs.write(b2);
+ }
+
+ i += 4;
+ remaining -= 4;
+ }
+
+ return bs.toByteArray();
+ }
+
+ /**
+ * Convenience method for getting the given entry as a double.
+ * When the string representation of the requested entry can be decoded
+ * with <code>Double.parseDouble()</code> then that double is returned,
+ * otherwise the given default double value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public double getDouble(String key, double defaultVal) {
+ String value = get(key, null);
+
+ if (value != null) {
+ try {
+ return Double.parseDouble(value);
+ } catch (NumberFormatException nfe) { /* ignore */ }
+ }
+
+ return defaultVal;
+ }
+
+ /**
+ * Convenience method for getting the given entry as a float.
+ * When the string representation of the requested entry can be decoded
+ * with <code>Float.parseFloat()</code> then that float is returned,
+ * otherwise the given default float value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public float getFloat(String key, float defaultVal) {
+ String value = get(key, null);
+
+ if (value != null) {
+ try {
+ return Float.parseFloat(value);
+ } catch (NumberFormatException nfe) { /* ignore */ }
+ }
+
+ return defaultVal;
+ }
+
+ /**
+ * Convenience method for getting the given entry as an integer.
+ * When the string representation of the requested entry can be decoded
+ * with <code>Integer.parseInt()</code> then that integer is returned,
+ * otherwise the given default integer value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public int getInt(String key, int defaultVal) {
+ String value = get(key, null);
+
+ if (value != null) {
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException nfe) { /* ignore */ }
+ }
+
+ return defaultVal;
+ }
+
+ /**
+ * Convenience method for getting the given entry as a long.
+ * When the string representation of the requested entry can be decoded
+ * with <code>Long.parseLong()</code> then that long is returned,
+ * otherwise the given default long value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public long getLong(String key, long defaultVal) {
+ String value = get(key, null);
+
+ if (value != null) {
+ try {
+ return Long.parseLong(value);
+ } catch (NumberFormatException nfe) { /* ignore */ }
+ }
+
+ return defaultVal;
+ }
+
+ /**
+ * Sets the value of the given preferences entry for this node.
+ * Key and value cannot be null, the key cannot exceed 80 characters
+ * and the value cannot exceed 8192 characters.
+ * <p>
+ * The result will be immediatly visible in this VM, but may not be
+ * immediatly written to the backing store.
+ * <p>
+ * Checks that key and value are valid, locks this node, and checks that
+ * the node has not been removed. Then it calls <code>putSpi()</code>.
+ *
+ * @exception NullPointerException if either key or value are null
+ * @exception IllegalArgumentException if either key or value are to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public void put(String key, String value) {
+ if (key.length() > MAX_KEY_LENGTH
+ || value.length() > MAX_VALUE_LENGTH)
+ throw new IllegalArgumentException("key ("
+ + key.length() + ")"
+ + " or value ("
+ + value.length() + ")"
+ + " to large");
+ synchronized(lock) {
+ if (isRemoved())
+ throw new IllegalStateException("Node removed");
+
+ putSpi(key, value);
+
+ // XXX - fire events
+ }
+
+ }
+
+ /**
+ * Convenience method for setting the given entry as a boolean.
+ * The boolean is converted with <code>Boolean.toString(value)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public void putBoolean(String key, boolean value) {
+ put(key, String.valueOf(value));
+ // XXX - Use when using 1.4 compatible Boolean
+ // put(key, Boolean.toString(value));
+ }
+
+ /**
+ * Convenience method for setting the given entry as an array of bytes.
+ * The byte array is converted to a Base64 encoded string
+ * and then stored in the preference entry as that string.
+ * <p>
+ * Note that a byte array encoded as a Base64 string will be about 1.3
+ * times larger then the original length of the byte array, which means
+ * that the byte array may not be larger about 6 KB.
+ *
+ * @exception NullPointerException if either key or value are null
+ * @exception IllegalArgumentException if either key or value are to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public void putByteArray(String key, byte[] value) {
+ put(key, encode64(value));
+ }
+
+ /**
+ * Helper method for encoding an array of bytes as a Base64 String.
+ */
+ private static String encode64(byte[] b) {
+ StringBuffer sb = new StringBuffer((b.length/3)*4);
+
+ int i = 0;
+ int remaining = b.length;
+ char c[] = new char[4];
+ while (remaining > 0) {
+ // Three input bytes are encoded as four chars (6 bits) as
+ // 00000011 11112222 22333333
+
+ c[0] = (char) ((b[i] & 0xFC) >> 2);
+ c[1] = (char) ((b[i] & 0x03) << 4);
+ if (remaining >= 2) {
+ c[1] += (char) ((b[i+1] & 0xF0) >> 4);
+ c[2] = (char) ((b[i+1] & 0x0F) << 2);
+ if (remaining >= 3) {
+ c[2] += (char) ((b[i+2] & 0xC0) >> 6);
+ c[3] = (char) (b[i+2] & 0x3F);
+ } else {
+ c[3] = 64;
+ }
+ } else {
+ c[2] = 64;
+ c[3] = 64;
+ }
+
+ // Convert to base64 chars
+ for(int j = 0; j < 4; j++) {
+ if (c[j] < 26) {
+ c[j] += 'A';
+ } else if (c[j] < 52) {
+ c[j] = (char) (c[j] - 26 + 'a');
+ } else if (c[j] < 62) {
+ c[j] = (char) (c[j] - 52 + '0');
+ } else if (c[j] == 62) {
+ c[j] = '+';
+ } else if (c[j] == 63) {
+ c[j] = '/';
+ } else {
+ c[j] = '=';
+ }
+ }
+
+ sb.append(c);
+ i += 3;
+ remaining -= 3;
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Convenience method for setting the given entry as a double.
+ * The double is converted with <code>Double.toString(double)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public void putDouble(String key, double value) {
+ put(key, Double.toString(value));
+ }
+
+ /**
+ * Convenience method for setting the given entry as a float.
+ * The float is converted with <code>Float.toString(float)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public void putFloat(String key, float value) {
+ put(key, Float.toString(value));
+ }
+
+ /**
+ * Convenience method for setting the given entry as an integer.
+ * The integer is converted with <code>Integer.toString(int)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public void putInt(String key, int value) {
+ put(key, Integer.toString(value));
+ }
+
+ /**
+ * Convenience method for setting the given entry as a long.
+ * The long is converted with <code>Long.toString(long)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public void putLong(String key, long value) {
+ put(key, Long.toString(value));
+ }
+
+ /**
+ * Removes the preferences entry from this preferences node.
+ * <p>
+ * The result will be immediatly visible in this VM, but may not be
+ * immediatly written to the backing store.
+ * <p>
+ * This implementation checks that the key is not larger then 80
+ * characters, gets the lock of this node, checks that the node has
+ * not been removed and calls <code>removeSpi</code> with the given key.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public void remove(String key) {
+ if (key.length() > MAX_KEY_LENGTH)
+ throw new IllegalArgumentException(key);
+
+ synchronized(lock) {
+ if (isRemoved())
+ throw new IllegalStateException("Node removed");
+
+ removeSpi(key);
+ }
+ }
+
+ /**
+ * Removes all entries from this preferences node. May need access to the
+ * backing store to get and clear all entries.
+ * <p>
+ * The result will be immediatly visible in this VM, but may not be
+ * immediatly written to the backing store.
+ * <p>
+ * This implementation locks this node, checks that the node has not been
+ * removed and calls <code>keys()</code> to get a complete array of keys
+ * for this node. For every key found <code>removeSpi()</code> is called.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ */
+ public void clear() throws BackingStoreException {
+ synchronized(lock) {
+ if (isRemoved())
+ throw new IllegalStateException("Node Removed");
+
+ String[] keys = keys();
+ for (int i = 0; i < keys.length; i++) {
+ removeSpi(keys[i]);
+ }
+ }
+ }
+
+ /**
+ * Writes all preference changes on this and any subnode that have not
+ * yet been written to the backing store. This has no effect on the
+ * preference entries in this VM, but it makes sure that all changes
+ * are visible to other programs (other VMs might need to call the
+ * <code>sync()</code> method to actually see the changes to the backing
+ * store.
+ * <p>
+ * Locks this node, calls the <code>flushSpi()</code> method, gets all
+ * the (cached - already existing in this VM) subnodes and then calls
+ * <code>flushSpi()</code> on every subnode with this node unlocked and
+ * only that particular subnode locked.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ */
+ public void flush() throws BackingStoreException {
+ flushNode(false);
+ }
+
+ /**
+ * Writes and reads all preference changes to and from this and any
+ * subnodes. This makes sure that all local changes are written to the
+ * backing store and that all changes to the backing store are visible
+ * in this preference node (and all subnodes).
+ * <p>
+ * Checks that this node is not removed, locks this node, calls the
+ * <code>syncSpi()</code> method, gets all the subnodes and then calls
+ * <code>syncSpi()</code> on every subnode with this node unlocked and
+ * only that particular subnode locked.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ */
+ public void sync() throws BackingStoreException {
+ flushNode(true);
+ }
+
+
+ /**
+ * Private helper method that locks this node and calls either
+ * <code>flushSpi()</code> if <code>sync</code> is false, or
+ * <code>flushSpi()</code> if <code>sync</code> is true. Then it gets all
+ * the currently cached subnodes. For every subnode it calls this method
+ * recursively with this node no longer locked.
+ * <p>
+ * Called by either <code>flush()</code> or <code>sync()</code>
+ */
+ private void flushNode(boolean sync) throws BackingStoreException {
+ String[] keys = null;
+ synchronized(lock) {
+ if (sync) {
+ syncSpi();
+ } else {
+ flushSpi();
+ }
+ keys = (String[]) childCache.keySet().toArray(new String[]{});
+ }
+
+ if (keys != null) {
+ for (int i = 0; i < keys.length; i++) {
+ // Have to lock this node again to access the childCache
+ AbstractPreferences subNode;
+ synchronized(this) {
+ subNode = (AbstractPreferences) childCache.get(keys[i]);
+ }
+
+ // The child could already have been removed from the cache
+ if (subNode != null) {
+ subNode.flushNode(sync);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes this and all subnodes from the backing store and clears all
+ * entries. After removal this instance will not be useable (except for
+ * a few methods that don't throw a <code>InvalidStateException</code>),
+ * even when a new node with the same path name is created this instance
+ * will not be usable again.
+ * <p>
+ * Checks that this is not a root node. If not it locks the parent node,
+ * then locks this node and checks that the node has not yet been removed.
+ * Then it makes sure that all subnodes of this node are in the child cache,
+ * by calling <code>childSpi()</code> on any children not yet in the cache.
+ * Then for all children it locks the subnode and removes it. After all
+ * subnodes have been purged the child cache is cleared, this nodes removed
+ * flag is set and any listeners are called. Finally this node is removed
+ * from the child cache of the parent node.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has already been removed
+ * @exception UnsupportedOperationException if this is a root node
+ */
+ public void removeNode() throws BackingStoreException {
+ // Check if it is a root node
+ if (parent == null)
+ throw new UnsupportedOperationException("Cannot remove root node");
+
+ synchronized(parent) {
+ synchronized(this) {
+ if (isRemoved())
+ throw new IllegalStateException("Node Removed");
+
+ purge();
+ }
+ parent.childCache.remove(name);
+ }
+ }
+
+ /**
+ * Private helper method used to completely remove this node.
+ * Called by <code>removeNode</code> with the parent node and this node
+ * locked.
+ * <p>
+ * Makes sure that all subnodes of this node are in the child cache,
+ * by calling <code>childSpi()</code> on any children not yet in the
+ * cache. Then for all children it locks the subnode and calls this method
+ * on that node. After all subnodes have been purged the child cache is
+ * cleared, this nodes removed flag is set and any listeners are called.
+ */
+ private void purge() throws BackingStoreException
+ {
+ // Make sure all children have an AbstractPreferences node in cache
+ String children[] = childrenNamesSpi();
+ for (int i = 0; i < children.length; i++) {
+ if (childCache.get(children[i]) == null)
+ childCache.put(children[i], childSpi(children[i]));
+ }
+
+ // purge all children
+ Iterator i = childCache.values().iterator();
+ while (i.hasNext()) {
+ AbstractPreferences node = (AbstractPreferences) i.next();
+ synchronized(node) {
+ node.purge();
+ }
+ }
+
+ // Cache is empty now
+ childCache.clear();
+
+ // remove this node
+ removeNodeSpi();
+ removed = true;
+
+ // XXX - check for listeners
+ }
+
+ // listener methods
+
+ /**
+ * XXX
+ */
+ public void addNodeChangeListener(NodeChangeListener listener) {
+ // XXX
+ }
+
+ public void addPreferenceChangeListener(PreferenceChangeListener listener) {
+ // XXX
+ }
+
+ public void removeNodeChangeListener(NodeChangeListener listener) {
+ // XXX
+ }
+
+ public void removePreferenceChangeListener
+ (PreferenceChangeListener listener)
+ {
+ // XXX
+ }
+
+ // abstract spi methods
+
+ /**
+ * Returns the names of the sub nodes of this preference node.
+ * This method only has to return any not yet cached child names,
+ * but may return all names if that is easier. It must not return
+ * null when there are no children, it has to return an empty array
+ * in that case. Since this method must consult the backing store to
+ * get all the sub node names it may throw a BackingStoreException.
+ * <p>
+ * Called by <code>childrenNames()</code> with this node locked.
+ */
+ protected abstract String[] childrenNamesSpi() throws BackingStoreException;
+
+ /**
+ * Returns a child note with the given name.
+ * This method is called by the <code>node()</code> method (indirectly
+ * through the <code>getNode()</code> helper method) with this node locked
+ * if a sub node with this name does not already exist in the child cache.
+ * If the child node did not aleady exist in the backing store the boolean
+ * field <code>newNode</code> of the returned node should be set.
+ * <p>
+ * Note that this method should even return a non-null child node if the
+ * backing store is not available since it may not throw a
+ * <code>BackingStoreException</code>.
+ */
+ protected abstract AbstractPreferences childSpi(String name);
+
+ /**
+ * Returns an (possibly empty) array with all the keys of the preference
+ * entries of this node.
+ * <p>
+ * Called by <code>keys()</code> with this node locked if this node has
+ * not been removed. May throw an exception when the backing store cannot
+ * be accessed.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ */
+ protected abstract String[] keysSpi() throws BackingStoreException;
+
+ /**
+ * Returns the value associated with the key in this preferences node or
+ * null when the key does not exist in this preferences node.
+ * <p>
+ * Called by <code>key()</code> with this node locked after checking that
+ * key is valid, not null and that the node has not been removed.
+ * <code>key()</code> will catch any exceptions that this method throws.
+ */
+ protected abstract String getSpi(String key);
+
+ /**
+ * Sets the value of the given preferences entry for this node.
+ * The implementation is not required to propagate the change to the
+ * backing store immediatly. It may not throw an exception when it tries
+ * to write to the backing store and that operation fails, the failure
+ * should be registered so a later invocation of <code>flush()</code>
+ * or <code>sync()</code> can signal the failure.
+ * <p>
+ * Called by <code>put()</code> with this node locked after checking that
+ * key and value are valid and non-null.
+ */
+ protected abstract void putSpi(String key, String value);
+
+ /**
+ * Removes the given key entry from this preferences node.
+ * The implementation is not required to propagate the change to the
+ * backing store immediatly. It may not throw an exception when it tries
+ * to write to the backing store and that operation fails, the failure
+ * should be registered so a later invocation of <code>flush()</code>
+ * or <code>sync()</code> can signal the failure.
+ * <p>
+ * Called by <code>remove()</code> with this node locked after checking
+ * that the key is valid and non-null.
+ */
+ protected abstract void removeSpi(String key);
+
+ /**
+ * Writes all entries of this preferences node that have not yet been
+ * written to the backing store and possibly creates this node in the
+ * backing store, if it does not yet exist. Should only write changes to
+ * this node and not write changes to any subnodes.
+ * Note that the node can be already removed in this VM. To check if
+ * that is the case the implementation can call <code>isRemoved()</code>.
+ * <p>
+ * Called (indirectly) by <code>flush()</code> with this node locked.
+ */
+ protected abstract void flushSpi() throws BackingStoreException;
+
+ /**
+ * Writes all entries of this preferences node that have not yet been
+ * written to the backing store and reads any entries that have changed
+ * in the backing store but that are not yet visible in this VM.
+ * Should only sync this node and not change any of the subnodes.
+ * Note that the node can be already removed in this VM. To check if
+ * that is the case the implementation can call <code>isRemoved()</code>.
+ * <p>
+ * Called (indirectly) by <code>sync()</code> with this node locked.
+ */
+ protected abstract void syncSpi() throws BackingStoreException;
+
+ /**
+ * Clears this node from this VM and removes it from the backing store.
+ * After this method has been called the node is marked as removed.
+ * <p>
+ * Called (indirectly) by <code>removeNode()</code> with this node locked
+ * after all the sub nodes of this node have already been removed.
+ */
+ protected abstract void removeNodeSpi() throws BackingStoreException;
+}
diff --git a/libjava/classpath/java/util/prefs/BackingStoreException.java b/libjava/classpath/java/util/prefs/BackingStoreException.java
new file mode 100644
index 00000000000..0ba358a5688
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/BackingStoreException.java
@@ -0,0 +1,104 @@
+/* BackingStoreException.java - chained exception thrown when backing store
+ fails
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.prefs;
+
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Chained exception thrown when backing store fails. This exception is
+ * only thrown from methods that actually have to access the backing store,
+ * such as <code>clear(), keys(), childrenNames(), nodeExists(), removeNode(),
+ * flush(), sync(), exportNode(), exportSubTree()</code>; normal operations
+ * do not throw BackingStoreExceptions.
+ *
+ * <p>Note that although this class inherits the Serializable interface, an
+ * attempt to serialize will fail with a <code>NotSerializableException</code>.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class BackingStoreException extends Exception
+{
+ static final long serialVersionUID = 859796500401108469L;
+
+ /**
+ * Creates a new exception with a descriptive message.
+ *
+ * @param message the message
+ */
+ public BackingStoreException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Create a new exception with the given cause.
+ *
+ * @param cause the cause
+ */
+ public BackingStoreException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ /**
+ * This class should not be serialized.
+ *
+ * @param o the output stream
+ */
+ private void writeObject(ObjectOutputStream o) throws NotSerializableException
+ {
+ throw new NotSerializableException
+ ("java.util.prefs.BackingStoreException");
+ }
+
+ /**
+ * This class should not be serialized.
+ *
+ * @param i the input stream
+ */
+ private void readObject(ObjectInputStream i) throws NotSerializableException
+ {
+ throw new NotSerializableException
+ ("java.util.prefs.BackingStoreException");
+ }
+}
diff --git a/libjava/classpath/java/util/prefs/InvalidPreferencesFormatException.java b/libjava/classpath/java/util/prefs/InvalidPreferencesFormatException.java
new file mode 100644
index 00000000000..f929b56f68e
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/InvalidPreferencesFormatException.java
@@ -0,0 +1,116 @@
+/* InvalidPreferencesFormatException - indicates reading prefs from stream
+ failed
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.prefs;
+
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Indicates reading prefs from stream failed. Thrown by the
+ * <code>importPreferences()</code> method when the supplied input stream
+ * could not be read because it was not in the correct XML format.
+ *
+ * <p>Note that although this class inherits the Serializable interface, an
+ * attempt to serialize will fail with a <code>NotSerializableException</code>.
+ * </p>
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @see Preferences
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class InvalidPreferencesFormatException extends Exception
+{
+ static final long serialVersionUID = -791715184232119669L;
+
+ /**
+ * Creates a new exception with a descriptive message. The cause remains
+ * uninitialized.
+ *
+ * @param message the message
+ */
+ public InvalidPreferencesFormatException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Creates a new exception with the given cause.
+ *
+ * @param cause the cause
+ */
+ public InvalidPreferencesFormatException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ /**
+ * Creates a new exception with a descriptive message and a cause.
+ *
+ * @param message the message
+ * @param cause the cause
+ */
+ public InvalidPreferencesFormatException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ /**
+ * This class should not be serialized.
+ *
+ * @param o the output stream
+ */
+ private void writeObject(ObjectOutputStream o) throws NotSerializableException
+ {
+ throw new NotSerializableException
+ ("java.util.prefs.InvalidPreferencesFormatException");
+ }
+
+ /**
+ * This class should not be serialized.
+ *
+ * @param i the input stream
+ */
+ private void readObject(ObjectInputStream i) throws NotSerializableException
+ {
+ throw new NotSerializableException
+ ("java.util.prefs.InvalidPreferencesFormatException");
+ }
+}
diff --git a/libjava/classpath/java/util/prefs/NodeChangeEvent.java b/libjava/classpath/java/util/prefs/NodeChangeEvent.java
new file mode 100644
index 00000000000..89986db88b3
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/NodeChangeEvent.java
@@ -0,0 +1,91 @@
+/* NodeChangeEvent - ObjectEvent fired when a Preference node is added/removed
+ Copyright (C) 2001 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.prefs;
+
+import java.util.EventObject;
+
+/**
+ * ObjectEvent fired when a Preference node is added/removed.
+ * This event is only generated when a new subnode is added or a subnode is
+ * removed from a preference node. Changes in the entries of a preference node
+ * are indicated with a <code>PreferenceChangeEvent</code>.
+ *
+ * @since 1.4
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class NodeChangeEvent extends EventObject {
+
+ private static final long serialVersionUID =8068949086596572957L;
+
+ /**
+ * The sub node that was added or removed.
+ * Defined transient just like <code>EventObject.source</code> since
+ * this object should be serializable, but Preferences is in general not
+ * serializable.
+ */
+ private final transient Preferences child;
+
+ /**
+ * Creates a new NodeChangeEvent.
+ *
+ * @param parentNode The source preference node from which a subnode was
+ * added or removed
+ * @param childNode The preference node that was added or removed
+ */
+ public NodeChangeEvent(Preferences parentNode, Preferences childNode) {
+ super(parentNode);
+ child = childNode;
+ }
+
+ /**
+ * Returns the source parent preference node from which a subnode was
+ * added or removed.
+ */
+ public Preferences getParent() {
+ return (Preferences) source;
+ }
+
+ /**
+ * Returns the child preference subnode that was added or removed.
+ * To see wether it is still a valid preference node one has to call
+ * <code>event.getChild().nodeExists("")</code>.
+ */
+ public Preferences getChild() {
+ return child;
+ }
+}
diff --git a/libjava/classpath/java/util/prefs/NodeChangeListener.java b/libjava/classpath/java/util/prefs/NodeChangeListener.java
new file mode 100644
index 00000000000..19664c6652d
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/NodeChangeListener.java
@@ -0,0 +1,64 @@
+/* NodeChangeListener - EventListener for Preferences node addition/removal
+ Copyright (C) 2001 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.prefs;
+
+import java.util.EventListener;
+
+/**
+ * EventListener for Preferences node addition/removal.
+ * <p>
+ * Note that these events are only generated for the addition and removal
+ * of sub nodes from the preference node. Entry changes in the preference
+ * node can be monitored with a <code>PreferenceChangeListener</code>.
+ *
+ * @since 1.4
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public interface NodeChangeListener extends EventListener {
+
+ /**
+ * Fired when a sub node is added to the preference node.
+ */
+ void childAdded(NodeChangeEvent event);
+
+ /**
+ * Fired when a sub node is removed from the preference node.
+ */
+ void childRemoved(NodeChangeEvent event);
+
+}
diff --git a/libjava/classpath/java/util/prefs/PreferenceChangeEvent.java b/libjava/classpath/java/util/prefs/PreferenceChangeEvent.java
new file mode 100644
index 00000000000..fe371f15e4e
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/PreferenceChangeEvent.java
@@ -0,0 +1,105 @@
+/* PreferenceChangeEvent - ObjectEvent fired when a Preferences entry changes
+ Copyright (C) 2001 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.prefs;
+
+import java.util.EventObject;
+
+/**
+ * ObjectEvent fired when a Preferences entry changes.
+ * This event is generated when a entry is added, changed or removed.
+ * When an entry is removed then <code>getNewValue</code> will return null.
+ * <p>
+ * Preference change events are only generated for entries in one particular
+ * preference node. Notification of subnode addition/removal is given by a
+ * <code>NodeChangeEvent</code>.
+ *
+ * @since 1.4
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public class PreferenceChangeEvent extends EventObject {
+
+ private static final long serialVersionUID = 793724513368024975L;
+
+ /**
+ * The key of the changed entry.
+ */
+ private final String key;
+
+ /**
+ * The new value of the changed entry, or null when the entry was removed.
+ */
+ private final String newValue;
+
+ /**
+ * Creates a new PreferenceChangeEvent.
+ *
+ * @param node The source preference node for which an entry was added,
+ * changed or removed
+ * @param key The key of the entry that was added, changed or removed
+ * @param value The new value of the entry that was added or changed, or
+ * null when the entry was removed
+ */
+ public PreferenceChangeEvent(Preferences node, String key, String value) {
+ super(node);
+ this.key = key;
+ this.newValue = value;
+ }
+
+ /**
+ * Returns the source Preference node from which an entry was added,
+ * changed or removed.
+ */
+ public Preferences getNode() {
+ return (Preferences) source;
+ }
+
+ /**
+ * Returns the key of the entry that was added, changed or removed.
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Returns the new value of the entry that was added or changed, or
+ * returns null when the entry was removed.
+ */
+ public String getNewValue() {
+ return newValue;
+ }
+}
diff --git a/libjava/classpath/java/util/prefs/PreferenceChangeListener.java b/libjava/classpath/java/util/prefs/PreferenceChangeListener.java
new file mode 100644
index 00000000000..adff3582079
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/PreferenceChangeListener.java
@@ -0,0 +1,60 @@
+/* PreferenceChangeListener - EventListener for Preferences entry changes
+ Copyright (C) 2001 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.prefs;
+
+import java.util.EventListener;
+
+/**
+ * EventListener for Preferences entry addition, change or removal.
+ * <p>
+ * Preference change events are only generated for entries in one particular
+ * preference node. Notification of subnode addition/removal can be monitored
+ * with a <code>NodeChangeListener</code>.
+ *
+ * @since 1.4
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public interface PreferenceChangeListener extends EventListener {
+
+ /**
+ * Fired when a entry has been added, changed or removed from the
+ * preference node.
+ */
+ void preferenceChange(PreferenceChangeEvent event);
+
+}
diff --git a/libjava/classpath/java/util/prefs/Preferences.java b/libjava/classpath/java/util/prefs/Preferences.java
new file mode 100644
index 00000000000..c407ae6127a
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/Preferences.java
@@ -0,0 +1,668 @@
+/* Preferences -- Preference node containing key value entries and subnodes
+ Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.prefs;
+
+import gnu.java.util.prefs.NodeReader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+
+/**
+ * Preference node containing key value entries and subnodes.
+ * <p>
+ * There are two preference node trees, a system tree which can be accessed
+ * by calling <code>systemRoot()</code> containing system preferences usefull
+ * for all users, and a user tree that can be accessed by calling
+ * <code>userRoot()</code> containing preferences that can differ between
+ * different users. How different users are identified is implementation
+ * depended. It can be determined by Thread, Access Control Context or Subject.
+ * <p>
+ * This implementation uses the "java.util.prefs.PreferencesFactory" system
+ * property to find a class that implement <code>PreferencesFactory</code>
+ * and initialized that class (if it has a public no arguments contructor)
+ * to get at the actual system or user root. If the system property is not set,
+ * or the class cannot be initialized it uses the default implementation
+ * <code>gnu.java.util.prefs.FileBasedFactory</code>.
+ * <p>
+ * Besides the two static method above to get the roots of the system and user
+ * preference node trees there are also two convenience methods to access the
+ * default preference node for a particular package an object is in. These are
+ * <code>userNodeForPackage()</code> and <code>systemNodeForPackage()</code>.
+ * Both methods take an Object as an argument so accessing preferences values
+ * can be as easy as calling <code>Preferences.userNodeForPackage(this)</code>.
+ * <p>
+ * Note that if a security manager is installed all static methods check for
+ * <code>RuntimePermission("preferences")</code>. But if this permission is
+ * given to the code then it can access and change all (user) preference nodes
+ * and entries. So you should be carefull not to store to sensitive information
+ * or make security decissions based on preference values since there is no
+ * more fine grained control over what preference values can be changed once
+ * code has been given the correct runtime permission.
+ * <p>
+ * XXX
+ *
+ * @since 1.4
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public abstract class Preferences {
+
+ // Static Fields
+
+ /**
+ * Default PreferencesFactory class used when the system property
+ * "java.util.prefs.PreferencesFactory" is not set.
+ * <p>
+ * XXX - Currently set to MemoryBasedFactory, should be changed
+ * when FileBasedPreferences backend works.
+ */
+ private static final String defaultFactoryClass
+ = "gnu.java.util.prefs.MemoryBasedFactory";
+
+ /** Permission needed to access system or user root. */
+ private static final Permission prefsPermission
+ = new RuntimePermission("preferences");
+
+ /**
+ * The preferences factory object that supplies the system and user root.
+ * Set and returned by the getFactory() method.
+ */
+ private static PreferencesFactory factory;
+
+ /** Maximum node name length. 80 characters. */
+ public static final int MAX_NAME_LENGTH = 80;
+
+ /** Maximum entry key length. 80 characters. */
+ public static final int MAX_KEY_LENGTH = 80;
+
+ /** Maximum entry value length. 8192 characters. */
+ public static final int MAX_VALUE_LENGTH = 8192;
+
+ // Constructors
+
+ /**
+ * Creates a new Preferences node. Can only be used by subclasses.
+ * Empty implementation.
+ */
+ protected Preferences() {}
+
+ // Static methods
+
+ /**
+ * Returns the system preferences root node containing usefull preferences
+ * for all users. It is save to cache this value since it should always
+ * return the same preference node.
+ *
+ * @return the root system preference node
+ * @exception SecurityException when a security manager is installed and
+ * the caller does not have <code>RuntimePermission("preferences")</code>.
+ */
+ public static Preferences systemRoot() throws SecurityException {
+ // Get the preferences factory and check for permission
+ PreferencesFactory factory = getFactory();
+
+ return factory.systemRoot();
+ }
+
+ /**
+ * Returns the user preferences root node containing preferences for the
+ * the current user. How different users are identified is implementation
+ * depended. It can be determined by Thread, Access Control Context or
+ * Subject.
+ *
+ * @return the root user preference node
+ * @exception SecurityException when a security manager is installed and
+ * the caller does not have <code>RuntimePermission("preferences")</code>.
+ */
+ public static Preferences userRoot() throws SecurityException {
+ // Get the preferences factory and check for permission
+ PreferencesFactory factory = getFactory();
+ return factory.userRoot();
+ }
+
+ /**
+ * Private helper method for <code>systemRoot()</code> and
+ * <code>userRoot()</code>. Checks security permission and instantiates the
+ * correct factory if it has not yet been set.
+ * <p>
+ * When the preferences factory has not yet been set this method first
+ * tries to get the system propery "java.util.prefs.PreferencesFactory"
+ * and tries to initializes that class. If the system property is not set
+ * or initialization fails it returns an instance of the default factory
+ * <code>gnu.java.util.prefs.FileBasedPreferencesFactory</code>.
+ *
+ * @return the preferences factory to use
+ * @exception SecurityException when a security manager is installed and
+ * the caller does not have <code>RuntimePermission("preferences")</code>.
+ */
+ private static PreferencesFactory getFactory() throws SecurityException {
+
+ // First check for permission
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(prefsPermission);
+ }
+
+ // Get the factory
+ if (factory == null) {
+ // Caller might not have enough permissions
+ factory = (PreferencesFactory) AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ PreferencesFactory pf = null;
+ String className = System.getProperty
+ ("java.util.prefs.PreferencesFactory");
+ if (className != null) {
+ try {
+ Class fc = Class.forName(className);
+ Object o = fc.newInstance();
+ pf = (PreferencesFactory) o;
+ } catch (ClassNotFoundException cnfe)
+ {/*ignore*/}
+ catch (InstantiationException ie)
+ {/*ignore*/}
+ catch (IllegalAccessException iae)
+ {/*ignore*/}
+ catch (ClassCastException cce)
+ {/*ignore*/}
+ }
+ return pf;
+ }
+ });
+
+ // Still no factory? Use our default.
+ if (factory == null)
+ {
+ try
+ {
+ Class cls = Class.forName (defaultFactoryClass);
+ factory = (PreferencesFactory) cls.newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException ("Couldn't load default factory"
+ + " '"+ defaultFactoryClass +"'");
+ // XXX - when using 1.4 compatible throwables add cause
+ }
+ }
+
+ }
+
+ return factory;
+ }
+
+ /**
+ * Returns the system preferences node for the package of an object.
+ * The package node name of the object is determined by dropping the
+ * class name of the object of the fully quallified class name and
+ * replacing all '.' to '/' in the package name. If the class of the
+ * object has no package then the package node name is "&lt;unnamed&gt;".
+ * The returened node is <code>systemRoot().node(packageNodeName)</code>.
+ *
+ * @param o Object whose default system preference node is requested
+ * @returns system preferences node that should be used by object o
+ * @exception SecurityException when a security manager is installed and
+ * the caller does not have <code>RuntimePermission("preferences")</code>.
+ */
+ public static Preferences systemNodeForPackage(Class c)
+ throws SecurityException
+ {
+ return nodeForPackage(c, systemRoot());
+ }
+
+ /**
+ * Returns the user preferences node for the package of an object.
+ * The package node name of the object is determined by dropping the
+ * class name of the object of the fully quallified class name and
+ * replacing all '.' to '/' in the package name. If the class of the
+ * object has no package then the package node name is "&lt;unnamed&gt;".
+ * The returened node is <code>userRoot().node(packageNodeName)</code>.
+ *
+ * @param o Object whose default user preference node is requested
+ * @returns user preferences node that should be used by object o
+ * @exception SecurityException when a security manager is installed and
+ * the caller does not have <code>RuntimePermission("preferences")</code>.
+ */
+ public static Preferences userNodeForPackage(Class c)
+ throws SecurityException
+ {
+ return nodeForPackage(c, userRoot());
+ }
+
+ /**
+ * Private helper method for <code>systemNodeForPackage()</code> and
+ * <code>userNodeForPackage()</code>. Given the correct system or user
+ * root it returns the correct Preference node for the package node name
+ * of the given object.
+ */
+ private static Preferences nodeForPackage(Class c, Preferences root) {
+ // Get the package path
+ String className = c.getName();
+ String packagePath;
+ int index = className.lastIndexOf('.');
+ if(index == -1) {
+ packagePath = "<unnamed>";
+ } else {
+ packagePath = className.substring(0,index).replace('.','/');
+ }
+
+ return root.node(packagePath);
+ }
+
+ /**
+ * XXX
+ */
+ public static void importPreferences(InputStream is)
+ throws InvalidPreferencesFormatException,
+ IOException
+ {
+ PreferencesFactory factory = getFactory();
+ NodeReader reader = new NodeReader(is, factory);
+ reader.importPreferences();
+ }
+
+ // abstract methods (identification)
+
+ /**
+ * Returns the absolute path name of this preference node.
+ * The absolute path name of a node is the path name of its parent node
+ * plus a '/' plus its own name. If the node is the root node and has no
+ * parent then its name is "" and its absolute path name is "/".
+ */
+ public abstract String absolutePath();
+
+ /**
+ * Returns true if this node comes from the user preferences tree, false
+ * if it comes from the system preferences tree.
+ */
+ public abstract boolean isUserNode();
+
+ /**
+ * Returns the name of this preferences node. The name of the node cannot
+ * be null, can be mostly 80 characters and cannot contain any '/'
+ * characters. The root node has as name "".
+ */
+ public abstract String name();
+
+ /**
+ * Returns the String given by
+ * <code>
+ * (isUserNode() ? "User":"System") + " Preference Node: " + absolutePath()
+ * </code>
+ */
+ public abstract String toString();
+
+ // abstract methods (navigation)
+
+ /**
+ * Returns all the direct sub nodes of this preferences node.
+ * Needs access to the backing store to give a meaningfull answer.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract String[] childrenNames() throws BackingStoreException;
+
+ /**
+ * Returns a sub node of this preferences node if the given path is
+ * relative (does not start with a '/') or a sub node of the root
+ * if the path is absolute (does start with a '/').
+ *
+ * @exception IllegalStateException if this node has been removed
+ * @exception IllegalArgumentException if the path contains two or more
+ * consecutive '/' characters, ends with a '/' charactor and is not the
+ * string "/" (indicating the root node) or any name on the path is more
+ * then 80 characters long
+ */
+ public abstract Preferences node(String path);
+
+ /**
+ * Returns true if the node that the path points to exists in memory or
+ * in the backing store. Otherwise it returns false or an exception is
+ * thrown. When this node is removed the only valid parameter is the
+ * empty string (indicating this node), the return value in that case
+ * will be false.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ * and the path is not the empty string (indicating this node)
+ * @exception IllegalArgumentException if the path contains two or more
+ * consecutive '/' characters, ends with a '/' charactor and is not the
+ * string "/" (indicating the root node) or any name on the path is more
+ * then 80 characters long
+ */
+ public abstract boolean nodeExists(String path)
+ throws BackingStoreException;
+
+ /**
+ * Returns the parent preferences node of this node or null if this is
+ * the root of the preferences tree.
+ *
+ * @exception IllegalStateException if this node has been removed
+ */
+ public abstract Preferences parent();
+
+ // abstract methods (export)
+
+ /**
+ * XXX
+ */
+ public abstract void exportNode(OutputStream os)
+ throws BackingStoreException,
+ IOException;
+
+ /**
+ * XXX
+ */
+ public abstract void exportSubtree(OutputStream os)
+ throws BackingStoreException,
+ IOException;
+
+ // abstract methods (preference entry manipulation)
+
+ /**
+ * Returns an (possibly empty) array with all the keys of the preference
+ * entries of this node.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ */
+ public abstract String[] keys() throws BackingStoreException;
+
+ /**
+ * Returns the value associated with the key in this preferences node. If
+ * the default value of the key cannot be found in the preferences node
+ * entries or something goes wrong with the backing store the supplied
+ * default value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public abstract String get(String key, String defaultVal);
+
+ /**
+ * Convenience method for getting the given entry as a boolean.
+ * When the string representation of the requested entry is either
+ * "true" or "false" (ignoring case) then that value is returned,
+ * otherwise the given default boolean value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public abstract boolean getBoolean(String key, boolean defaultVal);
+
+ /**
+ * Convenience method for getting the given entry as a byte array.
+ * When the string representation of the requested entry is a valid
+ * Base64 encoded string (without any other characters, such as newlines)
+ * then the decoded Base64 string is returned as byte array,
+ * otherwise the given default byte array value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public abstract byte[] getByteArray(String key, byte[] defaultVal);
+
+ /**
+ * Convenience method for getting the given entry as a double.
+ * When the string representation of the requested entry can be decoded
+ * with <code>Double.parseDouble()</code> then that double is returned,
+ * otherwise the given default double value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public abstract double getDouble(String key, double defaultVal);
+
+ /**
+ * Convenience method for getting the given entry as a float.
+ * When the string representation of the requested entry can be decoded
+ * with <code>Float.parseFloat()</code> then that float is returned,
+ * otherwise the given default float value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public abstract float getFloat(String key, float defaultVal);
+
+ /**
+ * Convenience method for getting the given entry as an integer.
+ * When the string representation of the requested entry can be decoded
+ * with <code>Integer.parseInt()</code> then that integer is returned,
+ * otherwise the given default integer value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public abstract int getInt(String key, int defaultVal);
+
+ /**
+ * Convenience method for getting the given entry as a long.
+ * When the string representation of the requested entry can be decoded
+ * with <code>Long.parseLong()</code> then that long is returned,
+ * otherwise the given default long value is returned.
+ *
+ * @exception IllegalArgumentException if key is larger then 80 characters
+ * @exception IllegalStateException if this node has been removed
+ * @exception NullPointerException if key is null
+ */
+ public abstract long getLong(String key, long defaultVal);
+
+ /**
+ * Sets the value of the given preferences entry for this node.
+ * Key and value cannot be null, the key cannot exceed 80 characters
+ * and the value cannot exceed 8192 characters.
+ * <p>
+ * The result will be immediatly visible in this VM, but may not be
+ * immediatly written to the backing store.
+ *
+ * @exception NullPointerException if either key or value are null
+ * @exception IllegalArgumentException if either key or value are to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract void put(String key, String value);
+
+ /**
+ * Convenience method for setting the given entry as a boolean.
+ * The boolean is converted with <code>Boolean.toString(value)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract void putBoolean(String key, boolean value);
+
+ /**
+ * Convenience method for setting the given entry as an array of bytes.
+ * The byte array is converted to a Base64 encoded string
+ * and then stored in the preference entry as that string.
+ * <p>
+ * Note that a byte array encoded as a Base64 string will be about 1.3
+ * times larger then the original length of the byte array, which means
+ * that the byte array may not be larger about 6 KB.
+ *
+ * @exception NullPointerException if either key or value are null
+ * @exception IllegalArgumentException if either key or value are to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract void putByteArray(String key, byte[] value);
+
+ /**
+ * Convenience method for setting the given entry as a double.
+ * The double is converted with <code>Double.toString(double)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract void putDouble(String key, double value);
+
+ /**
+ * Convenience method for setting the given entry as a float.
+ * The float is converted with <code>Float.toString(float)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract void putFloat(String key, float value);
+
+ /**
+ * Convenience method for setting the given entry as an integer.
+ * The integer is converted with <code>Integer.toString(int)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract void putInt(String key, int value);
+
+ /**
+ * Convenience method for setting the given entry as a long.
+ * The long is converted with <code>Long.toString(long)</code>
+ * and then stored in the preference entry as that string.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract void putLong(String key, long value);
+
+ /**
+ * Removes the preferences entry from this preferences node.
+ * <p>
+ * The result will be immediatly visible in this VM, but may not be
+ * immediatly written to the backing store.
+ *
+ * @exception NullPointerException if the key is null
+ * @exception IllegalArgumentException if the key length is to large
+ * @exception IllegalStateException when this node has been removed
+ */
+ public abstract void remove(String key);
+
+ // abstract methods (preference node manipulation)
+
+ /**
+ * Removes all entries from this preferences node. May need access to the
+ * backing store to get and clear all entries.
+ * <p>
+ * The result will be immediatly visible in this VM, but may not be
+ * immediatly written to the backing store.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ */
+ public abstract void clear() throws BackingStoreException;
+
+ /**
+ * Writes all preference changes on this and any subnode that have not
+ * yet been written to the backing store. This has no effect on the
+ * preference entries in this VM, but it makes sure that all changes
+ * are visible to other programs (other VMs might need to call the
+ * <code>sync()</code> method to actually see the changes to the backing
+ * store.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ */
+ public abstract void flush() throws BackingStoreException;
+
+ /**
+ * Writes and reads all preference changes to and from this and any
+ * subnodes. This makes sure that all local changes are written to the
+ * backing store and that all changes to the backing store are visible
+ * in this preference node (and all subnodes).
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has been removed
+ */
+ public abstract void sync() throws BackingStoreException;
+
+ /**
+ * Removes this and all subnodes from the backing store and clears all
+ * entries. After removal this instance will not be useable (except for
+ * a few methods that don't throw a <code>InvalidStateException</code>),
+ * even when a new node with the same path name is created this instance
+ * will not be usable again. The root (system or user) may never be removed.
+ * <p>
+ * Note that according to the specification an implementation may delay
+ * removal of the node from the backing store till the <code>flush()</code>
+ * method is called. But the <code>flush()</code> method may throw a
+ * <code>IllegalStateException</code> when the node has been removed.
+ * So most implementations will actually remove the node and any subnodes
+ * from the backing store immediatly.
+ *
+ * @exception BackingStoreException when the backing store cannot be
+ * reached
+ * @exception IllegalStateException if this node has already been removed
+ * @exception UnsupportedOperationException if this is a root node
+ */
+ public abstract void removeNode() throws BackingStoreException;
+
+ // abstract methods (listeners)
+
+ public abstract void addNodeChangeListener(NodeChangeListener listener);
+
+ public abstract void addPreferenceChangeListener
+ (PreferenceChangeListener listener);
+
+ public abstract void removeNodeChangeListener(NodeChangeListener listener);
+
+ public abstract void removePreferenceChangeListener
+ (PreferenceChangeListener listener);
+}
+
diff --git a/libjava/classpath/java/util/prefs/PreferencesFactory.java b/libjava/classpath/java/util/prefs/PreferencesFactory.java
new file mode 100644
index 00000000000..f4fe7e37ffe
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/PreferencesFactory.java
@@ -0,0 +1,65 @@
+/* PreferencesFactory - Preferences system and user root factory interface
+ Copyright (C) 2001 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.prefs;
+
+/**
+ * Preferences system and user root factory interface. Defines how to get
+ * to the system and user root preferences objects. Should be implemented by
+ * new preferences backends.
+ *
+ * @since 1.4
+ * @author Mark Wielaard (mark@klomp.org)
+ */
+public interface PreferencesFactory {
+
+ /**
+ * Returns the system root preferences node. Should always return the
+ * same object.
+ */
+ Preferences systemRoot();
+
+ /**
+ * Returns the user root preferences node. May return different objects
+ * depending on the user that called this method. The user may for example
+ * be determined by the current Thread or the Subject associated with the
+ * current AccessControllContext.
+ */
+ Preferences userRoot();
+
+}
diff --git a/libjava/classpath/java/util/prefs/package.html b/libjava/classpath/java/util/prefs/package.html
new file mode 100644
index 00000000000..65fc1ac7991
--- /dev/null
+++ b/libjava/classpath/java/util/prefs/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.util.prefs package.
+ Copyright (C) 2002 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 - java.util.prefs</title></head>
+
+<body>
+<p>Utility classes for storing and retrieving user and system preferences.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/util/regex/Matcher.java b/libjava/classpath/java/util/regex/Matcher.java
new file mode 100644
index 00000000000..bd97ace54a8
--- /dev/null
+++ b/libjava/classpath/java/util/regex/Matcher.java
@@ -0,0 +1,301 @@
+/* Matcher.java -- Instance of a regular expression applied to a char sequence.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.regex;
+
+import gnu.regexp.REMatch;
+
+/**
+ * Instance of a regular expression applied to a char sequence.
+ *
+ * @since 1.4
+ */
+public final class Matcher
+{
+ private Pattern pattern;
+ private CharSequence input;
+ private int position;
+ private int appendPosition;
+ private REMatch match;
+
+ Matcher(Pattern pattern, CharSequence input)
+ {
+ this.pattern = pattern;
+ this.input = input;
+ }
+
+ /**
+ * @param sb The target string buffer
+ * @param replacement The replacement string
+ *
+ * @exception IllegalStateException If no match has yet been attempted,
+ * or if the previous match operation failed
+ * @exception IndexOutOfBoundsException If the replacement string refers
+ * to a capturing group that does not exist in the pattern
+ */
+ public Matcher appendReplacement (StringBuffer sb, String replacement)
+ throws IllegalStateException
+ {
+ assertMatchOp();
+ sb.append(input.subSequence(appendPosition,
+ match.getStartIndex()).toString());
+ sb.append(match.substituteInto(replacement));
+ appendPosition = match.getEndIndex();
+ return this;
+ }
+
+ /**
+ * @param sb The target string buffer
+ */
+ public StringBuffer appendTail (StringBuffer sb)
+ {
+ sb.append(input.subSequence(appendPosition, input.length()).toString());
+ return sb;
+ }
+
+ /**
+ * @exception IllegalStateException If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int end ()
+ throws IllegalStateException
+ {
+ assertMatchOp();
+ return match.getEndIndex();
+ }
+
+ /**
+ * @param group The index of a capturing group in this matcher's pattern
+ *
+ * @exception IllegalStateException If no match has yet been attempted,
+ * or if the previous match operation failed
+ * @exception IndexOutOfBoundsException If the replacement string refers
+ * to a capturing group that does not exist in the pattern
+ */
+ public int end (int group)
+ throws IllegalStateException
+ {
+ assertMatchOp();
+ return match.getEndIndex(group);
+ }
+
+ public boolean find ()
+ {
+ boolean first = (match == null);
+ match = pattern.getRE().getMatch(input, position);
+ if (match != null)
+ {
+ int endIndex = match.getEndIndex();
+ // Are we stuck at the same position?
+ if (!first && endIndex == position)
+ {
+ match = null;
+ // Not at the end of the input yet?
+ if (position < input.length() - 1)
+ {
+ position++;
+ return find(position);
+ }
+ else
+ return false;
+ }
+ position = endIndex;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param start The index to start the new pattern matching
+ *
+ * @exception IndexOutOfBoundsException If the replacement string refers
+ * to a capturing group that does not exist in the pattern
+ */
+ public boolean find (int start)
+ {
+ match = pattern.getRE().getMatch(input, start);
+ if (match != null)
+ {
+ position = match.getEndIndex();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @exception IllegalStateException If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public String group ()
+ {
+ assertMatchOp();
+ return match.toString();
+ }
+
+ /**
+ * @param group The index of a capturing group in this matcher's pattern
+ *
+ * @exception IllegalStateException If no match has yet been attempted,
+ * or if the previous match operation failed
+ * @exception IndexOutOfBoundsException If the replacement string refers
+ * to a capturing group that does not exist in the pattern
+ */
+ public String group (int group)
+ throws IllegalStateException
+ {
+ assertMatchOp();
+ return match.toString(group);
+ }
+
+ /**
+ * @param replacement The replacement string
+ */
+ public String replaceFirst (String replacement)
+ {
+ reset();
+ // Semantics might not quite match
+ return pattern.getRE().substitute(input, replacement, position);
+ }
+
+ /**
+ * @param replacement The replacement string
+ */
+ public String replaceAll (String replacement)
+ {
+ reset();
+ return pattern.getRE().substituteAll(input, replacement, position);
+ }
+
+ public int groupCount ()
+ {
+ return pattern.getRE().getNumSubs();
+ }
+
+ public boolean lookingAt ()
+ {
+ match = pattern.getRE().getMatch(input, 0);
+ if (match != null)
+ {
+ if (match.getStartIndex() == 0)
+ {
+ position = match.getEndIndex();
+ return true;
+ }
+ match = null;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to match the entire input sequence against the pattern.
+ *
+ * If the match succeeds then more information can be obtained via the
+ * start, end, and group methods.
+ *
+ * @see #start
+ * @see #end
+ * @see #group
+ */
+ public boolean matches ()
+ {
+ if (lookingAt())
+ {
+ if (position == input.length())
+ return true;
+ match = null;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the Pattern that is interpreted by this Matcher
+ */
+ public Pattern pattern ()
+ {
+ return pattern;
+ }
+
+ public Matcher reset ()
+ {
+ position = 0;
+ match = null;
+ return this;
+ }
+
+ /**
+ * @param input The new input character sequence
+ */
+ public Matcher reset (CharSequence input)
+ {
+ this.input = input;
+ return reset();
+ }
+
+ /**
+ * @param group The index of a capturing group in this matcher's pattern
+ *
+ * @exception IllegalStateException If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int start ()
+ throws IllegalStateException
+ {
+ assertMatchOp();
+ return match.getStartIndex();
+ }
+
+ /**
+ * @param group The index of a capturing group in this matcher's pattern
+ *
+ * @exception IllegalStateException If no match has yet been attempted,
+ * or if the previous match operation failed
+ * @exception IndexOutOfBoundsException If the replacement string refers
+ * to a capturing group that does not exist in the pattern
+ */
+ public int start (int group)
+ throws IllegalStateException
+ {
+ assertMatchOp();
+ return match.getStartIndex(group);
+ }
+
+ private void assertMatchOp()
+ {
+ if (match == null) throw new IllegalStateException();
+ }
+}
diff --git a/libjava/classpath/java/util/regex/Pattern.java b/libjava/classpath/java/util/regex/Pattern.java
new file mode 100644
index 00000000000..6a31ef9bfd2
--- /dev/null
+++ b/libjava/classpath/java/util/regex/Pattern.java
@@ -0,0 +1,254 @@
+/* Pattern.java -- Compiled regular expression ready to be applied.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.regex;
+
+import gnu.regexp.RE;
+import gnu.regexp.REException;
+import gnu.regexp.RESyntax;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+
+/**
+ * Compiled regular expression ready to be applied.
+ *
+ * @since 1.4
+ */
+public final class Pattern implements Serializable
+{
+ private static final long serialVersionUID = 5073258162644648461L;
+
+ public static final int CANON_EQ = 128;
+ public static final int CASE_INSENSITIVE = 2;
+ public static final int COMMENTS = 4;
+ public static final int DOTALL = 32;
+ public static final int MULTILINE = 8;
+ public static final int UNICODE_CASE = 64;
+ public static final int UNIX_LINES = 1;
+
+ private final String regex;
+ private final int flags;
+
+ private final RE re;
+
+ private Pattern (String regex, int flags)
+ throws PatternSyntaxException
+ {
+ this.regex = regex;
+ this.flags = flags;
+
+ int gnuFlags = 0;
+ if ((flags & CASE_INSENSITIVE) != 0)
+ gnuFlags |= RE.REG_ICASE;
+ if ((flags & MULTILINE) != 0)
+ gnuFlags |= RE.REG_MULTILINE;
+ if ((flags & DOTALL) != 0)
+ gnuFlags |= RE.REG_DOT_NEWLINE;
+ // not yet supported:
+ // if ((flags & UNICODE_CASE) != 0) gnuFlags =
+ // 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?
+ syntax = new RESyntax(syntax);
+ syntax.setLineSeparator("\n");
+ }
+
+ if ((flags & COMMENTS) != 0)
+ {
+ // Use a syntax with support for comments?
+ }
+
+ try
+ {
+ this.re = new RE(regex, gnuFlags, syntax);
+ }
+ catch (REException e)
+ {
+ throw new PatternSyntaxException(e.getMessage(),
+ regex, e.getPosition());
+ }
+ }
+
+ // package private accessor method
+ RE getRE()
+ {
+ return re;
+ }
+
+ /**
+ * @param regex The regular expression
+ *
+ * @exception PatternSyntaxException If the expression's syntax is invalid
+ */
+ public static Pattern compile (String regex)
+ throws PatternSyntaxException
+ {
+ return compile(regex, 0);
+ }
+
+ /**
+ * @param regex The regular expression
+ * @param flags The match flags, a bit mask
+ *
+ * @exception PatternSyntaxException If the expression's syntax is invalid
+ * @exception IllegalArgumentException If bit values other than those
+ * corresponding to the defined match flags are set in flags
+ */
+ public static Pattern compile (String regex, int flags)
+ throws PatternSyntaxException
+ {
+ // FIXME: check which flags are really accepted
+ if ((flags & ~0xEF) != 0)
+ throw new IllegalArgumentException ();
+
+ return new Pattern (regex, flags);
+ }
+
+ public int flags ()
+ {
+ return this.flags;
+ }
+
+ /**
+ * @param regex The regular expression
+ * @param input The character sequence to be matched
+ *
+ * @exception PatternSyntaxException If the expression's syntax is invalid
+ */
+ public static boolean matches (String regex, CharSequence input)
+ {
+ return compile(regex).matcher(input).matches();
+ }
+
+ /**
+ * @param input The character sequence to be matched
+ */
+ public Matcher matcher (CharSequence input)
+ {
+ return new Matcher(this, input);
+ }
+
+ /**
+ * @param input The character sequence to be matched
+ */
+ public String[] split (CharSequence input)
+ {
+ return split(input, 0);
+ }
+
+ /**
+ * @param input The character sequence to be matched
+ * @param limit The result threshold
+ */
+ public String[] split (CharSequence input, int limit)
+ {
+ Matcher matcher = new Matcher(this, input);
+ ArrayList list = new ArrayList();
+ int empties = 0;
+ int count = 0;
+ int start = 0;
+ int end;
+ boolean matched = matcher.find();
+
+ while (matched && (limit <= 0 || count < limit - 1))
+ {
+ ++count;
+ end = matcher.start();
+ if (start == end)
+ empties++;
+ else
+ {
+ while (empties > 0)
+ {
+ list.add("");
+ empties--;
+ }
+
+ String text = input.subSequence(start, end).toString();
+ list.add(text);
+ }
+ start = matcher.end();
+ matched = matcher.find();
+ }
+
+ // We matched nothing.
+ if (!matched && count == 0)
+ return new String[] { input.toString() };
+
+ // Is the last token empty?
+ boolean emptyLast = (start == input.length());
+
+ // Can/Must we add empties or an extra last token at the end?
+ if (list.size() < limit || limit < 0 || (limit == 0 && !emptyLast))
+ {
+ if (limit > list.size())
+ {
+ int max = limit - list.size();
+ empties = (empties > max) ? max : empties;
+ }
+ while (empties > 0)
+ {
+ list.add("");
+ empties--;
+ }
+ }
+
+ // last token at end
+ if (limit != 0 || (limit == 0 && !emptyLast))
+ {
+ String t = input.subSequence(start, input.length()).toString();
+ if ("".equals(t) && limit == 0)
+ ; // Don't add.
+ else
+ list.add(t);
+ }
+
+ String[] output = new String [list.size()];
+ list.toArray(output);
+ return output;
+ }
+
+ public String pattern ()
+ {
+ return regex;
+ }
+}
diff --git a/libjava/classpath/java/util/regex/PatternSyntaxException.java b/libjava/classpath/java/util/regex/PatternSyntaxException.java
new file mode 100644
index 00000000000..0c80e119c37
--- /dev/null
+++ b/libjava/classpath/java/util/regex/PatternSyntaxException.java
@@ -0,0 +1,132 @@
+/* PatternSyntaxException - Indicates illegal pattern for regular expression.
+ Copyright (C) 2002 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.regex;
+
+/**
+ * Indicates illegal pattern for regular expression.
+ * Includes state to inspect the pattern and what and where the expression
+ * was not valid regular expression.
+ */
+public class PatternSyntaxException extends IllegalArgumentException
+{
+ private static final long serialVersionUID = -3864639126226059218L;
+
+ /**
+ * Human readable escription of the syntax error.
+ */
+ private final String desc;
+
+ /**
+ * The original pattern that contained the syntax error.
+ */
+ private final String pattern;
+
+ /**
+ * Index of the first character in the String that was probably invalid,
+ * or -1 when unknown.
+ */
+ private final int index;
+
+ /**
+ * Creates a new PatternSyntaxException.
+ *
+ * @param description Human readable escription of the syntax error.
+ * @param pattern The original pattern that contained the syntax error.
+ * @param index Index of the first character in the String that was
+ * probably invalid, or -1 when unknown.
+ */
+ public PatternSyntaxException(String description,
+ String pattern,
+ int index)
+ {
+ super(description);
+ this.desc = description;
+ this.pattern = pattern;
+ this.index = index;
+ }
+
+ /**
+ * Returns a human readable escription of the syntax error.
+ */
+ public String getDescription()
+ {
+ return desc;
+ }
+
+ /**
+ * Returns the original pattern that contained the syntax error.
+ */
+ public String getPattern()
+ {
+ return pattern;
+ }
+
+ /**
+ * Returns the index of the first character in the String that was probably
+ * invalid, or -1 when unknown.
+ */
+ public int getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * Returns a string containing a line with the description, a line with
+ * the original pattern and a line indicating with a ^ which character is
+ * probably the first invalid character in the pattern if the index is not
+ * negative.
+ */
+ public String getMessage()
+ {
+ String lineSep = System.getProperty("line.separator");
+ StringBuffer sb = new StringBuffer(desc);
+ sb.append(lineSep);
+ sb.append('\t');
+ sb.append(pattern);
+ if (index != -1)
+ {
+ sb.append(lineSep);
+ sb.append('\t');
+ for (int i=0; i<index; i++)
+ sb.append(' ');
+ sb.append('^');
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/libjava/classpath/java/util/regex/package.html b/libjava/classpath/java/util/regex/package.html
new file mode 100644
index 00000000000..0573a360c38
--- /dev/null
+++ b/libjava/classpath/java/util/regex/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.util.regex package.
+ Copyright (C) 2002 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 - java.util.regex</title></head>
+
+<body>
+<p>Regular expression patterns and matchers.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/util/zip/Adler32.java b/libjava/classpath/java/util/zip/Adler32.java
new file mode 100644
index 00000000000..7c411384057
--- /dev/null
+++ b/libjava/classpath/java/util/zip/Adler32.java
@@ -0,0 +1,205 @@
+/* Adler32.java - Computes Adler32 data checksum of a data stream
+ Copyright (C) 1999, 2000, 2001 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.zip;
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * The actual Adler32 algorithm is taken from RFC 1950.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * Computes Adler32 checksum for a stream of data. An Adler32
+ * checksum is not as reliable as a CRC32 checksum, but a lot faster to
+ * compute.
+ *<p>
+ * The specification for Adler32 may be found in RFC 1950.
+ * (ZLIB Compressed Data Format Specification version 3.3)
+ *<p>
+ *<p>
+ * From that document:
+ *<p>
+ * "ADLER32 (Adler-32 checksum)
+ * This contains a checksum value of the uncompressed data
+ * (excluding any dictionary data) computed according to Adler-32
+ * algorithm. This algorithm is a 32-bit extension and improvement
+ * of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
+ * standard.
+ *<p>
+ * Adler-32 is composed of two sums accumulated per byte: s1 is
+ * the sum of all bytes, s2 is the sum of all s1 values. Both sums
+ * are done modulo 65521. s1 is initialized to 1, s2 to zero. The
+ * Adler-32 checksum is stored as s2*65536 + s1 in most-
+ * significant-byte first (network) order."
+ *<p>
+ * "8.2. The Adler-32 algorithm
+ *<p>
+ * The Adler-32 algorithm is much faster than the CRC32 algorithm yet
+ * still provides an extremely low probability of undetected errors.
+ *<p>
+ * The modulo on unsigned long accumulators can be delayed for 5552
+ * bytes, so the modulo operation time is negligible. If the bytes
+ * are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
+ * and order sensitive, unlike the first sum, which is just a
+ * checksum. That 65521 is prime is important to avoid a possible
+ * large class of two-byte errors that leave the check unchanged.
+ * (The Fletcher checksum uses 255, which is not prime and which also
+ * makes the Fletcher check insensitive to single byte changes 0 <->
+ * 255.)
+ *<p>
+ * The sum s1 is initialized to 1 instead of zero to make the length
+ * of the sequence part of s2, so that the length does not have to be
+ * checked separately. (Any sequence of zeroes has a Fletcher
+ * checksum of zero.)"
+ *
+ * @author John Leuner, Per Bothner
+ * @since JDK 1.1
+ *
+ * @see InflaterInputStream
+ * @see DeflaterOutputStream
+ */
+public class Adler32 implements Checksum
+{
+
+ /** largest prime smaller than 65536 */
+ private static final int BASE = 65521;
+
+ private int checksum; //we do all in int.
+
+ //Note that java doesn't have unsigned integers,
+ //so we have to be careful with what arithmetic
+ //we do. We return the checksum as a long to
+ //avoid sign confusion.
+
+ /**
+ * Creates a new instance of the <code>Adler32</code> class.
+ * The checksum starts off with a value of 1.
+ */
+ public Adler32 ()
+ {
+ reset();
+ }
+
+ /**
+ * Resets the Adler32 checksum to the initial value.
+ */
+ public void reset ()
+ {
+ checksum = 1; //Initialize to 1
+ }
+
+ /**
+ * Updates the checksum with the byte b.
+ *
+ * @param bval the data value to add. The high byte of the int is ignored.
+ */
+ public void update (int bval)
+ {
+ //We could make a length 1 byte array and call update again, but I
+ //would rather not have that overhead
+ int s1 = checksum & 0xffff;
+ int s2 = checksum >>> 16;
+
+ s1 = (s1 + (bval & 0xFF)) % BASE;
+ s2 = (s1 + s2) % BASE;
+
+ checksum = (s2 << 16) + s1;
+ }
+
+ /**
+ * Updates the checksum with the bytes taken from the array.
+ *
+ * @param buffer an array of bytes
+ */
+ public void update (byte[] buffer)
+ {
+ update(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Updates the checksum with the bytes taken from the array.
+ *
+ * @param buf an array of bytes
+ * @param off the start of the data used for this update
+ * @param len the number of bytes to use for this update
+ */
+ public void update (byte[] buf, int off, int len)
+ {
+ //(By Per Bothner)
+ int s1 = checksum & 0xffff;
+ int s2 = checksum >>> 16;
+
+ while (len > 0)
+ {
+ // We can defer the modulo operation:
+ // s1 maximally grows from 65521 to 65521 + 255 * 3800
+ // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
+ int n = 3800;
+ if (n > len)
+ n = len;
+ len -= n;
+ while (--n >= 0)
+ {
+ s1 = s1 + (buf[off++] & 0xFF);
+ s2 = s2 + s1;
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+
+ /*Old implementation, borrowed from somewhere:
+ int n;
+
+ while (len-- > 0) {
+
+ s1 = (s1 + (bs[offset++] & 0xff)) % BASE;
+ s2 = (s2 + s1) % BASE;
+ }*/
+
+ checksum = (s2 << 16) | s1;
+ }
+
+ /**
+ * Returns the Adler32 data checksum computed so far.
+ */
+ public long getValue()
+ {
+ return (long) checksum & 0xffffffffL;
+ }
+}
diff --git a/libjava/classpath/java/util/zip/CRC32.java b/libjava/classpath/java/util/zip/CRC32.java
new file mode 100644
index 00000000000..1c2b3973852
--- /dev/null
+++ b/libjava/classpath/java/util/zip/CRC32.java
@@ -0,0 +1,132 @@
+/* CRC32.java - Computes CRC32 data checksum of a data stream
+ Copyright (C) 1999. 2000, 2001 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.zip;
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * The actual CRC32 algorithm is taken from RFC 1952.
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * Computes CRC32 data checksum of a data stream.
+ * The actual CRC32 algorithm is described in RFC 1952
+ * (GZIP file format specification version 4.3).
+ * Can be used to get the CRC32 over a stream if used with checked input/output
+ * streams.
+ *
+ * @see InflaterInputStream
+ * @see DeflaterOutputStream
+ *
+ * @author Per Bothner
+ * @date April 1, 1999.
+ */
+public class CRC32 implements Checksum
+{
+ /** The crc data checksum so far. */
+ private int crc = 0;
+
+ /** The fast CRC table. Computed once when the CRC32 class is loaded. */
+ private static int[] crc_table = make_crc_table();
+
+ /** Make the table for a fast CRC. */
+ private static int[] make_crc_table ()
+ {
+ int[] crc_table = new int[256];
+ for (int n = 0; n < 256; n++)
+ {
+ int c = n;
+ for (int k = 8; --k >= 0; )
+ {
+ if ((c & 1) != 0)
+ c = 0xedb88320 ^ (c >>> 1);
+ else
+ c = c >>> 1;
+ }
+ crc_table[n] = c;
+ }
+ return crc_table;
+ }
+
+ /**
+ * Returns the CRC32 data checksum computed so far.
+ */
+ public long getValue ()
+ {
+ return (long) crc & 0xffffffffL;
+ }
+
+ /**
+ * Resets the CRC32 data checksum as if no update was ever called.
+ */
+ public void reset () { crc = 0; }
+
+ /**
+ * Updates the checksum with the int bval.
+ *
+ * @param bval (the byte is taken as the lower 8 bits of bval)
+ */
+
+ public void update (int bval)
+ {
+ int c = ~crc;
+ c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8);
+ crc = ~c;
+ }
+
+ /**
+ * Adds the byte array to the data checksum.
+ *
+ * @param buf the buffer which contains the data
+ * @param off the offset in the buffer where the data starts
+ * @param len the length of the data
+ */
+ public void update (byte[] buf, int off, int len)
+ {
+ int c = ~crc;
+ while (--len >= 0)
+ c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);
+ crc = ~c;
+ }
+
+ /**
+ * Adds the complete byte array to the data checksum.
+ */
+ public void update (byte[] buf) { update(buf, 0, buf.length); }
+}
diff --git a/libjava/classpath/java/util/zip/CheckedInputStream.java b/libjava/classpath/java/util/zip/CheckedInputStream.java
new file mode 100644
index 00000000000..d743fbb2447
--- /dev/null
+++ b/libjava/classpath/java/util/zip/CheckedInputStream.java
@@ -0,0 +1,135 @@
+/* CheckedInputStream.java - Compute checksum of data being read
+ Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.zip;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+/**
+ * InputStream that computes a checksum of the data being read using a
+ * supplied Checksum object.
+ *
+ * @see Checksum
+ *
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+public class CheckedInputStream extends FilterInputStream
+{
+ /**
+ * Creates a new CheckInputStream on top of the supplied OutputStream
+ * using the supplied Checksum.
+ */
+ public CheckedInputStream (InputStream in, Checksum sum)
+ {
+ super (in);
+ this.sum = sum;
+ }
+
+ /**
+ * Returns the Checksum object used. To get the data checksum computed so
+ * far call <code>getChecksum.getValue()</code>.
+ */
+ public Checksum getChecksum ()
+ {
+ return sum;
+ }
+
+ /**
+ * Reads one byte, updates the checksum and returns the read byte
+ * (or -1 when the end of file was reached).
+ */
+ public int read () throws IOException
+ {
+ int x = in.read();
+ if (x != -1)
+ sum.update(x);
+ return x;
+ }
+
+ /**
+ * Reads at most len bytes in the supplied buffer and updates the checksum
+ * with it. Returns the number of bytes actually read or -1 when the end
+ * of file was reached.
+ */
+ public int read (byte[] buf, int off, int len) throws IOException
+ {
+ int r = in.read(buf, off, len);
+ if (r != -1)
+ sum.update(buf, off, r);
+ return r;
+ }
+
+ /**
+ * Skips n bytes by reading them in a temporary buffer and updating the
+ * the checksum with that buffer. Returns the actual number of bytes skiped
+ * which can be less then requested when the end of file is reached.
+ */
+ public long skip (long n) throws IOException
+ {
+ if (n == 0)
+ return 0;
+
+ int min = (int) Math.min(n, 1024);
+ byte[] buf = new byte[min];
+
+ long s = 0;
+ while (n > 0)
+ {
+ int r = in.read(buf, 0, min);
+ if (r == -1)
+ break;
+ n -= r;
+ s += r;
+ min = (int) Math.min(n, 1024);
+ sum.update(buf, 0, r);
+ }
+
+ return s;
+ }
+
+ /** The checksum object. */
+ private Checksum sum;
+}
diff --git a/libjava/classpath/java/util/zip/CheckedOutputStream.java b/libjava/classpath/java/util/zip/CheckedOutputStream.java
new file mode 100644
index 00000000000..a3c19292fae
--- /dev/null
+++ b/libjava/classpath/java/util/zip/CheckedOutputStream.java
@@ -0,0 +1,100 @@
+/* CheckedOutputStream.java - Compute checksum of data being written.
+ Copyright (C) 1999, 2000 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.zip;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+/**
+ * OutputStream that computes a checksum of data being written using a
+ * supplied Checksum object.
+ *
+ * @see Checksum
+ *
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+public class CheckedOutputStream extends FilterOutputStream
+{
+ /**
+ * Creates a new CheckInputStream on top of the supplied OutputStream
+ * using the supplied Checksum.
+ */
+ public CheckedOutputStream (OutputStream out, Checksum cksum)
+ {
+ super (out);
+ this.sum = cksum;
+ }
+
+ /**
+ * Returns the Checksum object used. To get the data checksum computed so
+ * far call <code>getChecksum.getValue()</code>.
+ */
+ public Checksum getChecksum ()
+ {
+ return sum;
+ }
+
+ /**
+ * Writes one byte to the OutputStream and updates the Checksum.
+ */
+ public void write (int bval) throws IOException
+ {
+ out.write(bval);
+ sum.update(bval);
+ }
+
+ /**
+ * Writes the byte array to the OutputStream and updates the Checksum.
+ */
+ public void write (byte[] buf, int off, int len) throws IOException
+ {
+ out.write(buf, off, len);
+ sum.update(buf, off, len);
+ }
+
+ /** The checksum object. */
+ private Checksum sum;
+}
diff --git a/libjava/classpath/java/util/zip/Checksum.java b/libjava/classpath/java/util/zip/Checksum.java
new file mode 100644
index 00000000000..3342ba3a609
--- /dev/null
+++ b/libjava/classpath/java/util/zip/Checksum.java
@@ -0,0 +1,86 @@
+/* Checksum.java - Interface to compute a data checksum
+ Copyright (C) 1999, 2000, 2001 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.zip;
+
+/*
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+/**
+ * Interface to compute a data checksum used by checked input/output streams.
+ * A data checksum can be updated by one byte or with a byte array. After each
+ * update the value of the current checksum can be returned by calling
+ * <code>getValue</code>. The complete checksum object can also be reset
+ * so it can be used again with new data.
+ *
+ * @see CheckedInputStream
+ * @see CheckedOutputStream
+ *
+ * @author Per Bothner
+ * @author Jochen Hoenicke
+ */
+public interface Checksum
+{
+ /**
+ * Returns the data checksum computed so far.
+ */
+ long getValue();
+
+ /**
+ * Resets the data checksum as if no update was ever called.
+ */
+ void reset();
+
+ /**
+ * Adds one byte to the data checksum.
+ *
+ * @param bval the data value to add. The high byte of the int is ignored.
+ */
+ void update (int bval);
+
+ /**
+ * Adds the byte array to the data checksum.
+ *
+ * @param buf the buffer which contains the data
+ * @param off the offset in the buffer where the data starts
+ * @param len the length of the data
+ */
+ void update (byte[] buf, int off, int len);
+}
diff --git a/libjava/classpath/java/util/zip/DataFormatException.java b/libjava/classpath/java/util/zip/DataFormatException.java
new file mode 100644
index 00000000000..dc5b10dec90
--- /dev/null
+++ b/libjava/classpath/java/util/zip/DataFormatException.java
@@ -0,0 +1,71 @@
+/* DataformatException.java -- thrown when compressed data is corrupt
+ Copyright (C) 1999, 2000, 2001, 2002 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.zip;
+
+/**
+ * Exception thrown when compressed data is corrupt.
+ *
+ * @author Tom Tromey
+ * @author John Leuner
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class DataFormatException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 2219632870893641452L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public DataFormatException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param msg the message
+ */
+ public DataFormatException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/util/zip/Deflater.java b/libjava/classpath/java/util/zip/Deflater.java
new file mode 100644
index 00000000000..7bc1a1911eb
--- /dev/null
+++ b/libjava/classpath/java/util/zip/Deflater.java
@@ -0,0 +1,520 @@
+/* Deflater.java - Compress a data stream
+ Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.zip;
+
+/**
+ * This is the Deflater class. The deflater class compresses input
+ * with the deflate algorithm described in RFC 1951. It has several
+ * compression levels and three different strategies described below.
+ *
+ * This class is <i>not</i> thread safe. This is inherent in the API, due
+ * to the split of deflate and setInput.
+ *
+ * @author Jochen Hoenicke
+ * @author Tom Tromey
+ */
+public class Deflater
+{
+ /**
+ * The best and slowest compression level. This tries to find very
+ * long and distant string repetitions.
+ */
+ public static final int BEST_COMPRESSION = 9;
+ /**
+ * The worst but fastest compression level.
+ */
+ public static final int BEST_SPEED = 1;
+ /**
+ * The default compression level.
+ */
+ public static final int DEFAULT_COMPRESSION = -1;
+ /**
+ * This level won't compress at all but output uncompressed blocks.
+ */
+ public static final int NO_COMPRESSION = 0;
+
+ /**
+ * The default strategy.
+ */
+ public static final int DEFAULT_STRATEGY = 0;
+ /**
+ * This strategy will only allow longer string repetitions. It is
+ * useful for random data with a small character set.
+ */
+ public static final int FILTERED = 1;
+
+ /**
+ * This strategy will not look for string repetitions at all. It
+ * only encodes with Huffman trees (which means, that more common
+ * characters get a smaller encoding.
+ */
+ public static final int HUFFMAN_ONLY = 2;
+
+ /**
+ * The compression method. This is the only method supported so far.
+ * There is no need to use this constant at all.
+ */
+ public static final int DEFLATED = 8;
+
+ /*
+ * The Deflater can do the following state transitions:
+ *
+ * (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---.
+ * / | (2) (5) |
+ * / v (5) |
+ * (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3)
+ * \ | (3) | ,-------'
+ * | | | (3) /
+ * v v (5) v v
+ * (1) -> BUSY_STATE ----> FINISHING_STATE
+ * | (6)
+ * v
+ * FINISHED_STATE
+ * \_____________________________________/
+ * | (7)
+ * v
+ * CLOSED_STATE
+ *
+ * (1) If we should produce a header we start in INIT_STATE, otherwise
+ * we start in BUSY_STATE.
+ * (2) A dictionary may be set only when we are in INIT_STATE, then
+ * we change the state as indicated.
+ * (3) Whether a dictionary is set or not, on the first call of deflate
+ * we change to BUSY_STATE.
+ * (4) -- intentionally left blank -- :)
+ * (5) FINISHING_STATE is entered, when flush() is called to indicate that
+ * there is no more INPUT. There are also states indicating, that
+ * the header wasn't written yet.
+ * (6) FINISHED_STATE is entered, when everything has been flushed to the
+ * internal pending output buffer.
+ * (7) At any time (7)
+ *
+ */
+
+ private static final int IS_SETDICT = 0x01;
+ private static final int IS_FLUSHING = 0x04;
+ private static final int IS_FINISHING = 0x08;
+
+ private static final int INIT_STATE = 0x00;
+ private static final int SETDICT_STATE = 0x01;
+ private static final int INIT_FINISHING_STATE = 0x08;
+ private static final int SETDICT_FINISHING_STATE = 0x09;
+ private static final int BUSY_STATE = 0x10;
+ private static final int FLUSHING_STATE = 0x14;
+ private static final int FINISHING_STATE = 0x1c;
+ private static final int FINISHED_STATE = 0x1e;
+ private static final int CLOSED_STATE = 0x7f;
+
+ /** Compression level. */
+ private int level;
+
+ /** should we include a header. */
+ private boolean noHeader;
+
+ /** The current state. */
+ private int state;
+
+ /** The total bytes of output written. */
+ private int totalOut;
+
+ /** The pending output. */
+ private DeflaterPending pending;
+
+ /** The deflater engine. */
+ private DeflaterEngine engine;
+
+ /**
+ * Creates a new deflater with default compression level.
+ */
+ public Deflater()
+ {
+ this(DEFAULT_COMPRESSION, false);
+ }
+
+ /**
+ * Creates a new deflater with given compression level.
+ * @param lvl the compression level, a value between NO_COMPRESSION
+ * and BEST_COMPRESSION, or DEFAULT_COMPRESSION.
+ * @exception IllegalArgumentException if lvl is out of range.
+ */
+ public Deflater(int lvl)
+ {
+ this(lvl, false);
+ }
+
+ /**
+ * Creates a new deflater with given compression level.
+ * @param lvl the compression level, a value between NO_COMPRESSION
+ * and BEST_COMPRESSION.
+ * @param nowrap true, iff we should suppress the deflate header at the
+ * beginning and the adler checksum at the end of the output. This is
+ * useful for the GZIP format.
+ * @exception IllegalArgumentException if lvl is out of range.
+ */
+ public Deflater(int lvl, boolean nowrap)
+ {
+ if (lvl == DEFAULT_COMPRESSION)
+ lvl = 6;
+ else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION)
+ throw new IllegalArgumentException();
+
+ pending = new DeflaterPending();
+ engine = new DeflaterEngine(pending);
+ this.noHeader = nowrap;
+ setStrategy(DEFAULT_STRATEGY);
+ setLevel(lvl);
+ reset();
+ }
+
+ /**
+ * Resets the deflater. The deflater acts afterwards as if it was
+ * just created with the same compression level and strategy as it
+ * had before.
+ */
+ public void reset()
+ {
+ state = (noHeader ? BUSY_STATE : INIT_STATE);
+ totalOut = 0;
+ pending.reset();
+ engine.reset();
+ }
+
+ /**
+ * Frees all objects allocated by the compressor. There's no
+ * reason to call this, since you can just rely on garbage
+ * collection. Exists only for compatibility against Sun's JDK,
+ * where the compressor allocates native memory.
+ * If you call any method (even reset) afterwards the behaviour is
+ * <i>undefined</i>.
+ * @deprecated Just clear all references to deflater instead.
+ */
+ public void end()
+ {
+ engine = null;
+ pending = null;
+ state = CLOSED_STATE;
+ }
+
+ /**
+ * Gets the current adler checksum of the data that was processed so
+ * far.
+ */
+ public int getAdler()
+ {
+ return engine.getAdler();
+ }
+
+ /**
+ * Gets the number of input bytes processed so far.
+ */
+ public int getTotalIn()
+ {
+ return engine.getTotalIn();
+ }
+
+ /**
+ * Gets the number of output bytes so far.
+ */
+ public int getTotalOut()
+ {
+ return totalOut;
+ }
+
+ /**
+ * Finalizes this object.
+ */
+ protected void finalize()
+ {
+ /* Exists solely for compatibility. We don't have any native state. */
+ }
+
+ /**
+ * Flushes the current input block. Further calls to deflate() will
+ * produce enough output to inflate everything in the current input
+ * block. This is not part of Sun's JDK so I have made it package
+ * private. It is used by DeflaterOutputStream to implement
+ * flush().
+ */
+ void flush() {
+ state |= IS_FLUSHING;
+ }
+
+ /**
+ * Finishes the deflater with the current input block. It is an error
+ * to give more input after this method was called. This method must
+ * be called to force all bytes to be flushed.
+ */
+ public void finish() {
+ state |= IS_FLUSHING | IS_FINISHING;
+ }
+
+ /**
+ * Returns true iff the stream was finished and no more output bytes
+ * are available.
+ */
+ public boolean finished()
+ {
+ return state == FINISHED_STATE && pending.isFlushed();
+ }
+
+ /**
+ * Returns true, if the input buffer is empty.
+ * You should then call setInput(). <br>
+ *
+ * <em>NOTE</em>: This method can also return true when the stream
+ * was finished.
+ */
+ public boolean needsInput()
+ {
+ return engine.needsInput();
+ }
+
+ /**
+ * Sets the data which should be compressed next. This should be only
+ * called when needsInput indicates that more input is needed.
+ * If you call setInput when needsInput() returns false, the
+ * previous input that is still pending will be thrown away.
+ * The given byte array should not be changed, before needsInput() returns
+ * true again.
+ * This call is equivalent to <code>setInput(input, 0, input.length)</code>.
+ * @param input the buffer containing the input data.
+ * @exception IllegalStateException if the buffer was finished() or ended().
+ */
+ public void setInput(byte[] input)
+ {
+ setInput(input, 0, input.length);
+ }
+
+ /**
+ * Sets the data which should be compressed next. This should be
+ * only called when needsInput indicates that more input is needed.
+ * The given byte array should not be changed, before needsInput() returns
+ * true again.
+ * @param input the buffer containing the input data.
+ * @param off the start of the data.
+ * @param len the length of the data.
+ * @exception IllegalStateException if the buffer was finished() or ended()
+ * or if previous input is still pending.
+ */
+ public void setInput(byte[] input, int off, int len)
+ {
+ if ((state & IS_FINISHING) != 0)
+ throw new IllegalStateException("finish()/end() already called");
+ engine.setInput(input, off, len);
+ }
+
+ /**
+ * Sets the compression level. There is no guarantee of the exact
+ * position of the change, but if you call this when needsInput is
+ * true the change of compression level will occur somewhere near
+ * before the end of the so far given input.
+ * @param lvl the new compression level.
+ */
+ public void setLevel(int lvl)
+ {
+ if (lvl == DEFAULT_COMPRESSION)
+ lvl = 6;
+ else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION)
+ throw new IllegalArgumentException();
+
+
+ if (level != lvl)
+ {
+ level = lvl;
+ engine.setLevel(lvl);
+ }
+ }
+
+ /**
+ * Sets the compression strategy. Strategy is one of
+ * DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact
+ * position where the strategy is changed, the same as for
+ * setLevel() applies.
+ * @param stgy the new compression strategy.
+ */
+ public void setStrategy(int stgy)
+ {
+ if (stgy != DEFAULT_STRATEGY && stgy != FILTERED
+ && stgy != HUFFMAN_ONLY)
+ throw new IllegalArgumentException();
+ engine.setStrategy(stgy);
+ }
+
+ /**
+ * Deflates the current input block to the given array. It returns
+ * the number of bytes compressed, or 0 if either
+ * needsInput() or finished() returns true or length is zero.
+ * @param output the buffer where to write the compressed data.
+ */
+ public int deflate(byte[] output)
+ {
+ return deflate(output, 0, output.length);
+ }
+
+ /**
+ * Deflates the current input block to the given array. It returns
+ * the number of bytes compressed, or 0 if either
+ * needsInput() or finished() returns true or length is zero.
+ * @param output the buffer where to write the compressed data.
+ * @param offset the offset into the output array.
+ * @param length the maximum number of bytes that may be written.
+ * @exception IllegalStateException if end() was called.
+ * @exception IndexOutOfBoundsException if offset and/or length
+ * don't match the array length.
+ */
+ public int deflate(byte[] output, int offset, int length)
+ {
+ int origLength = length;
+
+ if (state == CLOSED_STATE)
+ throw new IllegalStateException("Deflater closed");
+
+ if (state < BUSY_STATE)
+ {
+ /* output header */
+ int header = (DEFLATED +
+ ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;
+ int level_flags = (level - 1) >> 1;
+ if (level_flags < 0 || level_flags > 3)
+ level_flags = 3;
+ header |= level_flags << 6;
+ if ((state & IS_SETDICT) != 0)
+ /* Dictionary was set */
+ header |= DeflaterConstants.PRESET_DICT;
+ header += 31 - (header % 31);
+
+ pending.writeShortMSB(header);
+ if ((state & IS_SETDICT) != 0)
+ {
+ int chksum = engine.getAdler();
+ engine.resetAdler();
+ pending.writeShortMSB(chksum >> 16);
+ pending.writeShortMSB(chksum & 0xffff);
+ }
+
+ state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING));
+ }
+
+ for (;;)
+ {
+ int count = pending.flush(output, offset, length);
+ offset += count;
+ totalOut += count;
+ length -= count;
+ if (length == 0 || state == FINISHED_STATE)
+ break;
+
+ if (!engine.deflate((state & IS_FLUSHING) != 0,
+ (state & IS_FINISHING) != 0))
+ {
+ if (state == BUSY_STATE)
+ /* We need more input now */
+ return origLength - length;
+ else if (state == FLUSHING_STATE)
+ {
+ if (level != NO_COMPRESSION)
+ {
+ /* We have to supply some lookahead. 8 bit lookahead
+ * are needed by the zlib inflater, and we must fill
+ * the next byte, so that all bits are flushed.
+ */
+ int neededbits = 8 + ((-pending.getBitCount()) & 7);
+ while (neededbits > 0)
+ {
+ /* write a static tree block consisting solely of
+ * an EOF:
+ */
+ pending.writeBits(2, 10);
+ neededbits -= 10;
+ }
+ }
+ state = BUSY_STATE;
+ }
+ else if (state == FINISHING_STATE)
+ {
+ pending.alignToByte();
+ /* We have completed the stream */
+ if (!noHeader)
+ {
+ int adler = engine.getAdler();
+ pending.writeShortMSB(adler >> 16);
+ pending.writeShortMSB(adler & 0xffff);
+ }
+ state = FINISHED_STATE;
+ }
+ }
+ }
+
+ return origLength - length;
+ }
+
+ /**
+ * Sets the dictionary which should be used in the deflate process.
+ * This call is equivalent to <code>setDictionary(dict, 0,
+ * dict.length)</code>.
+ * @param dict the dictionary.
+ * @exception IllegalStateException if setInput () or deflate ()
+ * were already called or another dictionary was already set.
+ */
+ public void setDictionary(byte[] dict)
+ {
+ setDictionary(dict, 0, dict.length);
+ }
+
+ /**
+ * Sets the dictionary which should be used in the deflate process.
+ * The dictionary should be a byte array containing strings that are
+ * likely to occur in the data which should be compressed. The
+ * dictionary is not stored in the compressed output, only a
+ * checksum. To decompress the output you need to supply the same
+ * dictionary again.
+ * @param dict the dictionary.
+ * @param offset an offset into the dictionary.
+ * @param length the length of the dictionary.
+ * @exception IllegalStateException if setInput () or deflate () were
+ * already called or another dictionary was already set.
+ */
+ public void setDictionary(byte[] dict, int offset, int length)
+ {
+ if (state != INIT_STATE)
+ throw new IllegalStateException();
+
+ state = SETDICT_STATE;
+ engine.setDictionary(dict, offset, length);
+ }
+}
diff --git a/libjava/classpath/java/util/zip/DeflaterConstants.java b/libjava/classpath/java/util/zip/DeflaterConstants.java
new file mode 100644
index 00000000000..bfef86344a6
--- /dev/null
+++ b/libjava/classpath/java/util/zip/DeflaterConstants.java
@@ -0,0 +1,78 @@
+/* java.util.zip.DeflaterConstants
+ Copyright (C) 2001 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.zip;
+
+interface DeflaterConstants
+{
+ boolean DEBUGGING = false;
+
+ int STORED_BLOCK = 0;
+ int STATIC_TREES = 1;
+ int DYN_TREES = 2;
+ int PRESET_DICT = 0x20;
+
+ int DEFAULT_MEM_LEVEL = 8;
+
+ int MAX_MATCH = 258;
+ int MIN_MATCH = 3;
+
+ int MAX_WBITS = 15;
+ int WSIZE = 1 << MAX_WBITS;
+ int WMASK = WSIZE - 1;
+
+ int HASH_BITS = DEFAULT_MEM_LEVEL + 7;
+ int HASH_SIZE = 1 << HASH_BITS;
+ int HASH_MASK = HASH_SIZE - 1;
+ int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH;
+
+ int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
+ int MAX_DIST = WSIZE - MIN_LOOKAHEAD;
+
+ int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8);
+ int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE-5);
+
+ int DEFLATE_STORED = 0;
+ int DEFLATE_FAST = 1;
+ int DEFLATE_SLOW = 2;
+
+ int GOOD_LENGTH[] = { 0,4, 4, 4, 4, 8, 8, 8, 32, 32 };
+ int MAX_LAZY[] = { 0,4, 5, 6, 4,16, 16, 32, 128, 258 };
+ int NICE_LENGTH[] = { 0,8,16,32,16,32,128,128, 258, 258 };
+ int MAX_CHAIN[] = { 0,4, 8,32,16,32,128,256,1024,4096 };
+ int COMPR_FUNC[] = { 0,1, 1, 1, 1, 2, 2, 2, 2, 2 };
+}
diff --git a/libjava/classpath/java/util/zip/DeflaterEngine.java b/libjava/classpath/java/util/zip/DeflaterEngine.java
new file mode 100644
index 00000000000..3eea7c250fc
--- /dev/null
+++ b/libjava/classpath/java/util/zip/DeflaterEngine.java
@@ -0,0 +1,696 @@
+/* DeflaterEngine.java --
+ Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.zip;
+
+class DeflaterEngine implements DeflaterConstants
+{
+ private static final int TOO_FAR = 4096;
+
+ private int ins_h;
+
+ /**
+ * Hashtable, hashing three characters to an index for window, so
+ * that window[index]..window[index+2] have this hash code.
+ * Note that the array should really be unsigned short, so you need
+ * to and the values with 0xffff.
+ */
+ private short[] head;
+
+ /**
+ * prev[index & WMASK] points to the previous index that has the
+ * same hash code as the string starting at index. This way
+ * entries with the same hash code are in a linked list.
+ * Note that the array should really be unsigned short, so you need
+ * to and the values with 0xffff.
+ */
+ private short[] prev;
+
+ private int matchStart, matchLen;
+ private boolean prevAvailable;
+ private int blockStart;
+
+ /**
+ * strstart points to the current character in window.
+ */
+ private int strstart;
+
+ /**
+ * lookahead is the number of characters starting at strstart in
+ * window that are valid.
+ * So window[strstart] until window[strstart+lookahead-1] are valid
+ * characters.
+ */
+ private int lookahead;
+
+ /**
+ * This array contains the part of the uncompressed stream that
+ * is of relevance. The current character is indexed by strstart.
+ */
+ private byte[] window;
+
+ private int strategy, max_chain, max_lazy, niceLength, goodLength;
+
+ /** The current compression function. */
+ private int comprFunc;
+
+ /** The input data for compression. */
+ private byte[] inputBuf;
+
+ /** The total bytes of input read. */
+ private int totalIn;
+
+ /** The offset into inputBuf, where input data starts. */
+ private int inputOff;
+
+ /** The end offset of the input data. */
+ private int inputEnd;
+
+ private DeflaterPending pending;
+ private DeflaterHuffman huffman;
+
+ /** The adler checksum */
+ private Adler32 adler;
+
+ /* DEFLATE ALGORITHM:
+ *
+ * The uncompressed stream is inserted into the window array. When
+ * the window array is full the first half is thrown away and the
+ * second half is copied to the beginning.
+ *
+ * The head array is a hash table. Three characters build a hash value
+ * and they the value points to the corresponding index in window of
+ * the last string with this hash. The prev array implements a
+ * linked list of matches with the same hash: prev[index & WMASK] points
+ * to the previous index with the same hash.
+ *
+ *
+ */
+
+
+ DeflaterEngine(DeflaterPending pending) {
+ this.pending = pending;
+ huffman = new DeflaterHuffman(pending);
+ adler = new Adler32();
+
+ window = new byte[2*WSIZE];
+ head = new short[HASH_SIZE];
+ prev = new short[WSIZE];
+
+ /* We start at index 1, to avoid a implementation deficiency, that
+ * we cannot build a repeat pattern at index 0.
+ */
+ blockStart = strstart = 1;
+ }
+
+ public void reset()
+ {
+ huffman.reset();
+ adler.reset();
+ blockStart = strstart = 1;
+ lookahead = 0;
+ totalIn = 0;
+ prevAvailable = false;
+ matchLen = MIN_MATCH - 1;
+ for (int i = 0; i < HASH_SIZE; i++)
+ head[i] = 0;
+ for (int i = 0; i < WSIZE; i++)
+ prev[i] = 0;
+ }
+
+ public final void resetAdler()
+ {
+ adler.reset();
+ }
+
+ public final int getAdler()
+ {
+ int chksum = (int) adler.getValue();
+ return chksum;
+ }
+
+ public final int getTotalIn()
+ {
+ return totalIn;
+ }
+
+ public final void setStrategy(int strat)
+ {
+ strategy = strat;
+ }
+
+ public void setLevel(int lvl)
+ {
+ goodLength = DeflaterConstants.GOOD_LENGTH[lvl];
+ max_lazy = DeflaterConstants.MAX_LAZY[lvl];
+ niceLength = DeflaterConstants.NICE_LENGTH[lvl];
+ max_chain = DeflaterConstants.MAX_CHAIN[lvl];
+
+ if (DeflaterConstants.COMPR_FUNC[lvl] != comprFunc)
+ {
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("Change from "+comprFunc +" to "
+ + DeflaterConstants.COMPR_FUNC[lvl]);
+ switch (comprFunc)
+ {
+ case DEFLATE_STORED:
+ if (strstart > blockStart)
+ {
+ huffman.flushStoredBlock(window, blockStart,
+ strstart - blockStart, false);
+ blockStart = strstart;
+ }
+ updateHash();
+ break;
+ case DEFLATE_FAST:
+ if (strstart > blockStart)
+ {
+ huffman.flushBlock(window, blockStart, strstart - blockStart,
+ false);
+ blockStart = strstart;
+ }
+ break;
+ case DEFLATE_SLOW:
+ if (prevAvailable)
+ huffman.tallyLit(window[strstart-1] & 0xff);
+ if (strstart > blockStart)
+ {
+ huffman.flushBlock(window, blockStart, strstart - blockStart,
+ false);
+ blockStart = strstart;
+ }
+ prevAvailable = false;
+ matchLen = MIN_MATCH - 1;
+ break;
+ }
+ comprFunc = COMPR_FUNC[lvl];
+ }
+ }
+
+ private void updateHash() {
+ if (DEBUGGING)
+ System.err.println("updateHash: "+strstart);
+ ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1];
+ }
+
+ /**
+ * Inserts the current string in the head hash and returns the previous
+ * value for this hash.
+ */
+ private int insertString() {
+ short match;
+ int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)])
+ & HASH_MASK;
+
+ if (DEBUGGING)
+ {
+ if (hash != (((window[strstart] << (2*HASH_SHIFT))
+ ^ (window[strstart + 1] << HASH_SHIFT)
+ ^ (window[strstart + 2])) & HASH_MASK))
+ throw new InternalError("hash inconsistent: "+hash+"/"
+ +window[strstart]+","
+ +window[strstart+1]+","
+ +window[strstart+2]+","+HASH_SHIFT);
+ }
+
+ prev[strstart & WMASK] = match = head[hash];
+ head[hash] = (short) strstart;
+ ins_h = hash;
+ return match & 0xffff;
+ }
+
+ private void slideWindow()
+ {
+ System.arraycopy(window, WSIZE, window, 0, WSIZE);
+ matchStart -= WSIZE;
+ strstart -= WSIZE;
+ blockStart -= WSIZE;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ * at the expense of memory usage).
+ */
+ for (int i = 0; i < HASH_SIZE; i++)
+ {
+ int m = head[i] & 0xffff;
+ head[i] = m >= WSIZE ? (short) (m - WSIZE) : 0;
+ }
+
+ /* Slide the prev table.
+ */
+ for (int i = 0; i < WSIZE; i++)
+ {
+ int m = prev[i] & 0xffff;
+ prev[i] = m >= WSIZE ? (short) (m - WSIZE) : 0;
+ }
+ }
+
+ /**
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * OUT assertions: strstart + lookahead <= 2*WSIZE
+ * lookahead >= MIN_LOOKAHEAD or inputOff == inputEnd
+ */
+ private void fillWindow()
+ {
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (strstart >= WSIZE + MAX_DIST)
+ slideWindow();
+
+ /* If there is not enough lookahead, but still some input left,
+ * read in the input
+ */
+ while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd)
+ {
+ int more = 2*WSIZE - lookahead - strstart;
+
+ if (more > inputEnd - inputOff)
+ more = inputEnd - inputOff;
+
+ System.arraycopy(inputBuf, inputOff,
+ window, strstart + lookahead, more);
+ adler.update(inputBuf, inputOff, more);
+ inputOff += more;
+ totalIn += more;
+ lookahead += more;
+ }
+
+ if (lookahead >= MIN_MATCH)
+ updateHash();
+ }
+
+ /**
+ * Find the best (longest) string in the window matching the
+ * string starting at strstart.
+ *
+ * Preconditions:
+ * strstart + MAX_MATCH <= window.length.
+ *
+ *
+ * @param curMatch
+ */
+ private boolean findLongestMatch(int curMatch) {
+ int chainLength = this.max_chain;
+ int niceLength = this.niceLength;
+ short[] prev = this.prev;
+ int scan = this.strstart;
+ int match;
+ int best_end = this.strstart + matchLen;
+ int best_len = Math.max(matchLen, MIN_MATCH - 1);
+
+ int limit = Math.max(strstart - MAX_DIST, 0);
+
+ int strend = scan + MAX_MATCH - 1;
+ byte scan_end1 = window[best_end - 1];
+ byte scan_end = window[best_end];
+
+ /* Do not waste too much time if we already have a good match: */
+ if (best_len >= this.goodLength)
+ chainLength >>= 2;
+
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if (niceLength > lookahead)
+ niceLength = lookahead;
+
+ if (DeflaterConstants.DEBUGGING
+ && strstart > 2*WSIZE - MIN_LOOKAHEAD)
+ throw new InternalError("need lookahead");
+
+ do {
+ if (DeflaterConstants.DEBUGGING && curMatch >= strstart)
+ throw new InternalError("future match");
+ if (window[curMatch + best_len] != scan_end
+ || window[curMatch + best_len - 1] != scan_end1
+ || window[curMatch] != window[scan]
+ || window[curMatch+1] != window[scan + 1])
+ continue;
+
+ match = curMatch + 2;
+ scan += 2;
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ while (window[++scan] == window[++match]
+ && window[++scan] == window[++match]
+ && window[++scan] == window[++match]
+ && window[++scan] == window[++match]
+ && window[++scan] == window[++match]
+ && window[++scan] == window[++match]
+ && window[++scan] == window[++match]
+ && window[++scan] == window[++match]
+ && scan < strend);
+
+ if (scan > best_end) {
+// if (DeflaterConstants.DEBUGGING && ins_h == 0)
+// System.err.println("Found match: "+curMatch+"-"+(scan-strstart));
+ matchStart = curMatch;
+ best_end = scan;
+ best_len = scan - strstart;
+ if (best_len >= niceLength)
+ break;
+
+ scan_end1 = window[best_end-1];
+ scan_end = window[best_end];
+ }
+ scan = strstart;
+ } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit
+ && --chainLength != 0);
+
+ matchLen = Math.min(best_len, lookahead);
+ return matchLen >= MIN_MATCH;
+ }
+
+ void setDictionary(byte[] buffer, int offset, int length) {
+ if (DeflaterConstants.DEBUGGING && strstart != 1)
+ throw new IllegalStateException("strstart not 1");
+ adler.update(buffer, offset, length);
+ if (length < MIN_MATCH)
+ return;
+ if (length > MAX_DIST) {
+ offset += length - MAX_DIST;
+ length = MAX_DIST;
+ }
+
+ System.arraycopy(buffer, offset, window, strstart, length);
+
+ updateHash();
+ length--;
+ while (--length > 0)
+ {
+ insertString();
+ strstart++;
+ }
+ strstart += 2;
+ blockStart = strstart;
+ }
+
+ private boolean deflateStored(boolean flush, boolean finish)
+ {
+ if (!flush && lookahead == 0)
+ return false;
+
+ strstart += lookahead;
+ lookahead = 0;
+
+ int storedLen = strstart - blockStart;
+
+ if ((storedLen >= DeflaterConstants.MAX_BLOCK_SIZE)
+ /* Block is full */
+ || (blockStart < WSIZE && storedLen >= MAX_DIST)
+ /* Block may move out of window */
+ || flush)
+ {
+ boolean lastBlock = finish;
+ if (storedLen > DeflaterConstants.MAX_BLOCK_SIZE)
+ {
+ storedLen = DeflaterConstants.MAX_BLOCK_SIZE;
+ lastBlock = false;
+ }
+
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("storedBlock["+storedLen+","+lastBlock+"]");
+
+ huffman.flushStoredBlock(window, blockStart, storedLen, lastBlock);
+ blockStart += storedLen;
+ return !lastBlock;
+ }
+ return true;
+ }
+
+ private boolean deflateFast(boolean flush, boolean finish)
+ {
+ if (lookahead < MIN_LOOKAHEAD && !flush)
+ return false;
+
+ while (lookahead >= MIN_LOOKAHEAD || flush)
+ {
+ if (lookahead == 0)
+ {
+ /* We are flushing everything */
+ huffman.flushBlock(window, blockStart, strstart - blockStart,
+ finish);
+ blockStart = strstart;
+ return false;
+ }
+
+ if (strstart > 2 * WSIZE - MIN_LOOKAHEAD)
+ {
+ /* slide window, as findLongestMatch need this.
+ * This should only happen when flushing and the window
+ * is almost full.
+ */
+ slideWindow();
+ }
+
+ int hashHead;
+ if (lookahead >= MIN_MATCH
+ && (hashHead = insertString()) != 0
+ && strategy != Deflater.HUFFMAN_ONLY
+ && strstart - hashHead <= MAX_DIST
+ && findLongestMatch(hashHead))
+ {
+ /* longestMatch sets matchStart and matchLen */
+ if (DeflaterConstants.DEBUGGING)
+ {
+ for (int i = 0 ; i < matchLen; i++)
+ {
+ if (window[strstart+i] != window[matchStart + i])
+ throw new InternalError();
+ }
+ }
+ huffman.tallyDist(strstart - matchStart, matchLen);
+
+ lookahead -= matchLen;
+ if (matchLen <= max_lazy && lookahead >= MIN_MATCH)
+ {
+ while (--matchLen > 0)
+ {
+ strstart++;
+ insertString();
+ }
+ strstart++;
+ }
+ else
+ {
+ strstart += matchLen;
+ if (lookahead >= MIN_MATCH - 1)
+ updateHash();
+ }
+ matchLen = MIN_MATCH - 1;
+ continue;
+ }
+ else
+ {
+ /* No match found */
+ huffman.tallyLit(window[strstart] & 0xff);
+ strstart++;
+ lookahead--;
+ }
+
+ if (huffman.isFull())
+ {
+ boolean lastBlock = finish && lookahead == 0;
+ huffman.flushBlock(window, blockStart, strstart - blockStart,
+ lastBlock);
+ blockStart = strstart;
+ return !lastBlock;
+ }
+ }
+ return true;
+ }
+
+ private boolean deflateSlow(boolean flush, boolean finish)
+ {
+ if (lookahead < MIN_LOOKAHEAD && !flush)
+ return false;
+
+ while (lookahead >= MIN_LOOKAHEAD || flush)
+ {
+ if (lookahead == 0)
+ {
+ if (prevAvailable)
+ huffman.tallyLit(window[strstart-1] & 0xff);
+ prevAvailable = false;
+
+ /* We are flushing everything */
+ if (DeflaterConstants.DEBUGGING && !flush)
+ throw new InternalError("Not flushing, but no lookahead");
+ huffman.flushBlock(window, blockStart, strstart - blockStart,
+ finish);
+ blockStart = strstart;
+ return false;
+ }
+
+ if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD)
+ {
+ /* slide window, as findLongestMatch need this.
+ * This should only happen when flushing and the window
+ * is almost full.
+ */
+ slideWindow();
+ }
+
+ int prevMatch = matchStart;
+ int prevLen = matchLen;
+ if (lookahead >= MIN_MATCH)
+ {
+ int hashHead = insertString();
+ if (strategy != Deflater.HUFFMAN_ONLY
+ && hashHead != 0 && strstart - hashHead <= MAX_DIST
+ && findLongestMatch(hashHead))
+ {
+ /* longestMatch sets matchStart and matchLen */
+
+ /* Discard match if too small and too far away */
+ if (matchLen <= 5
+ && (strategy == Deflater.FILTERED
+ || (matchLen == MIN_MATCH
+ && strstart - matchStart > TOO_FAR))) {
+ matchLen = MIN_MATCH - 1;
+ }
+ }
+ }
+
+ /* previous match was better */
+ if (prevLen >= MIN_MATCH && matchLen <= prevLen)
+ {
+ if (DeflaterConstants.DEBUGGING)
+ {
+ for (int i = 0 ; i < matchLen; i++)
+ {
+ if (window[strstart-1+i] != window[prevMatch + i])
+ throw new InternalError();
+ }
+ }
+ huffman.tallyDist(strstart - 1 - prevMatch, prevLen);
+ prevLen -= 2;
+ do
+ {
+ strstart++;
+ lookahead--;
+ if (lookahead >= MIN_MATCH)
+ insertString();
+ }
+ while (--prevLen > 0);
+ strstart ++;
+ lookahead--;
+ prevAvailable = false;
+ matchLen = MIN_MATCH - 1;
+ }
+ else
+ {
+ if (prevAvailable)
+ huffman.tallyLit(window[strstart-1] & 0xff);
+ prevAvailable = true;
+ strstart++;
+ lookahead--;
+ }
+
+ if (huffman.isFull())
+ {
+ int len = strstart - blockStart;
+ if (prevAvailable)
+ len--;
+ boolean lastBlock = (finish && lookahead == 0 && !prevAvailable);
+ huffman.flushBlock(window, blockStart, len, lastBlock);
+ blockStart += len;
+ return !lastBlock;
+ }
+ }
+ return true;
+ }
+
+ public boolean deflate(boolean flush, boolean finish)
+ {
+ boolean progress;
+ do
+ {
+ fillWindow();
+ boolean canFlush = flush && inputOff == inputEnd;
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("window: ["+blockStart+","+strstart+","
+ +lookahead+"], "+comprFunc+","+canFlush);
+ switch (comprFunc)
+ {
+ case DEFLATE_STORED:
+ progress = deflateStored(canFlush, finish);
+ break;
+ case DEFLATE_FAST:
+ progress = deflateFast(canFlush, finish);
+ break;
+ case DEFLATE_SLOW:
+ progress = deflateSlow(canFlush, finish);
+ break;
+ default:
+ throw new InternalError();
+ }
+ }
+ while (pending.isFlushed() /* repeat while we have no pending output */
+ && progress); /* and progress was made */
+
+ return progress;
+ }
+
+ public void setInput(byte[] buf, int off, int len)
+ {
+ if (inputOff < inputEnd)
+ throw new IllegalStateException
+ ("Old input was not completely processed");
+
+ int end = off + len;
+
+ /* We want to throw an ArrayIndexOutOfBoundsException early. The
+ * check is very tricky: it also handles integer wrap around.
+ */
+ if (0 > off || off > end || end > buf.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ inputBuf = buf;
+ inputOff = off;
+ inputEnd = end;
+ }
+
+ public final boolean needsInput()
+ {
+ return inputEnd == inputOff;
+ }
+}
diff --git a/libjava/classpath/java/util/zip/DeflaterHuffman.java b/libjava/classpath/java/util/zip/DeflaterHuffman.java
new file mode 100644
index 00000000000..d040dde485d
--- /dev/null
+++ b/libjava/classpath/java/util/zip/DeflaterHuffman.java
@@ -0,0 +1,776 @@
+/* DeflaterHuffman.java --
+ Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.zip;
+
+/**
+ * This is the DeflaterHuffman class.
+ *
+ * This class is <i>not</i> thread safe. This is inherent in the API, due
+ * to the split of deflate and setInput.
+ *
+ * @author Jochen Hoenicke
+ * @date Jan 6, 2000
+ */
+class DeflaterHuffman
+{
+ private static final int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
+ private static final int LITERAL_NUM = 286;
+ private static final int DIST_NUM = 30;
+ private static final int BITLEN_NUM = 19;
+ private static final int REP_3_6 = 16;
+ private static final int REP_3_10 = 17;
+ private static final int REP_11_138 = 18;
+ private static final int EOF_SYMBOL = 256;
+ private static final int[] BL_ORDER =
+ { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
+
+ private static String bit4Reverse =
+ "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017";
+
+ class Tree {
+ short[] freqs;
+ short[] codes;
+ byte[] length;
+ int[] bl_counts;
+ int minNumCodes, numCodes;
+ int maxLength;
+
+ Tree(int elems, int minCodes, int maxLength) {
+ this.minNumCodes = minCodes;
+ this.maxLength = maxLength;
+ freqs = new short[elems];
+ bl_counts = new int[maxLength];
+ }
+
+ void reset() {
+ for (int i = 0; i < freqs.length; i++)
+ freqs[i] = 0;
+ codes = null;
+ length = null;
+ }
+
+ final void writeSymbol(int code)
+ {
+ if (DeflaterConstants.DEBUGGING)
+ {
+ freqs[code]--;
+// System.err.print("writeSymbol("+freqs.length+","+code+"): ");
+ }
+ pending.writeBits(codes[code] & 0xffff, length[code]);
+ }
+
+ final void checkEmpty()
+ {
+ boolean empty = true;
+ for (int i = 0; i < freqs.length; i++)
+ if (freqs[i] != 0)
+ {
+ System.err.println("freqs["+i+"] == "+freqs[i]);
+ empty = false;
+ }
+ if (!empty)
+ throw new InternalError();
+ System.err.println("checkEmpty suceeded!");
+ }
+
+ void setStaticCodes(short[] stCodes, byte[] stLength)
+ {
+ codes = stCodes;
+ length = stLength;
+ }
+
+ public void buildCodes() {
+ int[] nextCode = new int[maxLength];
+ int code = 0;
+ codes = new short[freqs.length];
+
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("buildCodes: "+freqs.length);
+ for (int bits = 0; bits < maxLength; bits++)
+ {
+ nextCode[bits] = code;
+ code += bl_counts[bits] << (15 - bits);
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("bits: "+(bits+1)+" count: "+bl_counts[bits]
+ +" nextCode: "+Integer.toHexString(code));
+ }
+ if (DeflaterConstants.DEBUGGING && code != 65536)
+ throw new RuntimeException("Inconsistent bl_counts!");
+
+ for (int i=0; i < numCodes; i++)
+ {
+ int bits = length[i];
+ if (bits > 0)
+ {
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("codes["+i+"] = rev("
+ +Integer.toHexString(nextCode[bits-1])+"),"
+ +bits);
+ codes[i] = bitReverse(nextCode[bits-1]);
+ nextCode[bits-1] += 1 << (16 - bits);
+ }
+ }
+ }
+
+ private void buildLength(int childs[])
+ {
+ this.length = new byte [freqs.length];
+ int numNodes = childs.length / 2;
+ int numLeafs = (numNodes + 1) / 2;
+ int overflow = 0;
+
+ for (int i = 0; i < maxLength; i++)
+ bl_counts[i] = 0;
+
+ /* First calculate optimal bit lengths */
+ int lengths[] = new int[numNodes];
+ lengths[numNodes-1] = 0;
+ for (int i = numNodes - 1; i >= 0; i--)
+ {
+ if (childs[2*i+1] != -1)
+ {
+ int bitLength = lengths[i] + 1;
+ if (bitLength > maxLength)
+ {
+ bitLength = maxLength;
+ overflow++;
+ }
+ lengths[childs[2*i]] = lengths[childs[2*i+1]] = bitLength;
+ }
+ else
+ {
+ /* A leaf node */
+ int bitLength = lengths[i];
+ bl_counts[bitLength - 1]++;
+ this.length[childs[2*i]] = (byte) lengths[i];
+ }
+ }
+
+ if (DeflaterConstants.DEBUGGING)
+ {
+ System.err.println("Tree "+freqs.length+" lengths:");
+ for (int i=0; i < numLeafs; i++)
+ System.err.println("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
+ + " len: "+length[childs[2*i]]);
+ }
+
+ if (overflow == 0)
+ return;
+
+ int incrBitLen = maxLength - 1;
+ do
+ {
+ /* Find the first bit length which could increase: */
+ while (bl_counts[--incrBitLen] == 0)
+ ;
+
+ /* Move this node one down and remove a corresponding
+ * amount of overflow nodes.
+ */
+ do
+ {
+ bl_counts[incrBitLen]--;
+ bl_counts[++incrBitLen]++;
+ overflow -= 1 << (maxLength - 1 - incrBitLen);
+ }
+ while (overflow > 0 && incrBitLen < maxLength - 1);
+ }
+ while (overflow > 0);
+
+ /* We may have overshot above. Move some nodes from maxLength to
+ * maxLength-1 in that case.
+ */
+ bl_counts[maxLength-1] += overflow;
+ bl_counts[maxLength-2] -= overflow;
+
+ /* Now recompute all bit lengths, scanning in increasing
+ * frequency. It is simpler to reconstruct all lengths instead of
+ * fixing only the wrong ones. This idea is taken from 'ar'
+ * written by Haruhiko Okumura.
+ *
+ * The nodes were inserted with decreasing frequency into the childs
+ * array.
+ */
+ int nodePtr = 2 * numLeafs;
+ for (int bits = maxLength; bits != 0; bits--)
+ {
+ int n = bl_counts[bits-1];
+ while (n > 0)
+ {
+ int childPtr = 2*childs[nodePtr++];
+ if (childs[childPtr + 1] == -1)
+ {
+ /* We found another leaf */
+ length[childs[childPtr]] = (byte) bits;
+ n--;
+ }
+ }
+ }
+ if (DeflaterConstants.DEBUGGING)
+ {
+ System.err.println("*** After overflow elimination. ***");
+ for (int i=0; i < numLeafs; i++)
+ System.err.println("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
+ + " len: "+length[childs[2*i]]);
+ }
+ }
+
+ void buildTree()
+ {
+ int numSymbols = freqs.length;
+
+ /* heap is a priority queue, sorted by frequency, least frequent
+ * nodes first. The heap is a binary tree, with the property, that
+ * the parent node is smaller than both child nodes. This assures
+ * that the smallest node is the first parent.
+ *
+ * The binary tree is encoded in an array: 0 is root node and
+ * the nodes 2*n+1, 2*n+2 are the child nodes of node n.
+ */
+ int[] heap = new int[numSymbols];
+ int heapLen = 0;
+ int maxCode = 0;
+ for (int n = 0; n < numSymbols; n++)
+ {
+ int freq = freqs[n];
+ if (freq != 0)
+ {
+ /* Insert n into heap */
+ int pos = heapLen++;
+ int ppos;
+ while (pos > 0 &&
+ freqs[heap[ppos = (pos - 1) / 2]] > freq) {
+ heap[pos] = heap[ppos];
+ pos = ppos;
+ }
+ heap[pos] = n;
+ maxCode = n;
+ }
+ }
+
+ /* We could encode a single literal with 0 bits but then we
+ * don't see the literals. Therefore we force at least two
+ * literals to avoid this case. We don't care about order in
+ * this case, both literals get a 1 bit code.
+ */
+ while (heapLen < 2)
+ {
+ int node = maxCode < 2 ? ++maxCode : 0;
+ heap[heapLen++] = node;
+ }
+
+ numCodes = Math.max(maxCode + 1, minNumCodes);
+
+ int numLeafs = heapLen;
+ int[] childs = new int[4*heapLen - 2];
+ int[] values = new int[2*heapLen - 1];
+ int numNodes = numLeafs;
+ for (int i = 0; i < heapLen; i++)
+ {
+ int node = heap[i];
+ childs[2*i] = node;
+ childs[2*i+1] = -1;
+ values[i] = freqs[node] << 8;
+ heap[i] = i;
+ }
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ do
+ {
+ int first = heap[0];
+ int last = heap[--heapLen];
+
+ /* Propagate the hole to the leafs of the heap */
+ int ppos = 0;
+ int path = 1;
+ while (path < heapLen)
+ {
+ if (path + 1 < heapLen
+ && values[heap[path]] > values[heap[path+1]])
+ path++;
+
+ heap[ppos] = heap[path];
+ ppos = path;
+ path = path * 2 + 1;
+ }
+
+ /* Now propagate the last element down along path. Normally
+ * it shouldn't go too deep.
+ */
+ int lastVal = values[last];
+ while ((path = ppos) > 0
+ && values[heap[ppos = (path - 1)/2]] > lastVal)
+ heap[path] = heap[ppos];
+ heap[path] = last;
+
+
+ int second = heap[0];
+
+ /* Create a new node father of first and second */
+ last = numNodes++;
+ childs[2*last] = first;
+ childs[2*last+1] = second;
+ int mindepth = Math.min(values[first] & 0xff, values[second] & 0xff);
+ values[last] = lastVal = values[first] + values[second] - mindepth + 1;
+
+ /* Again, propagate the hole to the leafs */
+ ppos = 0;
+ path = 1;
+ while (path < heapLen)
+ {
+ if (path + 1 < heapLen
+ && values[heap[path]] > values[heap[path+1]])
+ path++;
+
+ heap[ppos] = heap[path];
+ ppos = path;
+ path = ppos * 2 + 1;
+ }
+
+ /* Now propagate the new element down along path */
+ while ((path = ppos) > 0
+ && values[heap[ppos = (path - 1)/2]] > lastVal)
+ heap[path] = heap[ppos];
+ heap[path] = last;
+ }
+ while (heapLen > 1);
+
+ if (heap[0] != childs.length / 2 - 1)
+ throw new RuntimeException("Weird!");
+
+ buildLength(childs);
+ }
+
+ int getEncodedLength()
+ {
+ int len = 0;
+ for (int i = 0; i < freqs.length; i++)
+ len += freqs[i] * length[i];
+ return len;
+ }
+
+ void calcBLFreq(Tree blTree) {
+ int max_count; /* max repeat count */
+ int min_count; /* min repeat count */
+ int count; /* repeat count of the current code */
+ int curlen = -1; /* length of current code */
+
+ int i = 0;
+ while (i < numCodes)
+ {
+ count = 1;
+ int nextlen = length[i];
+ if (nextlen == 0)
+ {
+ max_count = 138;
+ min_count = 3;
+ }
+ else
+ {
+ max_count = 6;
+ min_count = 3;
+ if (curlen != nextlen)
+ {
+ blTree.freqs[nextlen]++;
+ count = 0;
+ }
+ }
+ curlen = nextlen;
+ i++;
+
+ while (i < numCodes && curlen == length[i])
+ {
+ i++;
+ if (++count >= max_count)
+ break;
+ }
+
+ if (count < min_count)
+ blTree.freqs[curlen] += count;
+ else if (curlen != 0)
+ blTree.freqs[REP_3_6]++;
+ else if (count <= 10)
+ blTree.freqs[REP_3_10]++;
+ else
+ blTree.freqs[REP_11_138]++;
+ }
+ }
+
+ void writeTree(Tree blTree)
+ {
+ int max_count; /* max repeat count */
+ int min_count; /* min repeat count */
+ int count; /* repeat count of the current code */
+ int curlen = -1; /* length of current code */
+
+ int i = 0;
+ while (i < numCodes)
+ {
+ count = 1;
+ int nextlen = length[i];
+ if (nextlen == 0)
+ {
+ max_count = 138;
+ min_count = 3;
+ }
+ else
+ {
+ max_count = 6;
+ min_count = 3;
+ if (curlen != nextlen)
+ {
+ blTree.writeSymbol(nextlen);
+ count = 0;
+ }
+ }
+ curlen = nextlen;
+ i++;
+
+ while (i < numCodes && curlen == length[i])
+ {
+ i++;
+ if (++count >= max_count)
+ break;
+ }
+
+ if (count < min_count)
+ {
+ while (count-- > 0)
+ blTree.writeSymbol(curlen);
+ }
+ else if (curlen != 0)
+ {
+ blTree.writeSymbol(REP_3_6);
+ pending.writeBits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ blTree.writeSymbol(REP_3_10);
+ pending.writeBits(count - 3, 3);
+ }
+ else
+ {
+ blTree.writeSymbol(REP_11_138);
+ pending.writeBits(count - 11, 7);
+ }
+ }
+ }
+ }
+
+
+
+ DeflaterPending pending;
+ private Tree literalTree, distTree, blTree;
+
+ private short d_buf[];
+ private byte l_buf[];
+ private int last_lit;
+ private int extra_bits;
+
+ private static short staticLCodes[];
+ private static byte staticLLength[];
+ private static short staticDCodes[];
+ private static byte staticDLength[];
+
+ /**
+ * Reverse the bits of a 16 bit value.
+ */
+ static short bitReverse(int value) {
+ return (short) (bit4Reverse.charAt(value & 0xf) << 12
+ | bit4Reverse.charAt((value >> 4) & 0xf) << 8
+ | bit4Reverse.charAt((value >> 8) & 0xf) << 4
+ | bit4Reverse.charAt(value >> 12));
+ }
+
+ static {
+ /* See RFC 1951 3.2.6 */
+ /* Literal codes */
+ staticLCodes = new short[LITERAL_NUM];
+ staticLLength = new byte[LITERAL_NUM];
+ int i = 0;
+ while (i < 144) {
+ staticLCodes[i] = bitReverse((0x030 + i) << 8);
+ staticLLength[i++] = 8;
+ }
+ while (i < 256) {
+ staticLCodes[i] = bitReverse((0x190 - 144 + i) << 7);
+ staticLLength[i++] = 9;
+ }
+ while (i < 280) {
+ staticLCodes[i] = bitReverse((0x000 - 256 + i) << 9);
+ staticLLength[i++] = 7;
+ }
+ while (i < LITERAL_NUM) {
+ staticLCodes[i] = bitReverse((0x0c0 - 280 + i) << 8);
+ staticLLength[i++] = 8;
+ }
+
+ /* Distant codes */
+ staticDCodes = new short[DIST_NUM];
+ staticDLength = new byte[DIST_NUM];
+ for (i = 0; i < DIST_NUM; i++) {
+ staticDCodes[i] = bitReverse(i << 11);
+ staticDLength[i] = 5;
+ }
+ }
+
+ public DeflaterHuffman(DeflaterPending pending)
+ {
+ this.pending = pending;
+
+ literalTree = new Tree(LITERAL_NUM, 257, 15);
+ distTree = new Tree(DIST_NUM, 1, 15);
+ blTree = new Tree(BITLEN_NUM, 4, 7);
+
+ d_buf = new short[BUFSIZE];
+ l_buf = new byte [BUFSIZE];
+ }
+
+ public final void reset() {
+ last_lit = 0;
+ extra_bits = 0;
+ literalTree.reset();
+ distTree.reset();
+ blTree.reset();
+ }
+
+ private int l_code(int len) {
+ if (len == 255)
+ return 285;
+
+ int code = 257;
+ while (len >= 8)
+ {
+ code += 4;
+ len >>= 1;
+ }
+ return code + len;
+ }
+
+ private int d_code(int distance) {
+ int code = 0;
+ while (distance >= 4)
+ {
+ code += 2;
+ distance >>= 1;
+ }
+ return code + distance;
+ }
+
+ public void sendAllTrees(int blTreeCodes) {
+ blTree.buildCodes();
+ literalTree.buildCodes();
+ distTree.buildCodes();
+ pending.writeBits(literalTree.numCodes - 257, 5);
+ pending.writeBits(distTree.numCodes - 1, 5);
+ pending.writeBits(blTreeCodes - 4, 4);
+ for (int rank = 0; rank < blTreeCodes; rank++)
+ pending.writeBits(blTree.length[BL_ORDER[rank]], 3);
+ literalTree.writeTree(blTree);
+ distTree.writeTree(blTree);
+ if (DeflaterConstants.DEBUGGING)
+ blTree.checkEmpty();
+ }
+
+ public void compressBlock() {
+ for (int i = 0; i < last_lit; i++)
+ {
+ int litlen = l_buf[i] & 0xff;
+ int dist = d_buf[i];
+ if (dist-- != 0)
+ {
+ if (DeflaterConstants.DEBUGGING)
+ System.err.print("["+(dist+1)+","+(litlen+3)+"]: ");
+
+ int lc = l_code(litlen);
+ literalTree.writeSymbol(lc);
+
+ int bits = (lc - 261) / 4;
+ if (bits > 0 && bits <= 5)
+ pending.writeBits(litlen & ((1 << bits) - 1), bits);
+
+ int dc = d_code(dist);
+ distTree.writeSymbol(dc);
+
+ bits = dc / 2 - 1;
+ if (bits > 0)
+ pending.writeBits(dist & ((1 << bits) - 1), bits);
+ }
+ else
+ {
+ if (DeflaterConstants.DEBUGGING)
+ {
+ if (litlen > 32 && litlen < 127)
+ System.err.print("("+(char)litlen+"): ");
+ else
+ System.err.print("{"+litlen+"}: ");
+ }
+ literalTree.writeSymbol(litlen);
+ }
+ }
+ if (DeflaterConstants.DEBUGGING)
+ System.err.print("EOF: ");
+ literalTree.writeSymbol(EOF_SYMBOL);
+ if (DeflaterConstants.DEBUGGING)
+ {
+ literalTree.checkEmpty();
+ distTree.checkEmpty();
+ }
+ }
+
+ public void flushStoredBlock(byte[] stored,
+ int stored_offset, int stored_len,
+ boolean lastBlock) {
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("Flushing stored block "+ stored_len);
+ pending.writeBits((DeflaterConstants.STORED_BLOCK << 1)
+ + (lastBlock ? 1 : 0), 3);
+ pending.alignToByte();
+ pending.writeShort(stored_len);
+ pending.writeShort(~stored_len);
+ pending.writeBlock(stored, stored_offset, stored_len);
+ reset();
+ }
+
+ public void flushBlock(byte[] stored, int stored_offset, int stored_len,
+ boolean lastBlock) {
+ literalTree.freqs[EOF_SYMBOL]++;
+
+ /* Build trees */
+ literalTree.buildTree();
+ distTree.buildTree();
+
+ /* Calculate bitlen frequency */
+ literalTree.calcBLFreq(blTree);
+ distTree.calcBLFreq(blTree);
+
+ /* Build bitlen tree */
+ blTree.buildTree();
+
+ int blTreeCodes = 4;
+ for (int i = 18; i > blTreeCodes; i--)
+ {
+ if (blTree.length[BL_ORDER[i]] > 0)
+ blTreeCodes = i+1;
+ }
+ int opt_len = 14 + blTreeCodes * 3 + blTree.getEncodedLength()
+ + literalTree.getEncodedLength() + distTree.getEncodedLength()
+ + extra_bits;
+
+ int static_len = extra_bits;
+ for (int i = 0; i < LITERAL_NUM; i++)
+ static_len += literalTree.freqs[i] * staticLLength[i];
+ for (int i = 0; i < DIST_NUM; i++)
+ static_len += distTree.freqs[i] * staticDLength[i];
+ if (opt_len >= static_len)
+ {
+ /* Force static trees */
+ opt_len = static_len;
+ }
+
+ if (stored_offset >= 0 && stored_len+4 < opt_len >> 3)
+ {
+ /* Store Block */
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("Storing, since " + stored_len + " < " + opt_len
+ + " <= " + static_len);
+ flushStoredBlock(stored, stored_offset, stored_len, lastBlock);
+ }
+ else if (opt_len == static_len)
+ {
+ /* Encode with static tree */
+ pending.writeBits((DeflaterConstants.STATIC_TREES << 1)
+ + (lastBlock ? 1 : 0), 3);
+ literalTree.setStaticCodes(staticLCodes, staticLLength);
+ distTree.setStaticCodes(staticDCodes, staticDLength);
+ compressBlock();
+ reset();
+ }
+ else
+ {
+ /* Encode with dynamic tree */
+ pending.writeBits((DeflaterConstants.DYN_TREES << 1)
+ + (lastBlock ? 1 : 0), 3);
+ sendAllTrees(blTreeCodes);
+ compressBlock();
+ reset();
+ }
+ }
+
+ public final boolean isFull()
+ {
+ return last_lit == BUFSIZE;
+ }
+
+ public final boolean tallyLit(int lit)
+ {
+ if (DeflaterConstants.DEBUGGING)
+ {
+ if (lit > 32 && lit < 127)
+ System.err.println("("+(char)lit+")");
+ else
+ System.err.println("{"+lit+"}");
+ }
+ d_buf[last_lit] = 0;
+ l_buf[last_lit++] = (byte) lit;
+ literalTree.freqs[lit]++;
+ return last_lit == BUFSIZE;
+ }
+
+ public final boolean tallyDist(int dist, int len)
+ {
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("["+dist+","+len+"]");
+
+ d_buf[last_lit] = (short) dist;
+ l_buf[last_lit++] = (byte) (len - 3);
+
+ int lc = l_code(len-3);
+ literalTree.freqs[lc]++;
+ if (lc >= 265 && lc < 285)
+ extra_bits += (lc - 261) / 4;
+
+ int dc = d_code(dist-1);
+ distTree.freqs[dc]++;
+ if (dc >= 4)
+ extra_bits += dc / 2 - 1;
+ return last_lit == BUFSIZE;
+ }
+}
diff --git a/libjava/classpath/java/util/zip/DeflaterOutputStream.java b/libjava/classpath/java/util/zip/DeflaterOutputStream.java
new file mode 100644
index 00000000000..b10100d8a28
--- /dev/null
+++ b/libjava/classpath/java/util/zip/DeflaterOutputStream.java
@@ -0,0 +1,198 @@
+/* DeflaterOutputStream.java - Output filter for compressing.
+ Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.zip;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+/**
+ * This is a special FilterOutputStream deflating the bytes that are
+ * written through it. It uses the Deflater for deflating.
+ *
+ * A special thing to be noted is that flush() doesn't flush
+ * everything in Sun's JDK, but it does so in jazzlib. This is because
+ * Sun's Deflater doesn't have a way to flush() everything, without
+ * finishing the stream.
+ *
+ * @author Tom Tromey, Jochen Hoenicke
+ * @date Jan 11, 2001
+ */
+public class DeflaterOutputStream extends FilterOutputStream
+{
+ /**
+ * This buffer is used temporarily to retrieve the bytes from the
+ * deflater and write them to the underlying output stream.
+ */
+ protected byte[] buf;
+
+ /**
+ * The deflater which is used to deflate the stream.
+ */
+ protected Deflater def;
+
+ /**
+ * Deflates everything in the def's input buffers. This will call
+ * <code>def.deflate()</code> until all bytes from the input buffers
+ * are processed.
+ */
+ protected void deflate() throws IOException
+ {
+ while (! def.needsInput())
+ {
+ int len = def.deflate(buf, 0, buf.length);
+
+ // System.err.println("DOS deflated " + len + " out of " + buf.length);
+ if (len <= 0)
+ break;
+ out.write(buf, 0, len);
+ }
+
+ if (! def.needsInput())
+ throw new InternalError("Can't deflate all input?");
+ }
+
+ /**
+ * Creates a new DeflaterOutputStream with a default Deflater and
+ * default buffer size.
+ * @param out the output stream where deflated output should be written.
+ */
+ public DeflaterOutputStream(OutputStream out)
+ {
+ this(out, new Deflater(), 512);
+ }
+
+ /**
+ * Creates a new DeflaterOutputStream with the given Deflater and
+ * default buffer size.
+ * @param out the output stream where deflated output should be written.
+ * @param defl the underlying deflater.
+ */
+ public DeflaterOutputStream(OutputStream out, Deflater defl)
+ {
+ this(out, defl, 512);
+ }
+
+ /**
+ * Creates a new DeflaterOutputStream with the given Deflater and
+ * buffer size.
+ * @param out the output stream where deflated output should be written.
+ * @param defl the underlying deflater.
+ * @param bufsize the buffer size.
+ * @exception IllegalArgumentException if bufsize isn't positive.
+ */
+ public DeflaterOutputStream(OutputStream out, Deflater defl, int bufsize)
+ {
+ super(out);
+ if (bufsize <= 0)
+ throw new IllegalArgumentException("bufsize <= 0");
+ buf = new byte[bufsize];
+ def = defl;
+ }
+
+ /**
+ * Flushes the stream by calling flush() on the deflater and then
+ * on the underlying stream. This ensures that all bytes are
+ * flushed. This function doesn't work in Sun's JDK, but only in
+ * jazzlib.
+ */
+ public void flush() throws IOException
+ {
+ def.flush();
+ deflate();
+ out.flush();
+ }
+
+ /**
+ * Finishes the stream by calling finish() on the deflater. This
+ * was the only way to ensure that all bytes are flushed in Sun's
+ * JDK.
+ */
+ public void finish() throws IOException
+ {
+ def.finish();
+ while (! def.finished())
+ {
+ int len = def.deflate(buf, 0, buf.length);
+ if (len <= 0)
+ break;
+ out.write(buf, 0, len);
+ }
+ if (! def.finished())
+ throw new InternalError("Can't deflate all input?");
+ out.flush();
+ }
+
+ /**
+ * Calls finish() and closes the stream.
+ */
+ public void close() throws IOException
+ {
+ finish();
+ out.close();
+ }
+
+ /**
+ * Writes a single byte to the compressed output stream.
+ * @param bval the byte value.
+ */
+ public void write(int bval) throws IOException
+ {
+ byte[] b = new byte[1];
+ b[0] = (byte) bval;
+ write(b, 0, 1);
+ }
+
+ /**
+ * Writes a len bytes from an array to the compressed stream.
+ * @param buf the byte array.
+ * @param off the offset into the byte array where to start.
+ * @param len the number of bytes to write.
+ */
+ public void write(byte[] buf, int off, int len) throws IOException
+ {
+ def.setInput(buf, off, len);
+ deflate();
+ }
+}
diff --git a/libjava/classpath/java/util/zip/DeflaterPending.java b/libjava/classpath/java/util/zip/DeflaterPending.java
new file mode 100644
index 00000000000..f38212c352d
--- /dev/null
+++ b/libjava/classpath/java/util/zip/DeflaterPending.java
@@ -0,0 +1,54 @@
+/* java.util.zip.DeflaterPending
+ Copyright (C) 2001 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.zip;
+
+/**
+ * This class stores the pending output of the Deflater.
+ *
+ * @author Jochen Hoenicke
+ * @date Jan 5, 2000
+ */
+
+class DeflaterPending extends PendingBuffer
+{
+ public DeflaterPending()
+ {
+ super(DeflaterConstants.PENDING_BUF_SIZE);
+ }
+}
+
diff --git a/libjava/classpath/java/util/zip/GZIPInputStream.java b/libjava/classpath/java/util/zip/GZIPInputStream.java
new file mode 100644
index 00000000000..2cea755b3cc
--- /dev/null
+++ b/libjava/classpath/java/util/zip/GZIPInputStream.java
@@ -0,0 +1,355 @@
+/* GZIPInputStream.java - Input filter for reading gzip file
+ Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.zip;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This filter stream is used to decompress a "GZIP" format stream.
+ * The "GZIP" format is described in RFC 1952.
+ *
+ * @author John Leuner
+ * @author Tom Tromey
+ * @since JDK 1.1
+ */
+public class GZIPInputStream
+ extends InflaterInputStream
+{
+ /**
+ * The magic number found at the start of a GZIP stream.
+ */
+ public static final int GZIP_MAGIC = 0x8b1f;
+
+ /**
+ * The mask for bit 0 of the flag byte.
+ */
+ static final int FTEXT = 0x1;
+
+ /**
+ * The mask for bit 1 of the flag byte.
+ */
+ static final int FHCRC = 0x2;
+
+ /**
+ * The mask for bit 2 of the flag byte.
+ */
+ static final int FEXTRA = 0x4;
+
+ /**
+ * The mask for bit 3 of the flag byte.
+ */
+ static final int FNAME = 0x8;
+
+ /**
+ * The mask for bit 4 of the flag byte.
+ */
+ static final int FCOMMENT = 0x10;
+
+ /**
+ * The CRC-32 checksum value for uncompressed data.
+ */
+ protected CRC32 crc;
+
+ /**
+ * Indicates whether or not the end of the stream has been reached.
+ */
+ protected boolean eos;
+
+ /**
+ * Indicates whether or not the GZIP header has been read in.
+ */
+ private boolean readGZIPHeader;
+
+ /**
+ * Creates a GZIPInputStream with the default buffer size.
+ *
+ * @param in The stream to read compressed data from
+ * (in GZIP format).
+ *
+ * @throws IOException if an error occurs during an I/O operation.
+ */
+ public GZIPInputStream(InputStream in)
+ throws IOException
+ {
+ this(in, 4096);
+ }
+
+ /**
+ * Creates a GZIPInputStream with the specified buffer size.
+ *
+ * @param in The stream to read compressed data from
+ * (in GZIP format).
+ * @param size The size of the buffer to use.
+ *
+ * @throws IOException if an error occurs during an I/O operation.
+ * @throws IllegalArgumentException if <code>size</code>
+ * is less than or equal to 0.
+ */
+ public GZIPInputStream(InputStream in, int size)
+ throws IOException
+ {
+ super(in, new Inflater(true), size);
+ crc = new CRC32();
+ readHeader();
+ }
+
+ /**
+ * Closes the input stream.
+ *
+ * @throws IOException if an error occurs during an I/O operation.
+ */
+ public void close()
+ throws IOException
+ {
+ // Nothing to do here.
+ super.close();
+ }
+
+ /**
+ * Reads in GZIP-compressed data and stores it in uncompressed form
+ * into an array of bytes. The method will block until either
+ * enough input data becomes available or the compressed stream
+ * reaches its end.
+ *
+ * @param buf the buffer into which the uncompressed data will
+ * be stored.
+ * @param offset the offset indicating where in <code>buf</code>
+ * the uncompressed data should be placed.
+ * @param len the number of uncompressed bytes to be read.
+ */
+ public int read(byte[] buf, int offset, int len) throws IOException
+ {
+ // We first have to slurp in the GZIP header, then we feed all the
+ // rest of the data to the superclass.
+ //
+ // As we do that we continually update the CRC32. Once the data is
+ // finished, we check the CRC32.
+ //
+ // This means we don't need our own buffer, as everything is done
+ // in the superclass.
+ if (!readGZIPHeader)
+ readHeader();
+
+ if (eos)
+ return -1;
+
+ // System.err.println("GZIPIS.read(byte[], off, len ... " + offset + " and len " + len);
+
+ /* We don't have to read the header,
+ * so we just grab data from the superclass.
+ */
+ int numRead = super.read(buf, offset, len);
+ if (numRead > 0)
+ crc.update(buf, offset, numRead);
+
+ if (inf.finished())
+ readFooter();
+ return numRead;
+ }
+
+
+ /**
+ * Reads in the GZIP header.
+ */
+ private void readHeader() throws IOException
+ {
+ /* 1. Check the two magic bytes */
+ CRC32 headCRC = new CRC32();
+ int magic = in.read();
+ if (magic < 0)
+ {
+ eos = true;
+ return;
+ }
+ int magic2 = in.read();
+ if ((magic + (magic2 << 8)) != GZIP_MAGIC)
+ throw new IOException("Error in GZIP header, bad magic code");
+ headCRC.update(magic);
+ headCRC.update(magic2);
+
+ /* 2. Check the compression type (must be 8) */
+ int CM = in.read();
+ if (CM != 8)
+ throw new IOException("Error in GZIP header, data not in deflate format");
+ headCRC.update(CM);
+
+ /* 3. Check the flags */
+ int flags = in.read();
+ if (flags < 0)
+ throw new EOFException("Early EOF in GZIP header");
+ headCRC.update(flags);
+
+ /* This flag byte is divided into individual bits as follows:
+
+ bit 0 FTEXT
+ bit 1 FHCRC
+ bit 2 FEXTRA
+ bit 3 FNAME
+ bit 4 FCOMMENT
+ bit 5 reserved
+ bit 6 reserved
+ bit 7 reserved
+ */
+
+ /* 3.1 Check the reserved bits are zero */
+ if ((flags & 0xd0) != 0)
+ throw new IOException("Reserved flag bits in GZIP header != 0");
+
+ /* 4.-6. Skip the modification time, extra flags, and OS type */
+ for (int i=0; i< 6; i++)
+ {
+ int readByte = in.read();
+ if (readByte < 0)
+ throw new EOFException("Early EOF in GZIP header");
+ headCRC.update(readByte);
+ }
+
+ /* 7. Read extra field */
+ if ((flags & FEXTRA) != 0)
+ {
+ /* Skip subfield id */
+ for (int i=0; i< 2; i++)
+ {
+ int readByte = in.read();
+ if (readByte < 0)
+ throw new EOFException("Early EOF in GZIP header");
+ headCRC.update(readByte);
+ }
+ if (in.read() < 0 || in.read() < 0)
+ throw new EOFException("Early EOF in GZIP header");
+
+ int len1, len2, extraLen;
+ len1 = in.read();
+ len2 = in.read();
+ if ((len1 < 0) || (len2 < 0))
+ throw new EOFException("Early EOF in GZIP header");
+ headCRC.update(len1);
+ headCRC.update(len2);
+
+ extraLen = (len1 << 8) | len2;
+ for (int i = 0; i < extraLen;i++)
+ {
+ int readByte = in.read();
+ if (readByte < 0)
+ throw new EOFException("Early EOF in GZIP header");
+ headCRC.update(readByte);
+ }
+ }
+
+ /* 8. Read file name */
+ if ((flags & FNAME) != 0)
+ {
+ int readByte;
+ while ( (readByte = in.read()) > 0)
+ headCRC.update(readByte);
+ if (readByte < 0)
+ throw new EOFException("Early EOF in GZIP file name");
+ headCRC.update(readByte);
+ }
+
+ /* 9. Read comment */
+ if ((flags & FCOMMENT) != 0)
+ {
+ int readByte;
+ while ( (readByte = in.read()) > 0)
+ headCRC.update(readByte);
+
+ if (readByte < 0)
+ throw new EOFException("Early EOF in GZIP comment");
+ headCRC.update(readByte);
+ }
+
+ /* 10. Read header CRC */
+ if ((flags & FHCRC) != 0)
+ {
+ int tempByte;
+ int crcval = in.read();
+ if (crcval < 0)
+ throw new EOFException("Early EOF in GZIP header");
+
+ tempByte = in.read();
+ if (tempByte < 0)
+ throw new EOFException("Early EOF in GZIP header");
+
+ crcval = (crcval << 8) | tempByte;
+ if (crcval != ((int) headCRC.getValue() & 0xffff))
+ throw new IOException("Header CRC value mismatch");
+ }
+
+ readGZIPHeader = true;
+ //System.err.println("Read GZIP header");
+ }
+
+ private void readFooter() throws IOException
+ {
+ byte[] footer = new byte[8];
+ int avail = inf.getRemaining();
+ if (avail > 8)
+ avail = 8;
+ System.arraycopy(buf, len - inf.getRemaining(), footer, 0, avail);
+ int needed = 8 - avail;
+ while (needed > 0)
+ {
+ int count = in.read(footer, 8-needed, needed);
+ if (count <= 0)
+ throw new EOFException("Early EOF in GZIP footer");
+ needed -= count; //Jewel Jan 16
+ }
+
+ int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8)
+ | ((footer[2] & 0xff) << 16) | (footer[3] << 24);
+ if (crcval != (int) crc.getValue())
+ throw new IOException("GZIP crc sum mismatch, theirs \""
+ + Integer.toHexString(crcval)
+ + "\" and ours \""
+ + Integer.toHexString( (int) crc.getValue()));
+
+ int total = (footer[4] & 0xff) | ((footer[5] & 0xff) << 8)
+ | ((footer[6] & 0xff) << 16) | (footer[7] << 24);
+ if (total != inf.getTotalOut())
+ throw new IOException("Number of bytes mismatch");
+
+ /* FIXME" XXX Should we support multiple members.
+ * Difficult, since there may be some bytes still in buf
+ */
+ eos = true;
+ }
+}
diff --git a/libjava/classpath/java/util/zip/GZIPOutputStream.java b/libjava/classpath/java/util/zip/GZIPOutputStream.java
new file mode 100644
index 00000000000..5b7b827a9ff
--- /dev/null
+++ b/libjava/classpath/java/util/zip/GZIPOutputStream.java
@@ -0,0 +1,151 @@
+/* GZIPOutputStream.java - Create a file in gzip format
+ Copyright (C) 1999, 2000, 2001 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.zip;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * This filter stream is used to compress a stream into a "GZIP" stream.
+ * The "GZIP" format is described in RFC 1952.
+ *
+ * @author John Leuner
+ * @author Tom Tromey
+ * @since JDK 1.1
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+public class GZIPOutputStream extends DeflaterOutputStream
+{
+ /**
+ * CRC-32 value for uncompressed data
+ */
+ protected CRC32 crc;
+
+ /**
+ * Creates a GZIPOutputStream with the default buffer size
+ *
+ * @param out The stream to read data (to be compressed) from
+ *
+ */
+ public GZIPOutputStream(OutputStream out) throws IOException
+ {
+ this(out, 4096);
+ }
+
+ /**
+ * Creates a GZIPOutputStream with the specified buffer size
+ *
+ * @param out The stream to read compressed data from
+ * @param size Size of the buffer to use
+ */
+ public GZIPOutputStream(OutputStream out, int size) throws IOException
+ {
+ super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
+ crc = new CRC32();
+ int mod_time = (int) (System.currentTimeMillis() / 1000L);
+ byte[] gzipHeader =
+ {
+ /* The two magic bytes */
+ (byte) GZIPInputStream.GZIP_MAGIC,
+ (byte) (GZIPInputStream.GZIP_MAGIC >> 8),
+
+ /* The compression type */
+ (byte) Deflater.DEFLATED,
+
+ /* The flags (not set) */
+ 0,
+
+ /* The modification time */
+ (byte) mod_time, (byte) (mod_time >> 8),
+ (byte) (mod_time >> 16), (byte) (mod_time >> 24),
+
+ /* The extra flags */
+ 0,
+
+ /* The OS type (unknown) */
+ (byte) 255
+ };
+
+ out.write(gzipHeader);
+ // System.err.println("wrote GZIP header (" + gzipHeader.length + " bytes )");
+ }
+
+ public synchronized void write(byte[] buf, int off, int len)
+ throws IOException
+ {
+ super.write(buf, off, len);
+ crc.update(buf, off, len);
+ }
+
+ /**
+ * Writes remaining compressed output data to the output stream
+ * and closes it.
+ */
+ public void close() throws IOException
+ {
+ finish();
+ out.close();
+ }
+
+ public void finish() throws IOException
+ {
+ super.finish();
+
+ int totalin = def.getTotalIn();
+ int crcval = (int) (crc.getValue() & 0xffffffff);
+
+ // System.err.println("CRC val is " + Integer.toHexString( crcval ) + " and length " + Integer.toHexString(totalin));
+
+ byte[] gzipFooter =
+ {
+ (byte) crcval, (byte) (crcval >> 8),
+ (byte) (crcval >> 16), (byte) (crcval >> 24),
+
+ (byte) totalin, (byte) (totalin >> 8),
+ (byte) (totalin >> 16), (byte) (totalin >> 24)
+ };
+
+ out.write(gzipFooter);
+ // System.err.println("wrote GZIP trailer (" + gzipFooter.length + " bytes )");
+ }
+}
diff --git a/libjava/classpath/java/util/zip/Inflater.java b/libjava/classpath/java/util/zip/Inflater.java
new file mode 100644
index 00000000000..76de891faa5
--- /dev/null
+++ b/libjava/classpath/java/util/zip/Inflater.java
@@ -0,0 +1,715 @@
+/* Inflater.java - Decompress a data stream
+ Copyright (C) 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.zip;
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+/**
+ * Inflater is used to decompress data that has been compressed according
+ * to the "deflate" standard described in rfc1950.
+ *
+ * The usage is as following. First you have to set some input with
+ * <code>setInput()</code>, then inflate() it. If inflate doesn't
+ * inflate any bytes there may be three reasons:
+ * <ul>
+ * <li>needsInput() returns true because the input buffer is empty.
+ * You have to provide more input with <code>setInput()</code>.
+ * NOTE: needsInput() also returns true when, the stream is finished.
+ * </li>
+ * <li>needsDictionary() returns true, you have to provide a preset
+ * dictionary with <code>setDictionary()</code>.</li>
+ * <li>finished() returns true, the inflater has finished.</li>
+ * </ul>
+ * Once the first output byte is produced, a dictionary will not be
+ * needed at a later stage.
+ *
+ * @author John Leuner, Jochen Hoenicke
+ * @author Tom Tromey
+ * @date May 17, 1999
+ * @since JDK 1.1
+ */
+public class Inflater
+{
+ /* Copy lengths for literal codes 257..285 */
+ private static final int CPLENS[] =
+ {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
+ };
+
+ /* Extra bits for literal codes 257..285 */
+ private static final int CPLEXT[] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
+ };
+
+ /* Copy offsets for distance codes 0..29 */
+ private static final int CPDIST[] = {
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ /* Extra bits for distance codes */
+ private static final int CPDEXT[] = {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13
+ };
+
+ /* This are the state in which the inflater can be. */
+ private static final int DECODE_HEADER = 0;
+ private static final int DECODE_DICT = 1;
+ private static final int DECODE_BLOCKS = 2;
+ private static final int DECODE_STORED_LEN1 = 3;
+ private static final int DECODE_STORED_LEN2 = 4;
+ private static final int DECODE_STORED = 5;
+ private static final int DECODE_DYN_HEADER = 6;
+ private static final int DECODE_HUFFMAN = 7;
+ private static final int DECODE_HUFFMAN_LENBITS = 8;
+ private static final int DECODE_HUFFMAN_DIST = 9;
+ private static final int DECODE_HUFFMAN_DISTBITS = 10;
+ private static final int DECODE_CHKSUM = 11;
+ private static final int FINISHED = 12;
+
+ /** This variable contains the current state. */
+ private int mode;
+
+ /**
+ * The adler checksum of the dictionary or of the decompressed
+ * stream, as it is written in the header resp. footer of the
+ * compressed stream. <br>
+ *
+ * Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
+ */
+ private int readAdler;
+ /**
+ * The number of bits needed to complete the current state. This
+ * is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
+ * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.
+ */
+ private int neededBits;
+ private int repLength, repDist;
+ private int uncomprLen;
+ /**
+ * True, if the last block flag was set in the last block of the
+ * inflated stream. This means that the stream ends after the
+ * current block.
+ */
+ private boolean isLastBlock;
+
+ /**
+ * The total number of inflated bytes.
+ */
+ private int totalOut;
+ /**
+ * The total number of bytes set with setInput(). This is not the
+ * value returned by getTotalIn(), since this also includes the
+ * unprocessed input.
+ */
+ private int totalIn;
+ /**
+ * This variable stores the nowrap flag that was given to the constructor.
+ * True means, that the inflated stream doesn't contain a header nor the
+ * checksum in the footer.
+ */
+ private boolean nowrap;
+
+ private StreamManipulator input;
+ private OutputWindow outputWindow;
+ private InflaterDynHeader dynHeader;
+ private InflaterHuffmanTree litlenTree, distTree;
+ private Adler32 adler;
+
+ /**
+ * Creates a new inflater.
+ */
+ public Inflater ()
+ {
+ this (false);
+ }
+
+ /**
+ * Creates a new inflater.
+ * @param nowrap true if no header and checksum field appears in the
+ * stream. This is used for GZIPed input. For compatibility with
+ * Sun JDK you should provide one byte of input more than needed in
+ * this case.
+ */
+ public Inflater (boolean nowrap)
+ {
+ this.nowrap = nowrap;
+ this.adler = new Adler32();
+ input = new StreamManipulator();
+ outputWindow = new OutputWindow();
+ mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
+ }
+
+ /**
+ * Finalizes this object.
+ */
+ protected void finalize ()
+ {
+ /* Exists only for compatibility */
+ }
+
+ /**
+ * Frees all objects allocated by the inflater. There's no reason
+ * to call this, since you can just rely on garbage collection (even
+ * for the Sun implementation). Exists only for compatibility
+ * with Sun's JDK, where the compressor allocates native memory.
+ * If you call any method (even reset) afterwards the behaviour is
+ * <i>undefined</i>.
+ * @deprecated Just clear all references to inflater instead.
+ */
+ public void end ()
+ {
+ outputWindow = null;
+ input = null;
+ dynHeader = null;
+ litlenTree = null;
+ distTree = null;
+ adler = null;
+ }
+
+ /**
+ * Returns true, if the inflater has finished. This means, that no
+ * input is needed and no output can be produced.
+ */
+ public boolean finished()
+ {
+ return mode == FINISHED && outputWindow.getAvailable() == 0;
+ }
+
+ /**
+ * Gets the adler checksum. This is either the checksum of all
+ * uncompressed bytes returned by inflate(), or if needsDictionary()
+ * returns true (and thus no output was yet produced) this is the
+ * adler checksum of the expected dictionary.
+ * @returns the adler checksum.
+ */
+ public int getAdler()
+ {
+ return needsDictionary() ? readAdler : (int) adler.getValue();
+ }
+
+ /**
+ * Gets the number of unprocessed input. Useful, if the end of the
+ * stream is reached and you want to further process the bytes after
+ * the deflate stream.
+ * @return the number of bytes of the input which were not processed.
+ */
+ public int getRemaining()
+ {
+ return input.getAvailableBytes();
+ }
+
+ /**
+ * Gets the total number of processed compressed input bytes.
+ * @return the total number of bytes of processed input bytes.
+ */
+ public int getTotalIn()
+ {
+ return totalIn - getRemaining();
+ }
+
+ /**
+ * Gets the total number of output bytes returned by inflate().
+ * @return the total number of output bytes.
+ */
+ public int getTotalOut()
+ {
+ return totalOut;
+ }
+
+ /**
+ * Inflates the compressed stream to the output buffer. If this
+ * returns 0, you should check, whether needsDictionary(),
+ * needsInput() or finished() returns true, to determine why no
+ * further output is produced.
+ * @param buf the output buffer.
+ * @return the number of bytes written to the buffer, 0 if no further
+ * output can be produced.
+ * @exception DataFormatException if deflated stream is invalid.
+ * @exception IllegalArgumentException if buf has length 0.
+ */
+ public int inflate (byte[] buf) throws DataFormatException
+ {
+ return inflate (buf, 0, buf.length);
+ }
+
+ /**
+ * Inflates the compressed stream to the output buffer. If this
+ * returns 0, you should check, whether needsDictionary(),
+ * needsInput() or finished() returns true, to determine why no
+ * further output is produced.
+ * @param buf the output buffer.
+ * @param off the offset into buffer where the output should start.
+ * @param len the maximum length of the output.
+ * @return the number of bytes written to the buffer, 0 if no further
+ * output can be produced.
+ * @exception DataFormatException if deflated stream is invalid.
+ * @exception IndexOutOfBoundsException if the off and/or len are wrong.
+ */
+ public int inflate (byte[] buf, int off, int len) throws DataFormatException
+ {
+ /* Special case: len may be zero */
+ if (len == 0)
+ return 0;
+ /* Check for correct buff, off, len triple */
+ if (0 > off || off > off + len || off + len > buf.length)
+ throw new ArrayIndexOutOfBoundsException();
+ int count = 0;
+ int more;
+ do
+ {
+ if (mode != DECODE_CHKSUM)
+ {
+ /* Don't give away any output, if we are waiting for the
+ * checksum in the input stream.
+ *
+ * With this trick we have always:
+ * needsInput() and not finished()
+ * implies more output can be produced.
+ */
+ more = outputWindow.copyOutput(buf, off, len);
+ adler.update(buf, off, more);
+ off += more;
+ count += more;
+ totalOut += more;
+ len -= more;
+ if (len == 0)
+ return count;
+ }
+ }
+ while (decode() || (outputWindow.getAvailable() > 0
+ && mode != DECODE_CHKSUM));
+ return count;
+ }
+
+ /**
+ * Returns true, if a preset dictionary is needed to inflate the input.
+ */
+ public boolean needsDictionary ()
+ {
+ return mode == DECODE_DICT && neededBits == 0;
+ }
+
+ /**
+ * Returns true, if the input buffer is empty.
+ * You should then call setInput(). <br>
+ *
+ * <em>NOTE</em>: This method also returns true when the stream is finished.
+ */
+ public boolean needsInput ()
+ {
+ return input.needsInput ();
+ }
+
+ /**
+ * Resets the inflater so that a new stream can be decompressed. All
+ * pending input and output will be discarded.
+ */
+ public void reset ()
+ {
+ mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
+ totalIn = totalOut = 0;
+ input.reset();
+ outputWindow.reset();
+ dynHeader = null;
+ litlenTree = null;
+ distTree = null;
+ isLastBlock = false;
+ adler.reset();
+ }
+
+ /**
+ * Sets the preset dictionary. This should only be called, if
+ * needsDictionary() returns true and it should set the same
+ * dictionary, that was used for deflating. The getAdler()
+ * function returns the checksum of the dictionary needed.
+ * @param buffer the dictionary.
+ * @exception IllegalStateException if no dictionary is needed.
+ * @exception IllegalArgumentException if the dictionary checksum is
+ * wrong.
+ */
+ public void setDictionary (byte[] buffer)
+ {
+ setDictionary(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Sets the preset dictionary. This should only be called, if
+ * needsDictionary() returns true and it should set the same
+ * dictionary, that was used for deflating. The getAdler()
+ * function returns the checksum of the dictionary needed.
+ * @param buffer the dictionary.
+ * @param off the offset into buffer where the dictionary starts.
+ * @param len the length of the dictionary.
+ * @exception IllegalStateException if no dictionary is needed.
+ * @exception IllegalArgumentException if the dictionary checksum is
+ * wrong.
+ * @exception IndexOutOfBoundsException if the off and/or len are wrong.
+ */
+ public void setDictionary (byte[] buffer, int off, int len)
+ {
+ if (!needsDictionary())
+ throw new IllegalStateException();
+
+ adler.update(buffer, off, len);
+ if ((int) adler.getValue() != readAdler)
+ throw new IllegalArgumentException("Wrong adler checksum");
+ adler.reset();
+ outputWindow.copyDict(buffer, off, len);
+ mode = DECODE_BLOCKS;
+ }
+
+ /**
+ * Sets the input. This should only be called, if needsInput()
+ * returns true.
+ * @param buf the input.
+ * @exception IllegalStateException if no input is needed.
+ */
+ public void setInput (byte[] buf)
+ {
+ setInput (buf, 0, buf.length);
+ }
+
+ /**
+ * Sets the input. This should only be called, if needsInput()
+ * returns true.
+ * @param buf the input.
+ * @param off the offset into buffer where the input starts.
+ * @param len the length of the input.
+ * @exception IllegalStateException if no input is needed.
+ * @exception IndexOutOfBoundsException if the off and/or len are wrong.
+ */
+ public void setInput (byte[] buf, int off, int len)
+ {
+ input.setInput (buf, off, len);
+ totalIn += len;
+ }
+
+ /**
+ * Decodes the deflate header.
+ * @return false if more input is needed.
+ * @exception DataFormatException if header is invalid.
+ */
+ private boolean decodeHeader () throws DataFormatException
+ {
+ int header = input.peekBits(16);
+ if (header < 0)
+ return false;
+ input.dropBits(16);
+
+ /* The header is written in "wrong" byte order */
+ header = ((header << 8) | (header >> 8)) & 0xffff;
+ if (header % 31 != 0)
+ throw new DataFormatException("Header checksum illegal");
+
+ if ((header & 0x0f00) != (Deflater.DEFLATED << 8))
+ throw new DataFormatException("Compression Method unknown");
+
+ /* Maximum size of the backwards window in bits.
+ * We currently ignore this, but we could use it to make the
+ * inflater window more space efficient. On the other hand the
+ * full window (15 bits) is needed most times, anyway.
+ int max_wbits = ((header & 0x7000) >> 12) + 8;
+ */
+
+ if ((header & 0x0020) == 0) // Dictionary flag?
+ {
+ mode = DECODE_BLOCKS;
+ }
+ else
+ {
+ mode = DECODE_DICT;
+ neededBits = 32;
+ }
+ return true;
+ }
+
+ /**
+ * Decodes the dictionary checksum after the deflate header.
+ * @return false if more input is needed.
+ */
+ private boolean decodeDict ()
+ {
+ while (neededBits > 0)
+ {
+ int dictByte = input.peekBits(8);
+ if (dictByte < 0)
+ return false;
+ input.dropBits(8);
+ readAdler = (readAdler << 8) | dictByte;
+ neededBits -= 8;
+ }
+ return false;
+ }
+
+ /**
+ * Decodes the huffman encoded symbols in the input stream.
+ * @return false if more input is needed, true if output window is
+ * full or the current block ends.
+ * @exception DataFormatException if deflated stream is invalid.
+ */
+ private boolean decodeHuffman () throws DataFormatException
+ {
+ int free = outputWindow.getFreeSpace();
+ while (free >= 258)
+ {
+ int symbol;
+ switch (mode)
+ {
+ case DECODE_HUFFMAN:
+ /* This is the inner loop so it is optimized a bit */
+ while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0)
+ {
+ outputWindow.write(symbol);
+ if (--free < 258)
+ return true;
+ }
+ if (symbol < 257)
+ {
+ if (symbol < 0)
+ return false;
+ else
+ {
+ /* symbol == 256: end of block */
+ distTree = null;
+ litlenTree = null;
+ mode = DECODE_BLOCKS;
+ return true;
+ }
+ }
+
+ try
+ {
+ repLength = CPLENS[symbol - 257];
+ neededBits = CPLEXT[symbol - 257];
+ }
+ catch (ArrayIndexOutOfBoundsException ex)
+ {
+ throw new DataFormatException("Illegal rep length code");
+ }
+ /* fall through */
+ case DECODE_HUFFMAN_LENBITS:
+ if (neededBits > 0)
+ {
+ mode = DECODE_HUFFMAN_LENBITS;
+ int i = input.peekBits(neededBits);
+ if (i < 0)
+ return false;
+ input.dropBits(neededBits);
+ repLength += i;
+ }
+ mode = DECODE_HUFFMAN_DIST;
+ /* fall through */
+ case DECODE_HUFFMAN_DIST:
+ symbol = distTree.getSymbol(input);
+ if (symbol < 0)
+ return false;
+ try
+ {
+ repDist = CPDIST[symbol];
+ neededBits = CPDEXT[symbol];
+ }
+ catch (ArrayIndexOutOfBoundsException ex)
+ {
+ throw new DataFormatException("Illegal rep dist code");
+ }
+ /* fall through */
+ case DECODE_HUFFMAN_DISTBITS:
+ if (neededBits > 0)
+ {
+ mode = DECODE_HUFFMAN_DISTBITS;
+ int i = input.peekBits(neededBits);
+ if (i < 0)
+ return false;
+ input.dropBits(neededBits);
+ repDist += i;
+ }
+ outputWindow.repeat(repLength, repDist);
+ free -= repLength;
+ mode = DECODE_HUFFMAN;
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Decodes the adler checksum after the deflate stream.
+ * @return false if more input is needed.
+ * @exception DataFormatException if checksum doesn't match.
+ */
+ private boolean decodeChksum () throws DataFormatException
+ {
+ while (neededBits > 0)
+ {
+ int chkByte = input.peekBits(8);
+ if (chkByte < 0)
+ return false;
+ input.dropBits(8);
+ readAdler = (readAdler << 8) | chkByte;
+ neededBits -= 8;
+ }
+ if ((int) adler.getValue() != readAdler)
+ throw new DataFormatException("Adler chksum doesn't match: "
+ +Integer.toHexString((int)adler.getValue())
+ +" vs. "+Integer.toHexString(readAdler));
+ mode = FINISHED;
+ return false;
+ }
+
+ /**
+ * Decodes the deflated stream.
+ * @return false if more input is needed, or if finished.
+ * @exception DataFormatException if deflated stream is invalid.
+ */
+ private boolean decode () throws DataFormatException
+ {
+ switch (mode)
+ {
+ case DECODE_HEADER:
+ return decodeHeader();
+ case DECODE_DICT:
+ return decodeDict();
+ case DECODE_CHKSUM:
+ return decodeChksum();
+
+ case DECODE_BLOCKS:
+ if (isLastBlock)
+ {
+ if (nowrap)
+ {
+ mode = FINISHED;
+ return false;
+ }
+ else
+ {
+ input.skipToByteBoundary();
+ neededBits = 32;
+ mode = DECODE_CHKSUM;
+ return true;
+ }
+ }
+
+ int type = input.peekBits(3);
+ if (type < 0)
+ return false;
+ input.dropBits(3);
+
+ if ((type & 1) != 0)
+ isLastBlock = true;
+ switch (type >> 1)
+ {
+ case DeflaterConstants.STORED_BLOCK:
+ input.skipToByteBoundary();
+ mode = DECODE_STORED_LEN1;
+ break;
+ case DeflaterConstants.STATIC_TREES:
+ litlenTree = InflaterHuffmanTree.defLitLenTree;
+ distTree = InflaterHuffmanTree.defDistTree;
+ mode = DECODE_HUFFMAN;
+ break;
+ case DeflaterConstants.DYN_TREES:
+ dynHeader = new InflaterDynHeader();
+ mode = DECODE_DYN_HEADER;
+ break;
+ default:
+ throw new DataFormatException("Unknown block type "+type);
+ }
+ return true;
+
+ case DECODE_STORED_LEN1:
+ {
+ if ((uncomprLen = input.peekBits(16)) < 0)
+ return false;
+ input.dropBits(16);
+ mode = DECODE_STORED_LEN2;
+ }
+ /* fall through */
+ case DECODE_STORED_LEN2:
+ {
+ int nlen = input.peekBits(16);
+ if (nlen < 0)
+ return false;
+ input.dropBits(16);
+ if (nlen != (uncomprLen ^ 0xffff))
+ throw new DataFormatException("broken uncompressed block");
+ mode = DECODE_STORED;
+ }
+ /* fall through */
+ case DECODE_STORED:
+ {
+ int more = outputWindow.copyStored(input, uncomprLen);
+ uncomprLen -= more;
+ if (uncomprLen == 0)
+ {
+ mode = DECODE_BLOCKS;
+ return true;
+ }
+ return !input.needsInput();
+ }
+
+ case DECODE_DYN_HEADER:
+ if (!dynHeader.decode(input))
+ return false;
+ litlenTree = dynHeader.buildLitLenTree();
+ distTree = dynHeader.buildDistTree();
+ mode = DECODE_HUFFMAN;
+ /* fall through */
+ case DECODE_HUFFMAN:
+ case DECODE_HUFFMAN_LENBITS:
+ case DECODE_HUFFMAN_DIST:
+ case DECODE_HUFFMAN_DISTBITS:
+ return decodeHuffman();
+ case FINISHED:
+ return false;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/zip/InflaterDynHeader.java b/libjava/classpath/java/util/zip/InflaterDynHeader.java
new file mode 100644
index 00000000000..bff84a894d8
--- /dev/null
+++ b/libjava/classpath/java/util/zip/InflaterDynHeader.java
@@ -0,0 +1,203 @@
+/* java.util.zip.InflaterDynHeader
+ Copyright (C) 2001 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.zip;
+
+class InflaterDynHeader
+{
+ private static final int LNUM = 0;
+ private static final int DNUM = 1;
+ private static final int BLNUM = 2;
+ private static final int BLLENS = 3;
+ private static final int LENS = 4;
+ private static final int REPS = 5;
+
+ private static final int repMin[] = { 3, 3, 11 };
+ private static final int repBits[] = { 2, 3, 7 };
+
+
+ private byte[] blLens;
+ private byte[] litdistLens;
+
+ private InflaterHuffmanTree blTree;
+
+ private int mode;
+ private int lnum, dnum, blnum, num;
+ private int repSymbol;
+ private byte lastLen;
+ private int ptr;
+
+ private static final int[] BL_ORDER =
+ { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
+
+ public InflaterDynHeader()
+ {
+ }
+
+ public boolean decode(StreamManipulator input) throws DataFormatException
+ {
+ decode_loop:
+ for (;;)
+ {
+ switch (mode)
+ {
+ case LNUM:
+ lnum = input.peekBits(5);
+ if (lnum < 0)
+ return false;
+ lnum += 257;
+ input.dropBits(5);
+// System.err.println("LNUM: "+lnum);
+ mode = DNUM;
+ /* fall through */
+ case DNUM:
+ dnum = input.peekBits(5);
+ if (dnum < 0)
+ return false;
+ dnum++;
+ input.dropBits(5);
+// System.err.println("DNUM: "+dnum);
+ num = lnum+dnum;
+ litdistLens = new byte[num];
+ mode = BLNUM;
+ /* fall through */
+ case BLNUM:
+ blnum = input.peekBits(4);
+ if (blnum < 0)
+ return false;
+ blnum += 4;
+ input.dropBits(4);
+ blLens = new byte[19];
+ ptr = 0;
+// System.err.println("BLNUM: "+blnum);
+ mode = BLLENS;
+ /* fall through */
+ case BLLENS:
+ while (ptr < blnum)
+ {
+ int len = input.peekBits(3);
+ if (len < 0)
+ return false;
+ input.dropBits(3);
+// System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
+ blLens[BL_ORDER[ptr]] = (byte) len;
+ ptr++;
+ }
+ blTree = new InflaterHuffmanTree(blLens);
+ blLens = null;
+ ptr = 0;
+ mode = LENS;
+ /* fall through */
+ case LENS:
+ {
+ int symbol;
+ while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
+ {
+ /* Normal case: symbol in [0..15] */
+
+// System.err.println("litdistLens["+ptr+"]: "+symbol);
+ litdistLens[ptr++] = lastLen = (byte) symbol;
+
+ if (ptr == num)
+ {
+ /* Finished */
+ return true;
+ }
+ }
+
+ /* need more input ? */
+ if (symbol < 0)
+ return false;
+
+ /* otherwise repeat code */
+ if (symbol >= 17)
+ {
+ /* repeat zero */
+// System.err.println("repeating zero");
+ lastLen = 0;
+ }
+ else
+ {
+ if (ptr == 0)
+ throw new DataFormatException();
+ }
+ repSymbol = symbol-16;
+ mode = REPS;
+ }
+ /* fall through */
+
+ case REPS:
+ {
+ int bits = repBits[repSymbol];
+ int count = input.peekBits(bits);
+ if (count < 0)
+ return false;
+ input.dropBits(bits);
+ count += repMin[repSymbol];
+// System.err.println("litdistLens repeated: "+count);
+
+ if (ptr + count > num)
+ throw new DataFormatException();
+ while (count-- > 0)
+ litdistLens[ptr++] = lastLen;
+
+ if (ptr == num)
+ {
+ /* Finished */
+ return true;
+ }
+ }
+ mode = LENS;
+ continue decode_loop;
+ }
+ }
+ }
+
+ public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
+ {
+ byte[] litlenLens = new byte[lnum];
+ System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
+ return new InflaterHuffmanTree(litlenLens);
+ }
+
+ public InflaterHuffmanTree buildDistTree() throws DataFormatException
+ {
+ byte[] distLens = new byte[dnum];
+ System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
+ return new InflaterHuffmanTree(distLens);
+ }
+}
diff --git a/libjava/classpath/java/util/zip/InflaterHuffmanTree.java b/libjava/classpath/java/util/zip/InflaterHuffmanTree.java
new file mode 100644
index 00000000000..6c9b2175d33
--- /dev/null
+++ b/libjava/classpath/java/util/zip/InflaterHuffmanTree.java
@@ -0,0 +1,217 @@
+/* InflaterHuffmanTree.java --
+ Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.zip;
+
+class InflaterHuffmanTree
+{
+ private static final int MAX_BITLEN = 15;
+
+ private short[] tree;
+
+ static InflaterHuffmanTree defLitLenTree, defDistTree;
+
+ static
+ {
+ try
+ {
+ byte[] codeLengths = new byte[288];
+ int i = 0;
+ while (i < 144)
+ codeLengths[i++] = 8;
+ while (i < 256)
+ codeLengths[i++] = 9;
+ while (i < 280)
+ codeLengths[i++] = 7;
+ while (i < 288)
+ codeLengths[i++] = 8;
+ defLitLenTree = new InflaterHuffmanTree(codeLengths);
+
+ codeLengths = new byte[32];
+ i = 0;
+ while (i < 32)
+ codeLengths[i++] = 5;
+ defDistTree = new InflaterHuffmanTree(codeLengths);
+ }
+ catch (DataFormatException ex)
+ {
+ throw new InternalError
+ ("InflaterHuffmanTree: static tree length illegal");
+ }
+ }
+
+ /**
+ * Constructs a Huffman tree from the array of code lengths.
+ *
+ * @param codeLengths the array of code lengths
+ */
+ InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException
+ {
+ buildTree(codeLengths);
+ }
+
+ private void buildTree(byte[] codeLengths) throws DataFormatException
+ {
+ int[] blCount = new int[MAX_BITLEN+1];
+ int[] nextCode = new int[MAX_BITLEN+1];
+ for (int i = 0; i < codeLengths.length; i++)
+ {
+ int bits = codeLengths[i];
+ if (bits > 0)
+ blCount[bits]++;
+ }
+
+ int code = 0;
+ int treeSize = 512;
+ for (int bits = 1; bits <= MAX_BITLEN; bits++)
+ {
+ nextCode[bits] = code;
+ code += blCount[bits] << (16 - bits);
+ if (bits >= 10)
+ {
+ /* We need an extra table for bit lengths >= 10. */
+ int start = nextCode[bits] & 0x1ff80;
+ int end = code & 0x1ff80;
+ treeSize += (end - start) >> (16 - bits);
+ }
+ }
+ if (code != 65536)
+ throw new DataFormatException("Code lengths don't add up properly.");
+
+ /* Now create and fill the extra tables from longest to shortest
+ * bit len. This way the sub trees will be aligned.
+ */
+ tree = new short[treeSize];
+ int treePtr = 512;
+ for (int bits = MAX_BITLEN; bits >= 10; bits--)
+ {
+ int end = code & 0x1ff80;
+ code -= blCount[bits] << (16 - bits);
+ int start = code & 0x1ff80;
+ for (int i = start; i < end; i += 1 << 7)
+ {
+ tree[DeflaterHuffman.bitReverse(i)]
+ = (short) ((-treePtr << 4) | bits);
+ treePtr += 1 << (bits-9);
+ }
+ }
+
+ for (int i = 0; i < codeLengths.length; i++)
+ {
+ int bits = codeLengths[i];
+ if (bits == 0)
+ continue;
+ code = nextCode[bits];
+ int revcode = DeflaterHuffman.bitReverse(code);
+ if (bits <= 9)
+ {
+ do
+ {
+ tree[revcode] = (short) ((i << 4) | bits);
+ revcode += 1 << bits;
+ }
+ while (revcode < 512);
+ }
+ else
+ {
+ int subTree = tree[revcode & 511];
+ int treeLen = 1 << (subTree & 15);
+ subTree = -(subTree >> 4);
+ do
+ {
+ tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits);
+ revcode += 1 << bits;
+ }
+ while (revcode < treeLen);
+ }
+ nextCode[bits] = code + (1 << (16 - bits));
+ }
+ }
+
+ /**
+ * Reads the next symbol from input. The symbol is encoded using the
+ * huffman tree.
+ * @param input the input source.
+ * @return the next symbol, or -1 if not enough input is available.
+ */
+ int getSymbol(StreamManipulator input) throws DataFormatException
+ {
+ int lookahead, symbol;
+ if ((lookahead = input.peekBits(9)) >= 0)
+ {
+ if ((symbol = tree[lookahead]) >= 0)
+ {
+ input.dropBits(symbol & 15);
+ return symbol >> 4;
+ }
+ int subtree = -(symbol >> 4);
+ int bitlen = symbol & 15;
+ if ((lookahead = input.peekBits(bitlen)) >= 0)
+ {
+ symbol = tree[subtree | (lookahead >> 9)];
+ input.dropBits(symbol & 15);
+ return symbol >> 4;
+ }
+ else
+ {
+ int bits = input.getAvailableBits();
+ lookahead = input.peekBits(bits);
+ symbol = tree[subtree | (lookahead >> 9)];
+ if ((symbol & 15) <= bits)
+ {
+ input.dropBits(symbol & 15);
+ return symbol >> 4;
+ }
+ else
+ return -1;
+ }
+ }
+ else
+ {
+ int bits = input.getAvailableBits();
+ lookahead = input.peekBits(bits);
+ symbol = tree[lookahead];
+ if (symbol >= 0 && (symbol & 15) <= bits)
+ {
+ input.dropBits(symbol & 15);
+ return symbol >> 4;
+ }
+ else
+ return -1;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/zip/InflaterInputStream.java b/libjava/classpath/java/util/zip/InflaterInputStream.java
new file mode 100644
index 00000000000..3c374570602
--- /dev/null
+++ b/libjava/classpath/java/util/zip/InflaterInputStream.java
@@ -0,0 +1,261 @@
+/* InflaterInputStream.java - Input stream filter for decompressing
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.zip;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This filter stream is used to decompress data compressed in the "deflate"
+ * format. The "deflate" format is described in RFC 1951.
+ *
+ * This stream may form the basis for other decompression filters, such
+ * as the <code>GZIPInputStream</code>.
+ *
+ * @author John Leuner
+ * @author Tom Tromey
+ * @since 1.1
+ */
+public class InflaterInputStream extends FilterInputStream
+{
+ /**
+ * Decompressor for this filter
+ */
+ protected Inflater inf;
+
+ /**
+ * Byte array used as a buffer
+ */
+ protected byte[] buf;
+
+ /**
+ * Size of buffer
+ */
+ protected int len;
+
+ // We just use this if we are decoding one byte at a time with the
+ // read() call.
+ private byte[] onebytebuffer = new byte[1];
+
+ /**
+ * Create an InflaterInputStream with the default decompresseor
+ * and a default buffer size.
+ *
+ * @param in the InputStream to read bytes from
+ */
+ public InflaterInputStream(InputStream in)
+ {
+ this(in, new Inflater(), 4096);
+ }
+
+ /**
+ * Create an InflaterInputStream with the specified decompresseor
+ * and a default buffer size.
+ *
+ * @param in the InputStream to read bytes from
+ * @param inf the decompressor used to decompress data read from in
+ */
+ public InflaterInputStream(InputStream in, Inflater inf)
+ {
+ this(in, inf, 4096);
+ }
+
+ /**
+ * Create an InflaterInputStream with the specified decompresseor
+ * and a specified buffer size.
+ *
+ * @param in the InputStream to read bytes from
+ * @param inf the decompressor used to decompress data read from in
+ * @param size size of the buffer to use
+ */
+ public InflaterInputStream(InputStream in, Inflater inf, int size)
+ {
+ super(in);
+
+ if (in == null)
+ throw new NullPointerException("in may not be null");
+ if (inf == null)
+ throw new NullPointerException("inf may not be null");
+ if (size < 0)
+ throw new IllegalArgumentException("size may not be negative");
+
+ this.inf = inf;
+ this.buf = new byte [size];
+ }
+
+ /**
+ * Returns 0 once the end of the stream (EOF) has been reached.
+ * Otherwise returns 1.
+ */
+ public int available() throws IOException
+ {
+ // According to the JDK 1.2 docs, this should only ever return 0
+ // or 1 and should not be relied upon by Java programs.
+ if (inf == null)
+ throw new IOException("stream closed");
+ return inf.finished() ? 0 : 1;
+ }
+
+ /**
+ * Closes the input stream
+ */
+ public synchronized void close() throws IOException
+ {
+ if (in != null)
+ in.close();
+ in = null;
+ }
+
+ /**
+ * Fills the buffer with more data to decompress.
+ */
+ protected void fill() throws IOException
+ {
+ if (in == null)
+ throw new ZipException ("InflaterInputStream is closed");
+
+ len = in.read(buf, 0, buf.length);
+
+ if (len < 0)
+ throw new ZipException("Deflated stream ends early.");
+
+ inf.setInput(buf, 0, len);
+ }
+
+ /**
+ * Reads one byte of decompressed data.
+ *
+ * The byte is in the lower 8 bits of the int.
+ */
+ public int read() throws IOException
+ {
+ int nread = read(onebytebuffer, 0, 1);
+ if (nread > 0)
+ return onebytebuffer[0] & 0xff;
+ return -1;
+ }
+
+ /**
+ * Decompresses data into the byte array
+ *
+ * @param b the array to read and decompress data into
+ * @param off the offset indicating where the data should be placed
+ * @param len the number of bytes to decompress
+ */
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (inf == null)
+ throw new IOException("stream closed");
+ if (len == 0)
+ return 0;
+
+ int count = 0;
+ for (;;)
+ {
+
+ try
+ {
+ count = inf.inflate(b, off, len);
+ }
+ catch (DataFormatException dfe)
+ {
+ throw new ZipException(dfe.getMessage());
+ }
+
+ if (count > 0)
+ return count;
+
+ if (inf.needsDictionary()
+ | inf.finished())
+ return -1;
+ else if (inf.needsInput())
+ fill();
+ else
+ throw new InternalError("Don't know what to do");
+ }
+ }
+
+ /**
+ * Skip specified number of bytes of uncompressed data
+ *
+ * @param n number of bytes to skip
+ */
+ public long skip(long n) throws IOException
+ {
+ if (inf == null)
+ throw new IOException("stream closed");
+ if (n < 0)
+ throw new IllegalArgumentException();
+
+ if (n == 0)
+ return 0;
+
+ int buflen = (int) Math.min(n, 2048);
+ byte[] tmpbuf = new byte[buflen];
+
+ long skipped = 0L;
+ while (n > 0L)
+ {
+ int numread = read(tmpbuf, 0, buflen);
+ if (numread <= 0)
+ break;
+ n -= numread;
+ skipped += numread;
+ buflen = (int) Math.min(n, 2048);
+ }
+
+ return skipped;
+ }
+
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ public void mark(int readLimit)
+ {
+ }
+
+ public void reset() throws IOException
+ {
+ throw new IOException("reset not supported");
+ }
+}
diff --git a/libjava/classpath/java/util/zip/OutputWindow.java b/libjava/classpath/java/util/zip/OutputWindow.java
new file mode 100644
index 00000000000..1f082a9faa4
--- /dev/null
+++ b/libjava/classpath/java/util/zip/OutputWindow.java
@@ -0,0 +1,178 @@
+/* OutputWindow.java --
+ Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.zip;
+
+/**
+ * Contains the output from the Inflation process.
+ *
+ * We need to have a window so that we can refer backwards into the output stream
+ * to repeat stuff.
+ *
+ * @author John Leuner
+ * @since 1.1
+ */
+class OutputWindow
+{
+ private static final int WINDOW_SIZE = 1 << 15;
+ private static final int WINDOW_MASK = WINDOW_SIZE - 1;
+
+ private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
+ private int window_end = 0;
+ private int window_filled = 0;
+
+ public void write(int abyte)
+ {
+ if (window_filled++ == WINDOW_SIZE)
+ throw new IllegalStateException("Window full");
+ window[window_end++] = (byte) abyte;
+ window_end &= WINDOW_MASK;
+ }
+
+ private void slowRepeat(int rep_start, int len, int dist)
+ {
+ while (len-- > 0)
+ {
+ window[window_end++] = window[rep_start++];
+ window_end &= WINDOW_MASK;
+ rep_start &= WINDOW_MASK;
+ }
+ }
+
+ public void repeat(int len, int dist)
+ {
+ if ((window_filled += len) > WINDOW_SIZE)
+ throw new IllegalStateException("Window full");
+
+ int rep_start = (window_end - dist) & WINDOW_MASK;
+ int border = WINDOW_SIZE - len;
+ if (rep_start <= border && window_end < border)
+ {
+ if (len <= dist)
+ {
+ System.arraycopy(window, rep_start, window, window_end, len);
+ window_end += len;
+ }
+ else
+ {
+ /* We have to copy manually, since the repeat pattern overlaps.
+ */
+ while (len-- > 0)
+ window[window_end++] = window[rep_start++];
+ }
+ }
+ else
+ slowRepeat(rep_start, len, dist);
+ }
+
+ public int copyStored(StreamManipulator input, int len)
+ {
+ len = Math.min(Math.min(len, WINDOW_SIZE - window_filled),
+ input.getAvailableBytes());
+ int copied;
+
+ int tailLen = WINDOW_SIZE - window_end;
+ if (len > tailLen)
+ {
+ copied = input.copyBytes(window, window_end, tailLen);
+ if (copied == tailLen)
+ copied += input.copyBytes(window, 0, len - tailLen);
+ }
+ else
+ copied = input.copyBytes(window, window_end, len);
+
+ window_end = (window_end + copied) & WINDOW_MASK;
+ window_filled += copied;
+ return copied;
+ }
+
+ public void copyDict(byte[] dict, int offset, int len)
+ {
+ if (window_filled > 0)
+ throw new IllegalStateException();
+
+ if (len > WINDOW_SIZE)
+ {
+ offset += len - WINDOW_SIZE;
+ len = WINDOW_SIZE;
+ }
+ System.arraycopy(dict, offset, window, 0, len);
+ window_end = len & WINDOW_MASK;
+ }
+
+ public int getFreeSpace()
+ {
+ return WINDOW_SIZE - window_filled;
+ }
+
+ public int getAvailable()
+ {
+ return window_filled;
+ }
+
+ public int copyOutput(byte[] output, int offset, int len)
+ {
+ int copy_end = window_end;
+ if (len > window_filled)
+ len = window_filled;
+ else
+ copy_end = (window_end - window_filled + len) & WINDOW_MASK;
+
+ int copied = len;
+ int tailLen = len - copy_end;
+
+ if (tailLen > 0)
+ {
+ System.arraycopy(window, WINDOW_SIZE - tailLen,
+ output, offset, tailLen);
+ offset += tailLen;
+ len = copy_end;
+ }
+ System.arraycopy(window, copy_end - len, output, offset, len);
+ window_filled -= copied;
+ if (window_filled < 0)
+ throw new IllegalStateException();
+ return copied;
+ }
+
+ public void reset() {
+ window_filled = window_end = 0;
+ }
+}
+
+
+
diff --git a/libjava/classpath/java/util/zip/PendingBuffer.java b/libjava/classpath/java/util/zip/PendingBuffer.java
new file mode 100644
index 00000000000..dd7ed1008fb
--- /dev/null
+++ b/libjava/classpath/java/util/zip/PendingBuffer.java
@@ -0,0 +1,200 @@
+/* java.util.zip.PendingBuffer
+ Copyright (C) 2001 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.zip;
+
+/**
+ * This class is general purpose class for writing data to a buffer.
+ *
+ * It allows you to write bits as well as bytes
+ *
+ * Based on DeflaterPending.java
+ *
+ * @author Jochen Hoenicke
+ * @date Jan 5, 2000
+ */
+
+class PendingBuffer
+{
+ protected byte[] buf;
+ int start;
+ int end;
+
+ int bits;
+ int bitCount;
+
+ public PendingBuffer()
+ {
+ this( 4096 );
+ }
+
+ public PendingBuffer(int bufsize)
+ {
+ buf = new byte[bufsize];
+ }
+
+ public final void reset() {
+ start = end = bitCount = 0;
+ }
+
+ public final void writeByte(int b)
+ {
+ if (DeflaterConstants.DEBUGGING && start != 0)
+ throw new IllegalStateException();
+ buf[end++] = (byte) b;
+ }
+
+ public final void writeShort(int s)
+ {
+ if (DeflaterConstants.DEBUGGING && start != 0)
+ throw new IllegalStateException();
+ buf[end++] = (byte) s;
+ buf[end++] = (byte) (s >> 8);
+ }
+
+ public final void writeInt(int s)
+ {
+ if (DeflaterConstants.DEBUGGING && start != 0)
+ throw new IllegalStateException();
+ buf[end++] = (byte) s;
+ buf[end++] = (byte) (s >> 8);
+ buf[end++] = (byte) (s >> 16);
+ buf[end++] = (byte) (s >> 24);
+ }
+
+ public final void writeBlock(byte[] block, int offset, int len)
+ {
+ if (DeflaterConstants.DEBUGGING && start != 0)
+ throw new IllegalStateException();
+ System.arraycopy(block, offset, buf, end, len);
+ end += len;
+ }
+
+ public final int getBitCount() {
+ return bitCount;
+ }
+
+ public final void alignToByte() {
+ if (DeflaterConstants.DEBUGGING && start != 0)
+ throw new IllegalStateException();
+ if (bitCount > 0)
+ {
+ buf[end++] = (byte) bits;
+ if (bitCount > 8)
+ buf[end++] = (byte) (bits >>> 8);
+ }
+ bits = 0;
+ bitCount = 0;
+ }
+
+ public final void writeBits(int b, int count)
+ {
+ if (DeflaterConstants.DEBUGGING && start != 0)
+ throw new IllegalStateException();
+ if (DeflaterConstants.DEBUGGING)
+ System.err.println("writeBits("+Integer.toHexString(b)+","+count+")");
+ bits |= b << bitCount;
+ bitCount += count;
+ if (bitCount >= 16) {
+ buf[end++] = (byte) bits;
+ buf[end++] = (byte) (bits >>> 8);
+ bits >>>= 16;
+ bitCount -= 16;
+ }
+ }
+
+ public final void writeShortMSB(int s) {
+ if (DeflaterConstants.DEBUGGING && start != 0)
+ throw new IllegalStateException();
+ buf[end++] = (byte) (s >> 8);
+ buf[end++] = (byte) s;
+ }
+
+ public final boolean isFlushed() {
+ return end == 0;
+ }
+
+ /**
+ * Flushes the pending buffer into the given output array. If the
+ * output array is to small, only a partial flush is done.
+ *
+ * @param output the output array;
+ * @param offset the offset into output array;
+ * @param length the maximum number of bytes to store;
+ * @exception IndexOutOfBoundsException if offset or length are
+ * invalid.
+ */
+ public final int flush(byte[] output, int offset, int length) {
+ if (bitCount >= 8)
+ {
+ buf[end++] = (byte) bits;
+ bits >>>= 8;
+ bitCount -= 8;
+ }
+ if (length > end - start)
+ {
+ length = end - start;
+ System.arraycopy(buf, start, output, offset, length);
+ start = 0;
+ end = 0;
+ }
+ else
+ {
+ System.arraycopy(buf, start, output, offset, length);
+ start += length;
+ }
+ return length;
+ }
+
+ /**
+ * Flushes the pending buffer and returns that data in a new array
+ *
+ * @param output the output stream
+ */
+
+ public final byte[] toByteArray()
+ {
+ byte[] ret = new byte[ end - start ];
+ System.arraycopy(buf, start, ret, 0, ret.length);
+ start = 0;
+ end = 0;
+ return ret;
+ }
+
+
+}
+
diff --git a/libjava/classpath/java/util/zip/StreamManipulator.java b/libjava/classpath/java/util/zip/StreamManipulator.java
new file mode 100644
index 00000000000..57d15ae283b
--- /dev/null
+++ b/libjava/classpath/java/util/zip/StreamManipulator.java
@@ -0,0 +1,216 @@
+/* java.util.zip.StreamManipulator
+ Copyright (C) 2001 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.zip;
+
+/**
+ * This class allows us to retrieve a specified amount of bits from
+ * the input buffer, as well as copy big byte blocks.
+ *
+ * It uses an int buffer to store up to 31 bits for direct
+ * manipulation. This guarantees that we can get at least 16 bits,
+ * but we only need at most 15, so this is all safe.
+ *
+ * There are some optimizations in this class, for example, you must
+ * never peek more then 8 bits more than needed, and you must first
+ * peek bits before you may drop them. This is not a general purpose
+ * class but optimized for the behaviour of the Inflater.
+ *
+ * @author John Leuner, Jochen Hoenicke
+ */
+
+class StreamManipulator
+{
+ private byte[] window;
+ private int window_start = 0;
+ private int window_end = 0;
+
+ private int buffer = 0;
+ private int bits_in_buffer = 0;
+
+ /**
+ * Get the next n bits but don't increase input pointer. n must be
+ * less or equal 16 and if you if this call succeeds, you must drop
+ * at least n-8 bits in the next call.
+ *
+ * @return the value of the bits, or -1 if not enough bits available. */
+ public final int peekBits(int n)
+ {
+ if (bits_in_buffer < n)
+ {
+ if (window_start == window_end)
+ return -1;
+ buffer |= (window[window_start++] & 0xff
+ | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
+ bits_in_buffer += 16;
+ }
+ return buffer & ((1 << n) - 1);
+ }
+
+ /* Drops the next n bits from the input. You should have called peekBits
+ * with a bigger or equal n before, to make sure that enough bits are in
+ * the bit buffer.
+ */
+ public final void dropBits(int n)
+ {
+ buffer >>>= n;
+ bits_in_buffer -= n;
+ }
+
+ /**
+ * Gets the next n bits and increases input pointer. This is equivalent
+ * to peekBits followed by dropBits, except for correct error handling.
+ * @return the value of the bits, or -1 if not enough bits available.
+ */
+ public final int getBits(int n)
+ {
+ int bits = peekBits(n);
+ if (bits >= 0)
+ dropBits(n);
+ return bits;
+ }
+ /**
+ * Gets the number of bits available in the bit buffer. This must be
+ * only called when a previous peekBits() returned -1.
+ * @return the number of bits available.
+ */
+ public final int getAvailableBits()
+ {
+ return bits_in_buffer;
+ }
+
+ /**
+ * Gets the number of bytes available.
+ * @return the number of bytes available.
+ */
+ public final int getAvailableBytes()
+ {
+ return window_end - window_start + (bits_in_buffer >> 3);
+ }
+
+ /**
+ * Skips to the next byte boundary.
+ */
+ public void skipToByteBoundary()
+ {
+ buffer >>= (bits_in_buffer & 7);
+ bits_in_buffer &= ~7;
+ }
+
+ public final boolean needsInput() {
+ return window_start == window_end;
+ }
+
+
+ /* Copies length bytes from input buffer to output buffer starting
+ * at output[offset]. You have to make sure, that the buffer is
+ * byte aligned. If not enough bytes are available, copies fewer
+ * bytes.
+ * @param length the length to copy, 0 is allowed.
+ * @return the number of bytes copied, 0 if no byte is available.
+ */
+ public int copyBytes(byte[] output, int offset, int length)
+ {
+ if (length < 0)
+ throw new IllegalArgumentException("length negative");
+ if ((bits_in_buffer & 7) != 0)
+ /* bits_in_buffer may only be 0 or 8 */
+ throw new IllegalStateException("Bit buffer is not aligned!");
+
+ int count = 0;
+ while (bits_in_buffer > 0 && length > 0)
+ {
+ output[offset++] = (byte) buffer;
+ buffer >>>= 8;
+ bits_in_buffer -= 8;
+ length--;
+ count++;
+ }
+ if (length == 0)
+ return count;
+
+ int avail = window_end - window_start;
+ if (length > avail)
+ length = avail;
+ System.arraycopy(window, window_start, output, offset, length);
+ window_start += length;
+
+ if (((window_start - window_end) & 1) != 0)
+ {
+ /* We always want an even number of bytes in input, see peekBits */
+ buffer = (window[window_start++] & 0xff);
+ bits_in_buffer = 8;
+ }
+ return count + length;
+ }
+
+ public StreamManipulator()
+ {
+ }
+
+ public void reset()
+ {
+ window_start = window_end = buffer = bits_in_buffer = 0;
+ }
+
+ public void setInput(byte[] buf, int off, int len)
+ {
+ if (window_start < window_end)
+ throw new IllegalStateException
+ ("Old input was not completely processed");
+
+ int end = off + len;
+
+ /* We want to throw an ArrayIndexOutOfBoundsException early. The
+ * check is very tricky: it also handles integer wrap around.
+ */
+ if (0 > off || off > end || end > buf.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ if ((len & 1) != 0)
+ {
+ /* We always want an even number of bytes in input, see peekBits */
+ buffer |= (buf[off++] & 0xff) << bits_in_buffer;
+ bits_in_buffer += 8;
+ }
+
+ window = buf;
+ window_start = off;
+ window_end = end;
+ }
+}
+
diff --git a/libjava/classpath/java/util/zip/ZipConstants.java b/libjava/classpath/java/util/zip/ZipConstants.java
new file mode 100644
index 00000000000..952a44def4c
--- /dev/null
+++ b/libjava/classpath/java/util/zip/ZipConstants.java
@@ -0,0 +1,97 @@
+/* java.util.zip.ZipConstants
+ Copyright (C) 2001 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.zip;
+
+interface ZipConstants
+{
+ /* The local file header */
+ int LOCHDR = 30;
+ int LOCSIG = 'P'|('K'<<8)|(3<<16)|(4<<24);
+
+ int LOCVER = 4;
+ int LOCFLG = 6;
+ int LOCHOW = 8;
+ int LOCTIM = 10;
+ int LOCCRC = 14;
+ int LOCSIZ = 18;
+ int LOCLEN = 22;
+ int LOCNAM = 26;
+ int LOCEXT = 28;
+
+ /* The Data descriptor */
+ int EXTSIG = 'P'|('K'<<8)|(7<<16)|(8<<24);
+ int EXTHDR = 16;
+
+ int EXTCRC = 4;
+ int EXTSIZ = 8;
+ int EXTLEN = 12;
+
+ /* The central directory file header */
+ int CENSIG = 'P'|('K'<<8)|(1<<16)|(2<<24);
+ int CENHDR = 46;
+
+ int CENVEM = 4;
+ int CENVER = 6;
+ int CENFLG = 8;
+ int CENHOW = 10;
+ int CENTIM = 12;
+ int CENCRC = 16;
+ int CENSIZ = 20;
+ int CENLEN = 24;
+ int CENNAM = 28;
+ int CENEXT = 30;
+ int CENCOM = 32;
+ int CENDSK = 34;
+ int CENATT = 36;
+ int CENATX = 38;
+ int CENOFF = 42;
+
+ /* The entries in the end of central directory */
+ int ENDSIG = 'P'|('K'<<8)|(5<<16)|(6<<24);
+ int ENDHDR = 22;
+
+ /* The following two fields are missing in SUN JDK */
+ int ENDNRD = 4;
+ int ENDDCD = 6;
+ int ENDSUB = 8;
+ int ENDTOT = 10;
+ int ENDSIZ = 12;
+ int ENDOFF = 16;
+ int ENDCOM = 20;
+}
+
diff --git a/libjava/classpath/java/util/zip/ZipEntry.java b/libjava/classpath/java/util/zip/ZipEntry.java
new file mode 100644
index 00000000000..ae21997dba2
--- /dev/null
+++ b/libjava/classpath/java/util/zip/ZipEntry.java
@@ -0,0 +1,432 @@
+/* ZipEntry.java --
+ Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.zip;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * This class represents a member of a zip archive. ZipFile and
+ * ZipInputStream will give you instances of this class as information
+ * about the members in an archive. On the other hand ZipOutputStream
+ * needs an instance of this class to create a new member.
+ *
+ * @author Jochen Hoenicke
+ */
+public class ZipEntry implements ZipConstants, Cloneable
+{
+ private static final int KNOWN_SIZE = 1;
+ private static final int KNOWN_CSIZE = 2;
+ private static final int KNOWN_CRC = 4;
+ private static final int KNOWN_TIME = 8;
+ private static final int KNOWN_EXTRA = 16;
+
+ private static Calendar cal;
+
+ private String name;
+ private int size;
+ private long compressedSize = -1;
+ private int crc;
+ private int dostime;
+ private short known = 0;
+ private short method = -1;
+ private byte[] extra = null;
+ private String comment = null;
+
+ int flags; /* used by ZipOutputStream */
+ int offset; /* used by ZipFile and ZipOutputStream */
+
+ /**
+ * Compression method. This method doesn't compress at all.
+ */
+ public static final int STORED = 0;
+ /**
+ * Compression method. This method uses the Deflater.
+ */
+ public static final int DEFLATED = 8;
+
+ /**
+ * Creates a zip entry with the given name.
+ * @param name the name. May include directory components separated
+ * by '/'.
+ *
+ * @exception NullPointerException when name is null.
+ * @exception IllegalArgumentException when name is bigger then 65535 chars.
+ */
+ public ZipEntry(String name)
+ {
+ int length = name.length();
+ if (length > 65535)
+ throw new IllegalArgumentException("name length is " + length);
+ this.name = name;
+ }
+
+ /**
+ * Creates a copy of the given zip entry.
+ * @param e the entry to copy.
+ */
+ public ZipEntry(ZipEntry e)
+ {
+ this(e, e.name);
+ }
+
+ ZipEntry(ZipEntry e, String name)
+ {
+ this.name = name;
+ known = e.known;
+ size = e.size;
+ compressedSize = e.compressedSize;
+ crc = e.crc;
+ dostime = e.dostime;
+ method = e.method;
+ extra = e.extra;
+ comment = e.comment;
+ }
+
+ final void setDOSTime(int dostime)
+ {
+ this.dostime = dostime;
+ known |= KNOWN_TIME;
+ }
+
+ final int getDOSTime()
+ {
+ if ((known & KNOWN_TIME) == 0)
+ return 0;
+ else
+ return dostime;
+ }
+
+ /**
+ * Creates a copy of this zip entry.
+ */
+ /**
+ * Clones the entry.
+ */
+ public Object clone()
+ {
+ try
+ {
+ // The JCL says that the `extra' field is also copied.
+ ZipEntry clone = (ZipEntry) super.clone();
+ if (extra != null)
+ clone.extra = (byte[]) extra.clone();
+ return clone;
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ throw new InternalError();
+ }
+ }
+
+ /**
+ * Returns the entry name. The path components in the entry are
+ * always separated by slashes ('/').
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Sets the time of last modification of the entry.
+ * @time the time of last modification of the entry.
+ */
+ public void setTime(long time)
+ {
+ Calendar cal = getCalendar();
+ synchronized (cal)
+ {
+ cal.setTime(new Date(time));
+ dostime = (cal.get(Calendar.YEAR) - 1980 & 0x7f) << 25
+ | (cal.get(Calendar.MONTH) + 1) << 21
+ | (cal.get(Calendar.DAY_OF_MONTH)) << 16
+ | (cal.get(Calendar.HOUR_OF_DAY)) << 11
+ | (cal.get(Calendar.MINUTE)) << 5
+ | (cal.get(Calendar.SECOND)) >> 1;
+ }
+ this.known |= KNOWN_TIME;
+ }
+
+ /**
+ * Gets the time of last modification of the entry.
+ * @return the time of last modification of the entry, or -1 if unknown.
+ */
+ public long getTime()
+ {
+ if ((known & KNOWN_TIME) == 0)
+ return -1;
+
+ // The extra bytes might contain the time (posix/unix extension)
+ parseExtra ();
+
+ int sec = 2 * (dostime & 0x1f);
+ int min = (dostime >> 5) & 0x3f;
+ int hrs = (dostime >> 11) & 0x1f;
+ int day = (dostime >> 16) & 0x1f;
+ int mon = ((dostime >> 21) & 0xf) - 1;
+ int year = ((dostime >> 25) & 0x7f) + 1980; /* since 1900 */
+
+ try
+ {
+ cal = getCalendar();
+ synchronized (cal)
+ {
+ cal.set(year, mon, day, hrs, min, sec);
+ return cal.getTime().getTime();
+ }
+ }
+ catch (RuntimeException ex)
+ {
+ /* Ignore illegal time stamp */
+ known &= ~KNOWN_TIME;
+ return -1;
+ }
+ }
+
+ private static synchronized Calendar getCalendar()
+ {
+ if (cal == null)
+ cal = Calendar.getInstance();
+
+ return cal;
+ }
+
+ /**
+ * Sets the size of the uncompressed data.
+ * @exception IllegalArgumentException if size is not in 0..0xffffffffL
+ */
+ public void setSize(long size)
+ {
+ if ((size & 0xffffffff00000000L) != 0)
+ throw new IllegalArgumentException();
+ this.size = (int) size;
+ this.known |= KNOWN_SIZE;
+ }
+
+ /**
+ * Gets the size of the uncompressed data.
+ * @return the size or -1 if unknown.
+ */
+ public long getSize()
+ {
+ return (known & KNOWN_SIZE) != 0 ? size & 0xffffffffL : -1L;
+ }
+
+ /**
+ * Sets the size of the compressed data.
+ */
+ public void setCompressedSize(long csize)
+ {
+ this.compressedSize = csize;
+ }
+
+ /**
+ * Gets the size of the compressed data.
+ * @return the size or -1 if unknown.
+ */
+ public long getCompressedSize()
+ {
+ return compressedSize;
+ }
+
+ /**
+ * Sets the crc of the uncompressed data.
+ * @exception IllegalArgumentException if crc is not in 0..0xffffffffL
+ */
+ public void setCrc(long crc)
+ {
+ if ((crc & 0xffffffff00000000L) != 0)
+ throw new IllegalArgumentException();
+ this.crc = (int) crc;
+ this.known |= KNOWN_CRC;
+ }
+
+ /**
+ * Gets the crc of the uncompressed data.
+ * @return the crc or -1 if unknown.
+ */
+ public long getCrc()
+ {
+ return (known & KNOWN_CRC) != 0 ? crc & 0xffffffffL : -1L;
+ }
+
+ /**
+ * Sets the compression method. Only DEFLATED and STORED are
+ * supported.
+ * @exception IllegalArgumentException if method is not supported.
+ * @see ZipOutputStream#DEFLATED
+ * @see ZipOutputStream#STORED
+ */
+ public void setMethod(int method)
+ {
+ if (method != ZipOutputStream.STORED
+ && method != ZipOutputStream.DEFLATED)
+ throw new IllegalArgumentException();
+ this.method = (short) method;
+ }
+
+ /**
+ * Gets the compression method.
+ * @return the compression method or -1 if unknown.
+ */
+ public int getMethod()
+ {
+ return method;
+ }
+
+ /**
+ * Sets the extra data.
+ * @exception IllegalArgumentException if extra is longer than 0xffff bytes.
+ */
+ public void setExtra(byte[] extra)
+ {
+ if (extra == null)
+ {
+ this.extra = null;
+ return;
+ }
+ if (extra.length > 0xffff)
+ throw new IllegalArgumentException();
+ this.extra = extra;
+ }
+
+ private void parseExtra()
+ {
+ // Already parsed?
+ if ((known & KNOWN_EXTRA) != 0)
+ return;
+
+ if (extra == null)
+ {
+ known |= KNOWN_EXTRA;
+ return;
+ }
+
+ try
+ {
+ int pos = 0;
+ while (pos < extra.length)
+ {
+ int sig = (extra[pos++] & 0xff)
+ | (extra[pos++] & 0xff) << 8;
+ int len = (extra[pos++] & 0xff)
+ | (extra[pos++] & 0xff) << 8;
+ if (sig == 0x5455)
+ {
+ /* extended time stamp */
+ int flags = extra[pos];
+ if ((flags & 1) != 0)
+ {
+ long time = ((extra[pos+1] & 0xff)
+ | (extra[pos+2] & 0xff) << 8
+ | (extra[pos+3] & 0xff) << 16
+ | (extra[pos+4] & 0xff) << 24);
+ setTime(time);
+ }
+ }
+ pos += len;
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException ex)
+ {
+ /* be lenient */
+ return;
+ }
+
+ known |= KNOWN_EXTRA;
+ }
+
+ /**
+ * Gets the extra data.
+ * @return the extra data or null if not set.
+ */
+ public byte[] getExtra()
+ {
+ return extra;
+ }
+
+ /**
+ * Sets the entry comment.
+ * @exception IllegalArgumentException if comment is longer than 0xffff.
+ */
+ public void setComment(String comment)
+ {
+ if (comment != null && comment.length() > 0xffff)
+ throw new IllegalArgumentException();
+ this.comment = comment;
+ }
+
+ /**
+ * Gets the comment.
+ * @return the comment or null if not set.
+ */
+ public String getComment()
+ {
+ return comment;
+ }
+
+ /**
+ * Gets true, if the entry is a directory. This is solely
+ * determined by the name, a trailing slash '/' marks a directory.
+ */
+ public boolean isDirectory()
+ {
+ int nlen = name.length();
+ return nlen > 0 && name.charAt(nlen - 1) == '/';
+ }
+
+ /**
+ * Gets the string representation of this ZipEntry. This is just
+ * the name as returned by getName().
+ */
+ public String toString()
+ {
+ return name;
+ }
+
+ /**
+ * Gets the hashCode of this ZipEntry. This is just the hashCode
+ * of the name. Note that the equals method isn't changed, though.
+ */
+ public int hashCode()
+ {
+ return name.hashCode();
+ }
+}
diff --git a/libjava/classpath/java/util/zip/ZipException.java b/libjava/classpath/java/util/zip/ZipException.java
new file mode 100644
index 00000000000..c5bfc1e7c39
--- /dev/null
+++ b/libjava/classpath/java/util/zip/ZipException.java
@@ -0,0 +1,72 @@
+/* ZipException.java - exception representing a zip related error
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 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.zip;
+
+import java.io.IOException;
+
+/**
+ * Thrown during the creation or input of a zip file.
+ *
+ * @author Jochen Hoenicke
+ * @author Per Bothner
+ * @status updated to 1.4
+ */
+public class ZipException extends IOException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 8000196834066748623L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public ZipException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param msg the message
+ */
+ public ZipException (String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/util/zip/ZipFile.java b/libjava/classpath/java/util/zip/ZipFile.java
new file mode 100644
index 00000000000..33f67c78bfe
--- /dev/null
+++ b/libjava/classpath/java/util/zip/ZipFile.java
@@ -0,0 +1,595 @@
+/* ZipFile.java --
+ Copyright (C) 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.zip;
+
+import gnu.java.util.EmptyEnumeration;
+
+import java.io.BufferedInputStream;
+import java.io.DataInput;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * This class represents a Zip archive. You can ask for the contained
+ * entries, or get an input stream for a file entry. The entry is
+ * automatically decompressed.
+ *
+ * This class is thread safe: You can open input streams for arbitrary
+ * entries in different threads.
+ *
+ * @author Jochen Hoenicke
+ * @author Artur Biesiadowski
+ */
+public class ZipFile implements ZipConstants
+{
+
+ /**
+ * Mode flag to open a zip file for reading.
+ */
+ public static final int OPEN_READ = 0x1;
+
+ /**
+ * Mode flag to delete a zip file after reading.
+ */
+ public static final int OPEN_DELETE = 0x4;
+
+ // Name of this zip file.
+ private final String name;
+
+ // File from which zip entries are read.
+ private final RandomAccessFile raf;
+
+ // The entries of this zip file when initialized and not yet closed.
+ private HashMap entries;
+
+ private boolean closed = false;
+
+ /**
+ * Opens a Zip file with the given name for reading.
+ * @exception IOException if a i/o error occured.
+ * @exception ZipException if the file doesn't contain a valid zip
+ * archive.
+ */
+ public ZipFile(String name) throws ZipException, IOException
+ {
+ this.raf = new RandomAccessFile(name, "r");
+ this.name = name;
+ checkZipFile();
+ }
+
+ /**
+ * Opens a Zip file reading the given File.
+ * @exception IOException if a i/o error occured.
+ * @exception ZipException if the file doesn't contain a valid zip
+ * archive.
+ */
+ public ZipFile(File file) throws ZipException, IOException
+ {
+ this.raf = new RandomAccessFile(file, "r");
+ this.name = file.getPath();
+ checkZipFile();
+ }
+
+ /**
+ * Opens a Zip file reading the given File in the given mode.
+ *
+ * If the OPEN_DELETE mode is specified, the zip file will be deleted at
+ * some time moment after it is opened. It will be deleted before the zip
+ * file is closed or the Virtual Machine exits.
+ *
+ * The contents of the zip file will be accessible until it is closed.
+ *
+ * @since JDK1.3
+ * @param mode Must be one of OPEN_READ or OPEN_READ | OPEN_DELETE
+ *
+ * @exception IOException if a i/o error occured.
+ * @exception ZipException if the file doesn't contain a valid zip
+ * archive.
+ */
+ public ZipFile(File file, int mode) throws ZipException, IOException
+ {
+ if (mode != OPEN_READ && mode != (OPEN_READ | OPEN_DELETE))
+ throw new IllegalArgumentException("invalid mode");
+ if ((mode & OPEN_DELETE) != 0)
+ file.deleteOnExit();
+ this.raf = new RandomAccessFile(file, "r");
+ this.name = file.getPath();
+ checkZipFile();
+ }
+
+ private void checkZipFile() throws IOException, ZipException
+ {
+ byte[] magicBuf = new byte[4];
+ raf.read(magicBuf);
+
+ if (readLeInt(magicBuf, 0) != LOCSIG)
+ {
+ raf.close();
+ throw new ZipException("Not a valid zip file");
+ }
+ }
+
+ /**
+ * Checks if file is closed and throws an exception.
+ */
+ private void checkClosed()
+ {
+ if (closed)
+ throw new IllegalStateException("ZipFile has closed: " + name);
+ }
+
+ /**
+ * Read an unsigned short in little endian byte order from the given
+ * DataInput stream using the given byte buffer.
+ *
+ * @param di DataInput stream to read from.
+ * @param b the byte buffer to read in (must be at least 2 bytes long).
+ * @return The value read.
+ *
+ * @exception IOException if a i/o error occured.
+ * @exception EOFException if the file ends prematurely
+ */
+ private int readLeShort(DataInput di, byte[] b) throws IOException
+ {
+ di.readFully(b, 0, 2);
+ return (b[0] & 0xff) | (b[1] & 0xff) << 8;
+ }
+
+ /**
+ * Read an int in little endian byte order from the given
+ * DataInput stream using the given byte buffer.
+ *
+ * @param di DataInput stream to read from.
+ * @param b the byte buffer to read in (must be at least 4 bytes long).
+ * @return The value read.
+ *
+ * @exception IOException if a i/o error occured.
+ * @exception EOFException if the file ends prematurely
+ */
+ private int readLeInt(DataInput di, byte[] b) throws IOException
+ {
+ di.readFully(b, 0, 4);
+ return ((b[0] & 0xff) | (b[1] & 0xff) << 8)
+ | ((b[2] & 0xff) | (b[3] & 0xff) << 8) << 16;
+ }
+
+ /**
+ * Read an unsigned short in little endian byte order from the given
+ * byte buffer at the given offset.
+ *
+ * @param b the byte array to read from.
+ * @param off the offset to read from.
+ * @return The value read.
+ */
+ private int readLeShort(byte[] b, int off)
+ {
+ return (b[off] & 0xff) | (b[off+1] & 0xff) << 8;
+ }
+
+ /**
+ * Read an int in little endian byte order from the given
+ * byte buffer at the given offset.
+ *
+ * @param b the byte array to read from.
+ * @param off the offset to read from.
+ * @return The value read.
+ */
+ private int readLeInt(byte[] b, int off)
+ {
+ return ((b[off] & 0xff) | (b[off+1] & 0xff) << 8)
+ | ((b[off+2] & 0xff) | (b[off+3] & 0xff) << 8) << 16;
+ }
+
+
+ /**
+ * Read the central directory of a zip file and fill the entries
+ * array. This is called exactly once when first needed. It is called
+ * while holding the lock on <code>raf</code>.
+ *
+ * @exception IOException if a i/o error occured.
+ * @exception ZipException if the central directory is malformed
+ */
+ private void readEntries() throws ZipException, IOException
+ {
+ /* Search for the End Of Central Directory. When a zip comment is
+ * present the directory may start earlier.
+ * FIXME: This searches the whole file in a very slow manner if the
+ * file isn't a zip file.
+ */
+ long pos = raf.length() - ENDHDR;
+ byte[] ebs = new byte[CENHDR];
+
+ do
+ {
+ if (pos < 0)
+ throw new ZipException
+ ("central directory not found, probably not a zip file: " + name);
+ raf.seek(pos--);
+ }
+ while (readLeInt(raf, ebs) != ENDSIG);
+
+ if (raf.skipBytes(ENDTOT - ENDNRD) != ENDTOT - ENDNRD)
+ throw new EOFException(name);
+ int count = readLeShort(raf, ebs);
+ if (raf.skipBytes(ENDOFF - ENDSIZ) != ENDOFF - ENDSIZ)
+ throw new EOFException(name);
+ int centralOffset = readLeInt(raf, ebs);
+
+ entries = new HashMap(count+count/2);
+ raf.seek(centralOffset);
+
+ byte[] buffer = new byte[16];
+ for (int i = 0; i < count; i++)
+ {
+ raf.readFully(ebs);
+ if (readLeInt(ebs, 0) != CENSIG)
+ throw new ZipException("Wrong Central Directory signature: " + name);
+
+ int method = readLeShort(ebs, CENHOW);
+ int dostime = readLeInt(ebs, CENTIM);
+ int crc = readLeInt(ebs, CENCRC);
+ int csize = readLeInt(ebs, CENSIZ);
+ int size = readLeInt(ebs, CENLEN);
+ int nameLen = readLeShort(ebs, CENNAM);
+ int extraLen = readLeShort(ebs, CENEXT);
+ int commentLen = readLeShort(ebs, CENCOM);
+
+ int offset = readLeInt(ebs, CENOFF);
+
+ int needBuffer = Math.max(nameLen, commentLen);
+ if (buffer.length < needBuffer)
+ buffer = new byte[needBuffer];
+
+ raf.readFully(buffer, 0, nameLen);
+ String name = new String(buffer, 0, 0, nameLen);
+
+ ZipEntry entry = new ZipEntry(name);
+ entry.setMethod(method);
+ entry.setCrc(crc & 0xffffffffL);
+ entry.setSize(size & 0xffffffffL);
+ entry.setCompressedSize(csize & 0xffffffffL);
+ entry.setDOSTime(dostime);
+ if (extraLen > 0)
+ {
+ byte[] extra = new byte[extraLen];
+ raf.readFully(extra);
+ entry.setExtra(extra);
+ }
+ if (commentLen > 0)
+ {
+ raf.readFully(buffer, 0, commentLen);
+ entry.setComment(new String(buffer, 0, commentLen));
+ }
+ entry.offset = offset;
+ entries.put(name, entry);
+ }
+ }
+
+ /**
+ * Closes the ZipFile. This also closes all input streams given by
+ * this class. After this is called, no further method should be
+ * called.
+ *
+ * @exception IOException if a i/o error occured.
+ */
+ public void close() throws IOException
+ {
+ synchronized (raf)
+ {
+ closed = true;
+ entries = null;
+ raf.close();
+ }
+ }
+
+ /**
+ * Calls the <code>close()</code> method when this ZipFile has not yet
+ * been explicitly closed.
+ */
+ protected void finalize() throws IOException
+ {
+ if (!closed && raf != null) close();
+ }
+
+ /**
+ * Returns an enumeration of all Zip entries in this Zip file.
+ *
+ * @exception IllegalStateException when the ZipFile has already been closed
+ */
+ public Enumeration entries()
+ {
+ checkClosed();
+
+ try
+ {
+ return new ZipEntryEnumeration(getEntries().values().iterator());
+ }
+ catch (IOException ioe)
+ {
+ return EmptyEnumeration.getInstance();
+ }
+ }
+
+ /**
+ * Checks that the ZipFile is still open and reads entries when necessary.
+ *
+ * @exception IllegalStateException when the ZipFile has already been closed.
+ * @exception IOEexception when the entries could not be read.
+ */
+ private HashMap getEntries() throws IOException
+ {
+ synchronized(raf)
+ {
+ checkClosed();
+
+ if (entries == null)
+ readEntries();
+
+ return entries;
+ }
+ }
+
+ /**
+ * Searches for a zip entry in this archive with the given name.
+ *
+ * @param the name. May contain directory components separated by
+ * slashes ('/').
+ * @return the zip entry, or null if no entry with that name exists.
+ *
+ * @exception IllegalStateException when the ZipFile has already been closed
+ */
+ public ZipEntry getEntry(String name)
+ {
+ checkClosed();
+
+ try
+ {
+ HashMap entries = getEntries();
+ ZipEntry entry = (ZipEntry) entries.get(name);
+ // If we didn't find it, maybe it's a directory.
+ if (entry == null && !name.endsWith("/"))
+ entry = (ZipEntry) entries.get(name + '/');
+ return entry != null ? new ZipEntry(entry, name) : null;
+ }
+ catch (IOException ioe)
+ {
+ return null;
+ }
+ }
+
+
+ //access should be protected by synchronized(raf)
+ private byte[] locBuf = new byte[LOCHDR];
+
+ /**
+ * Checks, if the local header of the entry at index i matches the
+ * central directory, and returns the offset to the data.
+ *
+ * @param entry to check.
+ * @return the start offset of the (compressed) data.
+ *
+ * @exception IOException if a i/o error occured.
+ * @exception ZipException if the local header doesn't match the
+ * central directory header
+ */
+ private long checkLocalHeader(ZipEntry entry) throws IOException
+ {
+ synchronized (raf)
+ {
+ raf.seek(entry.offset);
+ raf.readFully(locBuf);
+
+ if (readLeInt(locBuf, 0) != LOCSIG)
+ throw new ZipException("Wrong Local header signature: " + name);
+
+ if (entry.getMethod() != readLeShort(locBuf, LOCHOW))
+ throw new ZipException("Compression method mismatch: " + name);
+
+ if (entry.getName().length() != readLeShort(locBuf, LOCNAM))
+ throw new ZipException("file name length mismatch: " + name);
+
+ int extraLen = entry.getName().length() + readLeShort(locBuf, LOCEXT);
+ return entry.offset + LOCHDR + extraLen;
+ }
+ }
+
+ /**
+ * Creates an input stream reading the given zip entry as
+ * uncompressed data. Normally zip entry should be an entry
+ * returned by getEntry() or entries().
+ *
+ * This implementation returns null if the requested entry does not
+ * exist. This decision is not obviously correct, however, it does
+ * appear to mirror Sun's implementation, and it is consistant with
+ * their javadoc. On the other hand, the old JCL book, 2nd Edition,
+ * claims that this should return a "non-null ZIP entry". We have
+ * chosen for now ignore the old book, as modern versions of Ant (an
+ * important application) depend on this behaviour. See discussion
+ * in this thread:
+ * http://gcc.gnu.org/ml/java-patches/2004-q2/msg00602.html
+ *
+ * @param entry the entry to create an InputStream for.
+ * @return the input stream, or null if the requested entry does not exist.
+ *
+ * @exception IllegalStateException when the ZipFile has already been closed
+ * @exception IOException if a i/o error occured.
+ * @exception ZipException if the Zip archive is malformed.
+ */
+ public InputStream getInputStream(ZipEntry entry) throws IOException
+ {
+ checkClosed();
+
+ HashMap entries = getEntries();
+ String name = entry.getName();
+ ZipEntry zipEntry = (ZipEntry) entries.get(name);
+ if (zipEntry == null)
+ return null;
+
+ long start = checkLocalHeader(zipEntry);
+ int method = zipEntry.getMethod();
+ InputStream is = new BufferedInputStream(new PartialInputStream
+ (raf, start, zipEntry.getCompressedSize()));
+ switch (method)
+ {
+ case ZipOutputStream.STORED:
+ return is;
+ case ZipOutputStream.DEFLATED:
+ return new InflaterInputStream(is, new Inflater(true));
+ default:
+ throw new ZipException("Unknown compression method " + method);
+ }
+ }
+
+ /**
+ * Returns the (path) name of this zip file.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns the number of entries in this zip file.
+ *
+ * @exception IllegalStateException when the ZipFile has already been closed
+ */
+ public int size()
+ {
+ checkClosed();
+
+ try
+ {
+ return getEntries().size();
+ }
+ catch (IOException ioe)
+ {
+ return 0;
+ }
+ }
+
+ private static class ZipEntryEnumeration implements Enumeration
+ {
+ private final Iterator elements;
+
+ public ZipEntryEnumeration(Iterator elements)
+ {
+ this.elements = elements;
+ }
+
+ public boolean hasMoreElements()
+ {
+ return elements.hasNext();
+ }
+
+ public Object nextElement()
+ {
+ /* We return a clone, just to be safe that the user doesn't
+ * change the entry.
+ */
+ return ((ZipEntry)elements.next()).clone();
+ }
+ }
+
+ private static class PartialInputStream extends InputStream
+ {
+ private final RandomAccessFile raf;
+ long filepos, end;
+
+ public PartialInputStream(RandomAccessFile raf, long start, long len)
+ {
+ this.raf = raf;
+ filepos = start;
+ end = start + len;
+ }
+
+ public int available()
+ {
+ long amount = end - filepos;
+ if (amount > Integer.MAX_VALUE)
+ return Integer.MAX_VALUE;
+ return (int) amount;
+ }
+
+ public int read() throws IOException
+ {
+ if (filepos == end)
+ return -1;
+ synchronized (raf)
+ {
+ raf.seek(filepos++);
+ return raf.read();
+ }
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (len > end - filepos)
+ {
+ len = (int) (end - filepos);
+ if (len == 0)
+ return -1;
+ }
+ synchronized (raf)
+ {
+ raf.seek(filepos);
+ int count = raf.read(b, off, len);
+ if (count > 0)
+ filepos += len;
+ return count;
+ }
+ }
+
+ public long skip(long amount)
+ {
+ if (amount < 0)
+ throw new IllegalArgumentException();
+ if (amount > end - filepos)
+ amount = end - filepos;
+ filepos += amount;
+ return amount;
+ }
+ }
+}
diff --git a/libjava/classpath/java/util/zip/ZipInputStream.java b/libjava/classpath/java/util/zip/ZipInputStream.java
new file mode 100644
index 00000000000..5732523238e
--- /dev/null
+++ b/libjava/classpath/java/util/zip/ZipInputStream.java
@@ -0,0 +1,371 @@
+/* ZipInputStream.java --
+ Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.zip;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This is a FilterInputStream that reads the files in an zip archive
+ * one after another. It has a special method to get the zip entry of
+ * the next file. The zip entry contains information about the file name
+ * size, compressed size, CRC, etc.
+ *
+ * It includes support for STORED and DEFLATED entries.
+ *
+ * @author Jochen Hoenicke
+ */
+public class ZipInputStream extends InflaterInputStream implements ZipConstants
+{
+ private CRC32 crc = new CRC32();
+ private ZipEntry entry = null;
+
+ private int csize;
+ private int size;
+ private int method;
+ private int flags;
+ private int avail;
+ private boolean entryAtEOF;
+
+ /**
+ * Creates a new Zip input stream, reading a zip archive.
+ */
+ public ZipInputStream(InputStream in)
+ {
+ super(in, new Inflater(true));
+ }
+
+ private void fillBuf() throws IOException
+ {
+ avail = len = in.read(buf, 0, buf.length);
+ }
+
+ private int readBuf(byte[] out, int offset, int length) throws IOException
+ {
+ if (avail <= 0)
+ {
+ fillBuf();
+ if (avail <= 0)
+ return -1;
+ }
+ if (length > avail)
+ length = avail;
+ System.arraycopy(buf, len - avail, out, offset, length);
+ avail -= length;
+ return length;
+ }
+
+ private void readFully(byte[] out) throws IOException
+ {
+ int off = 0;
+ int len = out.length;
+ while (len > 0)
+ {
+ int count = readBuf(out, off, len);
+ if (count == -1)
+ throw new EOFException();
+ off += count;
+ len -= count;
+ }
+ }
+
+ private int readLeByte() throws IOException
+ {
+ if (avail <= 0)
+ {
+ fillBuf();
+ if (avail <= 0)
+ throw new ZipException("EOF in header");
+ }
+ return buf[len - avail--] & 0xff;
+ }
+
+ /**
+ * Read an unsigned short in little endian byte order.
+ */
+ private int readLeShort() throws IOException
+ {
+ return readLeByte() | (readLeByte() << 8);
+ }
+
+ /**
+ * Read an int in little endian byte order.
+ */
+ private int readLeInt() throws IOException
+ {
+ return readLeShort() | (readLeShort() << 16);
+ }
+
+ /**
+ * Open the next entry from the zip archive, and return its description.
+ * If the previous entry wasn't closed, this method will close it.
+ */
+ public ZipEntry getNextEntry() throws IOException
+ {
+ if (crc == null)
+ throw new IOException("Stream closed.");
+ if (entry != null)
+ closeEntry();
+
+ int header = readLeInt();
+ if (header == CENSIG)
+ {
+ /* Central Header reached. */
+ close();
+ return null;
+ }
+ if (header != LOCSIG)
+ throw new ZipException("Wrong Local header signature: "
+ + Integer.toHexString(header));
+ /* skip version */
+ readLeShort();
+ flags = readLeShort();
+ method = readLeShort();
+ int dostime = readLeInt();
+ int crc = readLeInt();
+ csize = readLeInt();
+ size = readLeInt();
+ int nameLen = readLeShort();
+ int extraLen = readLeShort();
+
+ if (method == ZipOutputStream.STORED && csize != size)
+ throw new ZipException("Stored, but compressed != uncompressed");
+
+
+ byte[] buffer = new byte[nameLen];
+ readFully(buffer);
+ String name = new String(buffer);
+
+ entry = createZipEntry(name);
+ entryAtEOF = false;
+ entry.setMethod(method);
+ if ((flags & 8) == 0)
+ {
+ entry.setCrc(crc & 0xffffffffL);
+ entry.setSize(size & 0xffffffffL);
+ entry.setCompressedSize(csize & 0xffffffffL);
+ }
+ entry.setDOSTime(dostime);
+ if (extraLen > 0)
+ {
+ byte[] extra = new byte[extraLen];
+ readFully(extra);
+ entry.setExtra(extra);
+ }
+
+ if (method == ZipOutputStream.DEFLATED && avail > 0)
+ {
+ System.arraycopy(buf, len - avail, buf, 0, avail);
+ len = avail;
+ avail = 0;
+ inf.setInput(buf, 0, len);
+ }
+ return entry;
+ }
+
+ private void readDataDescr() throws IOException
+ {
+ if (readLeInt() != EXTSIG)
+ throw new ZipException("Data descriptor signature not found");
+ entry.setCrc(readLeInt() & 0xffffffffL);
+ csize = readLeInt();
+ size = readLeInt();
+ entry.setSize(size & 0xffffffffL);
+ entry.setCompressedSize(csize & 0xffffffffL);
+ }
+
+ /**
+ * Closes the current zip entry and moves to the next one.
+ */
+ public void closeEntry() throws IOException
+ {
+ if (crc == null)
+ throw new IOException("Stream closed.");
+ if (entry == null)
+ return;
+
+ if (method == ZipOutputStream.DEFLATED)
+ {
+ if ((flags & 8) != 0)
+ {
+ /* We don't know how much we must skip, read until end. */
+ byte[] tmp = new byte[2048];
+ while (read(tmp) > 0)
+ ;
+ /* read will close this entry */
+ return;
+ }
+ csize -= inf.getTotalIn();
+ avail = inf.getRemaining();
+ }
+
+ if (avail > csize && csize >= 0)
+ avail -= csize;
+ else
+ {
+ csize -= avail;
+ avail = 0;
+ while (csize != 0)
+ {
+ long skipped = in.skip(csize & 0xffffffffL);
+ if (skipped <= 0)
+ throw new ZipException("zip archive ends early.");
+ csize -= skipped;
+ }
+ }
+
+ size = 0;
+ crc.reset();
+ if (method == ZipOutputStream.DEFLATED)
+ inf.reset();
+ entry = null;
+ entryAtEOF = true;
+ }
+
+ public int available() throws IOException
+ {
+ return entryAtEOF ? 0 : 1;
+ }
+
+ /**
+ * Reads a byte from the current zip entry.
+ * @return the byte or -1 on EOF.
+ * @exception IOException if a i/o error occured.
+ * @exception ZipException if the deflated stream is corrupted.
+ */
+ public int read() throws IOException
+ {
+ byte[] b = new byte[1];
+ if (read(b, 0, 1) <= 0)
+ return -1;
+ return b[0] & 0xff;
+ }
+
+ /**
+ * Reads a block of bytes from the current zip entry.
+ * @return the number of bytes read (may be smaller, even before
+ * EOF), or -1 on EOF.
+ * @exception IOException if a i/o error occured.
+ * @exception ZipException if the deflated stream is corrupted.
+ */
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (len == 0)
+ return 0;
+ if (crc == null)
+ throw new IOException("Stream closed.");
+ if (entry == null)
+ return -1;
+ boolean finished = false;
+ switch (method)
+ {
+ case ZipOutputStream.DEFLATED:
+ len = super.read(b, off, len);
+ if (len < 0)
+ {
+ if (!inf.finished())
+ throw new ZipException("Inflater not finished!?");
+ avail = inf.getRemaining();
+ if ((flags & 8) != 0)
+ readDataDescr();
+
+ if (inf.getTotalIn() != csize
+ || inf.getTotalOut() != size)
+ throw new ZipException("size mismatch: "+csize+";"+size+" <-> "+inf.getTotalIn()+";"+inf.getTotalOut());
+ inf.reset();
+ finished = true;
+ }
+ break;
+
+ case ZipOutputStream.STORED:
+
+ if (len > csize && csize >= 0)
+ len = csize;
+
+ len = readBuf(b, off, len);
+ if (len > 0)
+ {
+ csize -= len;
+ size -= len;
+ }
+
+ if (csize == 0)
+ finished = true;
+ else if (len < 0)
+ throw new ZipException("EOF in stored block");
+ break;
+ }
+
+ if (len > 0)
+ crc.update(b, off, len);
+
+ if (finished)
+ {
+ if ((crc.getValue() & 0xffffffffL) != entry.getCrc())
+ throw new ZipException("CRC mismatch");
+ crc.reset();
+ entry = null;
+ entryAtEOF = true;
+ }
+ return len;
+ }
+
+ /**
+ * Closes the zip file.
+ * @exception IOException if a i/o error occured.
+ */
+ public void close() throws IOException
+ {
+ super.close();
+ crc = null;
+ entry = null;
+ entryAtEOF = true;
+ }
+
+ /**
+ * Creates a new zip entry for the given name. This is equivalent
+ * to new ZipEntry(name).
+ * @param name the name of the zip entry.
+ */
+ protected ZipEntry createZipEntry(String name)
+ {
+ return new ZipEntry(name);
+ }
+}
diff --git a/libjava/classpath/java/util/zip/ZipOutputStream.java b/libjava/classpath/java/util/zip/ZipOutputStream.java
new file mode 100644
index 00000000000..5699ff046f5
--- /dev/null
+++ b/libjava/classpath/java/util/zip/ZipOutputStream.java
@@ -0,0 +1,399 @@
+/* ZipOutputStream.java --
+ Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.zip;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * This is a FilterOutputStream that writes the files into a zip
+ * archive one after another. It has a special method to start a new
+ * zip entry. The zip entries contains information about the file name
+ * size, compressed size, CRC, etc.
+ *
+ * It includes support for STORED and DEFLATED entries.
+ *
+ * This class is not thread safe.
+ *
+ * @author Jochen Hoenicke
+ */
+public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants
+{
+ private Vector entries = new Vector();
+ private CRC32 crc = new CRC32();
+ private ZipEntry curEntry = null;
+
+ private int curMethod;
+ private int size;
+ private int offset = 0;
+
+ private byte[] zipComment = new byte[0];
+ private int defaultMethod = DEFLATED;
+
+ /**
+ * Our Zip version is hard coded to 1.0 resp. 2.0
+ */
+ private static final int ZIP_STORED_VERSION = 10;
+ private static final int ZIP_DEFLATED_VERSION = 20;
+
+ /**
+ * Compression method. This method doesn't compress at all.
+ */
+ public static final int STORED = 0;
+
+ /**
+ * Compression method. This method uses the Deflater.
+ */
+ public static final int DEFLATED = 8;
+
+ /**
+ * Creates a new Zip output stream, writing a zip archive.
+ * @param out the output stream to which the zip archive is written.
+ */
+ public ZipOutputStream(OutputStream out)
+ {
+ super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
+ }
+
+ /**
+ * Set the zip file comment.
+ * @param comment the comment.
+ * @exception IllegalArgumentException if encoding of comment is
+ * longer than 0xffff bytes.
+ */
+ public void setComment(String comment)
+ {
+ byte[] commentBytes;
+ commentBytes = comment.getBytes();
+ if (commentBytes.length > 0xffff)
+ throw new IllegalArgumentException("Comment too long.");
+ zipComment = commentBytes;
+ }
+
+ /**
+ * Sets default compression method. If the Zip entry specifies
+ * another method its method takes precedence.
+ * @param method the method.
+ * @exception IllegalArgumentException if method is not supported.
+ * @see #STORED
+ * @see #DEFLATED
+ */
+ public void setMethod(int method)
+ {
+ if (method != STORED && method != DEFLATED)
+ throw new IllegalArgumentException("Method not supported.");
+ defaultMethod = method;
+ }
+
+ /**
+ * Sets default compression level. The new level will be activated
+ * immediately.
+ * @exception IllegalArgumentException if level is not supported.
+ * @see Deflater
+ */
+ public void setLevel(int level)
+ {
+ def.setLevel(level);
+ }
+
+ /**
+ * Write an unsigned short in little endian byte order.
+ */
+ private void writeLeShort(int value) throws IOException
+ {
+ out.write(value & 0xff);
+ out.write((value >> 8) & 0xff);
+ }
+
+ /**
+ * Write an int in little endian byte order.
+ */
+ private void writeLeInt(int value) throws IOException
+ {
+ writeLeShort(value);
+ writeLeShort(value >> 16);
+ }
+
+ /**
+ * Starts a new Zip entry. It automatically closes the previous
+ * entry if present. If the compression method is stored, the entry
+ * must have a valid size and crc, otherwise all elements (except
+ * name) are optional, but must be correct if present. If the time
+ * is not set in the entry, the current time is used.
+ * @param entry the entry.
+ * @exception IOException if an I/O error occured.
+ * @exception ZipException if stream was finished.
+ */
+ public void putNextEntry(ZipEntry entry) throws IOException
+ {
+ if (entries == null)
+ throw new ZipException("ZipOutputStream was finished");
+
+ int method = entry.getMethod();
+ int flags = 0;
+ if (method == -1)
+ method = defaultMethod;
+
+ if (method == STORED)
+ {
+ if (entry.getCompressedSize() >= 0)
+ {
+ if (entry.getSize() < 0)
+ entry.setSize(entry.getCompressedSize());
+ else if (entry.getSize() != entry.getCompressedSize())
+ throw new ZipException
+ ("Method STORED, but compressed size != size");
+ }
+ else
+ entry.setCompressedSize(entry.getSize());
+
+ if (entry.getSize() < 0)
+ throw new ZipException("Method STORED, but size not set");
+ if (entry.getCrc() < 0)
+ throw new ZipException("Method STORED, but crc not set");
+ }
+ else if (method == DEFLATED)
+ {
+ if (entry.getCompressedSize() < 0
+ || entry.getSize() < 0 || entry.getCrc() < 0)
+ flags |= 8;
+ }
+
+ if (curEntry != null)
+ closeEntry();
+
+ if (entry.getTime() < 0)
+ entry.setTime(System.currentTimeMillis());
+
+ entry.flags = flags;
+ entry.offset = offset;
+ entry.setMethod(method);
+ curMethod = method;
+ /* Write the local file header */
+ writeLeInt(LOCSIG);
+ writeLeShort(method == STORED
+ ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
+ writeLeShort(flags);
+ writeLeShort(method);
+ writeLeInt(entry.getDOSTime());
+ if ((flags & 8) == 0)
+ {
+ writeLeInt((int)entry.getCrc());
+ writeLeInt((int)entry.getCompressedSize());
+ writeLeInt((int)entry.getSize());
+ }
+ else
+ {
+ writeLeInt(0);
+ writeLeInt(0);
+ writeLeInt(0);
+ }
+ byte[] name = entry.getName().getBytes();
+ if (name.length > 0xffff)
+ throw new ZipException("Name too long.");
+ byte[] extra = entry.getExtra();
+ if (extra == null)
+ extra = new byte[0];
+ writeLeShort(name.length);
+ writeLeShort(extra.length);
+ out.write(name);
+ out.write(extra);
+
+ offset += LOCHDR + name.length + extra.length;
+
+ /* Activate the entry. */
+
+ curEntry = entry;
+ crc.reset();
+ if (method == DEFLATED)
+ def.reset();
+ size = 0;
+ }
+
+ /**
+ * Closes the current entry.
+ * @exception IOException if an I/O error occured.
+ * @exception ZipException if no entry is active.
+ */
+ public void closeEntry() throws IOException
+ {
+ if (curEntry == null)
+ throw new ZipException("No open entry");
+
+ /* First finish the deflater, if appropriate */
+ if (curMethod == DEFLATED)
+ super.finish();
+
+ int csize = curMethod == DEFLATED ? def.getTotalOut() : size;
+
+ if (curEntry.getSize() < 0)
+ curEntry.setSize(size);
+ else if (curEntry.getSize() != size)
+ throw new ZipException("size was "+size
+ +", but I expected "+curEntry.getSize());
+
+ if (curEntry.getCompressedSize() < 0)
+ curEntry.setCompressedSize(csize);
+ else if (curEntry.getCompressedSize() != csize)
+ throw new ZipException("compressed size was "+csize
+ +", but I expected "+curEntry.getSize());
+
+ if (curEntry.getCrc() < 0)
+ curEntry.setCrc(crc.getValue());
+ else if (curEntry.getCrc() != crc.getValue())
+ throw new ZipException("crc was " + Long.toHexString(crc.getValue())
+ + ", but I expected "
+ + Long.toHexString(curEntry.getCrc()));
+
+ offset += csize;
+
+ /* Now write the data descriptor entry if needed. */
+ if (curMethod == DEFLATED && (curEntry.flags & 8) != 0)
+ {
+ writeLeInt(EXTSIG);
+ writeLeInt((int)curEntry.getCrc());
+ writeLeInt((int)curEntry.getCompressedSize());
+ writeLeInt((int)curEntry.getSize());
+ offset += EXTHDR;
+ }
+
+ entries.addElement(curEntry);
+ curEntry = null;
+ }
+
+ /**
+ * Writes the given buffer to the current entry.
+ * @exception IOException if an I/O error occured.
+ * @exception ZipException if no entry is active.
+ */
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ if (curEntry == null)
+ throw new ZipException("No open entry.");
+
+ switch (curMethod)
+ {
+ case DEFLATED:
+ super.write(b, off, len);
+ break;
+
+ case STORED:
+ out.write(b, off, len);
+ break;
+ }
+
+ crc.update(b, off, len);
+ size += len;
+ }
+
+ /**
+ * Finishes the stream. This will write the central directory at the
+ * end of the zip file and flush the stream.
+ * @exception IOException if an I/O error occured.
+ */
+ public void finish() throws IOException
+ {
+ if (entries == null)
+ return;
+ if (curEntry != null)
+ closeEntry();
+
+ int numEntries = 0;
+ int sizeEntries = 0;
+
+ Enumeration e = entries.elements();
+ while (e.hasMoreElements())
+ {
+ ZipEntry entry = (ZipEntry) e.nextElement();
+
+ int method = entry.getMethod();
+ writeLeInt(CENSIG);
+ writeLeShort(method == STORED
+ ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
+ writeLeShort(method == STORED
+ ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
+ writeLeShort(entry.flags);
+ writeLeShort(method);
+ writeLeInt(entry.getDOSTime());
+ writeLeInt((int)entry.getCrc());
+ writeLeInt((int)entry.getCompressedSize());
+ writeLeInt((int)entry.getSize());
+
+ byte[] name = entry.getName().getBytes();
+ if (name.length > 0xffff)
+ throw new ZipException("Name too long.");
+ byte[] extra = entry.getExtra();
+ if (extra == null)
+ extra = new byte[0];
+ String strComment = entry.getComment();
+ byte[] comment = strComment != null
+ ? strComment.getBytes() : new byte[0];
+ if (comment.length > 0xffff)
+ throw new ZipException("Comment too long.");
+
+ writeLeShort(name.length);
+ writeLeShort(extra.length);
+ writeLeShort(comment.length);
+ writeLeShort(0); /* disk number */
+ writeLeShort(0); /* internal file attr */
+ writeLeInt(0); /* external file attr */
+ writeLeInt(entry.offset);
+
+ out.write(name);
+ out.write(extra);
+ out.write(comment);
+ numEntries++;
+ sizeEntries += CENHDR + name.length + extra.length + comment.length;
+ }
+
+ writeLeInt(ENDSIG);
+ writeLeShort(0); /* disk number */
+ writeLeShort(0); /* disk with start of central dir */
+ writeLeShort(numEntries);
+ writeLeShort(numEntries);
+ writeLeInt(sizeEntries);
+ writeLeInt(offset);
+ writeLeShort(zipComment.length);
+ out.write(zipComment);
+ out.flush();
+ entries = null;
+ }
+}
diff --git a/libjava/classpath/java/util/zip/package.html b/libjava/classpath/java/util/zip/package.html
new file mode 100644
index 00000000000..5f3ac491776
--- /dev/null
+++ b/libjava/classpath/java/util/zip/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.util.zip package.
+ Copyright (C) 2002 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 - java.util.zip</title></head>
+
+<body>
+<p>Utility classes to manipulate zip and gzip archives as files or streams,
+includes checksum and compression support.</p>
+
+</body>
+</html>